diff --git a/Telegram/SourceFiles/api/api_unread_things.cpp b/Telegram/SourceFiles/api/api_unread_things.cpp index 195cb35bc3..344a5815df 100644 --- a/Telegram/SourceFiles/api/api_unread_things.cpp +++ b/Telegram/SourceFiles/api/api_unread_things.cpp @@ -101,7 +101,7 @@ void UnreadThings::requestMentions(not_null history, int loaded) { MTP_int(minId) )).done([=](const MTPmessages_Messages &result) { _mentionsRequests.remove(history); - history->unreadMentions().addSlice(result); + history->unreadMentions().addSlice(result, loaded); }).fail([=] { _mentionsRequests.remove(history); }).send(); @@ -112,9 +112,9 @@ void UnreadThings::requestReactions(not_null history, int loaded) { if (_reactionsRequests.contains(history)) { return; } - const auto offsetId = std::max( - history->unreadMentions().maxLoaded(), - MsgId(1)); + const auto offsetId = loaded + ? std::max(history->unreadReactions().maxLoaded(), MsgId(1)) + : MsgId(1); const auto limit = loaded ? kNextRequestLimit : kFirstRequestLimit; const auto addOffset = loaded ? -(limit + 1) : -limit; const auto maxId = 0; @@ -128,8 +128,8 @@ void UnreadThings::requestReactions(not_null history, int loaded) { MTP_int(minId) )).done([=](const MTPmessages_Messages &result) { _reactionsRequests.remove(history); - history->unreadReactions().addSlice(result); - }).fail([this, history] { + history->unreadReactions().addSlice(result, loaded); + }).fail([=] { _reactionsRequests.remove(history); }).send(); _reactionsRequests.emplace(history, requestId); diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 3fd636be5d..7bb3faa0a2 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -1638,6 +1638,9 @@ void Updates::feedUpdate(const MTPUpdate &update) { // The unread reactions count could change. history->owner().histories().requestDialogEntry(history); } + if (hasUnreadReaction) { + history->unreadReactions().checkAdd(d.vmsg_id().v); + } } } } break; diff --git a/Telegram/SourceFiles/data/data_message_reactions.cpp b/Telegram/SourceFiles/data/data_message_reactions.cpp index f6bf0bb4d7..42aac1b243 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.cpp +++ b/Telegram/SourceFiles/data/data_message_reactions.cpp @@ -679,14 +679,13 @@ bool MessageReactions::empty() const { return _list.empty(); } -QString MessageReactions::findUnread() const { +bool MessageReactions::hasUnread() const { for (auto &[emoji, list] : _recent) { - const auto i = ranges::find(list, true, &RecentReaction::unread); - if (i != end(list)) { - return emoji; + if (ranges::contains(list, true, &RecentReaction::unread)) { + return true; } } - return QString(); + return false; } void MessageReactions::markRead() { diff --git a/Telegram/SourceFiles/data/data_message_reactions.h b/Telegram/SourceFiles/data/data_message_reactions.h index 9b0654fe08..0a587ea151 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.h +++ b/Telegram/SourceFiles/data/data_message_reactions.h @@ -163,7 +163,7 @@ public: [[nodiscard]] QString chosen() const; [[nodiscard]] bool empty() const; - [[nodiscard]] QString findUnread() const; + [[nodiscard]] bool hasUnread() const; void markRead(); private: diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index cb60506412..09c714aa07 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -200,6 +200,7 @@ using OnStackUsers = std::array; void CheckReactionNotificationSchedule( not_null item, const OnStackUsers &wasUsers) { + // Call to addToUnreadThings may have read the reaction already. if (!item->hasUnreadReaction()) { return; } @@ -897,6 +898,14 @@ void HistoryItem::toggleReaction(const QString &reaction) { history()->owner().notifyItemDataChange(this); } +void HistoryItem::setReactions(const MTPMessageReactions *reactions) { + Expects(!_reactions); + + if (changeReactions(reactions) && _reactions->hasUnread()) { + _flags |= MessageFlag::HasUnreadReaction; + } +} + void HistoryItem::updateReactions(const MTPMessageReactions *reactions) { const auto wasRecentUsers = LookupRecentReactedUsers(this); const auto hadUnread = hasUnreadReaction(); @@ -904,15 +913,11 @@ void HistoryItem::updateReactions(const MTPMessageReactions *reactions) { if (!changed) { return; } - const auto hasUnread = _reactions && !_reactions->findUnread().isEmpty(); + const auto hasUnread = _reactions && _reactions->hasUnread(); if (hasUnread && !hadUnread) { _flags |= MessageFlag::HasUnreadReaction; addToUnreadThings(HistoryUnreadThings::AddType::New); - - // Call to addToUnreadThings may have read the reaction already. - if (hasUnreadReaction()) { - } } else if (!hasUnread && hadUnread) { markReactionsRead(); } diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index fc629377eb..b8c5e44830 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -454,7 +454,8 @@ protected: void finishEdition(int oldKeyboardTop); void finishEditionToEmpty(); - bool changeReactions(const MTPMessageReactions *reactions); + void setReactions(const MTPMessageReactions *reactions); + [[nodiscard]] bool changeReactions(const MTPMessageReactions *reactions); const not_null _history; const not_null _from; diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 6033df9f6d..818794cd5a 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -512,10 +512,7 @@ HistoryMessage::HistoryMessage( setGroupId( MessageGroupId::FromRaw(history->peer->id, groupedId->v)); } - if (const auto reactions = data.vreactions()) { - changeReactions(reactions); - } - + setReactions(data.vreactions()); applyTTL(data); } diff --git a/Telegram/SourceFiles/history/history_unread_things.cpp b/Telegram/SourceFiles/history/history_unread_things.cpp index 88701d9f2a..7a850a7189 100644 --- a/Telegram/SourceFiles/history/history_unread_things.cpp +++ b/Telegram/SourceFiles/history/history_unread_things.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/history_item.h" #include "main/main_session.h" +#include "apiwrap.h" namespace HistoryUnreadThings { namespace { @@ -78,7 +79,7 @@ bool Proxy::add(MsgId msgId, AddType type) { const auto loaded = list.loadedCount(); const auto allLoaded = (count >= 0) && (loaded >= count); if (allLoaded) { - if (type == AddType::New) { + if (type == AddType::New || !list.contains(msgId)) { list.insert(msgId); setCount(count + 1); return true; @@ -117,7 +118,10 @@ void Proxy::clear() { UpdateFlag(_type)); } -void Proxy::addSlice(const MTPmessages_Messages &slice) { +void Proxy::addSlice(const MTPmessages_Messages &slice, int alreadyLoaded) { + if (!alreadyLoaded && _data) { + resolveList().clear(); + } auto fullCount = slice.match([&]( const MTPDmessages_messagesNotModified &) { LOG(("API Error: received messages.messagesNotModified! " @@ -148,15 +152,11 @@ void Proxy::addSlice(const MTPmessages_Messages &slice) { owner.processChats(data.vchats()); return data.vmessages().v; }); - if (messages.isEmpty()) { - return; - } - - if (!_data) { + if (!messages.isEmpty() && !_data) { createData(); } auto added = false; - auto &list = resolveList(); + const auto list = _data ? &resolveList() : nullptr; const auto localFlags = MessageFlags(); const auto type = NewMessageType::Existing; for (const auto &message : messages) { @@ -173,12 +173,12 @@ void Proxy::addSlice(const MTPmessages_Messages &slice) { Unexpected("Type in Proxy::addSlice."); }(); if (is) { - list.insert(item->id); + list->insert(item->id); added = true; } } if (!added) { - fullCount = list.loadedCount(); + fullCount = loadedCount(); } setCount(fullCount); _history->session().changes().historyUpdated( @@ -186,6 +186,28 @@ void Proxy::addSlice(const MTPmessages_Messages &slice) { UpdateFlag(_type)); } +void Proxy::checkAdd(MsgId msgId, bool resolved) { + Expects(_type == Type::Reactions); + + if (!_data) { + return; + } + auto &list = resolveList(); + if (!list.loadedCount() || list.maxLoaded() <= msgId) { + return; + } + const auto history = _history; + const auto peer = history->peer; + const auto item = peer->owner().message(peer, msgId); + if (item && item->hasUnreadReaction()) { + item->addToUnreadThings(AddType::Existing); + } else if (!item && !resolved) { + peer->session().api().requestMessageData(peer, msgId, [=] { + history->unreadReactions().checkAdd(msgId, true); + }); + } +} + void Proxy::createData() { _data = std::make_unique(); if (_known) { diff --git a/Telegram/SourceFiles/history/history_unread_things.h b/Telegram/SourceFiles/history/history_unread_things.h index 019f5347f5..6dba48e0fe 100644 --- a/Telegram/SourceFiles/history/history_unread_things.h +++ b/Telegram/SourceFiles/history/history_unread_things.h @@ -38,6 +38,9 @@ public: [[nodiscard]] bool has() const { return (count() > 0); } + [[nodiscard]] bool contains(MsgId msgId) const { + return _messages.contains(msgId); + } void setCount(int count) { _count = count; } @@ -120,7 +123,9 @@ public: void erase(MsgId msgId); void clear(); - void addSlice(const MTPmessages_Messages &slice); + void addSlice(const MTPmessages_Messages &slice, int alreadyLoaded); + + void checkAdd(MsgId msgId, bool resolved = false); private: void createData();