Allow blocking users from Replies chat.

This commit is contained in:
John Preston 2020-09-17 16:26:53 +03:00
parent afbc0c498f
commit 4c1213ce9e
13 changed files with 195 additions and 82 deletions

View File

@ -1350,10 +1350,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_replies_view_thread" = "View Thread";
"lng_replies_header#one" = "{count} reply";
"lng_replies_header#other" = "{count} replies";
"lng_replies_header_none" = "No replies";
"lng_replies_header_none" = "Replies";
"lng_comments_header#one" = "{count} comment";
"lng_comments_header#other" = "{count} comments";
"lng_comments_header_none" = "No comments";
"lng_comments_header_none" = "Comments";
"lng_comments_open_count#one" = "{count} comment";
"lng_comments_open_count#other" = "{count} comments";
"lng_comments_open_none" = "Leave a comment";

View File

@ -808,53 +808,7 @@ void DeleteMessagesBox::deleteAndClear() {
_deleteConfirmedCallback();
}
auto remove = std::vector<not_null<HistoryItem*>>();
remove.reserve(_ids.size());
base::flat_map<not_null<History*>, QVector<MTPint>> idsByPeer;
base::flat_map<not_null<PeerData*>, QVector<MTPint>> scheduledIdsByPeer;
for (const auto itemId : _ids) {
if (const auto item = _session->data().message(itemId)) {
const auto history = item->history();
if (item->isScheduled()) {
const auto wasOnServer = !item->isSending()
&& !item->hasFailed();
if (wasOnServer) {
scheduledIdsByPeer[history->peer].push_back(MTP_int(
_session->data().scheduledMessages().lookupId(item)));
} else {
_session->data().scheduledMessages().removeSending(item);
}
continue;
}
remove.push_back(item);
if (IsServerMsgId(item->id)) {
idsByPeer[history].push_back(MTP_int(itemId.msg));
}
}
}
for (const auto &[history, ids] : idsByPeer) {
history->owner().histories().deleteMessages(history, ids, revoke);
}
for (const auto &[peer, ids] : scheduledIdsByPeer) {
peer->session().api().request(MTPmessages_DeleteScheduledMessages(
peer->input,
MTP_vector<MTPint>(ids)
)).done([peer=peer](const MTPUpdates &result) {
peer->session().api().applyUpdates(result);
}).send();
}
for (const auto item : remove) {
const auto history = item->history();
const auto wasLast = (history->lastMessage() == item);
const auto wasInChats = (history->chatListMessage() == item);
item->destroy();
if (wasLast || wasInChats) {
history->requestChatListMessage();
}
}
_session->data().histories().deleteMessages(_ids, revoke);
const auto session = _session;
Ui::hideLayer();

View File

@ -9,8 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "boxes/confirm_box.h"
#include "history/history_item.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
@ -18,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "core/core_settings.h"
#include "core/application.h"
#include "window/window_session_controller.h"
#include "window/window_peer_menu.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_profile.h"
@ -207,3 +211,20 @@ void ReportBox::updateMaxHeight() {
}
setDimensions(st::boxWidth, newHeight);
}
void BlockSenderFromRepliesBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
MessageIdsList ids) {
Expects(!ids.empty());
const auto item = controller->session().data().message(ids.front());
Assert(item != nullptr);
PeerMenuBlockUserBox(
box,
&controller->window(),
item->senderOriginal(),
true,
std::move(ids));
}

View File

