Implement block + clear from ContactStatus bar.

This commit is contained in:
John Preston 2019-06-11 16:31:52 +02:00
parent 3a34b15841
commit aca3ec0ab8
9 changed files with 300 additions and 22 deletions

View File

@ -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";

View File

@ -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;
}

View File

@ -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<Ui::OverrideMargins>(this, std::move(_content));
setDimensionsToContent(_width ? _width : st::boxWidth, wrap.data());
setInnerWidget(std::move(wrap));
}
void GenericBox::addSkip(int height) {
addRow(object_ptr<Ui::FixedHeightWidget>(this, height));
}

View File

@ -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 <tuple>
namespace st {
extern const style::margins &boxRowPadding;
} // namespace st
class GenericBox : public BoxContent {
public:
// InitMethod::operator()(not_null<GenericBox*> box, InitArgs...)
// init(box, args...)
template <
typename InitMethod,
typename ...InitArgs,
typename = decltype(std::declval<std::decay_t<InitMethod>>()(
std::declval<not_null<GenericBox*>>(),
std::declval<std::decay_t<InitArgs>>()...))>
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<RpWidget, Widget>>>
Widget *insertRow(
int atPosition,
object_ptr<Widget> &&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<RpWidget, Widget>>>
Widget *addRow(
object_ptr<Widget> &&child,
const style::margins &margin = st::boxRowPadding) {
return _content->add(std::move(child), margin);
}
void addSkip(int height);
protected:
void prepare() override;
private:
template <typename InitMethod, typename ...InitArgs>
struct Initer {
template <typename OtherMethod, typename ...OtherArgs>
Initer(OtherMethod &&method, OtherArgs &&...args);
void operator()(not_null<GenericBox*> box);
template <std::size_t... I>
void call(
not_null<GenericBox*> box,
std::index_sequence<I...>);
InitMethod method;
std::tuple<InitArgs...> args;
};
template <typename InitMethod, typename ...InitArgs>
auto MakeIniter(InitMethod &&method, InitArgs &&...args)
-> Initer<std::decay_t<InitMethod>, std::decay_t<InitArgs>...>;
FnMut<void(not_null<GenericBox*>)> _init;
object_ptr<Ui::VerticalLayout> _content;
int _width = 0;
};
template <typename InitMethod, typename ...InitArgs>
template <typename OtherMethod, typename ...OtherArgs>
GenericBox::Initer<InitMethod, InitArgs...>::Initer(
OtherMethod &&method,
OtherArgs &&...args)
: method(std::forward<OtherMethod>(method))
, args(std::forward<OtherArgs>(args)...) {
}
template <typename InitMethod, typename ...InitArgs>
inline void GenericBox::Initer<InitMethod, InitArgs...>::operator()(
not_null<GenericBox*> box) {
call(box, std::make_index_sequence<sizeof...(InitArgs)>());
}
template <typename InitMethod, typename ...InitArgs>
template <std::size_t... I>
inline void GenericBox::Initer<InitMethod, InitArgs...>::call(
not_null<GenericBox*> box,
std::index_sequence<I...>) {
std::invoke(method, box, std::get<I>(args)...);
}
template <typename InitMethod, typename ...InitArgs>
inline auto GenericBox::MakeIniter(InitMethod &&method, InitArgs &&...args)
-> Initer<std::decay_t<InitMethod>, std::decay_t<InitArgs>...> {
return {
std::forward<InitMethod>(method),
std::forward<InitArgs>(args)...
};
}
template <typename InitMethod, typename ...InitArgs, typename>
inline GenericBox::GenericBox(
QWidget*,
InitMethod &&init,
InitArgs &&...args)
: _init(
MakeIniter(
std::forward<InitMethod>(init),
std::forward<InitArgs>(args)...))
, _content(this) {
}

View File

@ -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<TextWithEntities>(
lt_user,
nameWithEntities,
lt_visible,
BoldText(lang(lng_contact_phone_visible)),
lt_name,
nameWithEntities)
: lng_contact_phone_show__generic<TextWithEntities>(
lt_button,
BoldText(lang(lng_box_done).toUpper()),

View File

@ -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);
}
}

View File

@ -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<PeerData*> 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<GenericBox*> box,
not_null<UserData*> user,
not_null<Window::Controller*> 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<Ui::FlatLabel>(
box,
rpl::single(
lng_blocked_list_confirm_text__generic<TextWithEntities>(
lt_name,
BoldText(name))),
st::blockUserConfirmation));
box->addSkip(st::boxMediumSkip);
const auto report = (settings & Flag::f_report_spam)
? box->addRow(object_ptr<Ui::Checkbox>(
box,
lang(lng_report_spam),
true,
st::defaultBoxCheckbox))
: nullptr;
if (report) {
box->addSkip(st::boxMediumSkip);
}
const auto clear = box->addRow(object_ptr<Ui::Checkbox>(
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<Ui::RpWidget*> parent) {
auto ContactStatus::PeerState(not_null<PeerData*> peer)
-> rpl::producer<State> {
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<PeerData*> peer) {
setupCloseHandler(peer);
}
void ContactStatus::setupAddHandler(not_null<UserData*> peer) {
void ContactStatus::setupAddHandler(not_null<UserData*> 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<UserData*> peer) {
void ContactStatus::setupBlockHandler(not_null<UserData*> user) {
_bar.entity()->blockClicks(
) | rpl::start_with_next([=] {
_window->show(Box<GenericBox>(BlockUserBox, user, _window));
}, _bar.lifetime());
}
void ContactStatus::setupShareHandler(not_null<UserData*> peer) {
void ContactStatus::setupShareHandler(not_null<UserData*> 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());
}

View File

@ -79,9 +79,9 @@ private:
void setupWidgets(not_null<Ui::RpWidget*> parent);
void setupState(not_null<PeerData*> peer);
void setupHandlers(not_null<PeerData*> peer);
void setupAddHandler(not_null<UserData*> peer);
void setupBlockHandler(not_null<UserData*> peer);
void setupShareHandler(not_null<UserData*> peer);
void setupAddHandler(not_null<UserData*> user);
void setupBlockHandler(not_null<UserData*> user);
void setupShareHandler(not_null<UserData*> user);
void setupReportHandler(not_null<PeerData*> peer);
void setupCloseHandler(not_null<PeerData*> peer);

View File

@ -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