From e70f50d837287bdc4c59a70efcc9e2346a993872 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 20 Nov 2024 16:35:53 +0300 Subject: [PATCH] Changed engine of chats filters in forward box with restoring state. --- .../SourceFiles/window/window_peer_menu.cpp | 204 +++++------------- 1 file changed, 57 insertions(+), 147 deletions(-) diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 4a3abe2ea..b25df4709 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -2061,7 +2061,17 @@ QPointer ShowForwardMessagesBox( class ListBox final : public PeerListBox { public: - using PeerListBox::PeerListBox; + ListBox( + QWidget *parent, + std::unique_ptr controller, + Fn)> init) + : PeerListBox( + parent, + std::move(controller), + [=](not_null box) { + init(static_cast(box.get())); + }) { + } void setBottomSkip(int bottomSkip) { PeerListBox::setInnerBottomSkip(bottomSkip); @@ -2086,9 +2096,21 @@ QPointer ShowForwardMessagesBox( _forwardOptions = forwardOptions; } + not_null peerListContent() const { + return PeerListBox::content(); + } + + void setFilterId(FilterId filterId) { + _filterId = filterId; + } + [[nodiscard]] FilterId filterId() const { + return _filterId; + } + private: rpl::event_stream<> _focusRequests; Ui::ForwardOptions _forwardOptions; + FilterId _filterId = 0; }; @@ -2106,6 +2128,12 @@ QPointer ShowForwardMessagesBox( }) { } + std::unique_ptr createRestoredRow( + not_null peer) override final { + return ChooseRecipientBoxController::createRow( + peer->owner().history(peer)); + } + using PeerListController::setSearchNoResultsText; void rowClicked(not_null row) override final { @@ -2158,166 +2186,48 @@ QPointer ShowForwardMessagesBox( base::unique_qptr menu; }; - const auto applyFilter = [=](not_null box, FilterId id) { + const auto applyFilter = [=](not_null box, FilterId id) { box->scrollToY(0); auto &filters = session->data().chatsFilters(); const auto &list = filters.list(); if (list.size() <= 1) { return; } - const auto pinnedList = [&]( - not_null list, - bool foundSelf) { - const auto pinned = list->pinned()->order(); - auto peers = std::vector>(); - peers.reserve(pinned.size()); - for (const auto &pin : pinned) { - if (!foundSelf && pin.peer()->isSelf()) { - peers.insert(peers.begin(), pin.peer()); - foundSelf = true; - } else { - peers.push_back(pin.peer()); - } - } - if (!foundSelf) { - peers.insert(peers.begin(), session->user()); - } - return peers; - }; - const auto folder = session->data().folderLoaded( - Data::Folder::kId); - const auto pinned = pinnedList( - id - ? filters.chatsList(id) - : session->data().chatsList(nullptr), - !!id); - const auto pinnedInFolder = (!id && folder) - ? pinnedList(folder->chatsList(), true) - : std::vector>(); - box->peerListSortRows([&]( - const PeerListRow &r1, - const PeerListRow &r2) { - { // Pinned to top. - auto it1 = pinned.end(); - auto it2 = pinned.end(); - for (auto it = pinned.begin(); it != pinned.end(); ++it) { - if ((*it) == r1.peer()) { - it1 = it; - } - if ((*it) == r2.peer()) { - it2 = it; - } - if (it1 != pinned.end() && it2 != pinned.end()) { - break; - } - } - if (it1 == pinned.end() && it2 != pinned.end()) { - return false; - } else if (it2 == pinned.end() && it1 != pinned.end()) { - return true; - } else if (it1 != pinned.end() && it2 != pinned.end()) { - return it1 < it2; - } - } - { // Pinned to bottom. - const auto &indexed = session->data().contactsNoChatsList(); - auto it1 = indexed->end(); - auto it2 = indexed->end(); - for (auto it = indexed->begin(); it != indexed->end(); ++it) { - if (it->get()->key().peer() == r1.peer()) { - it1 = it; - } - if (it->get()->key().peer() == r2.peer()) { - it2 = it; - } - if (it1 != indexed->end() && it2 != indexed->end()) { - break; - } - } - if (it1 == indexed->end() && it2 != indexed->end()) { - return true; - } else if (it2 == indexed->end() && it1 != indexed->end()) { - return false; - } else if (it1 != indexed->end() && it2 != indexed->end()) { - return it1 > it2; - } - } - if (folder) { - const auto pinned1 = ranges::find(pinnedInFolder, r1.peer()); - const auto pinned2 = ranges::find(pinnedInFolder, r2.peer()); - const auto isPinned1 = pinned1 != pinnedInFolder.end(); - const auto isPinned2 = pinned2 != pinnedInFolder.end(); - if (isPinned1 && isPinned2) { - return pinned1 < pinned2; - } - - const auto &indexed = folder->chatsList()->indexed(); - auto it1 = indexed->end(); - auto it2 = indexed->end(); - for (auto it = indexed->begin(); it != indexed->end(); ++it) { - if (it->get()->key().peer() == r1.peer()) { - it1 = it; - } - if (it->get()->key().peer() == r2.peer()) { - it2 = it; - } - if (it1 != indexed->end() && it2 != indexed->end()) { - break; - } - } - const auto isFoldered1 = it1 != indexed->end(); - const auto isFoldered2 = it2 != indexed->end(); - if (isPinned1 && !isPinned2) { - return isFoldered2; - } - if (isPinned2 && !isPinned1) { - return !isFoldered1; - } - if (!isPinned1 && !isPinned2) { - if (!isFoldered1 && isFoldered2) { - return true; - } else if (!isFoldered2 && isFoldered1) { - return false; - } else if (isFoldered1 && isFoldered2) { - return it1 < it2; - } - } - } - const auto history1 = session->data().history(r1.peer()); - const auto history2 = session->data().history(r2.peer()); - const auto date1 = history1->lastMessage() - ? history1->lastMessage()->date() - : TimeId(0); - const auto date2 = history2->lastMessage() - ? history2->lastMessage()->date() - : TimeId(0); - return date1 > date2; - }); - const auto filter = ranges::find( - list, - id, - &Data::ChatFilter::id); - if (filter == list.end()) { + if (box->filterId() == id) { return; } - box->peerListPartitionRows([&](const PeerListRow &row) { - const auto rowPtr = const_cast(&row); - if (!filter->id()) { - box->peerListSetRowHidden(rowPtr, false); - } else { - const auto result = filter->contains( - session->data().history(row.peer())); - box->peerListSetRowHidden(rowPtr, !result); + box->setFilterId(id); + + using SavedState = PeerListController::SavedStateBase; + auto state = std::make_unique(); + state->controllerState = std::make_unique(); + + const auto addList = [&](auto chats) { + for (const auto &row : chats->all()) { + if (const auto history = row->history()) { + state->list.push_back(history->peer); + } } - return false; - }); - box->peerListRefreshRows(); + }; + + if (!id) { + state->list.push_back(session->user()); + addList(session->data().chatsList()->indexed()); + const auto folderId = Data::Folder::kId; + if (const auto folder = session->data().folderLoaded(folderId)) { + addList(folder->chatsList()->indexed()); + } + addList(session->data().contactsNoChatsList()); + } else { + addList(session->data().chatsFilters().chatsList(id)->indexed()); + } + box->peerListContent()->restoreState(std::move(state)); }; const auto state = [&] { auto controller = std::make_unique(session); const auto controllerRaw = controller.get(); - auto init = [=](not_null box) { + auto init = [=](not_null box) { controllerRaw->setSearchNoResultsText( tr::lng_bot_chats_not_found(tr::now)); box->setSpecialTabMode(true);