From 52a6282eb9b366d143728315404051dc87421fcf Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 30 Aug 2021 19:22:16 +0300 Subject: [PATCH] Count unread replies locally when possible. --- Telegram/SourceFiles/api/api_updates.cpp | 4 ++- Telegram/SourceFiles/data/data_session.cpp | 17 ++++++++++ Telegram/SourceFiles/data/data_session.h | 15 ++++++++- .../view/history_view_replies_section.cpp | 33 +++++++++++++++---- .../view/history_view_replies_section.h | 2 ++ 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index e889a9b674..b27b8d0941 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -2094,7 +2094,9 @@ void Updates::feedUpdate(const MTPUpdate &update) { const auto msgId = d.vtop_msg_id().v; const auto readTillId = d.vread_max_id().v; const auto item = session().data().message(channelId, msgId); - const auto unreadCount = std::nullopt; + const auto unreadCount = item + ? session().data().countUnreadRepliesLocally(item, readTillId) + : std::nullopt; if (item) { item->setRepliesInboxReadTill(readTillId, unreadCount); if (const auto post = item->lookupDiscussionPostOriginal()) { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 0c28808fa7..eeefca3669 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -2360,6 +2360,23 @@ void Session::notifyUnreadBadgeChanged() { _unreadBadgeChanges.fire({}); } +std::optional Session::countUnreadRepliesLocally( + not_null root, + MsgId afterId) const { + auto result = std::optional(); + _unreadRepliesCountRequests.fire({ + .root = root, + .afterId = afterId, + .result = &result, + }); + return result; +} + +auto Session::unreadRepliesCountRequests() const +-> rpl::producer { + return _unreadRepliesCountRequests.events(); +} + int Session::computeUnreadBadge(const Dialogs::UnreadState &state) const { const auto all = Core::App().settings().includeMutedCounter(); return std::max(state.marks - (all ? 0 : state.marksMuted), 0) diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index bb4fe354ed..7b30ec996d 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -430,11 +430,23 @@ public: [[nodiscard]] int unreadBadge() const; [[nodiscard]] bool unreadBadgeMuted() const; [[nodiscard]] int unreadBadgeIgnoreOne(const Dialogs::Key &key) const; - [[nodiscard]] bool unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const; + [[nodiscard]] bool unreadBadgeMutedIgnoreOne( + const Dialogs::Key &key) const; [[nodiscard]] int unreadOnlyMutedBadge() const; [[nodiscard]] rpl::producer<> unreadBadgeChanges() const; void notifyUnreadBadgeChanged(); + [[nodiscard]] std::optional countUnreadRepliesLocally( + not_null root, + MsgId afterId) const; + struct UnreadRepliesCountRequest { + not_null root; + MsgId afterId = 0; + not_null*> result; + }; + [[nodiscard]] auto unreadRepliesCountRequests() const + -> rpl::producer; + void selfDestructIn(not_null item, crl::time delay); [[nodiscard]] not_null photo(PhotoId id); @@ -855,6 +867,7 @@ private: rpl::event_stream _dialogsRowReplacements; rpl::event_stream _chatListEntryRefreshes; rpl::event_stream<> _unreadBadgeChanges; + rpl::event_stream _unreadRepliesCountRequests; Dialogs::MainList _chatsList; Dialogs::IndexedList _contactsList; diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 5d9e1a04c1..d12d4d7b26 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -275,6 +275,17 @@ RepliesWidget::RepliesWidget( _inner->update(); }, lifetime()); + _history->session().data().unreadRepliesCountRequests( + ) | rpl::filter([=]( + const Data::Session::UnreadRepliesCountRequest &request) { + return (request.root.get() == _root); + }) | rpl::start_with_next([=]( + const Data::Session::UnreadRepliesCountRequest &request) { + if (const auto result = computeUnreadCountLocally(request.afterId)) { + *request.result = result; + } + }, lifetime()); + setupScrollDownButton(); setupComposeControls(); orderWidgets(); @@ -1762,6 +1773,20 @@ void RepliesWidget::listSelectionChanged(SelectedItems &&items) { _topBar->showSelected(state); } +std::optional RepliesWidget::computeUnreadCountLocally( + MsgId afterId) const { + const auto views = _root ? _root->Get() : nullptr; + if (!views) { + return std::nullopt; + } + const auto wasReadTillId = views->repliesInboxReadTillId; + const auto wasUnreadCount = views->repliesUnreadCount; + return _replies->fullUnreadCountAfter( + afterId, + wasReadTillId, + wasUnreadCount); +} + void RepliesWidget::readTill(not_null item) { if (!_root) { return; @@ -1771,13 +1796,7 @@ void RepliesWidget::readTill(not_null item) { if (now < was) { return; } - const auto views = _root->Get(); - const auto wasReadTillId = views ? views->repliesInboxReadTillId : 0; - const auto wasUnreadCount = views ? views->repliesUnreadCount : -1; - const auto unreadCount = _replies->fullUnreadCountAfter( - now, - wasReadTillId, - wasUnreadCount); + const auto unreadCount = computeUnreadCountLocally(now); const auto fast = item->out() || !unreadCount.has_value(); if (was < now || (fast && now == was)) { _root->setRepliesInboxReadTill(now, unreadCount); diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index b317c0de58..14d6847f5a 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -173,6 +173,8 @@ private: void setupDragArea(); void sendReadTillRequest(); void readTill(not_null item); + [[nodiscard]] std::optional computeUnreadCountLocally( + MsgId afterId) const; void setupScrollDownButton(); void scrollDownClicked();