From e55e46a0f01ffe40ea70865620423ddf2878b2f3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 8 May 2019 11:50:39 +0300 Subject: [PATCH] Show last chats in archive dialog row. --- Telegram/Resources/langs/lang.strings | 8 +- Telegram/SourceFiles/data/data_folder.cpp | 92 ++++++-------------- Telegram/SourceFiles/data/data_folder.h | 10 +-- Telegram/SourceFiles/dialogs/dialogs_row.cpp | 55 +++++++----- 4 files changed, 65 insertions(+), 100 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 04b63f52e..846bad11b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1202,11 +1202,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_archived_remove" = "Unarchive"; "lng_archived_added" = "Chat archived.\nMuted chats will stay archived after new messages arrive."; "lng_archived_removed" = "Chat restored from your archive."; -"lng_archived_chats#one" = "{count} chat"; -"lng_archived_chats#other" = "{count} chats"; -"lng_archived_unread_two" = "{chat}, {second_chat}"; -"lng_archived_unread#one" = "{chat}, {second_chat} and {count} more unread chat"; -"lng_archived_unread#other" = "{chat}, {second_chat} and {count} more unread chats"; +"lng_archived_last_list" = "{accumulated}, {chat}"; +"lng_archived_last#one" = "{chats} and {count} more chat"; +"lng_archived_last#other" = "{chats} and {count} more chats"; "lng_dialogs_text_with_from" = "{from_part} {message}"; "lng_dialogs_text_from_wrapped" = "{from}:"; diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index a5c6a68aa..29ccfba03 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -26,7 +26,7 @@ namespace Data { namespace { constexpr auto kLoadedChatsMinCount = 20; -constexpr auto kShowChatNamesCount = 2; +constexpr auto kShowChatNamesCount = 8; rpl::producer PinnedDialogsInFolderMaxValue() { return rpl::single( @@ -60,7 +60,7 @@ Folder::Folder(not_null owner, FolderId id) Notify::PeerUpdateViewer( Notify::PeerUpdate::Flag::NameChanged ) | rpl::start_with_next([=](const Notify::PeerUpdate &update) { - for (const auto history : _unreadHistoriesLast) { + for (const auto history : _lastHistories) { if (history->peer == update.peer) { ++_chatListViewVersion; updateChatListEntry(); @@ -112,6 +112,7 @@ void Folder::registerOne(not_null history) { updateChatListEntry(); } applyChatListMessage(history->chatListMessage()); + reorderLastHistories(); } void Folder::unregisterOne(not_null history) { @@ -124,6 +125,7 @@ void Folder::unregisterOne(not_null history) { if (_chatListMessage && _chatListMessage->history() == history) { computeChatListMessage(); } + reorderLastHistories(); } void Folder::oneListMessageChanged(HistoryItem *from, HistoryItem *to) { @@ -131,10 +133,7 @@ void Folder::oneListMessageChanged(HistoryItem *from, HistoryItem *to) { computeChatListMessage(); } if (from || to) { - const auto history = from ? from->history() : to->history(); - if (!history->chatListUnreadState().empty()) { - reorderUnreadHistories(); - } + reorderLastHistories(); } } @@ -171,49 +170,34 @@ void Folder::computeChatListMessage() { updateChatListEntry(); } -void Folder::addUnreadHistory(not_null history) { - const auto i = ranges::find(_unreadHistories, history); - if (i == end(_unreadHistories)) { - _unreadHistories.push_back(history); - reorderUnreadHistories(); - } -} - -void Folder::removeUnreadHistory(not_null history) { - const auto i = ranges::find(_unreadHistories, history); - if (i != end(_unreadHistories)) { - _unreadHistories.erase(i); - reorderUnreadHistories(); - } -} - -void Folder::reorderUnreadHistories() { +void Folder::reorderLastHistories() { // We want first kShowChatNamesCount histories, by last message date. - const auto predicate = [](not_null a, not_null b) { + const auto pred = [](not_null a, not_null b) { const auto aItem = a->chatListMessage(); const auto bItem = b->chatListMessage(); const auto aDate = aItem ? aItem->date() : TimeId(0); const auto bDate = bItem ? bItem->date() : TimeId(0); return aDate > bDate; }; - if (size(_unreadHistories) <= kShowChatNamesCount) { - ranges::sort(_unreadHistories, predicate); - if (!ranges::equal(_unreadHistories, _unreadHistoriesLast)) { - _unreadHistoriesLast = _unreadHistories; + _lastHistories.erase(_lastHistories.begin(), _lastHistories.end()); + _lastHistories.reserve(kShowChatNamesCount + 1); + auto &&histories = ranges::view::all( + *_chatsList.indexed() + ) | ranges::view::transform([](not_null row) { + return row->history(); + }) | ranges::view::filter([](History *history) { + return (history != nullptr); + }) | ranges::view::transform([](History *history) { + return not_null(history); + }); + for (const auto history : histories) { + const auto i = ranges::upper_bound(_lastHistories, history, pred); + if (size(_lastHistories) < kShowChatNamesCount + || i != end(_lastHistories)) { + _lastHistories.insert(i, history); } - } else { - const auto till = begin(_unreadHistories) + kShowChatNamesCount - 1; - ranges::nth_element(_unreadHistories, till, predicate); - if constexpr (kShowChatNamesCount > 2) { - ranges::sort(begin(_unreadHistories), till, predicate); - } - auto &&head = ranges::view::all( - _unreadHistories - ) | ranges::view::take_exactly( - kShowChatNamesCount - ); - if (!ranges::equal(head, _unreadHistoriesLast)) { - _unreadHistoriesLast = head | ranges::to_vector; + if (size(_lastHistories) > kShowChatNamesCount) { + _lastHistories.pop_back(); } } ++_chatListViewVersion; @@ -296,12 +280,8 @@ int Folder::chatsListSize() const { _chatsList.loaded() ? 0 : _cloudChatsListSize); } -int Folder::unreadHistoriesCount() const { - return _unreadHistories.size(); -} - -const std::vector> &Folder::lastUnreadHistories() const { - return _unreadHistoriesLast; +const std::vector> &Folder::lastHistories() const { + return _lastHistories; } uint32 Folder::chatListViewVersion() const { @@ -380,14 +360,6 @@ void Folder::unreadStateChanged( const Dialogs::Key &key, const Dialogs::UnreadState &wasState, const Dialogs::UnreadState &nowState) { - if (const auto history = key.history()) { - if (!wasState.empty() && nowState.empty()) { - removeUnreadHistory(history); - } else if (wasState.empty() && !nowState.empty()) { - addUnreadHistory(history); - } - } - const auto updateCloudUnread = _cloudUnread.known && wasState.known; const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notifier = unreadStateChangeNotifier(notify); @@ -404,16 +376,6 @@ void Folder::unreadEntryChanged( const Dialogs::Key &key, const Dialogs::UnreadState &state, bool added) { - if (const auto history = key.history()) { - if (!state.empty()) { - if (added) { - addUnreadHistory(history); - } else { - removeUnreadHistory(history); - } - } - } - const auto updateCloudUnread = _cloudUnread.known && state.known; const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notifier = unreadStateChangeNotifier(notify); diff --git a/Telegram/SourceFiles/data/data_folder.h b/Telegram/SourceFiles/data/data_folder.h index 1fb2a5ac3..fd5ea6be4 100644 --- a/Telegram/SourceFiles/data/data_folder.h +++ b/Telegram/SourceFiles/data/data_folder.h @@ -80,8 +80,7 @@ public: void setCloudChatsListSize(int size); int chatsListSize() const; - int unreadHistoriesCount() const; - const std::vector> &lastUnreadHistories() const; + const std::vector> &lastHistories() const; uint32 chatListViewVersion() const; private: @@ -89,9 +88,7 @@ private: bool applyChatListMessage(HistoryItem *item); void computeChatListMessage(); - void addUnreadHistory(not_null history); - void removeUnreadHistory(not_null history); - void reorderUnreadHistories(); + void reorderLastHistories(); void finalizeCloudUnread(); FolderId _id = 0; @@ -103,8 +100,7 @@ private: Dialogs::UnreadState _cloudUnread; int _cloudChatsListSize = 0; - std::vector> _unreadHistories; - std::vector> _unreadHistoriesLast; + std::vector> _lastHistories; HistoryItem *_chatListMessage = nullptr; uint32 _chatListViewVersion = 0; //rpl::variable _unreadPosition; diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index 928faada4..3be737282 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -20,33 +20,42 @@ namespace Dialogs { namespace { QString ComposeFolderListEntryText(not_null folder) { - const auto &list = folder->lastUnreadHistories(); + const auto &list = folder->lastHistories(); if (list.empty()) { - const auto count = folder->chatsListSize(); - if (!count) { - return QString(); - } - return lng_archived_chats(lt_count, count); + return QString(); } + const auto count = std::max( int(list.size()), - folder->unreadHistoriesCount()); - if (list.size() == 1) { - return App::peerName(list[0]->peer); - } else if (count == 2) { - return lng_archived_unread_two( - lt_chat, - App::peerName(list[0]->peer), - lt_second_chat, - App::peerName(list[1]->peer)); - } - return lng_archived_unread( - lt_count, - count - 2, - lt_chat, - App::peerName(list[0]->peer), - lt_second_chat, - App::peerName(list[1]->peer)); + folder->chatsListSize()); + + const auto throwAwayLastName = (list.size() > 1) + && (count == list.size() + 1); + auto &&peers = ranges::view::all( + list + ) | ranges::view::take( + list.size() - (throwAwayLastName ? 1 : 0) + ) | ranges::view::transform([](not_null history) { + return history->peer; + }); + const auto shown = int(peers.size()); + const auto accumulated = [&] { + Expects(shown > 0); + + auto i = peers.begin(); + auto result = App::peerName(*i); + for (++i; i != peers.end(); ++i) { + result = lng_archived_last_list( + lt_accumulated, + result, + lt_chat, + App::peerName(*i)); + } + return result; + }(); + return (shown < count) + ? lng_archived_last(lt_count, (count - shown), lt_chats, accumulated) + : accumulated; } } // namespace