From 4c1213ce9e5ad19e1e8eca2784ff1579bb843eb8 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 17 Sep 2020 16:26:53 +0300 Subject: [PATCH] Allow blocking users from Replies chat. --- Telegram/Resources/langs/lang.strings | 4 +- Telegram/SourceFiles/boxes/confirm_box.cpp | 48 +------------- Telegram/SourceFiles/boxes/report_box.cpp | 21 ++++++ Telegram/SourceFiles/boxes/report_box.h | 10 +++ Telegram/SourceFiles/data/data_histories.cpp | 51 +++++++++++++++ Telegram/SourceFiles/data/data_histories.h | 2 + .../history/history_inner_widget.cpp | 38 ++++++++++- .../history/history_inner_widget.h | 2 + .../view/history_view_contact_status.cpp | 8 ++- .../view/history_view_replies_section.cpp | 18 ++++- .../info/profile/info_profile_actions.cpp | 2 +- .../SourceFiles/window/window_peer_menu.cpp | 65 ++++++++++++------- .../SourceFiles/window/window_peer_menu.h | 8 ++- 13 files changed, 195 insertions(+), 82 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3176ed87a..fb96812e0 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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"; diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp index afccdd719..b7c196c89 100644 --- a/Telegram/SourceFiles/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/boxes/confirm_box.cpp @@ -808,53 +808,7 @@ void DeleteMessagesBox::deleteAndClear() { _deleteConfirmedCallback(); } - auto remove = std::vector>(); - remove.reserve(_ids.size()); - base::flat_map, QVector> idsByPeer; - base::flat_map, QVector> 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(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(); diff --git a/Telegram/SourceFiles/boxes/report_box.cpp b/Telegram/SourceFiles/boxes/report_box.cpp index 4d6cb79a1..280f6f2d7 100644 --- a/Telegram/SourceFiles/boxes/report_box.cpp +++ b/Telegram/SourceFiles/boxes/report_box.cpp @@ -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 box, + not_null 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)); +} diff --git a/Telegram/SourceFiles/boxes/report_box.h b/Telegram/SourceFiles/boxes/report_box.h index 238ebfe3c..f8cd90a43 100644 --- a/Telegram/SourceFiles/boxes/report_box.h +++ b/Telegram/SourceFiles/boxes/report_box.h @@ -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 class RadioenumGroup; @@ -60,3 +65,8 @@ private: mtpRequestId _requestId = 0; }; + +void BlockSenderFromRepliesBox( + not_null box, + not_null controller, + MessageIdsList ids); diff --git a/Telegram/SourceFiles/data/data_histories.cpp b/Telegram/SourceFiles/data/data_histories.cpp index 05c54ff15..69ba4ddbc 100644 --- a/Telegram/SourceFiles/data/data_histories.cpp +++ b/Telegram/SourceFiles/data/data_histories.cpp @@ -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>(); + remove.reserve(ids.size()); + base::flat_map, QVector> idsByPeer; + base::flat_map, QVector> 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(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, RequestType type, diff --git a/Telegram/SourceFiles/data/data_histories.h b/Telegram/SourceFiles/data/data_histories.h index ba9f6459d..2d9514357 100644 --- a/Telegram/SourceFiles/data/data_histories.h +++ b/Telegram/SourceFiles/data/data_histories.h @@ -70,6 +70,8 @@ public: bool justClear, bool revoke); + void deleteMessages(const MessageIdsList &ids, bool revoke); + int sendRequest( not_null history, RequestType type, diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 5755342ca..bc9e2a5c3 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -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(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 toItems, not_null history, diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 89aa3d2a6..d58de44e1 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -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. diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp index a198b66ef..83cdd774c 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp @@ -324,8 +324,12 @@ void ContactStatus::setupAddHandler(not_null user) { void ContactStatus::setupBlockHandler(not_null 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()); } diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index f0cfb57d6..88a1caad1 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -1278,7 +1278,23 @@ void RepliesWidget::restoreState(not_null 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)); diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 711247cf6..c843d4e7b 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -631,7 +631,7 @@ void ActionsFiller::addBlockAction(not_null 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( diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 7bf04e536..9cd84a77a 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -437,7 +437,7 @@ void Filler::addBlockUser(not_null 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 box, not_null window, - not_null user, - bool suggestClearChat) { + not_null peer, + std::variant suggestReport, + std::variant 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(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( + box, + tr::lng_blocked_list_confirm_text( + lt_name, + rpl::single(Ui::Text::Bold(name)), + Ui::Text::WithEntities), + st::blockUserConfirmation)); - box->addRow(object_ptr( - 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( 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(suggestClear) ? box->addRow(object_ptr( box, tr::lng_blocked_list_confirm_clear(tr::now), true, st::defaultBoxCheckbox)) + : v::is(suggestClear) + ? box->addRow(object_ptr( + 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(&suggestClear)) { + peer->owner().histories().deleteMessages(*ids, false); + } else if (v::is(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(), [=] { diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 3268ffcbf..e64fb072c 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -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 box, not_null window, - not_null user, - bool suggestClearChat); + not_null peer, + std::variant suggestReport, + std::variant suggestClear); void PeerMenuUnblockUserWithBotRestart(not_null user); void ToggleHistoryArchived(not_null history, bool archived);