diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index da47b0efd..cffa80266 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1294,7 +1294,8 @@ void ApiWrap::markContentsRead( QVector>(); markedIds.reserve(items.size()); for (const auto &item : items) { - if (!item->markContentsRead() || !item->isRegular()) { + if (!item->markContentsRead() || !item->isRegular() || true) { + AssertIsDebug(); continue; } if (const auto channel = item->history()->peer->asChannel()) { diff --git a/Telegram/SourceFiles/data/data_message_reactions.cpp b/Telegram/SourceFiles/data/data_message_reactions.cpp index f5658abb1..a05a32ae0 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.cpp +++ b/Telegram/SourceFiles/data/data_message_reactions.cpp @@ -595,6 +595,24 @@ bool MessageReactions::empty() const { return _list.empty(); } +QString MessageReactions::findUnread() const { + for (auto &[emoji, list] : _recent) { + const auto i = ranges::find(list, true, &RecentReaction::unread); + if (i != end(list)) { + return emoji; + } + } + return QString(); +} + +void MessageReactions::markRead() { + for (auto &[emoji, list] : _recent) { + for (auto &reaction : list) { + reaction.unread = false; + } + } +} + QString MessageReactions::chosen() const { return _chosen; } diff --git a/Telegram/SourceFiles/data/data_message_reactions.h b/Telegram/SourceFiles/data/data_message_reactions.h index 50935f531..44a6776e7 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.h +++ b/Telegram/SourceFiles/data/data_message_reactions.h @@ -155,6 +155,9 @@ public: [[nodiscard]] QString chosen() const; [[nodiscard]] bool empty() const; + [[nodiscard]] QString findUnread() const; + void markRead(); + private: const not_null _item; diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 77e42ae9a..cfd8855cf 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -234,52 +234,53 @@ enum class MessageFlag : uint32 { Outgoing = (1U << 11), Pinned = (1U << 12), MediaIsUnread = (1U << 13), - MentionsMe = (1U << 14), - IsOrWasScheduled = (1U << 15), - NoForwards = (1U << 16), + HasUnreadReaction = (1U << 14), + MentionsMe = (1U << 15), + IsOrWasScheduled = (1U << 16), + NoForwards = (1U << 17), // Needs to return back to inline mode. - HasSwitchInlineButton = (1U << 17), + HasSwitchInlineButton = (1U << 18), // For "shared links" indexing. - HasTextLinks = (1U << 18), + HasTextLinks = (1U << 19), // Group / channel create or migrate service message. - IsGroupEssential = (1U << 19), + IsGroupEssential = (1U << 20), // Edited media is generated on the client // and should not update media from server. - IsLocalUpdateMedia = (1U << 20), + IsLocalUpdateMedia = (1U << 21), // Sent from inline bot, need to re-set media when sent. - FromInlineBot = (1U << 21), + FromInlineBot = (1U << 22), // Generated on the client side and should be unread. - ClientSideUnread = (1U << 22), + ClientSideUnread = (1U << 23), // In a supergroup. - HasAdminBadge = (1U << 23), + HasAdminBadge = (1U << 24), // Outgoing message that is being sent. - BeingSent = (1U << 24), + BeingSent = (1U << 25), // Outgoing message and failed to be sent. - SendingFailed = (1U << 25), + SendingFailed = (1U << 26), // No media and only a several emoji text. - IsolatedEmoji = (1U << 26), + IsolatedEmoji = (1U << 27), // Message existing in the message history. - HistoryEntry = (1U << 27), + HistoryEntry = (1U << 28), // Local message, not existing on the server. - Local = (1U << 28), + Local = (1U << 29), // Fake message for some UI element. - FakeHistoryItem = (1U << 29), + FakeHistoryItem = (1U << 30), // Contact sign-up message, notification should be skipped for Silent. - IsContactSignUp = (1U << 30), + IsContactSignUp = (1U << 31), }; inline constexpr bool is_flag_type(MessageFlag) { return true; } using MessageFlags = base::flags; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index ef535048b..54201c754 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -337,13 +337,7 @@ bool HistoryItem::isUnreadMention() const { } bool HistoryItem::hasUnreadReaction() const { - const auto &recent = recentReactions(); - for (const auto &[emoji, list] : recent) { - if (ranges::contains(list, true, &Data::RecentReaction::unread)) { - return true; - } - } - return false; + return (_flags & MessageFlag::HasUnreadReaction); } bool HistoryItem::mentionsMe() const { @@ -381,7 +375,12 @@ void HistoryItem::markMediaAndMentionRead() { } void HistoryItem::markReactionsRead() { - + if (_reactions) { + _reactions->markRead(); + } + _flags &= ~MessageFlag::HasUnreadReaction; + history()->updateChatListEntry(); + history()->unreadReactions().erase(id); } bool HistoryItem::markContentsRead() { @@ -850,7 +849,15 @@ void HistoryItem::updateReactions(const MTPMessageReactions *reactions) { : nullptr; const auto toContact = toUser && toUser->isContact(); const auto maybeNotify = toContact && lookupHisReaction().isEmpty(); + const auto hadUnread = hasUnreadReaction(); setReactions(reactions); + const auto hasUnread = _reactions && !_reactions->findUnread().isEmpty(); + if (hasUnread && !hadUnread) { + _flags |= MessageFlag::HasUnreadReaction; + addToUnreadThings(HistoryUnreadThings::AddType::New); + } else if (!hasUnread && hadUnread) { + markReactionsRead(); + } if (maybeNotify) { if (const auto reaction = lookupHisReaction(); !reaction.isEmpty()) { const auto notification = ItemNotification{ @@ -871,6 +878,9 @@ void HistoryItem::setReactions(const MTPMessageReactions *reactions) { _flags &= ~MessageFlag::CanViewReactions; if (_reactions) { _reactions = nullptr; + if (hasUnreadReaction()) { + markReactionsRead(); + } history()->owner().notifyItemDataChange(this); } return;