From 629da68cfcb69a4f0c03598659e7ef59b0a5d2f1 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 26 Apr 2024 02:47:39 +0300 Subject: [PATCH] Added api support to moderation box. --- .../SourceFiles/api/api_chat_participants.cpp | 27 +++ .../SourceFiles/api/api_chat_participants.h | 7 + .../boxes/moderate_messages_box.cpp | 165 +++++++++++++++--- .../SourceFiles/boxes/moderate_messages_box.h | 3 +- .../boxes/peers/edit_participants_box.cpp | 29 +-- 5 files changed, 182 insertions(+), 49 deletions(-) diff --git a/Telegram/SourceFiles/api/api_chat_participants.cpp b/Telegram/SourceFiles/api/api_chat_participants.cpp index d1c8650d3..a4cd0c367 100644 --- a/Telegram/SourceFiles/api/api_chat_participants.cpp +++ b/Telegram/SourceFiles/api/api_chat_participants.cpp @@ -592,6 +592,33 @@ ChatParticipants::Parsed ChatParticipants::ParseRecent( return result; } +void ChatParticipants::Restrict( + not_null channel, + not_null participant, + ChatRestrictionsInfo oldRights, + ChatRestrictionsInfo newRights, + Fn onDone, + Fn onFail) { + channel->session().api().request(MTPchannels_EditBanned( + channel->inputChannel, + participant->input, + MTP_chatBannedRights( + MTP_flags(MTPDchatBannedRights::Flags::from_raw( + uint32(newRights.flags))), + MTP_int(newRights.until)) + )).done([=](const MTPUpdates &result) { + channel->session().api().applyUpdates(result); + channel->applyEditBanned(participant, oldRights, newRights); + if (onDone) { + onDone(); + } + }).fail([=] { + if (onFail) { + onFail(); + } + }).send(); +} + void ChatParticipants::requestSelf(not_null channel) { if (_selfParticipantRequests.contains(channel)) { return; diff --git a/Telegram/SourceFiles/api/api_chat_participants.h b/Telegram/SourceFiles/api/api_chat_participants.h index fbab3f425..ad5aa930f 100644 --- a/Telegram/SourceFiles/api/api_chat_participants.h +++ b/Telegram/SourceFiles/api/api_chat_participants.h @@ -100,6 +100,13 @@ public: static Parsed ParseRecent( not_null channel, const TLMembers &data); + static void Restrict( + not_null channel, + not_null participant, + ChatRestrictionsInfo oldRights, + ChatRestrictionsInfo newRights, + Fn onDone, + Fn onFail); void add( std::shared_ptr show, not_null peer, diff --git a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp index 49d436700..a06fff512 100644 --- a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp +++ b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp @@ -7,15 +7,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/moderate_messages_box.h" +#include "api/api_chat_participants.h" +#include "apiwrap.h" +#include "base/timer.h" #include "boxes/delete_messages_box.h" #include "boxes/peers/edit_peer_permissions_box.h" #include "data/data_channel.h" #include "data/data_chat.h" +#include "data/data_chat_participant_status.h" +#include "data/data_histories.h" #include "data/data_peer.h" +#include "data/data_session.h" #include "data/data_user.h" #include "history/history.h" #include "history/history_item.h" #include "lang/lang_keys.h" +#include "main/main_session.h" #include "ui/controls/userpic_button.h" #include "ui/effects/ripple_animation.h" #include "ui/effects/toggle_arrow.h" @@ -167,12 +174,21 @@ QPoint Button::prepareRippleStartPosition() const { void CreateModerateMessagesBox( not_null box, - const HistoryItemsList &items) { + const HistoryItemsList &items, + Fn confirmed) { + using Users = std::vector>; + struct Controller final { + rpl::event_stream toggleRequestsFromTop; + rpl::event_stream toggleRequestsFromInner; + rpl::event_stream checkAllRequests; + Fn collectRequests; + }; + constexpr auto kSmallDelayMs = 5; const auto options = CalculateModerateOptions(items); const auto inner = box->verticalLayout(); const auto users = [&] { - auto result = std::vector>(); + auto result = Users(); for (const auto &item : items) { if (const auto user = item->from()->asUser()) { if (!ranges::contains(result, not_null{ user })) { @@ -184,16 +200,59 @@ void CreateModerateMessagesBox( }(); Assert(!users.empty()); + const auto confirms = inner->lifetime().make_state>(); + const auto isSingle = users.size() == 1; const auto buttonPadding = isSingle ? QMargins() : QMargins(0, 0, Button::ComputeSize(users.size()).width(), 0); - struct Controller final { - rpl::event_stream toggleRequestsFromTop; - rpl::event_stream toggleRequestsFromInner; - rpl::event_stream checkAllRequests; + using Request = Fn, not_null)>; + const auto sequentiallyRequest = [=](Request request, Users users) { + const auto session = &items.front()->history()->session(); + const auto history = items.front()->history(); + const auto peerId = history->peer->id; + const auto userIds = ranges::views::all( + users + ) | ranges::views::transform([](not_null user) { + return user->id; + }) | ranges::to_vector; + const auto lifetime = std::make_shared(); + const auto counter = lifetime->make_state(0); + const auto timer = lifetime->make_state(); + timer->setCallback(crl::guard(session, [=] { + if ((*counter) < userIds.size()) { + const auto peer = session->data().peer(peerId); + const auto channel = peer ? peer->asChannel() : nullptr; + const auto from = session->data().peer(userIds[*counter]); + if (const auto user = from->asUser(); channel && user) { + request(user, channel); + } + (*counter)++; + } else { + lifetime->destroy(); + } + })); + timer->callEach(kSmallDelayMs); }; + + const auto handleConfirmation = [=]( + not_null checkbox, + not_null controller, + Request request) { + confirms->events() | rpl::start_with_next([=] { + if (checkbox->checked()) { + if (isSingle) { + const auto item = items.front(); + const auto channel = item->history()->peer->asChannel(); + request(users.front(), channel); + } else if (const auto collect = controller->collectRequests) { + sequentiallyRequest(request, collect()); + } + } + }, checkbox->lifetime()); + }; + const auto createUsersList = [&](not_null controller) { const auto wrap = inner->add( object_ptr>( @@ -269,9 +328,21 @@ void CreateModerateMessagesBox( c->setChecked(checked); } }, container->lifetime()); + + controller->collectRequests = [=] { + auto result = Users(); + for (auto i = 0; i < checkboxes.size(); i++) { + if (checkboxes[i]->checked()) { + result.push_back(users[i]); + } + } + return result; + }; }; - const auto appendList = [&](not_null checkbox) { + const auto appendList = [&]( + not_null checkbox, + not_null controller) { const auto button = Ui::CreateChild