diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index 525a37dd18..0acd2a583b 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -104,7 +104,7 @@ void Folder::registerOne(not_null history) { ++_chatListViewVersion; if (_chatsList.indexed()->size() == 1) { updateChatListSortPosition(); - if (!_cloudUnread.messagesCount.has_value()) { + if (!_cloudUnread.known) { session().api().requestDialogEntry(this); } } else { @@ -337,22 +337,24 @@ void Folder::applyDialog(const MTPDdialogFolder &data) { void Folder::updateCloudUnread(const MTPDdialogFolder &data) { const auto notifier = unreadStateChangeNotifier(!_chatsList.loaded()); - _cloudUnread.messagesCountMuted = data.vunread_muted_messages_count.v; - _cloudUnread.messagesCount = _cloudUnread.messagesCountMuted + _cloudUnread.messagesMuted = data.vunread_muted_messages_count.v; + _cloudUnread.messages = _cloudUnread.messagesMuted + data.vunread_unmuted_messages_count.v; - _cloudUnread.chatsCountMuted = data.vunread_muted_peers_count.v; - _cloudUnread.chatsCount = _cloudUnread.chatsCountMuted + _cloudUnread.chatsMuted = data.vunread_muted_peers_count.v; + _cloudUnread.chats = _cloudUnread.chatsMuted + data.vunread_unmuted_peers_count.v; + _cloudUnread.known = true; } Dialogs::UnreadState Folder::chatListUnreadState() const { - const auto state = _chatsList.loaded() - ? _chatsList.unreadState() - : _cloudUnread; - auto result = Dialogs::UnreadState(); - result.messagesCount = state.messagesCount; - result.messagesCountMuted = result.messagesCount.value_or(0); - result.chatsCount = result.chatsCountMuted = state.chatsCount; + const auto localUnread = _chatsList.unreadState(); + auto result = _chatsList.loaded() ? localUnread : _cloudUnread; + result.messagesMuted = result.messages; + result.chatsMuted = result.chats; + + // We don't know the real value of marked chats counts. + result.marksMuted = result.marks = localUnread.marks; + return result; } @@ -376,25 +378,18 @@ void Folder::unreadStateChanged( } } - const auto updateCloudUnread = _cloudUnread.messagesCount.has_value() - && wasState.messagesCount.has_value(); + const auto updateCloudUnread = _cloudUnread.known && wasState.known; const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notifier = unreadStateChangeNotifier(notify); _chatsList.unreadStateChanged(wasState, nowState); - if (!_cloudUnread.messagesCount.has_value() - || !wasState.messagesCount.has_value()) { - return; - } - Assert(nowState.messagesCount.has_value()); + if (updateCloudUnread) { + Assert(nowState.known); + _cloudUnread += nowState - wasState; - *_cloudUnread.messagesCount += *nowState.messagesCount - - *wasState.messagesCount; - _cloudUnread.messagesCountMuted += nowState.messagesCountMuted - - wasState.messagesCountMuted; - _cloudUnread.chatsCount += nowState.chatsCount - wasState.chatsCount; - _cloudUnread.chatsCountMuted += nowState.chatsCountMuted - - wasState.chatsCountMuted; + // We don't know the real value of marked chats counts. + _cloudUnread.marks = _cloudUnread.marksMuted = 0; + } } void Folder::unreadEntryChanged( @@ -411,21 +406,21 @@ void Folder::unreadEntryChanged( } } - const auto updateCloudUnread = _cloudUnread.messagesCount.has_value() - && state.messagesCount.has_value(); + const auto updateCloudUnread = _cloudUnread.known && state.known; const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notifier = unreadStateChangeNotifier(notify); _chatsList.unreadEntryChanged(state, added); - if (!_cloudUnread.messagesCount.has_value() - || !state.messagesCount.has_value()) { - return; + if (updateCloudUnread) { + if (added) { + _cloudUnread += state; + } else { + _cloudUnread -= state; + } + + // We don't know the real value of marked chats counts. + _cloudUnread.marks = _cloudUnread.marksMuted = 0; } - const auto delta = (added ? 1 : -1); - *_cloudUnread.messagesCount += delta * *state.messagesCount; - _cloudUnread.messagesCountMuted += delta * state.messagesCountMuted; - _cloudUnread.chatsCount += delta * state.chatsCount; - _cloudUnread.chatsCountMuted += delta * state.chatsCountMuted; } // #feed @@ -450,9 +445,11 @@ bool Folder::shouldBeInChatList() const { } int Folder::chatListUnreadCount() const { - return session().settings().countUnreadMessages() - ? chatListUnreadState().messagesCount.value_or(0) - : chatListUnreadState().chatsCount; + const auto state = chatListUnreadState(); + return state.marks + + (session().settings().countUnreadMessages() + ? state.messages + : state.chats); } bool Folder::chatListUnreadMark() const { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index c51530aceb..d9975a5294 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1578,36 +1578,18 @@ void Session::updateSendActionAnimation( } int Session::unreadBadge() const { - const auto state = _chatsList.unreadState(); - return computeUnreadBadge( - state.messagesCount.value_or(0), - state.messagesCountMuted, - state.chatsCount, - state.chatsCountMuted); + return computeUnreadBadge(_chatsList.unreadState()); } bool Session::unreadBadgeMuted() const { - const auto state = _chatsList.unreadState(); - return computeUnreadBadgeMuted( - state.messagesCount.value_or(0), - state.messagesCountMuted, - state.chatsCount, - state.chatsCountMuted); + return computeUnreadBadgeMuted(_chatsList.unreadState()); } int Session::unreadBadgeIgnoreOne(const Dialogs::Key &key) const { const auto remove = (key && key.entry()->inChatList()) ? key.entry()->chatListUnreadState() : Dialogs::UnreadState(); - if (remove.empty()) { - return unreadBadge(); - } - const auto state = _chatsList.unreadState(); - return computeUnreadBadge( - state.messagesCount.value_or(0) - remove.messagesCount.value_or(0), - state.messagesCountMuted - remove.messagesCountMuted, - state.chatsCount - remove.chatsCount, - state.chatsCountMuted - remove.chatsCountMuted); + return computeUnreadBadge(_chatsList.unreadState() - remove); } bool Session::unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const { @@ -1617,46 +1599,33 @@ bool Session::unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const { const auto remove = (key && key.entry()->inChatList()) ? key.entry()->chatListUnreadState() : Dialogs::UnreadState(); - if (remove.empty()) { - return unreadBadgeMuted(); - } - const auto state = _chatsList.unreadState(); - return computeUnreadBadgeMuted( - state.messagesCount.value_or(0) - remove.messagesCount.value_or(0), - state.messagesCountMuted - remove.messagesCountMuted, - state.chatsCount - remove.chatsCount, - state.chatsCountMuted - remove.chatsCountMuted); + return computeUnreadBadgeMuted(_chatsList.unreadState() - remove); } int Session::unreadOnlyMutedBadge() const { const auto state = _chatsList.unreadState(); return _session->settings().countUnreadMessages() - ? state.messagesCountMuted - : state.chatsCountMuted; + ? state.messagesMuted + : state.chatsMuted; } -int Session::computeUnreadBadge( - int full, - int muted, - int entriesFull, - int entriesMuted) const { - const auto withMuted = _session->settings().includeMutedCounter(); - return _session->settings().countUnreadMessages() - ? (full - (withMuted ? 0 : muted)) - : (entriesFull - (withMuted ? 0 : entriesMuted)); +int Session::computeUnreadBadge(const Dialogs::UnreadState &state) const { + const auto all = _session->settings().includeMutedCounter(); + return std::max(state.marks - (all ? 0 : state.marksMuted), 0) + + (_session->settings().countUnreadMessages() + ? std::max(state.messages - (all ? 0 : state.messagesMuted), 0) + : std::max(state.chats - (all ? 0 : state.chatsMuted), 0)); } bool Session::computeUnreadBadgeMuted( - int full, - int muted, - int entriesFull, - int entriesMuted) const { + const Dialogs::UnreadState &state) const { if (!_session->settings().includeMutedCounter()) { return false; } - return _session->settings().countUnreadMessages() - ? (muted >= full) - : (entriesMuted >= entriesFull); + return (state.marksMuted >= state.marks) + && (_session->settings().countUnreadMessages() + ? (state.messagesMuted >= state.messages) + : (state.chatsMuted >= state.chats)); } void Session::unreadStateChanged( diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 7390df1a3f..136a98a55e 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -599,16 +599,8 @@ private: void checkSelfDestructItems(); - int computeUnreadBadge( - int full, - int muted, - int entriesFull, - int entriesMuted) const; - bool computeUnreadBadgeMuted( - int full, - int muted, - int entriesFull, - int entriesMuted) const; + int computeUnreadBadge(const Dialogs::UnreadState &state) const; + bool computeUnreadBadgeMuted(const Dialogs::UnreadState &state) const; void applyDialog(Data::Folder *requestFolder, const MTPDdialog &data); void applyDialog( diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index d610edee3c..714d764571 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -41,18 +41,50 @@ struct PositionChange { }; struct UnreadState { - std::optional messagesCount; - int messagesCountMuted = 0; - int chatsCount = 0; - int chatsCountMuted = 0; - bool mark = false; - bool markMuted = false; + int messages = 0; + int messagesMuted = 0; + int chats = 0; + int chatsMuted = 0; + int marks = 0; + int marksMuted = 0; + bool known = false; + + UnreadState &operator+=(const UnreadState &other) { + messages += other.messages; + messagesMuted += other.messagesMuted; + chats += other.chats; + chatsMuted += other.chatsMuted; + marks += other.marks; + marksMuted += other.marksMuted; + return *this; + } + UnreadState &operator-=(const UnreadState &other) { + messages -= other.messages; + messagesMuted -= other.messagesMuted; + chats -= other.chats; + chatsMuted -= other.chatsMuted; + marks -= other.marks; + marksMuted -= other.marksMuted; + return *this; + } bool empty() const { - return !messagesCount.value_or(0) && !chatsCount && !mark; + return !messages && !chats && !marks; } }; +inline UnreadState operator+(const UnreadState &a, const UnreadState &b) { + auto result = a; + result += b; + return result; +} + +inline UnreadState operator-(const UnreadState &a, const UnreadState &b) { + auto result = a; + result -= b; + return result; +} + class Entry { public: Entry(not_null owner, const Key &key); diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp index 347cfbd2ea..f0827f9b7d 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp @@ -11,41 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" namespace Dialogs { -namespace { - -UnreadState ApplyMarkToCounters(const UnreadState &state) { - auto result = UnreadState(); - const auto count = state.messagesCount.value_or(0); - result.messagesCount = (count > 0) - ? count - : state.mark - ? 1 - : 0; - result.messagesCountMuted = (state.messagesCountMuted > 0) - ? state.messagesCountMuted - : state.markMuted - ? 1 - : 0; - result.chatsCount = (state.chatsCount > 0) - ? state.chatsCount - : state.mark - ? 1 - : 0; - result.chatsCountMuted = (state.chatsCountMuted > 0) - ? state.chatsCountMuted - : state.markMuted - ? 1 - : 0; - return result; -} - -} // namespace MainList::MainList(rpl::producer pinnedLimit) : _all(SortMode::Date) , _important(SortMode::Date) , _pinned(1) { - _unreadState.messagesCount = 0; + _unreadState.known = true; std::move( pinnedLimit @@ -84,27 +55,17 @@ void MainList::clear() { void MainList::unreadStateChanged( const UnreadState &wasState, const UnreadState &nowState) { - const auto wasWithMark = ApplyMarkToCounters(wasState); - const auto nowWithMark = ApplyMarkToCounters(nowState); - *_unreadState.messagesCount += *nowWithMark.messagesCount - - *wasWithMark.messagesCount; - _unreadState.messagesCountMuted += nowWithMark.messagesCountMuted - - wasWithMark.messagesCountMuted; - _unreadState.chatsCount += nowWithMark.chatsCount - - wasWithMark.chatsCount; - _unreadState.chatsCountMuted += nowWithMark.chatsCountMuted - - wasWithMark.chatsCountMuted; + _unreadState += nowState - wasState; } void MainList::unreadEntryChanged( const Dialogs::UnreadState &state, bool added) { - const auto withMark = ApplyMarkToCounters(state); - const auto delta = (added ? 1 : -1); - *_unreadState.messagesCount += delta * *withMark.messagesCount; - _unreadState.messagesCountMuted += delta * withMark.messagesCountMuted; - _unreadState.chatsCount += delta * withMark.chatsCount; - _unreadState.chatsCountMuted += delta * withMark.chatsCountMuted; + if (added) { + _unreadState += state; + } else { + _unreadState -= state; + } } UnreadState MainList::unreadState() const { diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 742aa40ac4..328f0b152e 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -2029,12 +2029,14 @@ bool History::chatListMutedBadge() const { Dialogs::UnreadState History::chatListUnreadState() const { auto result = Dialogs::UnreadState(); const auto count = _unreadCount.value_or(0); - result.messagesCount = _unreadCount; - result.messagesCountMuted = (_unreadCount && mute()) ? count : 0; - result.chatsCount = count ? 1 : 0; - result.chatsCountMuted = (count && mute()) ? 1 : 0; - result.mark = _unreadMark; - result.markMuted = mute() ? _unreadMark : false; + const auto mark = !count && _unreadMark; + result.messages = count; + result.messagesMuted = mute() ? count : 0; + result.chats = count ? 1 : 0; + result.chatsMuted = (count && mute()) ? 1 : 0; + result.marks = mark ? 1 : 0; + result.marksMuted = (mark && mute()) ? 1 : 0; + result.known = _unreadCount.has_value(); return result; }