From aca3ec0ab8d1a599f7377d48de3c020bffdd0c52 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 11 Jun 2019 16:31:52 +0200 Subject: [PATCH] Implement block + clear from ContactStatus bar. --- Telegram/Resources/langs/lang.strings | 7 +- Telegram/SourceFiles/boxes/boxes.style | 5 + Telegram/SourceFiles/boxes/generic_box.cpp | 25 ++++ Telegram/SourceFiles/boxes/generic_box.h | 140 ++++++++++++++++++ .../boxes/peers/add_to_contacts_box.cpp | 11 +- Telegram/SourceFiles/data/data_user.cpp | 5 + .../view/history_view_contact_status.cpp | 121 +++++++++++++-- .../view/history_view_contact_status.h | 6 +- Telegram/gyp/telegram_sources.txt | 2 + 9 files changed, 300 insertions(+), 22 deletions(-) create mode 100644 Telegram/SourceFiles/boxes/generic_box.cpp create mode 100644 Telegram/SourceFiles/boxes/generic_box.h diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index ab7450ff4..e4c35a957 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -598,6 +598,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_blocked_list_already_blocked" = "blocked already"; "lng_blocked_list_about" = "Blocked users can't send you messages or add you to groups. They will not see your profile pictures, online and last seen status."; "lng_blocked_list_not_found" = "No users found."; +"lng_blocked_list_confirm_title" = "Block {name}"; +"lng_blocked_list_confirm_text" = "Do you want to block {name} from messaging and calling you on Telegram?"; +"lng_blocked_list_confirm_clear" = "Delete this chat"; +"lng_blocked_list_confirm_ok" = "Block"; "lng_edit_privacy_everyone" = "Everybody"; "lng_edit_privacy_contacts" = "My contacts"; @@ -1411,7 +1415,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_contact_phone" = "Phone Number"; "lng_enter_contact_data" = "New Contact"; "lng_contact_mobile_hidden" = "Mobile hidden"; -"lng_contact_phone_after" = "Phone number will be visible once {user} adds you as a contact. Your phone number will become visible to {name}."; +"lng_contact_phone_after" = "Phone number will be visible once {user} adds you as a contact. Your phone number will become {visible} to {name}."; +"lng_contact_phone_visible" = "visible"; "lng_contact_phone_show" = "When you click {button}, your phone number will become visible to {user}."; "lng_edit_contact_title" = "Edit contact name"; "lng_edit_channel_title" = "Edit channel"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 2d98862e2..b39ed0c41 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -90,6 +90,8 @@ boxLayerTitleAdditionalSkip: 9px; boxLayerTitleAdditionalFont: normalFont; boxLayerScroll: defaultSolidScroll; +boxRowPadding: margins(23px, 0px, 23px, 0px); + boxTopMargin: 6px; boxTitleClose: IconButton(defaultIconButton) { @@ -980,3 +982,6 @@ linkedChatAboutPadding: margins(20px, 20px, 20px, 20px); addContactFieldMargin: margins(19px, 0px, 19px, 10px); addContactWarningMargin: margins(19px, 10px, 19px, 5px); +blockUserConfirmation: FlatLabel(boxLabel) { + minWidth: 240px; +} diff --git a/Telegram/SourceFiles/boxes/generic_box.cpp b/Telegram/SourceFiles/boxes/generic_box.cpp new file mode 100644 index 000000000..0e49abcbb --- /dev/null +++ b/Telegram/SourceFiles/boxes/generic_box.cpp @@ -0,0 +1,25 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "boxes/generic_box.h" + +#include "ui/wrap/vertical_layout.h" +#include "ui/wrap/padding_wrap.h" +#include "ui/wrap/wrap.h" +#include "styles/style_boxes.h" + +void GenericBox::prepare() { + _init(this); + + auto wrap = object_ptr(this, std::move(_content)); + setDimensionsToContent(_width ? _width : st::boxWidth, wrap.data()); + setInnerWidget(std::move(wrap)); +} + +void GenericBox::addSkip(int height) { + addRow(object_ptr(this, height)); +} diff --git a/Telegram/SourceFiles/boxes/generic_box.h b/Telegram/SourceFiles/boxes/generic_box.h new file mode 100644 index 000000000..317bc4908 --- /dev/null +++ b/Telegram/SourceFiles/boxes/generic_box.h @@ -0,0 +1,140 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "boxes/abstract_box.h" +#include "ui/wrap/vertical_layout.h" + +#include + +namespace st { +extern const style::margins &boxRowPadding; +} // namespace st + +class GenericBox : public BoxContent { +public: + // InitMethod::operator()(not_null box, InitArgs...) + // init(box, args...) + template < + typename InitMethod, + typename ...InitArgs, + typename = decltype(std::declval>()( + std::declval>(), + std::declval>()...))> + GenericBox( + QWidget*, + InitMethod &&init, + InitArgs &&...args); + + void setWidth(int width) { + _width = width; + } + + int rowsCount() const { + return _content->count(); + } + + template < + typename Widget, + typename = std::enable_if_t< + std::is_base_of_v>> + Widget *insertRow( + int atPosition, + object_ptr &&child, + const style::margins &margin = st::boxRowPadding) { + return _content->insert( + atPosition, + std::move(child), + margin); + } + + template < + typename Widget, + typename = std::enable_if_t< + std::is_base_of_v>> + Widget *addRow( + object_ptr &&child, + const style::margins &margin = st::boxRowPadding) { + return _content->add(std::move(child), margin); + } + + void addSkip(int height); + +protected: + void prepare() override; + +private: + template + struct Initer { + template + Initer(OtherMethod &&method, OtherArgs &&...args); + + void operator()(not_null box); + + template + void call( + not_null box, + std::index_sequence); + + InitMethod method; + std::tuple args; + }; + + template + auto MakeIniter(InitMethod &&method, InitArgs &&...args) + -> Initer, std::decay_t...>; + + FnMut)> _init; + object_ptr _content; + int _width = 0; + +}; + +template +template +GenericBox::Initer::Initer( + OtherMethod &&method, + OtherArgs &&...args) +: method(std::forward(method)) +, args(std::forward(args)...) { +} + +template +inline void GenericBox::Initer::operator()( + not_null box) { + call(box, std::make_index_sequence()); +} + +template +template +inline void GenericBox::Initer::call( + not_null box, + std::index_sequence) { + std::invoke(method, box, std::get(args)...); +} + +template +inline auto GenericBox::MakeIniter(InitMethod &&method, InitArgs &&...args) +-> Initer, std::decay_t...> { + return { + std::forward(method), + std::forward(args)... + }; +} + +template +inline GenericBox::GenericBox( + QWidget*, + InitMethod &&init, + InitArgs &&...args) +: _init( + MakeIniter( + std::forward(init), + std::forward(args)...)) +, _content(this) { +} diff --git a/Telegram/SourceFiles/boxes/peers/add_to_contacts_box.cpp b/Telegram/SourceFiles/boxes/peers/add_to_contacts_box.cpp index b216c1e09..b040454ea 100644 --- a/Telegram/SourceFiles/boxes/peers/add_to_contacts_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/add_to_contacts_box.cpp @@ -173,10 +173,15 @@ void AddToContactsBox::setupWarning( const auto name = _user->firstName.isEmpty() ? _user->lastName : _user->firstName; + const auto nameWithEntities = TextWithEntities{ name }; const auto text = _phone.isEmpty() - ? TextWithEntities{ - lng_contact_phone_after(lt_user, name, lt_name, name) - } + ? lng_contact_phone_after__generic( + lt_user, + nameWithEntities, + lt_visible, + BoldText(lang(lng_contact_phone_visible)), + lt_name, + nameWithEntities) : lng_contact_phone_show__generic( lt_button, BoldText(lang(lng_box_done).toUpper()), diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index dcf9e122a..65a82b598 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -235,6 +235,11 @@ void UserData::setIsBlocked(bool is) { : BlockStatus::NotBlocked; if (_blockStatus != status) { _blockStatus = status; + if (is) { + _fullFlags.add(MTPDuserFull::Flag::f_blocked); + } else { + _fullFlags.remove(MTPDuserFull::Flag::f_blocked); + } Notify::peerUpdatedDelayed(this, UpdateFlag::UserIsBlocked); } } diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp index 7bb8ce97e..2c040d9c4 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp @@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/checkbox.h" +#include "ui/widgets/labels.h" #include "data/data_peer.h" #include "data/data_user.h" #include "data/data_chat.h" @@ -19,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "auth_session.h" #include "boxes/confirm_box.h" +#include "boxes/generic_box.h" #include "styles/style_history.h" #include "styles/style_boxes.h" @@ -41,7 +44,9 @@ bool BarCurrentlyHidden(not_null peer) { } using Setting = MTPDpeerSettings::Flag; if (const auto user = peer->asUser()) { - if (user->isContact() + if (user->isBlocked()) { + return true; + } else if (user->isContact() && !((*settings) & Setting::f_share_contact)) { return true; } @@ -55,6 +60,82 @@ auto MapToEmpty() { return rpl::map([] { return rpl::empty_value(); }); } +TextWithEntities BoldText(const QString &text) { + auto result = TextWithEntities{ text }; + result.entities.push_back({ EntityType::Bold, 0, text.size() }); + return result; +} + +void BlockUserBox( + not_null box, + not_null user, + not_null window) { + using Flag = MTPDpeerSettings::Flag; + const auto settings = user->settings().value_or(Flag(0)); + + const auto name = user->firstName.isEmpty() + ? user->lastName + : user->firstName; + + box->addRow(object_ptr( + box, + rpl::single( + lng_blocked_list_confirm_text__generic( + lt_name, + BoldText(name))), + st::blockUserConfirmation)); + + box->addSkip(st::boxMediumSkip); + + const auto report = (settings & Flag::f_report_spam) + ? box->addRow(object_ptr( + box, + lang(lng_report_spam), + true, + st::defaultBoxCheckbox)) + : nullptr; + + if (report) { + box->addSkip(st::boxMediumSkip); + } + + const auto clear = box->addRow(object_ptr( + box, + lang(lng_blocked_list_confirm_clear), + true, + st::defaultBoxCheckbox)); + + box->addSkip(st::boxLittleSkip); + + box->setTitle([=] { + return lng_blocked_list_confirm_title(lt_name, name); + }); + + box->addButton(langFactory(lng_blocked_list_confirm_ok), [=] { + const auto reportChecked = report && report->checked(); + const auto clearChecked = clear->checked(); + + box->closeBox(); + + user->session().api().blockUser(user); + if (reportChecked) { + user->session().api().request(MTPmessages_ReportSpam( + user->input + )).send(); + } + if (clearChecked) { + crl::on_main(&user->session(), [=] { + user->session().api().deleteConversation(user, false); + }); + window->sessionController()->showBackFromStack(); + } + }, st::attentionBoxButton); + + box->addButton(langFactory(lng_cancel), [=] { + box->closeBox(); + }); +} + } // namespace ContactStatus::Bar::Bar(QWidget *parent, const QString &name) @@ -215,23 +296,31 @@ void ContactStatus::setupWidgets(not_null parent) { auto ContactStatus::PeerState(not_null peer) -> rpl::producer { using SettingsChange = PeerData::Settings::Change; - using Settings = MTPDpeerSettings::Flags; using Setting = MTPDpeerSettings::Flag; if (const auto user = peer->asUser()) { using FlagsChange = UserData::Flags::Change; - using Flags = MTPDuser::Flags; + using FullFlagsChange = UserData::FullFlags::Change; using Flag = MTPDuser::Flag; + using FullFlag = MTPDuserFull::Flag; auto isContactChanges = user->flagsValue( ) | rpl::filter([](FlagsChange flags) { return flags.diff & (Flag::f_contact | Flag::f_mutual_contact); }); + auto isBlockedChanges = user->fullFlagsValue( + ) | rpl::filter([](FullFlagsChange full) { + return full.diff & FullFlag::f_blocked; + }); return rpl::combine( std::move(isContactChanges), + std::move(isBlockedChanges), user->settingsValue() - ) | rpl::map([=](FlagsChange flags, SettingsChange settings) { - if (!settings.value) { + ) | rpl::map([=]( + FlagsChange flags, + FullFlagsChange full, + SettingsChange settings) { + if (!settings.value || (full.value & FullFlag::f_blocked)) { return State::None; } else if (user->isContact()) { if (settings.value & Setting::f_share_contact) { @@ -283,26 +372,28 @@ void ContactStatus::setupHandlers(not_null peer) { setupCloseHandler(peer); } -void ContactStatus::setupAddHandler(not_null peer) { +void ContactStatus::setupAddHandler(not_null user) { _bar.entity()->addClicks( ) | rpl::start_with_next([=] { - Expects(peer->isUser()); - - Window::PeerMenuAddContact(peer->asUser()); + Window::PeerMenuAddContact(user); }, _bar.lifetime()); } -void ContactStatus::setupBlockHandler(not_null peer) { +void ContactStatus::setupBlockHandler(not_null user) { + _bar.entity()->blockClicks( + ) | rpl::start_with_next([=] { + _window->show(Box(BlockUserBox, user, _window)); + }, _bar.lifetime()); } -void ContactStatus::setupShareHandler(not_null peer) { +void ContactStatus::setupShareHandler(not_null user) { _bar.entity()->shareClicks( ) | rpl::start_with_next([=] { - peer->setSettings(0); - peer->session().api().request(MTPcontacts_AcceptContact( - peer->inputUser + user->setSettings(0); + user->session().api().request(MTPcontacts_AcceptContact( + user->inputUser )).done([=](const MTPUpdates &result) { - peer->session().api().applyUpdates(result); + user->session().api().applyUpdates(result); }).send(); }, _bar.lifetime()); } diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.h b/Telegram/SourceFiles/history/view/history_view_contact_status.h index 63f679769..e75198d8d 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.h +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.h @@ -79,9 +79,9 @@ private: void setupWidgets(not_null parent); void setupState(not_null peer); void setupHandlers(not_null peer); - void setupAddHandler(not_null peer); - void setupBlockHandler(not_null peer); - void setupShareHandler(not_null peer); + void setupAddHandler(not_null user); + void setupBlockHandler(not_null user); + void setupShareHandler(not_null user); void setupReportHandler(not_null peer); void setupCloseHandler(not_null peer); diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 49e608bf6..c4c5a53a4 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -50,6 +50,8 @@ <(src_loc)/boxes/edit_color_box.h <(src_loc)/boxes/edit_privacy_box.cpp <(src_loc)/boxes/edit_privacy_box.h +<(src_loc)/boxes/generic_box.cpp +<(src_loc)/boxes/generic_box.h <(src_loc)/boxes/language_box.cpp <(src_loc)/boxes/language_box.h <(src_loc)/boxes/local_storage_box.cpp