Implement complex filter delete from context menu.

This commit is contained in:
John Preston 2023-04-05 15:06:41 +04:00
parent 6f4eef035d
commit 1a1fa5db3e
5 changed files with 112 additions and 24 deletions

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/history.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
@ -828,4 +829,15 @@ void ProcessFilterRemove(
Box<PeerListBox>(std::move(controller), std::move(initBox))); Box<PeerListBox>(std::move(controller), std::move(initBox)));
} }
[[nodiscard]] std::vector<not_null<PeerData*>> ExtractSuggestRemoving(
const Data::ChatFilter &filter) {
if (!filter.chatlist()) {
return {};
}
return filter.always() | ranges::views::filter([](
not_null<History*> history) {
return history->peer->isChannel();
}) | ranges::views::transform(&History::peer) | ranges::to_vector;
}
} // namespace Api } // namespace Api

View file

@ -15,6 +15,10 @@ namespace Window {
class SessionController; class SessionController;
} // namespace Window } // namespace Window
namespace Data {
class ChatFilter;
} // namespace Data
namespace Api { namespace Api {
void SaveNewFilterPinned( void SaveNewFilterPinned(
@ -38,4 +42,7 @@ void ProcessFilterRemove(
std::vector<not_null<PeerData*>> suggest, std::vector<not_null<PeerData*>> suggest,
Fn<void(std::vector<not_null<PeerData*>>)> done); Fn<void(std::vector<not_null<PeerData*>>)> done);
[[nodiscard]] std::vector<not_null<PeerData*>> ExtractSuggestRemoving(
const Data::ChatFilter &filter);
} // namespace Api } // namespace Api

View file

@ -165,14 +165,6 @@ struct FilterRow {
: result; : result;
} }
[[nodiscard]] std::vector<not_null<PeerData*>> ExtractSuggestRemoving(
const base::flat_set<not_null<History*>> &histories) {
return histories | ranges::views::filter([](
not_null<History*> history) {
return history->peer->isChannel();
}) | ranges::views::transform(&History::peer) | ranges::to_vector;
}
FilterRowButton::FilterRowButton( FilterRowButton::FilterRowButton(
not_null<QWidget*> parent, not_null<QWidget*> parent,
not_null<Main::Session*> session, not_null<Main::Session*> session,
@ -378,9 +370,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
}; };
const auto markForRemovalSure = [=](not_null<FilterRowButton*> button) { const auto markForRemovalSure = [=](not_null<FilterRowButton*> button) {
const auto row = find(button); const auto row = find(button);
auto suggestRemoving = row->filter.chatlist() auto suggestRemoving = Api::ExtractSuggestRemoving(row->filter);
? ExtractSuggestRemoving(row->filter.always())
: std::vector<not_null<PeerData*>>();
if (row->removed || row->removePeersRequestId > 0) { if (row->removed || row->removePeersRequestId > 0) {
return; return;
} else if (!suggestRemoving.empty()) { } else if (!suggestRemoving.empty()) {

View file

@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
#include "styles/style_window.h" #include "styles/style_window.h"
#include "styles/style_layers.h" // attentionBoxButton
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
namespace Window { namespace Window {
@ -406,23 +407,98 @@ void FiltersMenu::showEditBox(FilterId id) {
} }
void FiltersMenu::showRemoveBox(FilterId id) { void FiltersMenu::showRemoveBox(FilterId id) {
_session->window().show(Ui::MakeConfirmBox({ const auto session = &_session->session();
.text = tr::lng_filters_remove_sure(), const auto &list = session->data().chatsFilters().list();
.confirmed = [=](Fn<void()> &&close) { close(); remove(id); }, const auto i = ranges::find(list, id, &Data::ChatFilter::id);
.confirmText = tr::lng_filters_remove_yes(), const auto filter = (i != end(list)) ? *i : Data::ChatFilter();
})); const auto has = filter.hasMyLinks();
const auto confirm = [=](Fn<void()> 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<void()> &&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<MTPPeer> &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<not_null<PeerData*>> 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) { void FiltersMenu::remove(
_session->session().data().chatsFilters().apply(MTP_updateDialogFilter( FilterId id,
std::vector<not_null<PeerData*>> leave) {
const auto session = &_session->session();
const auto api = &session->api();
session->data().chatsFilters().apply(MTP_updateDialogFilter(
MTP_flags(MTPDupdateDialogFilter::Flag(0)), MTP_flags(MTPDupdateDialogFilter::Flag(0)),
MTP_int(id), MTP_int(id),
MTPDialogFilter())); MTPDialogFilter()));
_session->session().api().request(MTPmessages_UpdateDialogFilter( if (leave.empty()) {
MTP_flags(MTPmessages_UpdateDialogFilter::Flag(0)), api->request(MTPmessages_UpdateDialogFilter(
MTP_int(id), MTP_flags(MTPmessages_UpdateDialogFilter::Flag(0)),
MTPDialogFilter() MTP_int(id),
)).send(); MTPDialogFilter()
)).send();
} else {
api->request(MTPchatlists_LeaveChatlist(
MTP_inputChatlistDialogFilter(MTP_int(id)),
MTP_vector<MTPInputPeer>(ranges::views::all(
leave
) | ranges::views::transform([](not_null<PeerData*> peer) {
return MTPInputPeer(peer->input);
}) | ranges::to<QVector>())
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result);
}).send();
}
} }
void FiltersMenu::applyReorder( void FiltersMenu::applyReorder(

View file

@ -50,7 +50,7 @@ private:
void showMenu(QPoint position, FilterId id); void showMenu(QPoint position, FilterId id);
void showEditBox(FilterId id); void showEditBox(FilterId id);
void showRemoveBox(FilterId id); void showRemoveBox(FilterId id);
void remove(FilterId id); void remove(FilterId id, std::vector<not_null<PeerData*>> leave = {});
void scrollToButton(not_null<Ui::RpWidget*> widget); void scrollToButton(not_null<Ui::RpWidget*> widget);
const not_null<SessionController*> _session; const not_null<SessionController*> _session;
@ -68,6 +68,9 @@ private:
bool _ignoreRefresh = false; bool _ignoreRefresh = false;
bool _waitingSuggested = false; bool _waitingSuggested = false;
FilterId _removingId = 0;
mtpRequestId _removingRequestId = 0;
base::unique_qptr<Ui::PopupMenu> _popupMenu; base::unique_qptr<Ui::PopupMenu> _popupMenu;
struct { struct {
base::Timer timer; base::Timer timer;