mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added api support to moderation box.
This commit is contained in:
parent
643ecd2c2c
commit
629da68cfc
5 changed files with 182 additions and 49 deletions
|
@ -592,6 +592,33 @@ ChatParticipants::Parsed ChatParticipants::ParseRecent(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatParticipants::Restrict(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
not_null<PeerData*> participant,
|
||||||
|
ChatRestrictionsInfo oldRights,
|
||||||
|
ChatRestrictionsInfo newRights,
|
||||||
|
Fn<void()> onDone,
|
||||||
|
Fn<void()> 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<ChannelData*> channel) {
|
void ChatParticipants::requestSelf(not_null<ChannelData*> channel) {
|
||||||
if (_selfParticipantRequests.contains(channel)) {
|
if (_selfParticipantRequests.contains(channel)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -100,6 +100,13 @@ public:
|
||||||
static Parsed ParseRecent(
|
static Parsed ParseRecent(
|
||||||
not_null<ChannelData*> channel,
|
not_null<ChannelData*> channel,
|
||||||
const TLMembers &data);
|
const TLMembers &data);
|
||||||
|
static void Restrict(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
not_null<PeerData*> participant,
|
||||||
|
ChatRestrictionsInfo oldRights,
|
||||||
|
ChatRestrictionsInfo newRights,
|
||||||
|
Fn<void()> onDone,
|
||||||
|
Fn<void()> onFail);
|
||||||
void add(
|
void add(
|
||||||
std::shared_ptr<Ui::Show> show,
|
std::shared_ptr<Ui::Show> show,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
|
|
@ -7,15 +7,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "boxes/moderate_messages_box.h"
|
#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/delete_messages_box.h"
|
||||||
#include "boxes/peers/edit_peer_permissions_box.h"
|
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_chat.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_peer.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
#include "ui/controls/userpic_button.h"
|
#include "ui/controls/userpic_button.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/effects/toggle_arrow.h"
|
#include "ui/effects/toggle_arrow.h"
|
||||||
|
@ -167,12 +174,21 @@ QPoint Button::prepareRippleStartPosition() const {
|
||||||
|
|
||||||
void CreateModerateMessagesBox(
|
void CreateModerateMessagesBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
const HistoryItemsList &items) {
|
const HistoryItemsList &items,
|
||||||
|
Fn<void()> confirmed) {
|
||||||
|
using Users = std::vector<not_null<UserData*>>;
|
||||||
|
struct Controller final {
|
||||||
|
rpl::event_stream<bool> toggleRequestsFromTop;
|
||||||
|
rpl::event_stream<bool> toggleRequestsFromInner;
|
||||||
|
rpl::event_stream<bool> checkAllRequests;
|
||||||
|
Fn<Users()> collectRequests;
|
||||||
|
};
|
||||||
|
constexpr auto kSmallDelayMs = 5;
|
||||||
const auto options = CalculateModerateOptions(items);
|
const auto options = CalculateModerateOptions(items);
|
||||||
const auto inner = box->verticalLayout();
|
const auto inner = box->verticalLayout();
|
||||||
|
|
||||||
const auto users = [&] {
|
const auto users = [&] {
|
||||||
auto result = std::vector<not_null<UserData*>>();
|
auto result = Users();
|
||||||
for (const auto &item : items) {
|
for (const auto &item : items) {
|
||||||
if (const auto user = item->from()->asUser()) {
|
if (const auto user = item->from()->asUser()) {
|
||||||
if (!ranges::contains(result, not_null{ user })) {
|
if (!ranges::contains(result, not_null{ user })) {
|
||||||
|
@ -184,16 +200,59 @@ void CreateModerateMessagesBox(
|
||||||
}();
|
}();
|
||||||
Assert(!users.empty());
|
Assert(!users.empty());
|
||||||
|
|
||||||
|
const auto confirms = inner->lifetime().make_state<rpl::event_stream<>>();
|
||||||
|
|
||||||
const auto isSingle = users.size() == 1;
|
const auto isSingle = users.size() == 1;
|
||||||
const auto buttonPadding = isSingle
|
const auto buttonPadding = isSingle
|
||||||
? QMargins()
|
? QMargins()
|
||||||
: QMargins(0, 0, Button::ComputeSize(users.size()).width(), 0);
|
: QMargins(0, 0, Button::ComputeSize(users.size()).width(), 0);
|
||||||
|
|
||||||
struct Controller final {
|
using Request = Fn<void(not_null<UserData*>, not_null<ChannelData*>)>;
|
||||||
rpl::event_stream<bool> toggleRequestsFromTop;
|
const auto sequentiallyRequest = [=](Request request, Users users) {
|
||||||
rpl::event_stream<bool> toggleRequestsFromInner;
|
const auto session = &items.front()->history()->session();
|
||||||
rpl::event_stream<bool> checkAllRequests;
|
const auto history = items.front()->history();
|
||||||
|
const auto peerId = history->peer->id;
|
||||||
|
const auto userIds = ranges::views::all(
|
||||||
|
users
|
||||||
|
) | ranges::views::transform([](not_null<UserData*> user) {
|
||||||
|
return user->id;
|
||||||
|
}) | ranges::to_vector;
|
||||||
|
const auto lifetime = std::make_shared<rpl::lifetime>();
|
||||||
|
const auto counter = lifetime->make_state<int>(0);
|
||||||
|
const auto timer = lifetime->make_state<base::Timer>();
|
||||||
|
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<Ui::Checkbox*> checkbox,
|
||||||
|
not_null<Controller*> 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*> controller) {
|
const auto createUsersList = [&](not_null<Controller*> controller) {
|
||||||
const auto wrap = inner->add(
|
const auto wrap = inner->add(
|
||||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
@ -269,9 +328,21 @@ void CreateModerateMessagesBox(
|
||||||
c->setChecked(checked);
|
c->setChecked(checked);
|
||||||
}
|
}
|
||||||
}, container->lifetime());
|
}, 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<Ui::Checkbox*> checkbox) {
|
const auto appendList = [&](
|
||||||
|
not_null<Ui::Checkbox*> checkbox,
|
||||||
|
not_null<Controller*> controller) {
|
||||||
const auto button = Ui::CreateChild<Button>(inner, users.size());
|
const auto button = Ui::CreateChild<Button>(inner, users.size());
|
||||||
button->resize(Button::ComputeSize(users.size()));
|
button->resize(Button::ComputeSize(users.size()));
|
||||||
|
|
||||||
|
@ -289,7 +360,6 @@ void CreateModerateMessagesBox(
|
||||||
button->raise();
|
button->raise();
|
||||||
}, button->lifetime());
|
}, button->lifetime());
|
||||||
|
|
||||||
const auto controller = checkbox->lifetime().make_state<Controller>();
|
|
||||||
controller->toggleRequestsFromInner.events(
|
controller->toggleRequestsFromInner.events(
|
||||||
) | rpl::start_with_next([=](bool toggled) {
|
) | rpl::start_with_next([=](bool toggled) {
|
||||||
checkbox->setChecked(toggled);
|
checkbox->setChecked(toggled);
|
||||||
|
@ -326,9 +396,29 @@ void CreateModerateMessagesBox(
|
||||||
false,
|
false,
|
||||||
st::defaultBoxCheckbox),
|
st::defaultBoxCheckbox),
|
||||||
st::boxRowPadding + buttonPadding);
|
st::boxRowPadding + buttonPadding);
|
||||||
|
const auto controller = box->lifetime().make_state<Controller>();
|
||||||
if (!isSingle) {
|
if (!isSingle) {
|
||||||
appendList(report);
|
appendList(report, controller);
|
||||||
}
|
}
|
||||||
|
const auto ids = items.front()->from()->owner().itemsToIds(items);
|
||||||
|
handleConfirmation(report, controller, [=](
|
||||||
|
not_null<UserData*> u,
|
||||||
|
not_null<ChannelData*> c) {
|
||||||
|
auto filtered = QVector<MTPint>();
|
||||||
|
for (const auto &id : ids) {
|
||||||
|
if (const auto item = u->session().data().message(id)) {
|
||||||
|
if (item->from()->asUser() == u) {
|
||||||
|
filtered.push_back(MTP_int(item->fullId().msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u->session().api().request(
|
||||||
|
MTPchannels_ReportSpam(
|
||||||
|
c->inputChannel,
|
||||||
|
u->input,
|
||||||
|
MTP_vector<MTPint>(std::move(filtered)))
|
||||||
|
).send();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options & ModerateOption::DeleteAll) {
|
if (options & ModerateOption::DeleteAll) {
|
||||||
|
@ -350,9 +440,16 @@ void CreateModerateMessagesBox(
|
||||||
false,
|
false,
|
||||||
st::defaultBoxCheckbox),
|
st::defaultBoxCheckbox),
|
||||||
st::boxRowPadding + buttonPadding);
|
st::boxRowPadding + buttonPadding);
|
||||||
|
|
||||||
|
const auto controller = box->lifetime().make_state<Controller>();
|
||||||
if (!isSingle) {
|
if (!isSingle) {
|
||||||
appendList(deleteAll);
|
appendList(deleteAll, controller);
|
||||||
}
|
}
|
||||||
|
handleConfirmation(deleteAll, controller, [=](
|
||||||
|
not_null<UserData*> u,
|
||||||
|
not_null<ChannelData*> c) {
|
||||||
|
u->session().api().deleteAllFromParticipant(c, u);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (options & ModerateOption::Ban) {
|
if (options & ModerateOption::Ban) {
|
||||||
auto ownedWrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
auto ownedWrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
@ -374,8 +471,9 @@ void CreateModerateMessagesBox(
|
||||||
false,
|
false,
|
||||||
st::defaultBoxCheckbox),
|
st::defaultBoxCheckbox),
|
||||||
st::boxRowPadding + buttonPadding);
|
st::boxRowPadding + buttonPadding);
|
||||||
|
const auto controller = box->lifetime().make_state<Controller>();
|
||||||
if (!isSingle) {
|
if (!isSingle) {
|
||||||
appendList(ban);
|
appendList(ban, controller);
|
||||||
}
|
}
|
||||||
Ui::AddSkip(inner);
|
Ui::AddSkip(inner);
|
||||||
Ui::AddSkip(inner);
|
Ui::AddSkip(inner);
|
||||||
|
@ -410,8 +508,7 @@ void CreateModerateMessagesBox(
|
||||||
wrap->toggle(!wrap->toggled(), anim::type::normal);
|
wrap->toggle(!wrap->toggled(), anim::type::normal);
|
||||||
{
|
{
|
||||||
const auto start = crl::now();
|
const auto start = crl::now();
|
||||||
inner->heightValue(
|
inner->heightValue() | rpl::start_with_next([=] {
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
if (!wrap->animating()) {
|
if (!wrap->animating()) {
|
||||||
scrollLifetime->destroy();
|
scrollLifetime->destroy();
|
||||||
Ui::PostponeCall(crl::guard(box, [=] {
|
Ui::PostponeCall(crl::guard(box, [=] {
|
||||||
|
@ -471,20 +568,48 @@ void CreateModerateMessagesBox(
|
||||||
prepareFlags,
|
prepareFlags,
|
||||||
disabledMessages,
|
disabledMessages,
|
||||||
{ .isForum = peer->isForum() });
|
{ .isForum = peer->isForum() });
|
||||||
std::move(
|
std::move(changes) | rpl::start_with_next([=] {
|
||||||
changes
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
ban->setChecked(true);
|
ban->setChecked(true);
|
||||||
}, ban->lifetime());
|
}, ban->lifetime());
|
||||||
Ui::AddSkip(container);
|
Ui::AddSkip(container);
|
||||||
Ui::AddDivider(container);
|
Ui::AddDivider(container);
|
||||||
Ui::AddSkip(container);
|
Ui::AddSkip(container);
|
||||||
container->add(std::move(checkboxes));
|
container->add(std::move(checkboxes));
|
||||||
}
|
|
||||||
Ui::AddSkip(inner);
|
|
||||||
|
|
||||||
box->addButton(tr::lng_box_delete(), [=] { box->closeBox(); });
|
handleConfirmation(ban, controller, [=](
|
||||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
not_null<UserData*> user,
|
||||||
|
not_null<ChannelData*> channel) {
|
||||||
|
if (wrap->toggled()) {
|
||||||
|
Api::ChatParticipants::Restrict(
|
||||||
|
channel,
|
||||||
|
user,
|
||||||
|
ChatRestrictionsInfo(), // Unused.
|
||||||
|
ChatRestrictionsInfo(getRestrictions(), 0),
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
} else {
|
||||||
|
channel->session().api().chatParticipants().kick(
|
||||||
|
channel,
|
||||||
|
user,
|
||||||
|
{ channel->restrictions(), 0 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto close = crl::guard(box, [=] { box->closeBox(); });
|
||||||
|
box->addButton(tr::lng_box_delete(), [=] {
|
||||||
|
confirms->fire({});
|
||||||
|
box->closeBox();
|
||||||
|
const auto data = &users.front()->session().data();
|
||||||
|
const auto ids = data->itemsToIds(items);
|
||||||
|
if (confirmed) {
|
||||||
|
confirmed();
|
||||||
|
}
|
||||||
|
data->histories().deleteMessages(ids, true);
|
||||||
|
data->sendHistoryChangeNotifications();
|
||||||
|
close();
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), close);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanCreateModerateMessagesBox(const HistoryItemsList &items) {
|
bool CanCreateModerateMessagesBox(const HistoryItemsList &items) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ class GenericBox;
|
||||||
|
|
||||||
void CreateModerateMessagesBox(
|
void CreateModerateMessagesBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
const HistoryItemsList &items);
|
const HistoryItemsList &items,
|
||||||
|
Fn<void()> confirmed);
|
||||||
|
|
||||||
[[nodiscard]] bool CanCreateModerateMessagesBox(const HistoryItemsList &);
|
[[nodiscard]] bool CanCreateModerateMessagesBox(const HistoryItemsList &);
|
||||||
|
|
|
@ -166,33 +166,6 @@ void SaveChannelAdmin(
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveChannelRestriction(
|
|
||||||
not_null<ChannelData*> channel,
|
|
||||||
not_null<PeerData*> participant,
|
|
||||||
ChatRestrictionsInfo oldRights,
|
|
||||||
ChatRestrictionsInfo newRights,
|
|
||||||
Fn<void()> onDone,
|
|
||||||
Fn<void()> 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 SaveChatParticipantKick(
|
void SaveChatParticipantKick(
|
||||||
not_null<ChatData*> chat,
|
not_null<ChatData*> chat,
|
||||||
not_null<UserData*> user,
|
not_null<UserData*> user,
|
||||||
|
@ -275,7 +248,7 @@ Fn<void(
|
||||||
ChatRestrictionsInfo newRights) {
|
ChatRestrictionsInfo newRights) {
|
||||||
const auto done = [=] { if (onDone) onDone(newRights); };
|
const auto done = [=] { if (onDone) onDone(newRights); };
|
||||||
const auto saveForChannel = [=](not_null<ChannelData*> channel) {
|
const auto saveForChannel = [=](not_null<ChannelData*> channel) {
|
||||||
SaveChannelRestriction(
|
Api::ChatParticipants::Restrict(
|
||||||
channel,
|
channel,
|
||||||
participant,
|
participant,
|
||||||
oldRights,
|
oldRights,
|
||||||
|
|
Loading…
Add table
Reference in a new issue