From ca3419ef2452604524a67157a3d10fd5c16a67cd Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 9 Mar 2020 15:17:56 +0400 Subject: [PATCH] Make filtered lists independent from folders. --- .../SourceFiles/data/data_chat_filters.cpp | 48 ++++++++++++++----- Telegram/SourceFiles/data/data_chat_filters.h | 8 ++++ Telegram/SourceFiles/data/data_folder.cpp | 2 +- .../data/data_scheduled_messages.cpp | 4 +- Telegram/SourceFiles/data/data_session.cpp | 2 +- .../SourceFiles/dialogs/dialogs_entry.cpp | 10 ++-- Telegram/SourceFiles/dialogs/dialogs_entry.h | 11 +++-- .../dialogs/dialogs_indexed_list.cpp | 8 ++-- .../dialogs/dialogs_indexed_list.h | 4 +- .../dialogs/dialogs_inner_widget.cpp | 6 ++- .../SourceFiles/dialogs/dialogs_layout.cpp | 2 + Telegram/SourceFiles/dialogs/dialogs_layout.h | 1 + Telegram/SourceFiles/dialogs/dialogs_list.cpp | 10 ++-- .../SourceFiles/dialogs/dialogs_main_list.cpp | 22 +++------ .../SourceFiles/dialogs/dialogs_main_list.h | 6 +-- Telegram/SourceFiles/dialogs/dialogs_row.cpp | 6 ++- Telegram/SourceFiles/dialogs/dialogs_row.h | 4 +- 17 files changed, 98 insertions(+), 56 deletions(-) diff --git a/Telegram/SourceFiles/data/data_chat_filters.cpp b/Telegram/SourceFiles/data/data_chat_filters.cpp index fff8b22241..32e1b53825 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.cpp +++ b/Telegram/SourceFiles/data/data_chat_filters.cpp @@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_channel.h" #include "data/data_session.h" +#include "data/data_folder.h" +#include "dialogs/dialogs_main_list.h" #include "main/main_session.h" #include "apiwrap.h" @@ -179,6 +181,18 @@ ChatFilters::ChatFilters(not_null owner) : _owner(owner) { ChatFilter(2, "Unread", all | Flag::NoRead, {}, {})); } +ChatFilters::~ChatFilters() = default; + +not_null ChatFilters::chatsList(FilterId filterId) { + auto &pointer = _chatsLists[filterId]; + if (!pointer) { + pointer = std::make_unique( + filterId, + rpl::single(1)); + } + return pointer.get(); +} + void ChatFilters::load() { load(false); } @@ -285,21 +299,31 @@ void ChatFilters::applyRemove(int position) { bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) { const auto rulesChanged = (filter.flags() != updated.flags()) - || (filter.always() != updated.always()); + || (filter.always() != updated.always()) + || (filter.never() != updated.never()); if (rulesChanged) { - const auto list = _owner->chatsList()->indexed(); - for (const auto &entry : *list) { - if (const auto history = entry->history()) { - const auto now = updated.contains(history); - const auto was = filter.contains(history); - if (now != was) { - if (now) { - history->addToChatList(filter.id()); - } else { - history->removeFromChatList(filter.id()); - } + const auto feedHistory = [&](not_null history) { + const auto now = updated.contains(history); + const auto was = filter.contains(history); + if (now != was) { + if (now) { + history->addToChatList(filter.id()); + } else { + history->removeFromChatList(filter.id()); } } + }; + const auto feedList = [&](not_null list) { + for (const auto &entry : *list->indexed()) { + if (const auto history = entry->history()) { + feedHistory(history); + } + } + }; + feedList(_owner->chatsList()); + const auto id = Data::Folder::kId; + if (const auto folder = _owner->folderLoaded(id)) { + feedList(folder->chatsList()); } } else if (filter.title() == updated.title()) { return false; diff --git a/Telegram/SourceFiles/data/data_chat_filters.h b/Telegram/SourceFiles/data/data_chat_filters.h index a933e834ee..ca97352006 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.h +++ b/Telegram/SourceFiles/data/data_chat_filters.h @@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class History; +namespace Dialogs { +class MainList; +} // namespace Dialogs + namespace Data { class Session; @@ -63,6 +67,7 @@ private: class ChatFilters final { public: explicit ChatFilters(not_null owner); + ~ChatFilters(); void load(); void apply(const MTPUpdate &update); @@ -75,6 +80,8 @@ public: [[nodiscard]] auto refreshHistoryRequests() const -> rpl::producer>; + [[nodiscard]] not_null chatsList(FilterId filterId); + private: void load(bool force); bool applyOrder(const QVector &order); @@ -85,6 +92,7 @@ private: const not_null _owner; std::vector _list; + base::flat_map> _chatsLists; rpl::event_stream<> _listChanged; rpl::event_stream> _refreshHistoryRequests; mtpRequestId _loadRequestId = 0; diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index df513684ba..41d3a52829 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -57,7 +57,7 @@ rpl::producer PinnedDialogsInFolderMaxValue( Folder::Folder(not_null owner, FolderId id) : Entry(owner, this) , _id(id) -, _chatsList(PinnedDialogsInFolderMaxValue(&owner->session())) +, _chatsList(FilterId(), PinnedDialogsInFolderMaxValue(&owner->session())) , _name(tr::lng_archived_name(tr::now)) { indexNameParts(); diff --git a/Telegram/SourceFiles/data/data_scheduled_messages.cpp b/Telegram/SourceFiles/data/data_scheduled_messages.cpp index 7bbce72fa8..8d6831675b 100644 --- a/Telegram/SourceFiles/data/data_scheduled_messages.cpp +++ b/Telegram/SourceFiles/data/data_scheduled_messages.cpp @@ -139,8 +139,8 @@ int ScheduledMessages::count(not_null history) const { } void ScheduledMessages::sendNowSimpleMessage( - const MTPDupdateShortSentMessage &update, - not_null local) { + const MTPDupdateShortSentMessage &update, + not_null local) { Expects(local->isSending()); Expects(local->isScheduled()); Expects(local->date() == kScheduledUntilOnlineTimestamp); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 01d4b7a425..1f134b8e0e 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -184,7 +184,7 @@ Session::Session(not_null session) , _bigFileCache(Core::App().databases().get( Local::cacheBigFilePath(), Local::cacheBigFileSettings())) -, _chatsList(PinnedDialogsCountMaxValue(session)) +, _chatsList(FilterId(), PinnedDialogsCountMaxValue(session)) , _contactsList(Dialogs::SortMode::Name) , _contactsNoChatsList(Dialogs::SortMode::Name) , _selfDestructTimer([=] { checkSelfDestructItems(); }) diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index 4db2f9ff2e..05cb676ab5 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_indexed_list.h" #include "data/data_session.h" #include "data/data_folder.h" +#include "data/data_chat_filters.h" #include "mainwidget.h" #include "main/main_session.h" #include "history/history_item.h" @@ -92,16 +93,17 @@ void Entry::updateChatListSortPosition() { updateChatListEntry(); return; } + _sortKeyByDate = DialogPosFromDate(adjustedChatListTimeId()); const auto fixedIndex = fixedOnTopIndex(); _sortKeyInChatList = fixedIndex ? FixedOnTopDialogPos(fixedIndex) : isPinnedDialog() ? PinnedDialogPos(_pinnedIndex) - : DialogPosFromDate(adjustedChatListTimeId()); + : _sortKeyByDate; if (needUpdateInChatList()) { setChatListExistence(true); } else { - _sortKeyInChatList = 0; + _sortKeyInChatList = _sortKeyByDate = 0; } } @@ -229,7 +231,9 @@ void Entry::updateChatListEntry() const { } not_null Entry::myChatsList(FilterId filterId) const { - return owner().chatsList(folder())->indexed(filterId); + return filterId + ? owner().chatsFilters().chatsList(filterId)->indexed() + : owner().chatsList(folder())->indexed(); } } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index 0f8945693a..05be48d33b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -31,9 +31,10 @@ struct RowsByLetter { }; enum class SortMode { - Date = 0x00, - Name = 0x01, - Add = 0x02, + Complex = 0x00, + Date = 0x01, + Name = 0x02, + Add = 0x04, }; struct PositionChange { @@ -120,6 +121,9 @@ public: uint64 sortKeyInChatList() const { return _sortKeyInChatList; } + uint64 sortKeyByDate() const { + return _sortKeyByDate; + } void updateChatListSortPosition(); void setChatListTimeId(TimeId date); virtual void updateChatListExistence(); @@ -199,6 +203,7 @@ private: Dialogs::Key _key; base::flat_map _chatListLinks; uint64 _sortKeyInChatList = 0; + uint64 _sortKeyByDate = 0; int _pinnedIndex = 0; bool _isProxyPromoted = false; TimeId _timeId = 0; diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp index 2ee60cebb6..5af4ca39c8 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp @@ -87,7 +87,7 @@ void IndexedList::movePinned(Row *row, int deltaSign) { void IndexedList::peerNameChanged( not_null peer, const base::flat_set &oldLetters) { - Expects(_sortMode != SortMode::Date); + Expects(_sortMode != SortMode::Date && _sortMode != SortMode::Complex); if (const auto history = peer->owner().historyLoaded(peer)) { if (_sortMode == SortMode::Name) { @@ -102,7 +102,7 @@ void IndexedList::peerNameChanged( FilterId filterId, not_null peer, const base::flat_set &oldLetters) { - Expects(_sortMode == SortMode::Date); + Expects(_sortMode == SortMode::Date || _sortMode == SortMode::Complex); if (const auto history = peer->owner().historyLoaded(peer)) { adjustNames(filterId, history, oldLetters); @@ -165,7 +165,7 @@ void IndexedList::adjustNames( } } for (auto ch : toRemove) { - if (_sortMode == SortMode::Date) { + if (_sortMode == SortMode::Date || _sortMode == SortMode::Complex) { history->removeChatListEntryByLetter(filterId, ch); } if (auto it = _index.find(ch); it != _index.cend()) { @@ -178,7 +178,7 @@ void IndexedList::adjustNames( j = _index.emplace(ch, _sortMode).first; } auto row = j->second.addToEnd(key); - if (_sortMode == SortMode::Date) { + if (_sortMode == SortMode::Date || _sortMode == SortMode::Complex) { history->addChatListEntryByLetter(filterId, ch, row); } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h index 65bb30d899..e2ae1346f0 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h @@ -26,12 +26,12 @@ public: // row must belong to this indexed list all(). void movePinned(Row *row, int deltaSign); - // For sortMode != SortMode::Date + // For sortMode != SortMode::Date && != Complex void peerNameChanged( not_null peer, const base::flat_set &oldChars); - //For sortMode == SortMode::Date + //For sortMode == SortMode::Date || == Complex void peerNameChanged( FilterId filterId, not_null peer, diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index f5e592af4d..ee702a6f3b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -440,6 +440,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) { Layout::RowPainter::paint( p, row, + _filterId, fullWidth, isActive, isSelected, @@ -565,6 +566,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) { Layout::RowPainter::paint( p, _filterResults[from], + _filterId, fullWidth, active, selected, @@ -1680,7 +1682,9 @@ void InnerWidget::updateSelectedRow(Key key) { } not_null InnerWidget::shownDialogs() const { - return session().data().chatsList(_openedFolder)->indexed(_filterId); + return _filterId + ? session().data().chatsFilters().chatsList(_filterId)->indexed() + : session().data().chatsList(_openedFolder)->indexed(); } void InnerWidget::leaveEventHook(QEvent *e) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index 4af73bf69a..879cf8e3ca 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -613,6 +613,7 @@ void paintUnreadCount( void RowPainter::paint( Painter &p, not_null row, + int filterId, int fullWidth, bool active, bool selected, @@ -668,6 +669,7 @@ void RowPainter::paint( const auto displayPinnedIcon = !displayUnreadCounter && !displayMentionBadge && !displayUnreadMark + && !filterId && entry->isPinnedDialog() && !entry->fixedOnTopIndex(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.h b/Telegram/SourceFiles/dialogs/dialogs_layout.h index c8b03e7925..6745569de7 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.h +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.h @@ -29,6 +29,7 @@ public: static void paint( Painter &p, not_null row, + int filterId, int fullWidth, bool active, bool selected, diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_list.cpp index 37302ace8e..7d3c196b48 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_list.cpp @@ -32,7 +32,7 @@ not_null List::addToEnd(Key key) { std::make_unique(key, _rows.size()) ).first->second.get(); _rows.emplace_back(result); - if (_sortMode == SortMode::Date) { + if (_sortMode == SortMode::Date || _sortMode == SortMode::Complex) { adjustByDate(result); } return result; @@ -82,20 +82,20 @@ void List::adjustByName(not_null row) { } void List::adjustByDate(not_null row) { - Expects(_sortMode == SortMode::Date); + Expects(_sortMode == SortMode::Date || _sortMode == SortMode::Complex); - const auto key = row->sortKey(); + const auto key = row->sortKey(_sortMode); const auto index = row->pos(); const auto i = _rows.begin() + index; const auto before = std::find_if(i + 1, _rows.end(), [&](Row *row) { - return (row->sortKey() <= key); + return (row->sortKey(_sortMode) <= key); }); if (before != i + 1) { rotate(i, i + 1, before); } else { const auto from = std::make_reverse_iterator(i); const auto after = std::find_if(from, _rows.rend(), [&](Row *row) { - return (row->sortKey() >= key); + return (row->sortKey(_sortMode) >= key); }).base(); if (after != i) { rotate(after, i, i + 1); diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp index 26081a0d7d..c6f01db277 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp @@ -12,8 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Dialogs { -MainList::MainList(rpl::producer pinnedLimit) -: _all(SortMode::Date) +MainList::MainList(FilterId filterId, rpl::producer pinnedLimit) +: _filterId(filterId) +, _all(filterId ? SortMode::Date : SortMode::Complex) , _pinned(1) { _unreadState.known = true; @@ -28,10 +29,7 @@ MainList::MainList(rpl::producer pinnedLimit) ) | rpl::start_with_next([=](const Notify::PeerUpdate &update) { const auto peer = update.peer; const auto &oldLetters = update.oldNameFirstLetters; - _all.peerNameChanged(FilterId(), peer, oldLetters); - for (auto &[filterId, list] : _other) { - list.peerNameChanged(filterId, peer, oldLetters); - } + _all.peerNameChanged(_filterId, peer, oldLetters); }, _lifetime); } @@ -49,7 +47,6 @@ void MainList::setLoaded(bool loaded) { void MainList::clear() { _all.clear(); - _other.clear(); _unreadState = UnreadState(); } @@ -73,15 +70,8 @@ UnreadState MainList::unreadState() const { return _unreadState; } -not_null MainList::indexed(FilterId filterId) { - if (!filterId) { - return &_all; - } - const auto i = _other.find(filterId); - if (i != end(_other)) { - return &i->second; - } - return &_other.emplace(filterId, SortMode::Date).first->second; +not_null MainList::indexed() { + return &_all; } not_null MainList::indexed() const { diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.h b/Telegram/SourceFiles/dialogs/dialogs_main_list.h index 4319b836ad..5bc69ba0e6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.h @@ -14,7 +14,7 @@ namespace Dialogs { class MainList final { public: - explicit MainList(rpl::producer pinnedLimit); + MainList(FilterId filterId, rpl::producer pinnedLimit); bool empty() const; bool loaded() const; @@ -29,14 +29,14 @@ public: bool added); [[nodiscard]] UnreadState unreadState() const; - not_null indexed(FilterId filterId = 0); + not_null indexed(); not_null indexed() const; not_null pinned(); not_null pinned() const; private: + FilterId _filterId = 0; IndexedList _all; - base::flat_map _other; PinnedList _pinned; UnreadState _unreadState; diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index 7ce16d30fd..1953ad5dbf 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -220,8 +220,10 @@ Row::Row(Key key, int pos) : _id(key), _pos(pos) { } } -uint64 Row::sortKey() const { - return _id.entry()->sortKeyInChatList(); +uint64 Row::sortKey(SortMode mode) const { + return (mode == SortMode::Complex) + ? _id.entry()->sortKeyInChatList() + : _id.entry()->sortKeyByDate(); } void Row::validateListEntryCache() const { diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index e8caf1d638..8fc58f74ac 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -23,6 +23,8 @@ namespace Layout { class RowPainter; } // namespace Layout +enum class SortMode; + class BasicRow { public: BasicRow(); @@ -88,7 +90,7 @@ public: int pos() const { return _pos; } - uint64 sortKey() const; + uint64 sortKey(SortMode mode) const; void validateListEntryCache() const; const Ui::Text::String &listEntryCache() const {