@ -8,8 +8,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/generic_box.h"
#include "mtproto/sender.h"
namespace Window {
class SessionController;
} // namespace Window
namespace Ui {
template <typename Enum>
class RadioenumGroup;
@ -60,3 +65,8 @@ private:
mtpRequestId _requestId = 0;
};
void BlockSenderFromRepliesBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
MessageIdsList ids);

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_channel.h"
#include "data/data_folder.h"
#include "data/data_scheduled_messages.h"
#include "main/main_session.h"
#include "window/notifications_manager.h"
#include "history/history.h"
@ -624,6 +625,56 @@ void Histories::deleteAllMessages(
});
}
void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) {
auto remove = std::vector<not_null<HistoryItem*>>();
remove.reserve(ids.size());
base::flat_map<not_null<History*>, QVector<MTPint>> idsByPeer;
base::flat_map<not_null<PeerData*>, QVector<MTPint>> scheduledIdsByPeer;
for (const auto itemId : ids) {
if (const auto item = _owner->message(itemId)) {
const auto history = item->history();
if (item->isScheduled()) {
const auto wasOnServer = !item->isSending()
&& !item->hasFailed();
if (wasOnServer) {
scheduledIdsByPeer[history->peer].push_back(MTP_int(
_owner->scheduledMessages().lookupId(item)));
} else {
_owner->scheduledMessages().removeSending(item);
}
continue;
}
remove.push_back(item);
if (IsServerMsgId(item->id)) {
idsByPeer[history].push_back(MTP_int(itemId.msg));
}
}
}
for (const auto &[history, ids] : idsByPeer) {
history->owner().histories().deleteMessages(history, ids, revoke);
}
for (const auto &[peer, ids] : scheduledIdsByPeer) {
peer->session().api().request(MTPmessages_DeleteScheduledMessages(
peer->input,
MTP_vector<MTPint>(ids)
)).done([peer = peer](const MTPUpdates &result) {
peer->session().api().applyUpdates(result);
}).send();
}
for (const auto item : remove) {
const auto history = item->history();
const auto wasLast = (history->lastMessage() == item);
const auto wasInChats = (history->chatListMessage() == item);
item->destroy();
if (wasLast || wasInChats) {
history->requestChatListMessage();
}
}
}
int Histories::sendRequest(
not_null<History*> history,
RequestType type,

View File

@ -70,6 +70,8 @@ public:
bool justClear,
bool revoke);
void deleteMessages(const MessageIdsList &ids, bool revoke);
int sendRequest(
not_null<History*> history,
RequestType type,

View File

@ -1666,6 +1666,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
});
} else if (item) {
const auto itemId = item->fullId();
const auto blockSender = item->history()->peer->isRepliesChat();
if (isUponSelected != -2) {
if (item->allowsForward()) {
_menu->addAction(tr::lng_context_forward_msg(tr::now), [=] {
@ -1677,7 +1678,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
deleteItem(itemId);
});
}
if (item->suggestReport()) {
if (!blockSender && item->suggestReport()) {
_menu->addAction(tr::lng_context_report_msg(tr::now), [=] {
reportItem(itemId);
});
@ -1694,6 +1695,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
});
}
if (isUponSelected != -2 && blockSender) {
_menu->addAction(tr::lng_profile_block_user(tr::now), [=] {
blockSenderItem(itemId);
});
}
}
} else { // maybe cursor on some text history item?
const auto item = [&]() -> HistoryItem* {
@ -1715,6 +1721,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
&& (item->id > 0 || !item->serviceMsg());
const auto canForward = item && item->allowsForward();
const auto canReport = item && item->suggestReport();
const auto canBlockSender = item && item->history()->peer->isRepliesChat();
const auto view = item ? item->mainView() : nullptr;
const auto msg = dynamic_cast<HistoryMessage*>(item);
@ -1814,7 +1821,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
deleteAsGroup(itemId);
});
}
if (canReport) {
if (!canBlockSender && canReport) {
_menu->addAction(tr::lng_context_report_msg(tr::now), [=] {
reportAsGroup(itemId);
});
@ -1831,6 +1838,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
});
}
if (isUponSelected != -2 && canBlockSender) {
_menu->addAction(tr::lng_profile_block_user(tr::now), [=] {
blockSenderAsGroup(itemId);
});
}
} else {
if (App::mousedItem()
&& IsServerMsgId(App::mousedItem()->data()->id)
@ -3160,6 +3172,28 @@ void HistoryInner::reportAsGroup(FullMsgId itemId) {
}
}
void HistoryInner::blockSenderItem(FullMsgId itemId) {
if (const auto item = session().data().message(itemId)) {
Ui::show(Box(
BlockSenderFromRepliesBox,
_controller,
MessageIdsList(1, itemId)));
}
}
void HistoryInner::blockSenderAsGroup(FullMsgId itemId) {
if (const auto item = session().data().message(itemId)) {
const auto group = session().data().groups().find(item);
if (!group) {
return blockSenderItem(itemId);
}
Ui::show(Box(
BlockSenderFromRepliesBox,
_controller,
session().data().itemsToIds(group->items)));
}
}
void HistoryInner::addSelectionRange(
not_null<SelectedItems*> toItems,
not_null<History*> history,

View File

@ -306,6 +306,8 @@ private:
void deleteAsGroup(FullMsgId itemId);
void reportItem(FullMsgId itemId);
void reportAsGroup(FullMsgId itemId);
void blockSenderItem(FullMsgId itemId);
void blockSenderAsGroup(FullMsgId itemId);
void copySelectedText();
// Does any of the shown histories has this flag set.

View File

@ -324,8 +324,12 @@ void ContactStatus::setupAddHandler(not_null<UserData*> user) {
void ContactStatus::setupBlockHandler(not_null<UserData*> user) {
_bar.entity()->blockClicks(
) | rpl::start_with_next([=] {
_controller->window().show(
Box(Window::PeerMenuBlockUserBox, &_controller->window(), user, true));
_controller->window().show(Box(
Window::PeerMenuBlockUserBox,
&_controller->window(),
user,
v::null,
Window::ClearChat{}));
}, _bar.lifetime());
}

View File

@ -1278,7 +1278,23 @@ void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
updatePinnedVisibility();
}, lifetime());
_topBar->setCustomTitle(tr::lng_manage_discussion_group(tr::now));
rpl::combine(
rpl::single(0) | rpl::then(_replies->fullCount()),
_areComments.value()
) | rpl::map([=](int count, bool areComments) {
return count
? (areComments
? tr::lng_comments_header
: tr::lng_replies_header)(
lt_count,
rpl::single(count) | tr::to_count())
: (areComments
? tr::lng_comments_header_none
: tr::lng_replies_header_none)();
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const QString &text) {
_topBar->setCustomTitle(text);
}, lifetime());
};
if (auto replies = memento->getReplies()) {
setReplies(std::move(replies));

View File

@ -631,7 +631,7 @@ void ActionsFiller::addBlockAction(not_null<UserData*> user) {
user->session().api().blockPeer(user);
} else {
window->show(
Box(Window::PeerMenuBlockUserBox, window, user, false));
Box(Window::PeerMenuBlockUserBox, window, user, v::null, v::null));
}
};
AddActionButton(

View File

@ -437,7 +437,7 @@ void Filler::addBlockUser(not_null<UserData*> user) {
} else if (user->isBot()) {
user->session().api().blockPeer(user);
} else {
window->show(Box(PeerMenuBlockUserBox, window, user, false));
window->show(Box(PeerMenuBlockUserBox, window, user, v::null, v::null));
}
});
@ -851,24 +851,29 @@ void PeerMenuCreatePoll(
void PeerMenuBlockUserBox(
not_null<Ui::GenericBox*> box,
not_null<Window::Controller*> window,
not_null<UserData*> user,
bool suggestClearChat) {
not_null<PeerData*> peer,
std::variant<v::null_t, bool> suggestReport,
std::variant<v::null_t, ClearChat, MessageIdsList> suggestClear) {
using Flag = MTPDpeerSettings::Flag;
const auto settings = user->settings().value_or(Flag(0));
const auto settings = peer->settings().value_or(Flag(0));
const auto reportNeeded = v::is_null(suggestReport)
? ((settings & Flag::f_report_spam) != 0)
: v::get<bool>(suggestReport);
const auto name = user->shortName();
const auto user = peer->asUser();
const auto name = user ? user->shortName() : peer->name;
if (user) {
box->addRow(object_ptr<Ui::FlatLabel>(
box,
tr::lng_blocked_list_confirm_text(
lt_name,
rpl::single(Ui::Text::Bold(name)),
Ui::Text::WithEntities),
st::blockUserConfirmation));
box->addRow(object_ptr<Ui::FlatLabel>(
box,
tr::lng_blocked_list_confirm_text(
lt_name,
rpl::single(Ui::Text::Bold(name)),
Ui::Text::WithEntities),
st::blockUserConfirmation));
box->addSkip(st::boxMediumSkip);
const auto report = (settings & Flag::f_report_spam)
box->addSkip(st::boxMediumSkip);
}
const auto report = reportNeeded
? box->addRow(object_ptr<Ui::Checkbox>(
box,
tr::lng_report_spam(tr::now),
@ -880,12 +885,18 @@ void PeerMenuBlockUserBox(
box->addSkip(st::boxMediumSkip);
}
const auto clear = suggestClearChat
const auto clear = v::is<ClearChat>(suggestClear)
? box->addRow(object_ptr<Ui::Checkbox>(
box,
tr::lng_blocked_list_confirm_clear(tr::now),
true,
st::defaultBoxCheckbox))
: v::is<MessageIdsList>(suggestClear)
? box->addRow(object_ptr<Ui::Checkbox>(
box,
tr::lng_context_delete_msg(tr::now),
true,
st::defaultBoxCheckbox))
: nullptr;
if (report || clear) {
@ -902,21 +913,25 @@ void PeerMenuBlockUserBox(
box->closeBox();
user->session().api().blockPeer(user);
peer->session().api().blockPeer(peer);
if (reportChecked) {
user->session().api().request(MTPmessages_ReportSpam(
user->input
peer->session().api().request(MTPmessages_ReportSpam(
peer->input
)).send();
}
if (clearChecked) {
crl::on_main(&user->session(), [=] {
user->session().api().deleteConversation(user, false);
});
window->sessionController()->showBackFromStack();
if (const auto ids = std::get_if<MessageIdsList>(&suggestClear)) {
peer->owner().histories().deleteMessages(*ids, false);
} else if (v::is<ClearChat>(suggestClear)) {
crl::on_main(&peer->session(), [=] {
peer->session().api().deleteConversation(peer, false);
});
window->sessionController()->showBackFromStack();
}
}
Ui::Toast::Show(
tr::lng_new_contact_block_done(tr::now, lt_user, user->shortName()));
tr::lng_new_contact_block_done(tr::now, lt_user, name));
}, st::attentionBoxButton);
box->addButton(tr::lng_cancel(), [=] {

View File

@ -69,11 +69,15 @@ void PeerMenuCreatePoll(
PollData::Flags chosen = PollData::Flags(),
PollData::Flags disabled = PollData::Flags(),
Api::SendType sendType = Api::SendType::Normal);
struct ClearChat {
};
void PeerMenuBlockUserBox(
not_null<Ui::GenericBox*> box,
not_null<Window::Controller*> window,
not_null<UserData*> user,
bool suggestClearChat);
not_null<PeerData*> peer,
std::variant<v::null_t, bool> suggestReport,
std::variant<v::null_t, ClearChat, MessageIdsList> suggestClear);
void PeerMenuUnblockUserWithBotRestart(not_null<UserData*> user);
void ToggleHistoryArchived(not_null<History*> history, bool archived);