Support nice leaving of shareable folder.

This commit is contained in:
John Preston 2023-03-31 22:55:19 +04:00
parent 4444844443
commit 6be2fb9790
8 changed files with 396 additions and 79 deletions

View File

@ -3558,9 +3558,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_filters_toast_add" = "{chat} added to {folder} folder";
"lng_filters_toast_remove" = "{chat} removed from {folder} folder";
"lng_filters_link" = "Invite links";
"lng_filters_delete_sure" = "Are you sure you want to delete this folder? This will also deactivate all the invite links used to share this folder.";
"lng_filters_link" = "Share Folder";
"lng_filters_link_has" = "Invite links";
"lng_filters_link_badge" = "New";
"lng_filters_link_create" = "Share Folder";
"lng_filters_link_create" = "Create an Invite Link";
"lng_filters_link_cant" = "No way to share folders with chat types or excluded chats.";
"lng_filters_link_about" = "Share access to some of this folder's groups and channels with others.";
"lng_filters_link_about_many" = "Create more links to set up different access levels for different people.";
@ -3577,6 +3579,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_filters_link_noadmin_status" = "you can't invite others here";
"lng_filters_link_noadmin_group_error" = "You don't have the admin rights to share invite links to this group chat.";
"lng_filters_link_noadmin_channel_error" = "You don't have the admin rights to share invite links to this channel.";
"lng_filters_link_already_group" = "you are already a member";
"lng_filters_link_already_channel" = "you are already subscribed";
"lng_filters_link_chats_about" = "Select groups and channels that you want everyone who adds the folder via invite link to join.";
"lng_filters_link_no_about" = "There are no chats in this folder that you can share with others.";
"lng_filters_link_chats_no" = "These chats cannot be shared";
@ -3604,8 +3608,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_filters_by_link_quit#other" = "{count} chats to quit";
"lng_filters_by_link_select" = "Select All";
"lng_filters_by_link_deselect" = "Deselect All";
"lng_filters_by_link_about_quit" = "You can deselect the chats you don't want to quit.";
"lng_filters_by_link_remove_button" = "Remove Folder";
"lng_filters_by_link_quit_button" = "Remove Folder and Chats";
"lng_filters_added_title" = "Folder {folder} Added";
"lng_filters_added_also#one" = "You also joined {count} chat.";
"lng_filters_added_also#other" = "You also joined {count} chats.";
"lng_filters_updated_title" = "Folder {folder} Updated";
"lng_filters_updated_also#one" = "You have joined {count} new chat.";
"lng_filters_updated_also#other" = "You have joined {count} new chats.";
"lng_filters_bar_you_can#one" = "You can join {count} new chat";
"lng_filters_bar_you_can#other" = "You can join {count} new chats";
"lng_filters_bar_view" = "Click here to view them";

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "boxes/peer_list_box.h"
#include "boxes/filters/edit_filter_links.h" // FilterChatStatusText
#include "core/application.h"
#include "data/data_chat_filters.h"
#include "data/data_peer.h"
@ -21,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h"
#include "ui/toasts/common_toasts.h"
#include "ui/widgets/buttons.h"
#include "ui/filter_icons.h"
#include "window/window_session_controller.h"
#include "styles/style_filter_icons.h"
#include "styles/style_layers.h"
@ -41,10 +43,9 @@ public:
ToggleChatsController(
not_null<Window::SessionController*> window,
ToggleAction action,
const QString &slug,
FilterId filterId,
const QString &title,
std::vector<not_null<PeerData*>> chats);
std::vector<not_null<PeerData*>> chats,
std::vector<not_null<PeerData*>> additional);
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
@ -63,10 +64,9 @@ private:
Ui::RpWidget *_addedTopWidget = nullptr;
ToggleAction _action = ToggleAction::Adding;
QString _slug;
FilterId _filterId = 0;
QString _filterTitle;
std::vector<not_null<PeerData*>> _chats;
std::vector<not_null<PeerData*>> _additional;
rpl::variable<base::flat_set<not_null<PeerData*>>> _selected;
base::unique_qptr<Ui::PopupMenu> _menu;
@ -128,13 +128,18 @@ void InitFilterLinkHeader(
Fn<void(int)> setAddedTopHeight,
Ui::FilterLinkHeaderType type,
const QString &title,
const QString &iconEmoji,
rpl::producer<int> count) {
const auto icon = Ui::LookupFilterIcon(
Ui::LookupFilterIconByEmoji(
iconEmoji
).value_or(Ui::FilterIcon::Custom)).active;
auto header = Ui::MakeFilterLinkHeader(box, {
.type = type,
.title = TitleText(type)(tr::now),
.about = AboutText(type, title),
.folderTitle = title,
.folderIcon = &st::foldersCustomActive,
.folderIcon = icon,
.badge = (type == Ui::FilterLinkHeaderType::AddingChats
? std::move(count)
: rpl::single(0)),
@ -220,16 +225,14 @@ void ImportInvite(
ToggleChatsController::ToggleChatsController(
not_null<Window::SessionController*> window,
ToggleAction action,
const QString &slug,
FilterId filterId,
const QString &title,
std::vector<not_null<PeerData*>> chats)
std::vector<not_null<PeerData*>> chats,
std::vector<not_null<PeerData*>> additional)
: _window(window)
, _action(action)
, _slug(slug)
, _filterId(filterId)
, _filterTitle(title)
, _chats(std::move(chats)) {
, _chats(std::move(chats))
, _additional(std::move(additional)) {
setStyleOverrides(&st::filterLinkChatsList);
}
@ -237,12 +240,34 @@ void ToggleChatsController::prepare() {
setupAboveWidget();
setupBelowWidget();
auto selected = base::flat_set<not_null<PeerData*>>();
for (const auto &peer : _chats) {
const auto add = [&](not_null<PeerData*> peer, bool additional = false) {
auto row = std::make_unique<PeerListRow>(peer);
if (delegate()->peerListFindRow(peer->id.value)) {
return;
}
const auto raw = row.get();
delegate()->peerListAppendRow(std::move(row));
delegate()->peerListSetRowChecked(raw, true);
selected.emplace(peer);
if (!additional || _action == ToggleAction::Removing) {
if (const auto status = FilterChatStatusText(peer)
; !status.isEmpty()) {
raw->setCustomStatus(status);
}
}
if (!additional) {
delegate()->peerListSetRowChecked(raw, true);
selected.emplace(peer);
} else if (_action == ToggleAction::Adding) {
raw->setDisabledState(PeerListRow::State::DisabledChecked);
raw->setCustomStatus(peer->isBroadcast()
? tr::lng_filters_link_already_channel(tr::now)
: tr::lng_filters_link_already_group(tr::now));
}
};
for (const auto &peer : _chats) {
add(peer);
}
for (const auto &peer : _additional) {
add(peer, true);
}
delegate()->peerListRefreshRows();
_selected = std::move(selected);
@ -269,23 +294,51 @@ void ToggleChatsController::setupAboveWidget() {
_addedTopWidget = container->add(object_ptr<Ui::RpWidget>(container));
AddDivider(container);
const auto totalCount = [&] {
if (_chats.empty()) {
return _additional.size();
} else if (_additional.empty()) {
return _chats.size();
}
auto result = _chats.size();
for (const auto &peer : _additional) {
if (!ranges::contains(_chats, peer)) {
++result;
}
}
return result;
};
const auto count = (_action == ToggleAction::Removing)
? totalCount()
: _chats.empty()
? _additional.size()
: _chats.size();
AddSubsectionTitle(
container,
tr::lng_filters_by_link_join(
lt_count,
rpl::single(float64(_chats.size()))),
(_action == ToggleAction::Removing
? tr::lng_filters_by_link_quit
: _chats.empty()
? tr::lng_filters_by_link_in
: tr::lng_filters_by_link_join)(
lt_count,
rpl::single(float64(count))),
st::filterLinkSubsectionTitlePadding);
delegate()->peerListSetAboveWidget(std::move(wrap));
}
void ToggleChatsController::setupBelowWidget() {
if (_chats.empty()) {
return;
}
delegate()->peerListSetBelowWidget(
object_ptr<Ui::DividerLabel>(
(QWidget*)nullptr,
object_ptr<Ui::FlatLabel>(
(QWidget*)nullptr,
tr::lng_filters_by_link_about(tr::now),
(_action == ToggleAction::Removing
? tr::lng_filters_by_link_about_quit
: tr::lng_filters_by_link_about)(tr::now),
st::boxDividerLabel),
st::settingsDividerLabelPadding));
}
@ -305,12 +358,40 @@ void ToggleChatsController::setAddedTopHeight(int addedTopHeight) {
_addedTopWidget->resize(_addedTopWidget->width(), addedTopHeight);
}
void ShowImportToast(
base::weak_ptr<Window::SessionController> weak,
const QString &title,
Ui::FilterLinkHeaderType type,
int added) {
const auto strong = weak.get();
if (!strong) {
return;
}
const auto created = (type == Ui::FilterLinkHeaderType::AddingFilter);
const auto phrase = created
? tr::lng_filters_added_title
: tr::lng_filters_updated_title;
auto text = Ui::Text::Bold(phrase(tr::now, lt_folder, title));
if (added > 0) {
const auto phrase = created
? tr::lng_filters_added_also
: tr::lng_filters_updated_also;
text.append('\n').append(phrase(tr::now, lt_count, added));
}
Ui::ShowMultilineToast({
.parentOverride = Window::Show(strong).toastParent(),
.text = { std::move(text) },
});
}
void ProcessFilterInvite(
base::weak_ptr<Window::SessionController> weak,
const QString &slug,
FilterId filterId,
const QString &title,
std::vector<not_null<PeerData*>> peers) {
const QString &iconEmoji,
std::vector<not_null<PeerData*>> peers,
std::vector<not_null<PeerData*>> already) {
const auto strong = weak.get();
if (!strong) {
return;
@ -323,19 +404,21 @@ void ProcessFilterInvite(
});
return;
}
const auto fullyAdded = (peers.empty() && filterId);
auto controller = std::make_unique<ToggleChatsController>(
strong,
ToggleAction::Adding,
slug,
filterId,
title,
std::move(peers));
std::move(peers),
std::move(already));
const auto raw = controller.get();
auto initBox = [=](not_null<PeerListBox*> box) {
box->setStyle(st::filterInviteBox);
using Type = Ui::FilterLinkHeaderType;
const auto type = !filterId
const auto type = fullyAdded
? Type::AllAdded
: !filterId
? Type::AddingFilter
: Type::AddingChats;
auto badge = raw->selectedValue(
@ -344,7 +427,7 @@ void ProcessFilterInvite(
});
InitFilterLinkHeader(box, [=](int addedTopHeight) {
raw->setAddedTopHeight(addedTopHeight);
}, type, title, rpl::duplicate(badge));
}, type, title, iconEmoji, rpl::duplicate(badge));
auto owned = Ui::FilterLinkProcessButton(
box,
@ -380,6 +463,7 @@ void ProcessFilterInvite(
} else if (!state->importing) {
state->importing = true;
ImportInvite(weak, slug, peers, crl::guard(box, [=] {
ShowImportToast(weak, title, type, peers.size());
box->closeBox();
}), crl::guard(box, [=] {
state->importing = false;
@ -396,7 +480,8 @@ void ProcessFilterInvite(
base::weak_ptr<Window::SessionController> weak,
const QString &slug,
FilterId filterId,
std::vector<not_null<PeerData*>> peers) {
std::vector<not_null<PeerData*>> peers,
std::vector<not_null<PeerData*>> already) {
const auto strong = weak.get();
if (!strong) {
return;
@ -411,7 +496,14 @@ void ProcessFilterInvite(
});
return;
}
ProcessFilterInvite(weak, slug, filterId, it->title(), std::move(peers));
ProcessFilterInvite(
weak,
slug,
filterId,
it->title(),
it->iconEmoji(),
std::move(peers),
std::move(already));
}
} // namespace
@ -441,6 +533,7 @@ void CheckFilterInvite(
return;
}
auto title = QString();
auto iconEmoji = QString();
auto filterId = FilterId();
auto peers = std::vector<not_null<PeerData*>>();
auto already = std::vector<not_null<PeerData*>>();
@ -459,6 +552,7 @@ void CheckFilterInvite(
};
result.match([&](const MTPDcommunities_communityInvite &data) {
title = qs(data.vtitle());
iconEmoji = data.vemoticon().value_or_empty();
peers = parseList(data.vpeers());
}, [&](const MTPDcommunities_communityInviteAlready &data) {
filterId = data.vfilter_id().v;
@ -477,20 +571,103 @@ void CheckFilterInvite(
owner.chatsFilters().changed(
) | rpl::start_with_next([=] {
lifetime->destroy();
ProcessFilterInvite(weak, slug, filterId, std::move(peers));
ProcessFilterInvite(
weak,
slug,
filterId,
std::move(peers),
std::move(already));
}, *lifetime);
owner.chatsFilters().reload();
} else if (filterId) {
ProcessFilterInvite(weak, slug, filterId, std::move(peers));
ProcessFilterInvite(
weak,
slug,
filterId,
std::move(peers),
std::move(already));
} else {
ProcessFilterInvite(weak, slug, filterId, title, std::move(peers));
ProcessFilterInvite(
weak,
slug,
filterId,
title,
iconEmoji,
std::move(peers),
std::move(already));
}
}, [=](const MTP::Error &error) {
if (error.code() != 400) {
return;
}
ProcessFilterInvite(weak, slug, FilterId(), QString(), {});
ProcessFilterInvite(weak, slug, {}, {}, {}, {}, {});
});
}
void ProcessFilterRemove(
base::weak_ptr<Window::SessionController> weak,
const QString &title,
const QString &iconEmoji,
std::vector<not_null<PeerData*>> all,
std::vector<not_null<PeerData*>> suggest,
Fn<void(std::vector<not_null<PeerData*>>)> done) {
const auto strong = weak.get();
if (!strong) {
return;
}
Core::App().hideMediaView();
if (all.empty() && suggest.empty()) {
done({});
return;
}
auto controller = std::make_unique<ToggleChatsController>(
strong,
ToggleAction::Removing,
title,
std::move(suggest),
std::move(all));
const auto raw = controller.get();
auto initBox = [=](not_null<PeerListBox*> box) {
box->setStyle(st::filterInviteBox);
const auto type = Ui::FilterLinkHeaderType::Removing;
auto badge = raw->selectedValue(
) | rpl::map([=](const base::flat_set<not_null<PeerData*>> &peers) {
return int(peers.size());
});
InitFilterLinkHeader(box, [=](int addedTopHeight) {
raw->setAddedTopHeight(addedTopHeight);
}, type, title, iconEmoji, rpl::single(0));
auto owned = Ui::FilterLinkProcessButton(
box,
type,
title,
std::move(badge));
const auto button = owned.data();
box->widthValue(
) | rpl::start_with_next([=](int width) {
const auto &padding = st::filterInviteBox.buttonPadding;
button->resizeToWidth(width
- padding.left()
- padding.right());
button->moveToLeft(padding.left(), padding.top());
}, button->lifetime());
box->addButton(std::move(owned));
raw->selectedValue(
) | rpl::start_with_next([=](
base::flat_set<not_null<PeerData*>> &&peers) {
button->setClickedCallback([=] {
done(peers | ranges::to_vector);
box->closeBox();
});
}, box->lifetime());
};
strong->show(
Box<PeerListBox>(std::move(controller), std::move(initBox)));
}
} // namespace Api

View File

@ -25,4 +25,12 @@ void CheckFilterInvite(
not_null<Window::SessionController*> controller,
const QString &slug);
void ProcessFilterRemove(
base::weak_ptr<Window::SessionController> weak,
const QString &title,
const QString &iconEmoji,
std::vector<not_null<PeerData*>> all,
std::vector<not_null<PeerData*>> suggest,
Fn<void(std::vector<not_null<PeerData*>>)> done);
} // namespace Api

View File

@ -706,7 +706,16 @@ void EditFilterBox(
return result;
};
AddSubsectionTitle(content, tr::lng_filters_link());
AddSubsectionTitle(
content,
rpl::conditional(
state->hasLinks.value(),
tr::lng_filters_link_has(),
tr::lng_filters_link()));
state->hasLinks.changes() | rpl::start_with_next([=] {
content->resizeToWidth(content->widthNoMargins());
}, content->lifetime());
if (filter.community()) {
window->session().data().chatsFilters().reloadCommunityLinks(

View File

@ -679,26 +679,12 @@ void LinkController::prepare() {
setupAboveWidget();
setupBelowWidget();
const auto countStatus = [&](not_null<PeerData*> peer) {
if (const auto chat = peer->asChat()) {
if (const auto count = chat->count; count > 0) {
return tr::lng_chat_status_members(tr::now, lt_count, count);
}
} else if (const auto channel = peer->asChannel()) {
if (channel->membersCountKnown()) {
return (channel->isBroadcast()
? tr::lng_chat_status_subscribers
: tr::lng_chat_status_members)(
tr::now,
lt_count,
channel->membersCount());
}
}
return QString();
};
for (const auto &history : _data.chats) {
const auto peer = history->peer;
auto row = std::make_unique<ChatRow>(peer, countStatus(peer), false);
auto row = std::make_unique<ChatRow>(
peer,
FilterChatStatusText(peer),
false);
const auto raw = row.get();
delegate()->peerListAppendRow(std::move(row));
delegate()->peerListSetRowChecked(raw, true);
@ -712,7 +698,7 @@ void LinkController::prepare() {
const auto error = ErrorForSharing(history);
auto row = std::make_unique<ChatRow>(
peer,
error ? error->status : countStatus(peer),
error ? error->status : FilterChatStatusText(peer),
error.has_value());
const auto raw = row.get();
delegate()->peerListAppendRow(std::move(row));
@ -1160,6 +1146,24 @@ object_ptr<Ui::BoxContent> ShowLinkBox(
return Box<PeerListBox>(std::move(controller), std::move(initBox));
}
QString FilterChatStatusText(not_null<PeerData*> peer) {
if (const auto chat = peer->asChat()) {
if (const auto count = chat->count; count > 0) {
return tr::lng_chat_status_members(tr::now, lt_count, count);
}
} else if (const auto channel = peer->asChannel()) {
if (channel->membersCountKnown()) {
return (channel->isBroadcast()
? tr::lng_chat_status_subscribers
: tr::lng_chat_status_members)(
tr::now,
lt_count,
channel->membersCount());
}
}
return QString();
}
void SetupFilterLinks(
not_null<Ui::VerticalLayout*> container,
not_null<Window::SessionController*> window,

View File

@ -36,10 +36,11 @@ void ExportFilterLink(
Fn<void(Data::ChatFilterLink)> done,
Fn<void(QString)> fail);
object_ptr<Ui::BoxContent> ShowLinkBox(
[[nodiscard]] object_ptr<Ui::BoxContent> ShowLinkBox(
not_null<Window::SessionController*> window,
const Data::ChatFilter &filter,
const Data::ChatFilterLink &link);
[[nodiscard]] QString FilterChatStatusText(not_null<PeerData*> peer);
void SetupFilterLinks(
not_null<Ui::VerticalLayout*> container,

View File

@ -1354,6 +1354,9 @@ void Session::setupChannelLeavingViewer() {
history->removeJoinedMessage();
history->updateChatListExistence();
history->updateChatListSortPosition();
if (!history->inChatList()) {
history->clearFolder();
}
}
}
}, _lifetime);

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_folders.h"
#include "apiwrap.h"
#include "api/api_chat_filters.h" // ProcessFilterRemove.
#include "boxes/premium_limits_box.h"
#include "boxes/filters/edit_filter_box.h"
#include "core/application.h"
@ -22,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lottie/lottie_icon.h"
#include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h"
#include "ui/filter_icons.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
@ -102,6 +104,10 @@ struct FilterRow {
not_null<FilterRowButton*> button;
Data::ChatFilter filter;
bool removed = false;
bool removeHasLinks = false;
mtpRequestId removePeersRequestId = 0;
std::vector<not_null<PeerData*>> suggestRemovePeers;
std::vector<not_null<PeerData*>> removePeers;
bool added = false;
bool postponedCountUpdate = false;
};
@ -361,6 +367,81 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
controller->show(Box(FiltersLimitBox, session));
return true;
};
const auto markForRemovalSure = [=](not_null<FilterRowButton*> button) {
const auto row = find(button);
if (row->removed || row->removePeersRequestId > 0) {
return;
} else if (row->filter.community()
&& !row->filter.always().empty()) {
const auto chosen = crl::guard(button, [=](
std::vector<not_null<PeerData*>> peers) {
const auto row = find(button);
row->removePeers = std::move(peers);
row->removed = true;
button->setRemoved(true);
});
Api::ProcessFilterRemove(
controller,
row->filter.title(),
row->filter.iconEmoji(),
row->filter.always() | ranges::views::transform(
&History::peer
) | ranges::to_vector,
row->suggestRemovePeers,
chosen);
} else {
row->removePeers = {};
row->removed = true;
button->setRemoved(true);
}
};
const auto markForRemoval = [=](not_null<FilterRowButton*> button) {
const auto row = find(button);
if (row->removed || row->removePeersRequestId > 0) {
return;
} else if (row->filter.community() && row->removeHasLinks) {
controller->show(Ui::MakeConfirmBox({
.text = { tr::lng_filters_delete_sure(tr::now) },
.confirmed = crl::guard(button, [=](Fn<void()> close) {
markForRemovalSure(button);
close();
}),
.confirmText = tr::lng_box_delete(),
.confirmStyle = &st::attentionBoxButton,
}));
} else {
markForRemovalSure(button);
}
};
const auto remove = [=](not_null<FilterRowButton*> button) {
const auto row = find(button);
if (row->removed || row->removePeersRequestId > 0) {
return;
} else if (row->filter.community() && !row->removePeersRequestId) {
row->removePeersRequestId = session->api().request(
MTPcommunities_GetLeaveCommunitySuggestions(
MTP_inputCommunityDialogFilter(
MTP_int(row->filter.id())))
).done(crl::guard(button, [=](const MTPVector<MTPPeer> &result) {
const auto row = find(button);
row->removePeersRequestId = -1;
row->suggestRemovePeers = ranges::views::all(
result.v
) | ranges::views::transform([=](const MTPPeer &peer) {
return session->data().peer(peerFromMTP(peer));
}) | ranges::to_vector;
row->removeHasLinks = true; // #TODO filters
markForRemoval(button);
})).fail(crl::guard(button, [=] {
const auto row = find(button);
row->removePeersRequestId = -1;
row->removeHasLinks = false;
markForRemoval(button);
})).send();
} else {
markForRemoval(button);
}
};
const auto wrap = container->add(object_ptr<Ui::VerticalLayout>(
container));
const auto addFilter = [=](const Data::ChatFilter &filter) {
@ -368,8 +449,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
object_ptr<FilterRowButton>(wrap, session, filter));
button->removeRequests(
) | rpl::start_with_next([=] {
button->setRemoved(true);
find(button)->removed = true;
remove(button);
}, button->lifetime());
button->restoreRequests(
) | rpl::start_with_next([=] {
@ -562,6 +642,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
auto updates = std::vector<MTPUpdate>();
auto addRequests = std::vector<MTPmessages_UpdateDialogFilter>();
auto removeRequests = std::vector<MTPmessages_UpdateDialogFilter>();
auto removeCommunityRequests = std::vector<MTPcommunities_LeaveCommunity>();
auto &realFilters = session->data().chatsFilters();
const auto &list = realFilters.list();
@ -590,17 +671,32 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
const auto tl = removed
? MTPDialogFilter()
: row.filter.tl(newId);
const auto request = MTPmessages_UpdateDialogFilter(
MTP_flags(removed
? MTPmessages_UpdateDialogFilter::Flag(0)
: MTPmessages_UpdateDialogFilter::Flag::f_filter),
MTP_int(newId),
tl);
if (removed) {
removeRequests.push_back(request);
const auto removeCommunityWithChats = removed
&& row.filter.community()
&& !row.removePeers.empty();
if (removeCommunityWithChats) {
auto inputs = ranges::views::all(
row.removePeers
) | ranges::views::transform([](not_null<PeerData*> peer) {
return MTPInputPeer(peer->input);
}) | ranges::to<QVector>();
removeCommunityRequests.push_back(
MTPcommunities_LeaveCommunity(
MTP_inputCommunityDialogFilter(MTP_int(newId)),
MTP_vector<MTPInputPeer>(std::move(inputs))));
} else {
addRequests.push_back(request);
order.push_back(newId);
const auto request = MTPmessages_UpdateDialogFilter(
MTP_flags(removed
? MTPmessages_UpdateDialogFilter::Flag(0)
: MTPmessages_UpdateDialogFilter::Flag::f_filter),
MTP_int(newId),
tl);
if (removed) {
removeRequests.push_back(request);
} else {
addRequests.push_back(request);
order.push_back(newId);
}
}
updates.push_back(MTP_updateDialogFilter(
MTP_flags(removed
@ -629,7 +725,8 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
order = std::move(order),
updates = std::move(updates),
addRequests = std::move(addRequests),
removeRequests = std::move(removeRequests)
removeRequests = std::move(removeRequests),
removeCommunityRequests = std::move(removeCommunityRequests)
] {
const auto api = &session->api();
const auto filters = &session->data().chatsFilters();
@ -646,18 +743,25 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
filters->apply(update);
}
auto previousId = mtpRequestId(0);
auto &&requests = ranges::views::concat(
removeRequests,
addRequests);
for (auto &request : requests) {
previousId = api->request(
std::move(request)
).done([=](const auto &, mtpRequestId id) {
ids->remove(id);
checkFinished();
}).afterRequest(previousId).send();
ids->emplace(previousId);
}
const auto sendRequests = [&](const auto &requests) {
for (auto &request : requests) {
previousId = api->request(
std::move(request)
).done([=](const auto &result, mtpRequestId id) {
if constexpr (std::is_same_v<
std::decay_t<decltype(result)>,
MTPUpdates>) {
session->api().applyUpdates(result);
}
ids->remove(id);
checkFinished();
}).afterRequest(previousId).send();
ids->emplace(previousId);
}
};
sendRequests(removeRequests);
sendRequests(removeCommunityRequests);
sendRequests(addRequests);
if (!order.empty() && !addRequests.empty()) {
filters->saveOrder(order, previousId);
}