Fix possible crashes in pinned bar button.

This commit is contained in:
John Preston 2022-04-26 10:24:36 +04:00
parent c37b08ac8b
commit 7bfe096f3b

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_pinned_tracker.h" #include "history/view/history_view_pinned_tracker.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history.h" #include "history/history.h"
#include "base/weak_ptr.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
@ -163,27 +164,32 @@ rpl::producer<HistoryItem*> PinnedBarItemWithReplyMarkup(
consumer.put_next(nullptr); consumer.put_next(nullptr);
struct State { struct State {
HistoryMessageReplyMarkup *previousReplyMarkup = nullptr; bool hasReplyMarkup = false;
base::has_weak_ptr guard;
rpl::lifetime lifetime; rpl::lifetime lifetime;
FullMsgId resolvedId;
}; };
const auto state = lifetime.make_state<State>(); const auto state = lifetime.make_state<State>();
const auto pushUnique = [=](not_null<HistoryItem*> item) { const auto pushUnique = [=](not_null<HistoryItem*> item) {
const auto replyMarkup = item->inlineReplyMarkup(); const auto replyMarkup = item->inlineReplyMarkup();
if (state->previousReplyMarkup == replyMarkup) { if (!state->hasReplyMarkup && !replyMarkup) {
return; return;
} }
state->hasReplyMarkup = (replyMarkup != nullptr);
consumer.put_next(item.get()); consumer.put_next(item.get());
state->previousReplyMarkup = replyMarkup;
}; };
rpl::duplicate( rpl::duplicate(
id id
) | rpl::start_with_next([=](PinnedId current) { ) | rpl::filter([=](PinnedId current) {
return current.message && (current.message != state->resolvedId);
}) | rpl::start_with_next([=](PinnedId current) {
const auto fullId = current.message; const auto fullId = current.message;
if (!fullId) { state->lifetime.destroy();
return; state->resolvedId = fullId;
} invalidate_weak_ptrs(&state->guard);
const auto messageFlag = [=](not_null<HistoryItem*> item) { const auto messageFlag = [=](not_null<HistoryItem*> item) {
using Update = Data::MessageUpdate; using Update = Data::MessageUpdate;
session->changes().messageFlagsValue( session->changes().messageFlagsValue(
@ -195,12 +201,17 @@ rpl::producer<HistoryItem*> PinnedBarItemWithReplyMarkup(
}; };
if (const auto item = session->data().message(fullId)) { if (const auto item = session->data().message(fullId)) {
messageFlag(item); messageFlag(item);
} else { return;
}
const auto resolved = crl::guard(&state->guard, [=] {
if (const auto item = session->data().message(fullId)) {
messageFlag(item);
}
});
session->api().requestMessageData( session->api().requestMessageData(
session->data().peer(fullId.peer), session->data().peer(fullId.peer),
fullId.msg, fullId.msg,
[=] { messageFlag(session->data().message(fullId)); }); resolved);
}
}, lifetime); }, lifetime);
return lifetime; return lifetime;
}); });