From 1a1fa5db3e81b4dd31ddf0c768206f2829a0e3e2 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 5 Apr 2023 15:06:41 +0400 Subject: [PATCH] Implement complex filter delete from context menu. --- Telegram/SourceFiles/api/api_chat_filters.cpp | 12 +++ Telegram/SourceFiles/api/api_chat_filters.h | 7 ++ .../SourceFiles/settings/settings_folders.cpp | 12 +-- .../window/window_filters_menu.cpp | 100 +++++++++++++++--- .../SourceFiles/window/window_filters_menu.h | 5 +- 5 files changed, 112 insertions(+), 24 deletions(-) diff --git a/Telegram/SourceFiles/api/api_chat_filters.cpp b/Telegram/SourceFiles/api/api_chat_filters.cpp index 8e1f44329..5729d38b6 100644 --- a/Telegram/SourceFiles/api/api_chat_filters.cpp +++ b/Telegram/SourceFiles/api/api_chat_filters.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat_filters.h" #include "data/data_peer.h" #include "data/data_session.h" +#include "history/history.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "settings/settings_common.h" @@ -828,4 +829,15 @@ void ProcessFilterRemove( Box(std::move(controller), std::move(initBox))); } +[[nodiscard]] std::vector> ExtractSuggestRemoving( + const Data::ChatFilter &filter) { + if (!filter.chatlist()) { + return {}; + } + return filter.always() | ranges::views::filter([]( + not_null history) { + return history->peer->isChannel(); + }) | ranges::views::transform(&History::peer) | ranges::to_vector; +} + } // namespace Api diff --git a/Telegram/SourceFiles/api/api_chat_filters.h b/Telegram/SourceFiles/api/api_chat_filters.h index c9d7e6732..9167a41db 100644 --- a/Telegram/SourceFiles/api/api_chat_filters.h +++ b/Telegram/SourceFiles/api/api_chat_filters.h @@ -15,6 +15,10 @@ namespace Window { class SessionController; } // namespace Window +namespace Data { +class ChatFilter; +} // namespace Data + namespace Api { void SaveNewFilterPinned( @@ -38,4 +42,7 @@ void ProcessFilterRemove( std::vector> suggest, Fn>)> done); +[[nodiscard]] std::vector> ExtractSuggestRemoving( + const Data::ChatFilter &filter); + } // namespace Api diff --git a/Telegram/SourceFiles/settings/settings_folders.cpp b/Telegram/SourceFiles/settings/settings_folders.cpp index f6c83ce78..5511e62c6 100644 --- a/Telegram/SourceFiles/settings/settings_folders.cpp +++ b/Telegram/SourceFiles/settings/settings_folders.cpp @@ -165,14 +165,6 @@ struct FilterRow { : result; } -[[nodiscard]] std::vector> ExtractSuggestRemoving( - const base::flat_set> &histories) { - return histories | ranges::views::filter([]( - not_null history) { - return history->peer->isChannel(); - }) | ranges::views::transform(&History::peer) | ranges::to_vector; -} - FilterRowButton::FilterRowButton( not_null parent, not_null session, @@ -378,9 +370,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) { }; const auto markForRemovalSure = [=](not_null button) { const auto row = find(button); - auto suggestRemoving = row->filter.chatlist() - ? ExtractSuggestRemoving(row->filter.always()) - : std::vector>(); + auto suggestRemoving = Api::ExtractSuggestRemoving(row->filter); if (row->removed || row->removePeersRequestId > 0) { return; } else if (!suggestRemoving.empty()) { diff --git a/Telegram/SourceFiles/window/window_filters_menu.cpp b/Telegram/SourceFiles/window/window_filters_menu.cpp index 6e7f07301..251742be7 100644 --- a/Telegram/SourceFiles/window/window_filters_menu.cpp +++ b/Telegram/SourceFiles/window/window_filters_menu.cpp @@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "styles/style_widgets.h" #include "styles/style_window.h" +#include "styles/style_layers.h" // attentionBoxButton #include "styles/style_menu_icons.h" namespace Window { @@ -406,23 +407,98 @@ void FiltersMenu::showEditBox(FilterId id) { } void FiltersMenu::showRemoveBox(FilterId id) { - _session->window().show(Ui::MakeConfirmBox({ - .text = tr::lng_filters_remove_sure(), - .confirmed = [=](Fn &&close) { close(); remove(id); }, - .confirmText = tr::lng_filters_remove_yes(), - })); + const auto session = &_session->session(); + const auto &list = session->data().chatsFilters().list(); + const auto i = ranges::find(list, id, &Data::ChatFilter::id); + const auto filter = (i != end(list)) ? *i : Data::ChatFilter(); + const auto has = filter.hasMyLinks(); + const auto confirm = [=](Fn action, bool onlyWhenHas = false) { + if (!has && onlyWhenHas) { + action(); + return; + } + _session->window().show(Ui::MakeConfirmBox({ + .text = (has + ? tr::lng_filters_delete_sure() + : tr::lng_filters_remove_sure()), + .confirmed = [=](Fn &&close) { close(); action(); }, + .confirmText = (has + ? tr::lng_box_delete() + : tr::lng_filters_remove_yes()), + .confirmStyle = &st::attentionBoxButton, + })); + }; + const auto simple = [=] { + confirm([=] { remove(id); }); + }; + const auto suggestRemoving = Api::ExtractSuggestRemoving(filter); + if (suggestRemoving.empty()) { + simple(); + return; + } else if (_removingRequestId) { + if (_removingId == id) { + return; + } + session->api().request(_removingRequestId).cancel(); + } + _removingId = id; + _removingRequestId = session->api().request( + MTPchatlists_GetLeaveChatlistSuggestions( + MTP_inputChatlistDialogFilter( + MTP_int(id))) + ).done(crl::guard(&_outer, [=](const MTPVector &result) { + _removingRequestId = 0; + const auto suggestRemovePeers = ranges::views::all( + result.v + ) | ranges::views::transform([=](const MTPPeer &peer) { + return session->data().peer(peerFromMTP(peer)); + }) | ranges::to_vector; + const auto chosen = crl::guard(&_outer, [=]( + std::vector> peers) { + remove(id, std::move(peers)); + }); + confirm(crl::guard(&_outer, [=] { + Api::ProcessFilterRemove( + _session, + filter.title(), + filter.iconEmoji(), + suggestRemoving, + suggestRemovePeers, + chosen); + }), true); + })).fail(crl::guard(&_outer, [=] { + _removingRequestId = 0; + simple(); + })).send(); } -void FiltersMenu::remove(FilterId id) { - _session->session().data().chatsFilters().apply(MTP_updateDialogFilter( +void FiltersMenu::remove( + FilterId id, + std::vector> leave) { + const auto session = &_session->session(); + const auto api = &session->api(); + session->data().chatsFilters().apply(MTP_updateDialogFilter( MTP_flags(MTPDupdateDialogFilter::Flag(0)), MTP_int(id), MTPDialogFilter())); - _session->session().api().request(MTPmessages_UpdateDialogFilter( - MTP_flags(MTPmessages_UpdateDialogFilter::Flag(0)), - MTP_int(id), - MTPDialogFilter() - )).send(); + if (leave.empty()) { + api->request(MTPmessages_UpdateDialogFilter( + MTP_flags(MTPmessages_UpdateDialogFilter::Flag(0)), + MTP_int(id), + MTPDialogFilter() + )).send(); + } else { + api->request(MTPchatlists_LeaveChatlist( + MTP_inputChatlistDialogFilter(MTP_int(id)), + MTP_vector(ranges::views::all( + leave + ) | ranges::views::transform([](not_null peer) { + return MTPInputPeer(peer->input); + }) | ranges::to()) + )).done([=](const MTPUpdates &result) { + api->applyUpdates(result); + }).send(); + } } void FiltersMenu::applyReorder( diff --git a/Telegram/SourceFiles/window/window_filters_menu.h b/Telegram/SourceFiles/window/window_filters_menu.h index dcc1efb7b..a4084164b 100644 --- a/Telegram/SourceFiles/window/window_filters_menu.h +++ b/Telegram/SourceFiles/window/window_filters_menu.h @@ -50,7 +50,7 @@ private: void showMenu(QPoint position, FilterId id); void showEditBox(FilterId id); void showRemoveBox(FilterId id); - void remove(FilterId id); + void remove(FilterId id, std::vector> leave = {}); void scrollToButton(not_null widget); const not_null _session; @@ -68,6 +68,9 @@ private: bool _ignoreRefresh = false; bool _waitingSuggested = false; + FilterId _removingId = 0; + mtpRequestId _removingRequestId = 0; + base::unique_qptr _popupMenu; struct { base::Timer timer;