From 85fd1176750fbb844f0792d3ddfbb1090b65168e Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 16 Mar 2017 18:15:07 +0300 Subject: [PATCH] Add EditPrivacyBox. Edit last seen privacy. Selecting exception users is not supported yet. --- Telegram/Resources/langs/lang.strings | 15 + Telegram/SourceFiles/boxes/boxes.style | 20 ++ .../SourceFiles/boxes/edit_privacy_box.cpp | 295 ++++++++++++++++++ Telegram/SourceFiles/boxes/edit_privacy_box.h | 112 +++++++ Telegram/SourceFiles/core/lambda.h | 10 +- .../settings/settings_privacy_controllers.cpp | 38 +++ .../settings/settings_privacy_controllers.h | 16 + .../settings/settings_privacy_widget.cpp | 10 +- .../settings/settings_privacy_widget.h | 2 + Telegram/SourceFiles/ui/twidget.h | 6 + Telegram/gyp/telegram_sources.txt | 6 +- 11 files changed, 521 insertions(+), 9 deletions(-) create mode 100644 Telegram/SourceFiles/boxes/edit_privacy_box.cpp create mode 100644 Telegram/SourceFiles/boxes/edit_privacy_box.h diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 7cf3b1416..43cd8c60a 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -405,6 +405,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_connection_save" = "Save"; "lng_settings_blocked_users" = "Blocked users"; +"lng_settings_last_seen_privacy" = "Last Seen privacy"; "lng_settings_show_sessions" = "Show all sessions"; "lng_settings_reset" = "Terminate all other sessions"; "lng_settings_reset_sure" = "Are you sure you want to terminate\nall other sessions?"; @@ -439,6 +440,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "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_edit_privacy_everyone" = "Everybody"; +"lng_edit_privacy_contacts" = "My contacts"; +"lng_edit_privacy_nobody" = "Nobody"; +"lng_edit_privacy_exceptions" = "Add exceptions"; + +"lng_edit_privacy_lastseen_title" = "Last Seen time privacy"; +"lng_edit_privacy_lastseen_everyone" = "Anyone can see my Last Seen time"; +"lng_edit_privacy_lastseen_contacts" = "Only contacts can see my Last Seen time"; +"lng_edit_privacy_lastseen_nobody" = "No one can see my Last Seen time"; +"lng_edit_privacy_lastseen_description" = "Important: you won't be able to see Last Seen times for people with whom you don't share your Last Seen time. Approximate last seen will be shown instead (recently, within a week, within a month)."; +"lng_edit_privacy_lastseen_always" = "Always share with{count:| # user| # users}"; +"lng_edit_privacy_lastseen_never" = "Never share with{count:| # user| # users}"; +"lng_edit_privacy_lastseen_exceptions" = "These settings will override the values above."; + "lng_preview_loading" = "Getting Link Info..."; "lng_profile_chat_unaccessible" = "Group is inaccessible"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index fe22dc941..bd6cff7fc 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -584,3 +584,23 @@ colorValueInput: InputField(defaultInputField) { } colorResultInput: InputField(colorValueInput) { } + +editPrivacyOptionMargin: margins(23px, 0px, 21px, 10px); +editPrivacyPadding: margins(23px, 0px, 21px, 0px); +editPrivacyTitle: FlatLabel(defaultFlatLabel) { + width: 320px; + textFg: boxTitleFg; + maxHeight: 46px; + margin: margins(0px, 13px, 0px, 10px); + style: TextStyle(defaultTextStyle) { + font: boxTitleFont; + linkFont: boxTitleFont; + linkFontOver: boxTitleFont; + } +} +editPrivacyLabel: FlatLabel(defaultFlatLabel) { + width: 320px; + textFg: membersAboutLimitFg; + style: defaultTextStyle; +} +editPrivacyLinkMargin: margins(0px, 0px, 0px, 10px); diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp new file mode 100644 index 000000000..cc2d56331 --- /dev/null +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -0,0 +1,295 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "boxes/edit_privacy_box.h" + +#include "styles/style_boxes.h" +#include "ui/widgets/checkbox.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/buttons.h" +#include "ui/effects/widget_slide_wrap.h" +#include "lang.h" + +class EditPrivacyBox::OptionWidget : public TWidget { +public: + OptionWidget(QWidget *parent, int value, bool selected, const QString &text, const QString &description); + + void setChangedCallback(base::lambda callback) { + connect(_option, SIGNAL(changed()), base::lambda_slot(this, std::move(callback)), SLOT(action())); + } + bool checked() const { + return _option->checked(); + } + +protected: + int resizeGetHeight(int newWidth) override; + +private: + object_ptr _option; + object_ptr _description; + +}; + +EditPrivacyBox::OptionWidget::OptionWidget(QWidget *parent, int value, bool selected, const QString &text, const QString &description) : TWidget(parent) +, _option(this, qsl("privacy_option"), value, text, selected, st::defaultBoxCheckbox) +, _description(this, description, Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel) { +} + +int EditPrivacyBox::OptionWidget::resizeGetHeight(int newWidth) { + _option->resizeToNaturalWidth(newWidth); + auto optionTextLeft = st::defaultBoxCheckbox.textPosition.x(); + _description->resizeToWidth(newWidth - optionTextLeft); + _option->moveToLeft(0, 0); + _description->moveToLeft(optionTextLeft, _option->bottomNoMargins()); + return _description->bottomNoMargins(); +} + +EditPrivacyBox::EditPrivacyBox(QWidget*, std::unique_ptr controller) : BoxContent() +, _controller(std::move(controller)) +, _loading(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout) { +} + +void EditPrivacyBox::prepare() { + _controller->setView(this); + + setTitle(_controller->title()); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + _loadRequestId = MTP::send(MTPaccount_GetPrivacy(_controller->key()), rpcDone(base::lambda_guarded(this, [this](const MTPaccount_PrivacyRules &result) { + _loadRequestId = 0; + loadDone(result); + })), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) { + if (MTP::isDefaultHandledError(error)) { + return false; + } + _loadRequestId = 0; + return true; + }))); + + setDimensions(st::boxWideWidth, countDefaultHeight(st::boxWideWidth)); + + _loading->resizeToWidth(width()); + _loading->moveToLeft(0, height() / 3); +} + +int EditPrivacyBox::resizeGetHeight(int newWidth) { + auto top = 0; + auto layoutRow = [this, newWidth, &top](auto &widget, style::margins padding) { + if (!widget) return; + widget->resizeToNaturalWidth(newWidth - padding.left() - padding.right()); + widget->moveToLeft(padding.left(), top + padding.top()); + top = widget->bottomNoMargins() + padding.bottom(); + }; + + layoutRow(_everyone, st::editPrivacyOptionMargin); + layoutRow(_contacts, st::editPrivacyOptionMargin); + layoutRow(_nobody, st::editPrivacyOptionMargin); + layoutRow(_description, st::editPrivacyPadding); + layoutRow(_exceptionsTitle, st::editPrivacyPadding); + auto linksTop = top; + layoutRow(_alwaysLink, st::editPrivacyPadding); + layoutRow(_neverLink, st::editPrivacyPadding); + auto linksHeight = top - linksTop; + layoutRow(_exceptionsDescription, st::editPrivacyPadding); + + // Add full width of both links in any case + auto linkMargins = exceptionLinkMargins(); + top -= linksHeight; + top += linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); + top += linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); + + return top; +} + +int EditPrivacyBox::countDefaultHeight(int newWidth) { + auto height = 0; + auto optionHeight = [this, newWidth](Option option, const QString &label) { + auto description = _controller->optionDescription(option); + if (description.isEmpty()) { + return 0; + } + + auto value = static_cast(Option::Everyone); + auto selected = false; + auto fake = object_ptr(nullptr, value, selected, label, description); + fake->resizeToWidth(newWidth); + return st::editPrivacyOptionMargin.top() + fake->heightNoMargins() + st::editPrivacyOptionMargin.bottom(); + }; + auto labelHeight = [this, newWidth](const QString &text, const style::FlatLabel &st) { + auto fake = object_ptr(nullptr, text, Ui::FlatLabel::InitType::Simple, st); + fake->resizeToWidth(newWidth); + return st::editPrivacyPadding.top() + fake->heightNoMargins() + st::editPrivacyPadding.bottom(); + }; + auto linkMargins = exceptionLinkMargins(); + height += optionHeight(Option::Everyone, lang(lng_edit_privacy_everyone)); + height += optionHeight(Option::Contacts, lang(lng_edit_privacy_contacts)); + height += optionHeight(Option::Nobody, lang(lng_edit_privacy_nobody)); + height += labelHeight(_controller->description(), st::editPrivacyLabel); + height += labelHeight(lang(lng_edit_privacy_exceptions), st::editPrivacyTitle); + height += linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); // linkHeight(_controller->alwaysLinkText(0)) + height += linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); // linkHeight(_controller->neverLinkText(0)) + height += labelHeight(_controller->exceptionsDescription(), st::editPrivacyLabel); + return height; +} + +void EditPrivacyBox::editAlwaysUsers() { + // not implemented +} + +void EditPrivacyBox::editNeverUsers() { + // not implemented +} + +QVector EditPrivacyBox::collectResult() { + auto collectInputUsers = [](auto &users) { + auto result = QVector(); + result.reserve(users.size()); + for (auto user : users) { + result.push_back(user->inputUser); + } + return result; + }; + + auto result = QVector(); + result.reserve(3); + if (showAlwaysLink() && !_alwaysUsers.empty()) { + result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector(collectInputUsers(_alwaysUsers)))); + } + if (showNeverLink() && !_neverUsers.empty()) { + result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector(collectInputUsers(_neverUsers)))); + } + switch (_option) { + case Option::Everyone: result.push_back(MTP_inputPrivacyValueAllowAll()); break; + case Option::Contacts: result.push_back(MTP_inputPrivacyValueAllowContacts()); break; + case Option::Nobody: result.push_back(MTP_inputPrivacyValueDisallowAll()); break; + } + + return result; +} + +style::margins EditPrivacyBox::exceptionLinkMargins() const { + return st::editPrivacyLinkMargin; +} + +bool EditPrivacyBox::showAlwaysLink() const { + return (_option == Option::Contacts) || (_option == Option::Nobody); +} + +bool EditPrivacyBox::showNeverLink() const { + return (_option == Option::Everyone) || (_option == Option::Contacts); +} + +void EditPrivacyBox::createOption(Option option, object_ptr &widget, const QString &label) { + auto description = _controller->optionDescription(option); + auto selected = (_option == option); + if (!description.isEmpty() || selected) { + auto value = static_cast(option); + widget.create(this, value, selected, label, description); + widget->setChangedCallback([this, option, widget = widget.data()] { + if (widget->checked()) { + _option = option; + _alwaysLink->toggleAnimated(showAlwaysLink()); + _neverLink->toggleAnimated(showNeverLink()); + } + }); + } +} + +void EditPrivacyBox::createWidgets() { + _loading.destroy(); + + createOption(Option::Everyone, _everyone, lang(lng_edit_privacy_everyone)); + createOption(Option::Contacts, _contacts, lang(lng_edit_privacy_contacts)); + createOption(Option::Nobody, _nobody, lang(lng_edit_privacy_nobody)); + _description.create(this, _controller->description(), Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel); + + _exceptionsTitle.create(this, lang(lng_edit_privacy_exceptions), Ui::FlatLabel::InitType::Simple, st::editPrivacyTitle); + auto linkResizedCallback = [this] { + resizeGetHeight(width()); + }; + _alwaysLink.create(this, object_ptr(this, _controller->alwaysLinkText(_alwaysUsers.size())), exceptionLinkMargins(), linkResizedCallback); + _alwaysLink->entity()->setClickedCallback([this] { editAlwaysUsers(); }); + _neverLink.create(this, object_ptr(this, _controller->neverLinkText(_neverUsers.size())), exceptionLinkMargins(), linkResizedCallback); + _neverLink->entity()->setClickedCallback([this] { editNeverUsers(); }); + _exceptionsDescription.create(this, _controller->exceptionsDescription(), Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel); + + addButton(lang(lng_settings_save), [this] { + _controller->save(collectResult()); + }); + + showChildren(); + _alwaysLink->toggleFast(showAlwaysLink()); + _neverLink->toggleFast(showNeverLink()); + + setDimensions(st::boxWideWidth, resizeGetHeight(st::boxWideWidth)); +} + +void EditPrivacyBox::loadDone(const MTPaccount_PrivacyRules &result) { + t_assert(result.type() == mtpc_account_privacyRules); + auto &rules = result.c_account_privacyRules(); + App::feedUsers(rules.vusers); + + // This is simplified version of privacy rules interpretation. + // But it should be fine for all the apps that use the same subset of features. + auto optionSet = false; + auto setOption = [this, &optionSet](Option option) { + if (optionSet) return; + optionSet = true; + _option = option; + }; + auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) { + switch (rule.type()) { + case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break; + case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break; + case mtpc_privacyValueAllowUsers: { + auto &users = rule.c_privacyValueAllowUsers().vusers.v; + _alwaysUsers.reserve(_alwaysUsers.size() + users.size()); + for (auto &userId : users) { + auto user = App::user(UserId(userId.v)); + if (!_neverUsers.contains(user) && !_alwaysUsers.contains(user)) { + _alwaysUsers.push_back(user); + } + } + } break; + case mtpc_privacyValueDisallowContacts: // not supported, fall through + case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break; + case mtpc_privacyValueDisallowUsers: { + auto &users = rule.c_privacyValueDisallowUsers().vusers.v; + _neverUsers.reserve(_neverUsers.size() + users.size()); + for (auto &userId : users) { + auto user = App::user(UserId(userId.v)); + if (!_alwaysUsers.contains(user) && !_neverUsers.contains(user)) { + _neverUsers.push_back(user); + } + } + } break; + } + }; + for (auto &rule : rules.vrules.v) { + feedRule(rule); + } + feedRule(MTP_privacyValueDisallowAll()); // disallow by default. + + createWidgets(); +} + +EditPrivacyBox::~EditPrivacyBox() { + MTP::cancel(_loadRequestId); +} diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.h b/Telegram/SourceFiles/boxes/edit_privacy_box.h new file mode 100644 index 000000000..d356b72ca --- /dev/null +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.h @@ -0,0 +1,112 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "boxes/abstractbox.h" + +namespace Ui { +class FlatLabel; +class LinkButton; +template +class WidgetSlideWrap; +} // namespace Ui + +class EditPrivacyBox : public BoxContent { +public: + enum class Option { + Everyone = 0, + Contacts, + Nobody, + }; + + class Controller { + public: + virtual MTPInputPrivacyKey key() = 0; + virtual void save(QVector &&result) = 0; + + virtual QString title() = 0; + virtual QString optionDescription(Option option) { + return QString(); + } + virtual QString description() = 0; + virtual QString alwaysLinkText(int count) = 0; + virtual QString neverLinkText(int count) = 0; + virtual QString exceptionsDescription() = 0; + + virtual ~Controller() = default; + + protected: + EditPrivacyBox *view() const { + return _view; + } + + private: + void setView(EditPrivacyBox *box) { + _view = box; + } + + EditPrivacyBox *_view = nullptr; + + friend class EditPrivacyBox; + + }; + + EditPrivacyBox(QWidget*, std::unique_ptr controller); + ~EditPrivacyBox(); + +protected: + void prepare() override; + + int resizeGetHeight(int newWidth) override; + +private: + class OptionWidget; + + style::margins exceptionLinkMargins() const; + bool showAlwaysLink() const; + bool showNeverLink() const; + void createWidgets(); + void createOption(Option option, object_ptr &widget, const QString &label); + QVector collectResult(); + void loadDone(const MTPaccount_PrivacyRules &result); + int countDefaultHeight(int newWidth); + void editAlwaysUsers(); + void editNeverUsers(); + + std::unique_ptr _controller; + + object_ptr _loading; + object_ptr _everyone = { nullptr }; + object_ptr _contacts = { nullptr }; + object_ptr _nobody = { nullptr }; + object_ptr _description = { nullptr }; + object_ptr _exceptionsTitle = { nullptr }; + object_ptr> _alwaysLink = { nullptr }; + object_ptr> _neverLink = { nullptr }; + object_ptr _exceptionsDescription = { nullptr }; + + mtpRequestId _loadRequestId = 0; + + Option _option = Option::Everyone; + QVector _alwaysUsers; + QVector _neverUsers; + +}; diff --git a/Telegram/SourceFiles/core/lambda.h b/Telegram/SourceFiles/core/lambda.h index 6438aea66..324133fc4 100644 --- a/Telegram/SourceFiles/core/lambda.h +++ b/Telegram/SourceFiles/core/lambda.h @@ -583,20 +583,20 @@ class lambda_slot_wrap : public QObject { Q_OBJECT public: - lambda_slot_wrap(QObject *parent, lambda_once lambda) : QObject(parent), _lambda(std::move(lambda)) { + lambda_slot_wrap(QObject *parent, lambda lambda) : QObject(parent), _lambda(std::move(lambda)) { } - public slots : - void action() { +public slots : + void action() { _lambda(); } private: - lambda_once _lambda; + lambda _lambda; }; -inline lambda_slot_wrap *lambda_slot(QObject *parent, lambda_once lambda) { +inline lambda_slot_wrap *lambda_slot(QObject *parent, lambda lambda) { return new lambda_slot_wrap(parent, std::move(lambda)); } diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index 1d11c4439..d4ed0a0e7 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -299,4 +299,42 @@ std::unique_ptr BlockedBoxController::createRow(UserData *user return row; } +MTPInputPrivacyKey LastSeenPrivacyController::key() { + return MTP_inputPrivacyKeyStatusTimestamp(); +} + +void LastSeenPrivacyController::save(QVector &&result) { + MTP::send(MTPaccount_SetPrivacy(MTP_inputPrivacyKeyStatusTimestamp(), MTP_vector(result))); + view()->closeBox(); +} + +QString LastSeenPrivacyController::title() { + return lang(lng_edit_privacy_lastseen_title); +} + +QString LastSeenPrivacyController::optionDescription(Option option) { + switch (option) { + case Option::Everyone: return lang(lng_edit_privacy_lastseen_everyone); + case Option::Contacts: return lang(lng_edit_privacy_lastseen_contacts); + case Option::Nobody: return lang(lng_edit_privacy_lastseen_nobody); + } + return QString(); +} + +QString LastSeenPrivacyController::description() { + return lang(lng_edit_privacy_lastseen_description); +} + +QString LastSeenPrivacyController::alwaysLinkText(int count) { + return lng_edit_privacy_lastseen_always(lt_count, count); +} + +QString LastSeenPrivacyController::neverLinkText(int count) { + return lng_edit_privacy_lastseen_never(lt_count, count); +} + +QString LastSeenPrivacyController::exceptionsDescription() { + return lang(lng_edit_privacy_lastseen_exceptions); +} + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.h b/Telegram/SourceFiles/settings/settings_privacy_controllers.h index 3486b1052..43ff36793 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.h +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.h @@ -47,4 +47,20 @@ private: }; +class LastSeenPrivacyController : public EditPrivacyBox::Controller, private base::Subscriber { +public: + using Option = EditPrivacyBox::Option; + + MTPInputPrivacyKey key() override; + void save(QVector &&result) override; + + QString title() override; + QString optionDescription(Option option) override; + QString description() override; + QString alwaysLinkText(int count) override; + QString neverLinkText(int count) override; + QString exceptionsDescription() override; + +}; + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_privacy_widget.cpp b/Telegram/SourceFiles/settings/settings_privacy_widget.cpp index 456ea8df3..e84e888d6 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_widget.cpp @@ -25,12 +25,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "styles/style_settings.h" #include "lang.h" #include "application.h" +#include "platform/platform_specific.h" #include "boxes/sessionsbox.h" #include "boxes/passcodebox.h" #include "boxes/autolockbox.h" #include "boxes/peer_list_box.h" -#include "platform/platform_specific.h" -#include "settings/settings_blocked_box_controller.h" +#include "boxes/edit_privacy_box.h" +#include "settings/settings_privacy_controllers.h" namespace Settings { @@ -173,6 +174,7 @@ void PrivacyWidget::createControls() { style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2)); addChildRow(_blockedUsers, marginSmall, lang(lng_settings_blocked_users), SLOT(onBlockedUsers())); + addChildRow(_lastSeenPrivacy, marginSmall, lang(lng_settings_last_seen_privacy), SLOT(onLastSeenPrivacy())); addChildRow(_localPasscodeState, marginSmall); auto label = lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive); auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600); @@ -197,6 +199,10 @@ void PrivacyWidget::onBlockedUsers() { Ui::show(Box(std::make_unique())); } +void PrivacyWidget::onLastSeenPrivacy() { + Ui::show(Box(std::make_unique())); +} + void PrivacyWidget::onAutoLock() { Ui::show(Box()); } diff --git a/Telegram/SourceFiles/settings/settings_privacy_widget.h b/Telegram/SourceFiles/settings/settings_privacy_widget.h index 599150265..eb8a0511c 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_widget.h +++ b/Telegram/SourceFiles/settings/settings_privacy_widget.h @@ -86,6 +86,7 @@ public: private slots: void onBlockedUsers(); + void onLastSeenPrivacy(); void onAutoLock(); void onShowSessions(); @@ -94,6 +95,7 @@ private: void autoLockUpdated(); object_ptr _blockedUsers = { nullptr }; + object_ptr _lastSeenPrivacy = { nullptr }; object_ptr _localPasscodeState = { nullptr }; object_ptr> _autoLock = { nullptr }; object_ptr _cloudPasswordState = { nullptr }; diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index cdea29fb1..55fd4eb70 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -271,6 +271,12 @@ public: } } + // Resize to minimum of natural width and available width. + void resizeToNaturalWidth(int newWidth) { + auto maxWidth = naturalWidth(); + resizeToWidth((maxWidth >= 0) ? qMin(newWidth, maxWidth) : newWidth); + } + QRect rectNoMargins() const { return rect().marginsRemoved(getMargins()); } diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 1968ed65e..ece75c3d1 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -22,6 +22,8 @@ <(src_loc)/boxes/downloadpathbox.h <(src_loc)/boxes/editcolorbox.cpp <(src_loc)/boxes/editcolorbox.h +<(src_loc)/boxes/edit_privacy_box.cpp +<(src_loc)/boxes/edit_privacy_box.h <(src_loc)/boxes/emojibox.cpp <(src_loc)/boxes/emojibox.h <(src_loc)/boxes/languagebox.cpp @@ -295,8 +297,6 @@ <(src_loc)/settings/settings_advanced_widget.h <(src_loc)/settings/settings_background_widget.cpp <(src_loc)/settings/settings_background_widget.h -<(src_loc)/settings/settings_blocked_box_controller.cpp -<(src_loc)/settings/settings_blocked_box_controller.h <(src_loc)/settings/settings_block_widget.cpp <(src_loc)/settings/settings_block_widget.h <(src_loc)/settings/settings_chat_settings_widget.cpp @@ -315,6 +315,8 @@ <(src_loc)/settings/settings_layer.h <(src_loc)/settings/settings_notifications_widget.cpp <(src_loc)/settings/settings_notifications_widget.h +<(src_loc)/settings/settings_privacy_controllers.cpp +<(src_loc)/settings/settings_privacy_controllers.h <(src_loc)/settings/settings_privacy_widget.cpp <(src_loc)/settings/settings_privacy_widget.h <(src_loc)/settings/settings_scale_widget.cpp