Support all required deep links.

This commit is contained in:
John Preston
2026-01-09 17:12:54 +04:00
parent 808a9e6fb9
commit 1e5a93249c
49 changed files with 1247 additions and 293 deletions
+43 -8
View File
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/local_url_handlers.h" #include "core/local_url_handlers.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_session.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
@@ -352,10 +353,12 @@ public:
ProxiesBox( ProxiesBox(
QWidget*, QWidget*,
not_null<ProxiesBoxController*> controller, not_null<ProxiesBoxController*> controller,
Core::SettingsProxy &settings); Core::SettingsProxy &settings,
const QString &highlightId = QString());
protected: protected:
void prepare() override; void prepare() override;
void showFinished() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
private: private:
@@ -381,6 +384,10 @@ private:
base::flat_map<int, base::unique_qptr<ProxyRow>> _rows; base::flat_map<int, base::unique_qptr<ProxyRow>> _rows;
QPointer<Ui::RpWidget> _addProxyButton;
QPointer<Ui::RpWidget> _shareListButton;
QString _highlightId;
}; };
class ProxyBox final : public Ui::BoxContent { class ProxyBox final : public Ui::BoxContent {
@@ -749,10 +756,12 @@ void ProxyRow::showMenu() {
ProxiesBox::ProxiesBox( ProxiesBox::ProxiesBox(
QWidget*, QWidget*,
not_null<ProxiesBoxController*> controller, not_null<ProxiesBoxController*> controller,
Core::SettingsProxy &settings) Core::SettingsProxy &settings,
const QString &highlightId)
: _controller(controller) : _controller(controller)
, _settings(settings) , _settings(settings)
, _initialWrap(this) { , _initialWrap(this)
, _highlightId(highlightId) {
_controller->views( _controller->views(
) | rpl::on_next([=](View &&view) { ) | rpl::on_next([=](View &&view) {
applyView(std::move(view)); applyView(std::move(view));
@@ -774,13 +783,29 @@ void ProxiesBox::keyPressEvent(QKeyEvent *e) {
void ProxiesBox::prepare() { void ProxiesBox::prepare() {
setTitle(tr::lng_proxy_settings()); setTitle(tr::lng_proxy_settings());
addButton(tr::lng_proxy_add(), [=] { addNewProxy(); }); _addProxyButton = addButton(tr::lng_proxy_add(), [=] { addNewProxy(); });
addButton(tr::lng_close(), [=] { closeBox(); }); addButton(tr::lng_close(), [=] { closeBox(); });
setupTopButton(); setupTopButton();
setupContent(); setupContent();
} }
void ProxiesBox::showFinished() {
if (_highlightId == u"proxy/add-proxy"_q) {
if (_addProxyButton) {
_highlightId = QString();
Settings::HighlightWidget(
_addProxyButton,
{ .rippleShape = true });
}
} else if (_highlightId == u"proxy/share-list"_q) {
if (_shareListButton) {
_highlightId = QString();
Settings::HighlightWidget(_shareListButton);
}
}
}
void ProxiesBox::setupTopButton() { void ProxiesBox::setupTopButton() {
const auto top = addTopButton(st::infoTopBarMenu); const auto top = addTopButton(st::infoTopBarMenu);
const auto menu const auto menu
@@ -923,6 +948,7 @@ void ProxiesBox::setupContent() {
tr::lng_proxy_edit_share_list_button(), tr::lng_proxy_edit_share_list_button(),
st::settingsButton, st::settingsButton,
{ &st::menuIconCopy }); { &st::menuIconCopy });
_shareListButton = shareList;
shareList->setClickedCallback([=] { shareList->setClickedCallback([=] {
_controller->shareItems(); _controller->shareItems();
}); });
@@ -1514,15 +1540,17 @@ void ProxiesBoxController::setupChecker(int id, const Checker &checker) {
} }
object_ptr<Ui::BoxContent> ProxiesBoxController::CreateOwningBox( object_ptr<Ui::BoxContent> ProxiesBoxController::CreateOwningBox(
not_null<Main::Account*> account) { not_null<Main::Account*> account,
const QString &highlightId) {
auto controller = std::make_unique<ProxiesBoxController>(account); auto controller = std::make_unique<ProxiesBoxController>(account);
auto box = controller->create(); auto box = controller->create(highlightId);
Ui::AttachAsChild(box, std::move(controller)); Ui::AttachAsChild(box, std::move(controller));
return box; return box;
} }
object_ptr<Ui::BoxContent> ProxiesBoxController::create() { object_ptr<Ui::BoxContent> ProxiesBoxController::create(
auto result = Box<ProxiesBox>(this, _settings); const QString &highlightId) {
auto result = Box<ProxiesBox>(this, _settings, highlightId);
_show = result->uiShow(); _show = result->uiShow();
for (const auto &item : _list) { for (const auto &item : _list) {
updateView(item); updateView(item);
@@ -1848,6 +1876,13 @@ void ProxiesBoxController::share(const ProxyData &proxy, bool qr) {
_show->showToast(tr::lng_username_copied(tr::now)); _show->showToast(tr::lng_username_copied(tr::now));
} }
void ProxiesBoxController::Show(
not_null<Window::SessionController*> controller,
const QString &highlightId) {
controller->show(
CreateOwningBox(&controller->session().account(), highlightId));
}
ProxiesBoxController::~ProxiesBoxController() { ProxiesBoxController::~ProxiesBoxController() {
if (_saveTimer.isActive()) { if (_saveTimer.isActive()) {
base::call_delayed( base::call_delayed(
+6 -2
View File
@@ -47,8 +47,12 @@ public:
const QMap<QString, QString> &fields); const QMap<QString, QString> &fields);
static object_ptr<Ui::BoxContent> CreateOwningBox( static object_ptr<Ui::BoxContent> CreateOwningBox(
not_null<Main::Account*> account); not_null<Main::Account*> account,
object_ptr<Ui::BoxContent> create(); const QString &highlightId = QString());
static void Show(
not_null<Window::SessionController*> controller,
const QString &highlightId = QString());
object_ptr<Ui::BoxContent> create(const QString &highlightId = QString());
enum class ItemState { enum class ItemState {
Connecting, Connecting,
@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_app_config.h" #include "main/main_app_config.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "settings/settings_privacy_controllers.h" #include "settings/settings_privacy_controllers.h"
#include "settings/settings_privacy_security.h" #include "settings/settings_privacy_security.h"
@@ -962,7 +963,8 @@ void EditPrivacyBox::showFinished() {
void EditMessagesPrivacyBox( void EditMessagesPrivacyBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller) { not_null<Window::SessionController*> controller,
const QString &highlightControlId) {
box->setTitle(tr::lng_messages_privacy_title()); box->setTitle(tr::lng_messages_privacy_title());
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);
@@ -979,6 +981,9 @@ void EditMessagesPrivacyBox(
const auto inner = box->verticalLayout(); const auto inner = box->verticalLayout();
inner->add(object_ptr<Ui::PlainShadow>(box)); inner->add(object_ptr<Ui::PlainShadow>(box));
auto highlightCharged = (Ui::RpWidget*)nullptr;
auto highlightRemoveFee = (Ui::RpWidget*)nullptr;
Ui::AddSkip(inner, st::messagePrivacyTopSkip); Ui::AddSkip(inner, st::messagePrivacyTopSkip);
Ui::AddSubsectionTitle(inner, tr::lng_messages_privacy_subtitle()); Ui::AddSubsectionTitle(inner, tr::lng_messages_privacy_subtitle());
const auto group = std::make_shared<Ui::RadiobuttonGroup>( const auto group = std::make_shared<Ui::RadiobuttonGroup>(
@@ -1028,6 +1033,7 @@ void EditMessagesPrivacyBox(
0, 0,
st::messagePrivacyBottomSkip)) st::messagePrivacyBottomSkip))
: nullptr; : nullptr;
highlightCharged = charged;
struct State { struct State {
rpl::variable<int> stars; rpl::variable<int> stars;
@@ -1077,6 +1083,7 @@ void EditMessagesPrivacyBox(
tr::lng_messages_privacy_remove_fee(), tr::lng_messages_privacy_remove_fee(),
std::move(label), std::move(label),
st::settingsButtonNoIcon); st::settingsButtonNoIcon);
highlightRemoveFee = exceptions;
const auto shower = exceptions->lifetime().make_state<rpl::lifetime>(); const auto shower = exceptions->lifetime().make_state<rpl::lifetime>();
exceptions->setClickedCallback([=] { exceptions->setClickedCallback([=] {
@@ -1174,6 +1181,18 @@ void EditMessagesPrivacyBox(
box->closeBox(); box->closeBox();
}); });
} }
if (!highlightControlId.isEmpty()) {
box->showFinishes() | rpl::take(1) | rpl::on_next([=] {
if (highlightControlId == u"privacy/set-price"_q) {
Settings::HighlightWidget(
highlightCharged,
{ .radius = st::boxRadius });
} else if (highlightControlId == u"privacy/remove-fee"_q) {
Settings::HighlightWidget(highlightRemoveFee);
}
}, box->lifetime());
}
} }
rpl::producer<int> SetupChargeSlider( rpl::producer<int> SetupChargeSlider(
@@ -175,7 +175,8 @@ private:
void EditMessagesPrivacyBox( void EditMessagesPrivacyBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller); not_null<Window::SessionController*> controller,
const QString &highlightControlId = QString());
[[nodiscard]] rpl::producer<int> SetupChargeSlider( [[nodiscard]] rpl::producer<int> SetupChargeSlider(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
+31 -5
View File
@@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_cloud_manager.h" #include "lang/lang_cloud_manager.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "spellcheck/spellcheck_types.h" #include "spellcheck/spellcheck_types.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@@ -1102,8 +1103,12 @@ Ui::ScrollToRequest Content::jump(int rows) {
} // namespace } // namespace
LanguageBox::LanguageBox(QWidget*, Window::SessionController *controller) LanguageBox::LanguageBox(
: _controller(controller) { QWidget*,
Window::SessionController *controller,
const QString &highlightId)
: _controller(controller)
, _highlightId(highlightId) {
} }
void LanguageBox::prepare() { void LanguageBox::prepare() {
@@ -1176,6 +1181,22 @@ void LanguageBox::prepare() {
}; };
} }
void LanguageBox::showFinished() {
if (_controller && !_highlightId.isEmpty()) {
if (const auto window = Core::App().findWindow(this)) {
window->checkHighlightControl(
u"language/show-button"_q,
_showButtonToggle.data());
window->checkHighlightControl(
u"language/translate-chats"_q,
_translateChatsToggle.data());
window->checkHighlightControl(
u"language/do-not-translate"_q,
_doNotTranslateButton.data());
}
}
}
void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) { void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
if (!_controller) { if (!_controller) {
return; return;
@@ -1186,6 +1207,7 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
tr::lng_translate_settings_show(), tr::lng_translate_settings_show(),
st::settingsButtonNoIcon))->toggleOn( st::settingsButtonNoIcon))->toggleOn(
rpl::single(Core::App().settings().translateButtonEnabled())); rpl::single(Core::App().settings().translateButtonEnabled()));
_showButtonToggle = translateEnabled;
translateEnabled->toggledValue( translateEnabled->toggledValue(
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
@@ -1207,6 +1229,7 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
rpl::duplicate(premium), rpl::duplicate(premium),
_1 && _2), _1 && _2),
_translateChatTurnOff.events())); _translateChatTurnOff.events()));
_translateChatsToggle = translateChat;
std::move(premium) | rpl::on_next([=](bool value) { std::move(premium) | rpl::on_next([=](bool value) {
translateChat->setToggleLocked(!value); translateChat->setToggleLocked(!value);
}, translateChat->lifetime()); }, translateChat->lifetime());
@@ -1249,6 +1272,7 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
: Ui::LanguageName(list.front()); : Ui::LanguageName(list.front());
}), }),
st::settingsButtonNoIcon); st::settingsButtonNoIcon);
_doNotTranslateButton = translateSkip;
translateSkip->setClickedCallback([=] { translateSkip->setClickedCallback([=] {
uiShow()->showBox(Ui::EditSkipTranslationLanguages()); uiShow()->showBox(Ui::EditSkipTranslationLanguages());
@@ -1288,7 +1312,9 @@ void LanguageBox::setInnerFocus() {
_setInnerFocus(); _setInnerFocus();
} }
base::binary_guard LanguageBox::Show(Window::SessionController *controller) { base::binary_guard LanguageBox::Show(
Window::SessionController *controller,
const QString &highlightId) {
auto result = base::binary_guard(); auto result = base::binary_guard();
auto &manager = Lang::CurrentCloudManager(); auto &manager = Lang::CurrentCloudManager();
@@ -1306,11 +1332,11 @@ base::binary_guard LanguageBox::Show(Window::SessionController *controller) {
base::take(lifetime)->destroy(); base::take(lifetime)->destroy();
} }
if (show) { if (show) {
Ui::show(Box<LanguageBox>(weak.get())); Ui::show(Box<LanguageBox>(weak.get(), highlightId));
} }
}, *lifetime); }, *lifetime);
} else { } else {
Ui::show(Box<LanguageBox>(controller)); Ui::show(Box<LanguageBox>(controller, highlightId));
} }
manager.requestLanguageList(); manager.requestLanguageList();
+11 -2
View File
@@ -24,15 +24,20 @@ class SessionController;
class LanguageBox : public Ui::BoxContent { class LanguageBox : public Ui::BoxContent {
public: public:
LanguageBox(QWidget*, Window::SessionController *controller); LanguageBox(
QWidget*,
Window::SessionController *controller,
const QString &highlightId = QString());
void setInnerFocus() override; void setInnerFocus() override;
[[nodiscard]] static base::binary_guard Show( [[nodiscard]] static base::binary_guard Show(
Window::SessionController *controller); Window::SessionController *controller,
const QString &highlightId = QString());
protected: protected:
void prepare() override; void prepare() override;
void showFinished() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
@@ -41,6 +46,10 @@ private:
[[nodiscard]] int rowsInPage() const; [[nodiscard]] int rowsInPage() const;
Window::SessionController *_controller = nullptr; Window::SessionController *_controller = nullptr;
QString _highlightId;
QPointer<Ui::RpWidget> _showButtonToggle;
QPointer<Ui::RpWidget> _translateChatsToggle;
QPointer<Ui::RpWidget> _doNotTranslateButton;
rpl::event_stream<bool> _translateChatTurnOff; rpl::event_stream<bool> _translateChatTurnOff;
Fn<void()> _setInnerFocus; Fn<void()> _setInnerFocus;
Fn<Ui::ScrollToRequest(int rows)> _jump; Fn<Ui::ScrollToRequest(int rows)> _jump;
@@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@@ -132,6 +133,7 @@ public:
void toggleProgress(bool shown); void toggleProgress(bool shown);
rpl::producer<> clearRequests() const; rpl::producer<> clearRequests() const;
[[nodiscard]] not_null<Ui::RoundButton*> clearButton() const;
protected: protected:
int resizeGetHeight(int newWidth) override; int resizeGetHeight(int newWidth) override;
@@ -210,6 +212,10 @@ rpl::producer<> LocalStorageBox::Row::clearRequests() const {
return _clear->clicks() | rpl::to_empty; return _clear->clicks() | rpl::to_empty;
} }
not_null<Ui::RoundButton*> LocalStorageBox::Row::clearButton() const {
return _clear.data();
}
int LocalStorageBox::Row::resizeGetHeight(int newWidth) { int LocalStorageBox::Row::resizeGetHeight(int newWidth) {
const auto height = st::localStorageRowHeight; const auto height = st::localStorageRowHeight;
const auto padding = st::localStorageRowPadding; const auto padding = st::localStorageRowPadding;
@@ -281,10 +287,13 @@ LocalStorageBox::LocalStorageBox(
_timeLimit = settings.totalTimeLimit; _timeLimit = settings.totalTimeLimit;
} }
void LocalStorageBox::Show(not_null<Window::SessionController*> controller) { void LocalStorageBox::Show(
not_null<Window::SessionController*> controller,
const QString &highlightId) {
auto shared = std::make_shared<object_ptr<LocalStorageBox>>( auto shared = std::make_shared<object_ptr<LocalStorageBox>>(
Box<LocalStorageBox>(&controller->session(), CreateTag())); Box<LocalStorageBox>(&controller->session(), CreateTag()));
const auto weak = shared->data(); const auto weak = shared->data();
weak->_highlightId = highlightId;
rpl::combine( rpl::combine(
controller->session().data().cache().statsOnMain(), controller->session().data().cache().statsOnMain(),
controller->session().data().cacheBigFile().statsOnMain() controller->session().data().cacheBigFile().statsOnMain()
@@ -306,6 +315,26 @@ void LocalStorageBox::prepare() {
setupControls(); setupControls();
} }
void LocalStorageBox::showFinished() {
if (_highlightId.isEmpty()) {
return;
}
if (_highlightId == u"storage/clear-cache"_q) {
if (const auto i = _rows.find(0); i != _rows.end()) {
Settings::HighlightWidget(
i->second->entity()->clearButton(),
{ .rippleShape = true });
}
} else if (_highlightId == u"storage/max-cache"_q) {
if (_totalSlider) {
const auto add = st::roundRadiusSmall;
Settings::HighlightWidget(
_totalSlider,
{ .margin = { -add, -add, -add, -add }, .radius = add });
}
}
}
void LocalStorageBox::updateRow( void LocalStorageBox::updateRow(
not_null<Ui::SlideWrap<Row>*> row, not_null<Ui::SlideWrap<Row>*> row,
const Database::TaggedSummary *data) { const Database::TaggedSummary *data) {
@@ -44,10 +44,13 @@ public:
not_null<Main::Session*> session, not_null<Main::Session*> session,
CreateTag); CreateTag);
static void Show(not_null<Window::SessionController*> controller); static void Show(
not_null<Window::SessionController*> controller,
const QString &highlightId = QString());
protected: protected:
void prepare() override; void prepare() override;
void showFinished() override;
private: private:
class Row; class Row;
@@ -102,5 +105,6 @@ private:
int64 _mediaSizeLimit = 0; int64 _mediaSizeLimit = 0;
size_type _timeLimit = 0; size_type _timeLimit = 0;
bool _limitsChanged = false; bool _limitsChanged = false;
QString _highlightId;
}; };
@@ -824,7 +824,7 @@ void CreateModerateMessagesBox(
tr::lng_restrict_users_part_header( tr::lng_restrict_users_part_header(
lt_count, lt_count,
rpl::single(participants.size()) | tr::to_count()))); rpl::single(participants.size()) | tr::to_count())));
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( auto [checkboxes, getRestrictions, changes, highlightWidget] = CreateEditRestrictions(
box, box,
prepareFlags, prepareFlags,
disabledMessages, disabledMessages,
@@ -368,7 +368,7 @@ void EditAdminBox::prepare() {
.anyoneCanAddMembers = anyoneCanAddMembers, .anyoneCanAddMembers = anyoneCanAddMembers,
}; };
Ui::AddSubsectionTitle(inner, tr::lng_rights_edit_admin_header()); Ui::AddSubsectionTitle(inner, tr::lng_rights_edit_admin_header());
auto [checkboxes, getChecked, changes] = CreateEditAdminRights( auto [checkboxes, getChecked, changes, highlightWidget] = CreateEditAdminRights(
inner, inner,
prepareFlags, prepareFlags,
disabledMessages, disabledMessages,
@@ -799,7 +799,7 @@ void EditRestrictedBox::prepare() {
Ui::AddSubsectionTitle( Ui::AddSubsectionTitle(
verticalLayout(), verticalLayout(),
tr::lng_rights_user_restrictions_header()); tr::lng_rights_user_restrictions_header());
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( auto [checkboxes, getRestrictions, changes, highlightWidget] = CreateEditRestrictions(
this, this,
prepareFlags, prepareFlags,
disabledMessages, disabledMessages,
@@ -712,6 +712,8 @@ template <typename Flags>
return checkView; return checkView;
}; };
auto highlightWidget = QPointer<Ui::RpWidget>();
const auto highlightFlags = descriptor.highlightFlags;
for (const auto &nestedWithLabel : descriptor.labels) { for (const auto &nestedWithLabel : descriptor.labels) {
Assert(!nestedWithLabel.nested.empty()); Assert(!nestedWithLabel.nested.empty());
@@ -723,16 +725,18 @@ template <typename Flags>
: object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>{ nullptr }; : object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>{ nullptr };
const auto verticalLayout = wrap ? wrap->entity() : container.get(); const auto verticalLayout = wrap ? wrap->entity() : container.get();
auto innerChecks = std::vector<not_null<Ui::AbstractCheckView*>>(); auto innerChecks = std::vector<not_null<Ui::AbstractCheckView*>>();
auto sectionFlags = Flags();
for (const auto &entry : nestedWithLabel.nested) { for (const auto &entry : nestedWithLabel.nested) {
const auto c = addCheckbox(verticalLayout, isInner, entry); const auto c = addCheckbox(verticalLayout, isInner, entry);
if (isInner) { if (isInner) {
innerChecks.push_back(c); innerChecks.push_back(c);
sectionFlags |= entry.flags;
} }
} }
if (wrap) { if (wrap) {
const auto raw = wrap.data(); const auto raw = wrap.data();
raw->hide(anim::type::instant); raw->hide(anim::type::instant);
AddInnerToggle( const auto toggle = AddInnerToggle(
container, container,
st, st,
innerChecks, innerChecks,
@@ -740,6 +744,9 @@ template <typename Flags>
*nestedWithLabel.nestingLabel, *nestedWithLabel.nestingLabel,
std::nullopt, std::nullopt,
{ nestedWithLabel.nested.front().icon }); { nestedWithLabel.nested.front().icon });
if (highlightFlags && (sectionFlags & highlightFlags)) {
highlightWidget = toggle;
}
container->add(std::move(wrap)); container->add(std::move(wrap));
container->widthValue( container->widthValue(
) | rpl::on_next([=](int w) { ) | rpl::on_next([=](int w) {
@@ -754,9 +761,10 @@ template <typename Flags>
} }
return { return {
nullptr, .widget = nullptr,
value, .value = value,
state->anyChanges.events() | rpl::map(value) .changes = state->anyChanges.events() | rpl::map(value),
.highlightWidget = highlightWidget,
}; };
} }
@@ -1143,7 +1151,7 @@ void ShowEditPeerPermissionsBox(
Ui::AddSubsectionTitle( Ui::AddSubsectionTitle(
inner, inner,
tr::lng_rights_default_restrictions_header()); tr::lng_rights_default_restrictions_header());
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( auto [checkboxes, getRestrictions, changes, highlightWidget] = CreateEditRestrictions(
inner, inner,
restrictions, restrictions,
disabledMessages, disabledMessages,
@@ -1461,10 +1469,12 @@ ChatAdminRights AdminRightsForOwnershipTransfer(
EditFlagsControl<PowerSaving::Flags> CreateEditPowerSaving( EditFlagsControl<PowerSaving::Flags> CreateEditPowerSaving(
QWidget *parent, QWidget *parent,
PowerSaving::Flags flags, PowerSaving::Flags flags,
rpl::producer<QString> forceDisabledMessage) { rpl::producer<QString> forceDisabledMessage,
PowerSaving::Flags highlightFlags) {
auto widget = object_ptr<Ui::VerticalLayout>(parent); auto widget = object_ptr<Ui::VerticalLayout>(parent);
auto descriptor = Settings::PowerSavingLabels(); auto descriptor = Settings::PowerSavingLabels();
descriptor.forceDisabledMessage = std::move(forceDisabledMessage); descriptor.forceDisabledMessage = std::move(forceDisabledMessage);
descriptor.highlightFlags = highlightFlags;
auto result = CreateEditFlags( auto result = CreateEditFlags(
widget.data(), widget.data(),
flags, flags,
@@ -69,6 +69,7 @@ struct EditFlagsControl {
object_ptr<Ui::RpWidget> widget; object_ptr<Ui::RpWidget> widget;
Fn<Flags()> value; Fn<Flags()> value;
rpl::producer<Flags> changes; rpl::producer<Flags> changes;
QPointer<Ui::RpWidget> highlightWidget;
}; };
template <typename Flags> template <typename Flags>
@@ -83,6 +84,7 @@ struct EditFlagsDescriptor {
base::flat_map<Flags, QString> disabledMessages; base::flat_map<Flags, QString> disabledMessages;
const style::SettingsButton *st = nullptr; const style::SettingsButton *st = nullptr;
rpl::producer<QString> forceDisabledMessage; rpl::producer<QString> forceDisabledMessage;
Flags highlightFlags = Flags();
}; };
using RestrictionLabel = EditFlagsLabel<ChatRestrictions>; using RestrictionLabel = EditFlagsLabel<ChatRestrictions>;
@@ -117,7 +119,8 @@ using AdminRightLabel = EditFlagsLabel<ChatAdminRights>;
[[nodiscard]] auto CreateEditPowerSaving( [[nodiscard]] auto CreateEditPowerSaving(
QWidget *parent, QWidget *parent,
PowerSaving::Flags flags, PowerSaving::Flags flags,
rpl::producer<QString> forceDisabledMessage rpl::producer<QString> forceDisabledMessage,
PowerSaving::Flags highlightFlags = PowerSaving::Flags()
) -> EditFlagsControl<PowerSaving::Flags>; ) -> EditFlagsControl<PowerSaving::Flags>;
[[nodiscard]] auto CreateEditAdminLogFilter( [[nodiscard]] auto CreateEditAdminLogFilter(
+12 -12
View File
@@ -750,28 +750,28 @@ void StickersBox::refreshTabs() {
sections.push_back(tr::lng_stickers_masks_tab(tr::now)); sections.push_back(tr::lng_stickers_masks_tab(tr::now));
_tabIndices.push_back(Section::Masks); _tabIndices.push_back(Section::Masks);
} }
if (!stickers.featuredSetsOrder().isEmpty() && _featured.widget()) { const auto showFeatured = _featured.widget()
&& (!stickers.featuredSetsOrder().isEmpty()
|| _section == Section::Featured);
if (showFeatured) {
sections.push_back(tr::lng_stickers_featured_tab(tr::now)); sections.push_back(tr::lng_stickers_featured_tab(tr::now));
_tabIndices.push_back(Section::Featured); _tabIndices.push_back(Section::Featured);
} }
if (!archivedSetsOrder().isEmpty() && _archived.widget()) { const auto showArchived = _archived.widget()
&& (!archivedSetsOrder().isEmpty()
|| _section == Section::Archived);
if (showArchived) {
sections.push_back(tr::lng_stickers_archived_tab(tr::now)); sections.push_back(tr::lng_stickers_archived_tab(tr::now));
_tabIndices.push_back(Section::Archived); _tabIndices.push_back(Section::Archived);
} }
_tabs->setSections(sections); _tabs->setSections(sections);
if ((_tab == &_archived && !_tabIndices.contains(Section::Archived)) if ((_section == Section::Archived && !_tabIndices.contains(Section::Archived))
|| (_tab == &_featured && !_tabIndices.contains(Section::Featured)) || (_section == Section::Featured && !_tabIndices.contains(Section::Featured))
|| (_tab == &_masks && !_tabIndices.contains(Section::Masks))) { || (_section == Section::Masks && !_tabIndices.contains(Section::Masks))) {
switchTab(); switchTab();
} else { } else {
_ignoreTabActivation = true; _ignoreTabActivation = true;
_tabs->setActiveSectionFast(_tabIndices.indexOf((_tab == &_archived) _tabs->setActiveSectionFast(_tabIndices.indexOf(_section));
? Section::Archived
: (_tab == &_featured)
? Section::Featured
: (_tab == &_masks)
? Section::Masks
: Section::Installed));
_ignoreTabActivation = false; _ignoreTabActivation = false;
} }
updateTabsGeometry(); updateTabsGeometry();
@@ -43,6 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_icon.h"
#include "settings/settings_calls.h" #include "settings/settings_calls.h"
#include "settings/settings_common.h"
#include "styles/style_info.h" // infoTopBarMenu #include "styles/style_info.h" // infoTopBarMenu
#include "styles/style_layers.h" // st::boxLabel. #include "styles/style_layers.h" // st::boxLabel.
#include "styles/style_calls.h" #include "styles/style_calls.h"
@@ -803,7 +804,9 @@ void ClearCallsBox(
return result; return result;
} }
void ShowCallsBox(not_null<::Window::SessionController*> window) { void ShowCallsBox(
not_null<::Window::SessionController*> window,
bool highlightStartCall) {
struct State { struct State {
State(not_null<::Window::SessionController*> window) State(not_null<::Window::SessionController*> window)
: callsController(window) : callsController(window)
@@ -893,6 +896,13 @@ void ShowCallsBox(not_null<::Window::SessionController*> window) {
state->menu->popup(QCursor::pos()); state->menu->popup(QCursor::pos());
return true; return true;
}); });
if (highlightStartCall) {
box->showFinishes(
) | rpl::take(1) | rpl::on_next([=] {
Settings::HighlightWidget(button);
}, box->lifetime());
}
})); }));
} }
@@ -81,6 +81,8 @@ void ClearCallsBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<::Window::SessionController*> window); not_null<::Window::SessionController*> window);
void ShowCallsBox(not_null<::Window::SessionController*> window); void ShowCallsBox(
not_null<::Window::SessionController*> window,
bool highlightStartCall = false);
} // namespace Calls } // namespace Calls
@@ -10,9 +10,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "base/binary_guard.h" #include "base/binary_guard.h"
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "boxes/gift_credits_box.h"
#include "boxes/language_box.h" #include "boxes/language_box.h"
#include "boxes/stickers_box.h"
#include "chat_helpers/emoji_sets_manager.h"
#include "boxes/edit_privacy_box.h" #include "boxes/edit_privacy_box.h"
#include "boxes/peers/edit_peer_color_box.h" #include "boxes/peers/edit_peer_color_box.h"
#include "info/bot/earn/info_bot_earn_widget.h"
#include "info/bot/starref/info_bot_starref_common.h"
#include "info/bot/starref/info_bot_starref_join_widget.h"
#include "settings/settings_privacy_controllers.h" #include "settings/settings_privacy_controllers.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "boxes/star_gift_box.h" #include "boxes/star_gift_box.h"
@@ -24,36 +30,77 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h" #include "data/data_user.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "info/info_memento.h" #include "info/info_memento.h"
#include "info/peer_gifts/info_peer_gifts_widget.h"
#include "info/stories/info_stories_widget.h" #include "info/stories/info_stories_widget.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "ui/boxes/peer_qr_box.h" #include "ui/boxes/peer_qr_box.h"
#include "ui/layers/generic_box.h" #include "ui/layers/generic_box.h"
#include "main/main_domain.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "storage/storage_domain.h"
#include "settings/settings_active_sessions.h" #include "settings/settings_active_sessions.h"
#include "settings/settings_advanced.h" #include "settings/settings_advanced.h"
#include "settings/settings_blocked_peers.h" #include "settings/settings_blocked_peers.h"
#include "settings/settings_business.h" #include "settings/settings_business.h"
#include "settings/settings_calls.h" #include "settings/settings_calls.h"
#include "settings/settings_chat.h" #include "settings/settings_chat.h"
#include "settings/settings_passkeys.h"
#include "data/components/passkeys.h"
#include "calls/calls_box_controller.h"
#include "settings/settings_credits.h" #include "settings/settings_credits.h"
#include "settings/settings_folders.h" #include "settings/settings_folders.h"
#include "settings/settings_global_ttl.h" #include "settings/settings_global_ttl.h"
#include "settings/settings_information.h" #include "settings/settings_information.h"
#include "settings/settings_local_passcode.h" #include "settings/settings_local_passcode.h"
#include "settings/settings_main.h" #include "settings/settings_main.h"
#include "settings/cloud_password/settings_cloud_password_email_confirm.h"
#include "settings/cloud_password/settings_cloud_password_input.h"
#include "settings/cloud_password/settings_cloud_password_start.h"
#include "api/api_cloud_password.h"
#include "core/core_cloud_password.h"
#include "settings/settings_notifications.h" #include "settings/settings_notifications.h"
#include "settings/settings_notifications_type.h" #include "settings/settings_notifications_type.h"
#include "settings/settings_power_saving.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "ui/power_saving.h"
#include "settings/settings_privacy_security.h" #include "settings/settings_privacy_security.h"
#include "settings/settings_websites.h" #include "settings/settings_websites.h"
#include "boxes/connection_box.h"
#include "boxes/local_storage_box.h"
#include "mainwindow.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
namespace Core::DeepLinks { namespace Core::DeepLinks {
namespace { namespace {
Result ShowLanguageBox(const Context &ctx) { Result ShowLanguageBox(const Context &ctx, const QString &highlightId = QString()) {
static auto Guard = base::binary_guard(); static auto Guard = base::binary_guard();
Guard = LanguageBox::Show(ctx.controller); if (!highlightId.isEmpty() && ctx.controller) {
ctx.controller->setHighlightControlId(highlightId);
}
Guard = LanguageBox::Show(ctx.controller, highlightId);
return Result::Handled;
}
Result ShowPowerSavingBox(
const Context &ctx,
PowerSaving::Flags highlightFlags = PowerSaving::Flags()) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(
Box(::Settings::PowerSavingBox, highlightFlags),
Ui::LayerOption::KeepOther,
anim::type::normal);
return Result::Handled;
}
Result ShowMainMenuWithHighlight(const Context &ctx, const QString &highlightId) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->setHighlightControlId(highlightId);
ctx.controller->widget()->showMainMenu();
return Result::Handled; return Result::Handled;
} }
@@ -61,7 +108,9 @@ Result ShowSavedMessages(const Context &ctx) {
if (!ctx.controller) { if (!ctx.controller) {
return Result::NeedsAuth; return Result::NeedsAuth;
} }
ctx.controller->showPeerHistory(ctx.controller->session().userPeerId()); ctx.controller->showPeerHistory(
ctx.controller->session().userPeerId(),
Window::SectionShow::Way::Forward);
return Result::Handled; return Result::Handled;
} }
@@ -178,6 +227,49 @@ Result ShowLogOutMenu(const Context &ctx) {
return Result::Handled; return Result::Handled;
} }
Result ShowPasskeys(const Context &ctx, bool highlightCreate) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
const auto controller = ctx.controller;
const auto session = &controller->session();
const auto showBox = [=] {
if (highlightCreate) {
controller->setHighlightControlId(u"passkeys/create"_q);
}
if (session->passkeys().list().empty()) {
controller->show(Box([=](not_null<Ui::GenericBox*> box) {
::Settings::PasskeysNoneBox(box, session);
box->boxClosing() | rpl::on_next([=] {
if (!session->passkeys().list().empty()) {
controller->showSettings(::Settings::PasskeysId());
}
}, box->lifetime());
}));
} else {
controller->showSettings(::Settings::PasskeysId());
}
};
if (session->passkeys().listKnown()) {
showBox();
} else {
session->passkeys().requestList(
) | rpl::take(1) | rpl::on_next([=] {
showBox();
}, controller->lifetime());
}
return Result::Handled;
}
Result ShowAutoDeleteSetCustom(const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->setHighlightControlId(u"auto-delete/set-custom"_q);
ctx.controller->showSettings(::Settings::GlobalTTLId());
return Result::Handled;
}
Result ShowNotificationType( Result ShowNotificationType(
const Context &ctx, const Context &ctx,
Data::DefaultNotify type, Data::DefaultNotify type,
@@ -249,22 +341,49 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"my-profile/posts"_q, .path = u"my-profile/posts"_q,
.action = CodeBlock{ ShowMyProfile }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->setHighlightControlId(u"my-profile/posts"_q);
return ShowMyProfile(ctx);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"my-profile/posts/add-album"_q, .path = u"my-profile/posts/add-album"_q,
.action = CodeBlock{ ShowMyProfile }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->setHighlightControlId(u"my-profile/posts/add-album"_q);
return ShowMyProfile(ctx);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"my-profile/gifts"_q, .path = u"my-profile/gifts"_q,
.action = CodeBlock{ ShowMyProfile }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->showSection(
Info::PeerGifts::Make(ctx.controller->session().user()));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"my-profile/archived-posts"_q, .path = u"my-profile/archived-posts"_q,
.action = CodeBlock{ ShowMyProfile }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->showSection(Info::Stories::Make(
ctx.controller->session().user(),
Info::Stories::ArchiveId()));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -395,12 +514,60 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/active-websites/disconnect-all"_q, .path = u"privacy/active-websites/disconnect-all"_q,
.action = SettingsSection{ ::Settings::Websites::Id() }, .action = SettingsControl{
::Settings::Websites::Id(),
u"websites/disconnect-all"_q,
},
}); });
const auto openPasscode = [](const Context &ctx, const QString &highlight) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
if (!highlight.isEmpty()) {
ctx.controller->setHighlightControlId(highlight);
}
const auto &local = ctx.controller->session().domain().local();
if (local.hasLocalPasscode()) {
ctx.controller->showSettings(::Settings::LocalPasscodeCheckId());
} else {
ctx.controller->showSettings(::Settings::LocalPasscodeCreateId());
}
return Result::Handled;
};
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/passcode"_q, .path = u"privacy/passcode"_q,
.action = SettingsSection{ ::Settings::LocalPasscodeManageId() }, .action = CodeBlock{ [=](const Context &ctx) {
return openPasscode(ctx, QString());
}},
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/disable"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openPasscode(ctx, u"passcode/disable"_q);
}},
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/change"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openPasscode(ctx, u"passcode/change"_q);
}},
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/auto-lock"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openPasscode(ctx, u"passcode/auto-lock"_q);
}},
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/face-id"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openPasscode(ctx, u"passcode/biometrics"_q);
}},
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/fingerprint"_q,
.action = AliasTo{ u"settings"_q, u"privacy/passcode/face-id"_q },
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -408,64 +575,67 @@ void RegisterSettingsHandlers(Router &router) {
.action = SettingsSection{ ::Settings::GlobalTTLId() }, .action = SettingsSection{ ::Settings::GlobalTTLId() },
}); });
const auto openCloudPassword = [](const Context &ctx, const QString &highlight) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
if (!highlight.isEmpty()) {
ctx.controller->setHighlightControlId(highlight);
}
const auto state = ctx.controller->session().api().cloudPassword().stateCurrent();
if (!state) {
ctx.controller->showSettings(::Settings::CloudPasswordStartId());
} else if (!state->unconfirmedPattern.isEmpty()) {
ctx.controller->showSettings(::Settings::CloudPasswordEmailConfirmId());
} else if (state->hasPassword) {
ctx.controller->showSettings(::Settings::CloudPasswordInputId());
} else {
ctx.controller->showSettings(::Settings::CloudPasswordStartId());
}
return Result::Handled;
};
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/2sv"_q, .path = u"privacy/2sv"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = CodeBlock{ [=](const Context &ctx) {
return openCloudPassword(ctx, QString());
}},
});
router.add(u"settings"_q, {
.path = u"privacy/2sv/change"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openCloudPassword(ctx, u"2sv/change"_q);
}},
});
router.add(u"settings"_q, {
.path = u"privacy/2sv/disable"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openCloudPassword(ctx, u"2sv/disable"_q);
}},
});
router.add(u"settings"_q, {
.path = u"privacy/2sv/change-email"_q,
.action = CodeBlock{ [=](const Context &ctx) {
return openCloudPassword(ctx, u"2sv/change-email"_q);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/passkey"_q, .path = u"privacy/passkey"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = CodeBlock{ [](const Context &ctx) {
return ShowPasskeys(ctx, false);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/passkey/create"_q, .path = u"privacy/passkey/create"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = CodeBlock{ [](const Context &ctx) {
}); return ShowPasskeys(ctx, true);
}},
router.add(u"settings"_q, {
.path = u"privacy/passcode/disable"_q,
.action = SettingsSection{ ::Settings::LocalPasscodeManageId() },
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/change"_q,
.action = SettingsSection{ ::Settings::LocalPasscodeManageId() },
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/auto-lock"_q,
.action = SettingsSection{ ::Settings::LocalPasscodeManageId() },
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/face-id"_q,
.action = SettingsSection{ ::Settings::LocalPasscodeManageId() },
});
router.add(u"settings"_q, {
.path = u"privacy/passcode/fingerprint"_q,
.action = SettingsSection{ ::Settings::LocalPasscodeManageId() },
});
router.add(u"settings"_q, {
.path = u"privacy/2sv/change"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() },
});
router.add(u"settings"_q, {
.path = u"privacy/2sv/disable"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() },
});
router.add(u"settings"_q, {
.path = u"privacy/2sv/change-email"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() },
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/auto-delete/set-custom"_q, .path = u"privacy/auto-delete/set-custom"_q,
.action = SettingsSection{ ::Settings::GlobalTTLId() }, .action = CodeBlock{ ShowAutoDeleteSetCustom },
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -925,17 +1095,41 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/messages"_q, .path = u"privacy/messages"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(Box(EditMessagesPrivacyBox, ctx.controller, QString()));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/messages/set-price"_q, .path = u"privacy/messages/set-price"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(Box(
EditMessagesPrivacyBox,
ctx.controller,
u"privacy/set-price"_q));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/messages/remove-fee"_q, .path = u"privacy/messages/remove-fee"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(Box(
EditMessagesPrivacyBox,
ctx.controller,
u"privacy/remove-fee"_q));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -972,57 +1166,104 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/self-destruct"_q, .path = u"privacy/self-destruct"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = SettingsControl{
::Settings::PrivacySecurity::Id(),
u"privacy/self_destruct"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/data-settings/suggest-contacts"_q, .path = u"privacy/data-settings/suggest-contacts"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = SettingsControl{
::Settings::PrivacySecurity::Id(),
u"privacy/top_peers"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/data-settings/clear-payment-info"_q, .path = u"privacy/data-settings/clear-payment-info"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = SettingsControl{
::Settings::PrivacySecurity::Id(),
u"privacy/bots_payment"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"privacy/archive-and-mute"_q, .path = u"privacy/archive-and-mute"_q,
.action = SettingsSection{ ::Settings::PrivacySecurity::Id() }, .action = SettingsControl{
::Settings::PrivacySecurity::Id(),
u"privacy/archive_and_mute"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"data/storage"_q, .path = u"data/storage"_q,
.action = SettingsSection{ ::Settings::Advanced::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
LocalStorageBox::Show(ctx.controller);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, {
.path = u"data/proxy"_q,
.action = SettingsSection{ ::Settings::Advanced::Id() },
});
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"data/storage/clear-cache"_q, .path = u"data/storage/clear-cache"_q,
.action = SettingsSection{ ::Settings::Advanced::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
LocalStorageBox::Show(ctx.controller, u"storage/clear-cache"_q);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"data/max-cache"_q, .path = u"data/max-cache"_q,
.action = SettingsSection{ ::Settings::Advanced::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
LocalStorageBox::Show(ctx.controller, u"storage/max-cache"_q);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"data/show-18-content"_q, .path = u"data/show-18-content"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/show-18-content"_q,
},
}); });
router.add(u"settings"_q, {
.path = u"data/proxy"_q,
.action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ProxiesBoxController::Show(ctx.controller);
return Result::Handled;
}},
});
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"data/proxy/add-proxy"_q, .path = u"data/proxy/add-proxy"_q,
.action = SettingsSection{ ::Settings::Advanced::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ProxiesBoxController::Show(ctx.controller, u"proxy/add-proxy"_q);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"data/proxy/share-list"_q, .path = u"data/proxy/share-list"_q,
.action = SettingsSection{ ::Settings::Advanced::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ProxiesBoxController::Show(ctx.controller, u"proxy/share-list"_q);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -1032,52 +1273,78 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"power-saving"_q, .path = u"power-saving"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
return ShowPowerSavingBox(ctx);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"power-saving/stickers"_q, .path = u"power-saving/stickers"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
return ShowPowerSavingBox(ctx, PowerSaving::kStickersPanel);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"power-saving/emoji"_q, .path = u"power-saving/emoji"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
return ShowPowerSavingBox(ctx, PowerSaving::kEmojiPanel);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"power-saving/effects"_q, .path = u"power-saving/effects"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
return ShowPowerSavingBox(ctx, PowerSaving::kChatBackground);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/themes"_q, .path = u"appearance/themes"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/themes"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/themes/edit"_q, .path = u"appearance/themes/edit"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/themes-edit"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/themes/create"_q, .path = u"appearance/themes/create"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/themes-create"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/wallpapers"_q, .path = u"appearance/wallpapers"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/wallpapers"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/wallpapers/set"_q, .path = u"appearance/wallpapers/set"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/wallpapers-set"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/wallpapers/choose-photo"_q, .path = u"appearance/wallpapers/choose-photo"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/wallpapers-choose-photo"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -1122,95 +1389,160 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/night-mode"_q, .path = u"appearance/night-mode"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
return ShowMainMenuWithHighlight(ctx, u"main-menu/night-mode"_q);
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/auto-night-mode"_q, .path = u"appearance/auto-night-mode"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/auto-night-mode"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/text-size"_q, .path = u"appearance/text-size"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Main::Id(),
u"main/scale"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/animations"_q, .path = u"appearance/animations"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = AliasTo{ u"settings"_q, u"power-saving"_q },
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji"_q, .path = u"appearance/stickers-and-emoji"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/stickers-emoji"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/edit"_q, .path = u"appearance/stickers-and-emoji/edit"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(Box<StickersBox>(
ctx.controller->uiShow(),
StickersBox::Section::Installed));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/trending"_q, .path = u"appearance/stickers-and-emoji/trending"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(Box<StickersBox>(
ctx.controller->uiShow(),
StickersBox::Section::Featured));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/archived"_q, .path = u"appearance/stickers-and-emoji/archived"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(Box<StickersBox>(
ctx.controller->uiShow(),
StickersBox::Section::Archived));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/emoji"_q, .path = u"appearance/stickers-and-emoji/emoji"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
ctx.controller->show(
Box<Ui::Emoji::ManageSetsBox>(&ctx.controller->session()));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/emoji/suggest"_q, .path = u"appearance/stickers-and-emoji/emoji/suggest"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/suggest-animated-emoji"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/emoji/quick-reaction"_q, .path = u"appearance/stickers-and-emoji/emoji/quick-reaction"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/quick-reaction"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/emoji/quick-reaction/choose"_q, .path = u"appearance/stickers-and-emoji/emoji/quick-reaction/choose"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/quick-reaction-choose"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/suggest-by-emoji"_q, .path = u"appearance/stickers-and-emoji/suggest-by-emoji"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/suggest-by-emoji"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"appearance/stickers-and-emoji/emoji/large"_q, .path = u"appearance/stickers-and-emoji/emoji/large"_q,
.action = SettingsSection{ ::Settings::Chat::Id() }, .action = SettingsControl{
::Settings::Chat::Id(),
u"chat/large-emoji"_q,
},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"language"_q, .path = u"language"_q,
.action = CodeBlock{ ShowLanguageBox }, .action = CodeBlock{ [](const Context &ctx) {
return ShowLanguageBox(ctx);
}},
.requiresAuth = false, .requiresAuth = false,
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"language/show-button"_q, .path = u"language/show-button"_q,
.action = CodeBlock{ ShowLanguageBox }, .action = CodeBlock{ [](const Context &ctx) {
return ShowLanguageBox(ctx, u"language/show-button"_q);
}},
.requiresAuth = false, .requiresAuth = false,
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"language/translate-chats"_q, .path = u"language/translate-chats"_q,
.action = CodeBlock{ ShowLanguageBox }, .action = CodeBlock{ [](const Context &ctx) {
return ShowLanguageBox(ctx, u"language/translate-chats"_q);
}},
.requiresAuth = false, .requiresAuth = false,
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"language/do-not-translate"_q, .path = u"language/do-not-translate"_q,
.action = CodeBlock{ ShowLanguageBox }, .action = CodeBlock{ [](const Context &ctx) {
return ShowLanguageBox(ctx, u"language/do-not-translate"_q);
}},
.requiresAuth = false, .requiresAuth = false,
}); });
@@ -1226,31 +1558,51 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"stars/top-up"_q, .path = u"stars/top-up"_q,
.action = SettingsSection{ ::Settings::CreditsId() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
static auto handler = ::Settings::BuyStarsHandler();
handler.handler(ctx.controller->uiShow())();
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"stars/stats"_q, .path = u"stars/stats"_q,
.action = SettingsControl{ .action = CodeBlock{ [](const Context &ctx) {
::Settings::CreditsId(), if (!ctx.controller) {
u"stars/stats"_q, return Result::NeedsAuth;
}, }
const auto self = ctx.controller->session().user();
ctx.controller->showSection(Info::BotEarn::Make(self));
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"stars/gift"_q, .path = u"stars/gift"_q,
.action = SettingsControl{ .action = CodeBlock{ [](const Context &ctx) {
::Settings::CreditsId(), if (!ctx.controller) {
u"stars/gift"_q, return Result::NeedsAuth;
}, }
Ui::ShowGiftCreditsBox(ctx.controller, nullptr);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"stars/earn"_q, .path = u"stars/earn"_q,
.action = SettingsControl{ .action = CodeBlock{ [](const Context &ctx) {
::Settings::CreditsId(), if (!ctx.controller) {
u"stars/earn"_q, return Result::NeedsAuth;
}, }
const auto self = ctx.controller->session().user();
if (Info::BotStarRef::Join::Allowed(self)) {
ctx.controller->showSection(Info::BotStarRef::Join::Make(self));
}
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -1273,10 +1625,13 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"send-gift"_q, .path = u"send-gift"_q,
.action = SettingsControl{ .action = CodeBlock{ [](const Context &ctx) {
::Settings::Main::Id(), if (!ctx.controller) {
u"main/send-gift"_q, return Result::NeedsAuth;
}, }
Ui::ChooseStarGiftRecipient(ctx.controller);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -1302,7 +1657,13 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"calls/all"_q, .path = u"calls/all"_q,
.action = SettingsSection{ ::Settings::Calls::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
Calls::ShowCallsBox(ctx.controller);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -1313,18 +1674,22 @@ void RegisterSettingsHandlers(Router &router) {
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"ask-question"_q, .path = u"ask-question"_q,
.action = SettingsControl{ .action = CodeBlock{ [](const Context &ctx) {
::Settings::Main::Id(), if (!ctx.controller) {
u"main/ask-question"_q, return Result::NeedsAuth;
}, }
::Settings::OpenAskQuestionConfirm(ctx.controller);
return Result::Handled;
}},
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"features"_q, .path = u"features"_q,
.action = SettingsControl{ .action = CodeBlock{ [](const Context &ctx) {
::Settings::Main::Id(), UrlClickHandler::Open(tr::lng_telegram_features_url(tr::now));
u"main/features"_q, return Result::Handled;
}, }},
.requiresAuth = false,
}); });
router.add(u"settings"_q, { router.add(u"settings"_q, {
@@ -1415,7 +1780,13 @@ void RegisterSettingsHandlers(Router &router) {
// Calls deep links. // Calls deep links.
router.add(u"settings"_q, { router.add(u"settings"_q, {
.path = u"calls/start-call"_q, .path = u"calls/start-call"_q,
.action = SettingsSection{ ::Settings::Calls::Id() }, .action = CodeBlock{ [](const Context &ctx) {
if (!ctx.controller) {
return Result::NeedsAuth;
}
Calls::ShowCallsBox(ctx.controller, true);
return Result::Handled;
}},
}); });
// Devices (sessions) deep links. // Devices (sessions) deep links.
@@ -1280,7 +1280,7 @@ bool EditPaidMessagesFee(
ShowEditChatPermissions(controller, channel); ShowEditChatPermissions(controller, channel);
} }
} else { } else {
controller->show(Box(EditMessagesPrivacyBox, controller)); controller->show(Box(EditMessagesPrivacyBox, controller, QString()));
} }
return true; return true;
} }
@@ -104,7 +104,7 @@ Fn<FilterValue::Flags()> FillFilterValueList(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
bool isChannel, bool isChannel,
const FilterValue &filter) { const FilterValue &filter) {
auto [checkboxes, getResult, changes] = CreateEditAdminLogFilter( auto [checkboxes, getResult, changes, highlightWidget] = CreateEditAdminLogFilter(
container, container,
filter.flags ? (*filter.flags) : ~FilterValue::Flags(0), filter.flags ? (*filter.flags) : ~FilterValue::Flags(0),
isChannel); isChannel);
+13 -5
View File
@@ -786,17 +786,25 @@ void WrapWidget::showFinishedHook() {
_content->showFinished(); _content->showFinished();
if (_topBarMenuToggle if (_topBarMenuToggle
&& _controller->section().type() == Section::Type::Settings && _controller->section().type() == Section::Type::Settings) {
&& _controller->section().settingsType() == ::Settings::Main::Id()) {
const auto controller = _controller->parentController(); const auto controller = _controller->parentController();
const auto logoutId = u"settings/log-out"_q; const auto settingsType = _controller->section().settingsType();
if (controller->takeHighlightControlId(logoutId)) { const auto highlightId = [&]() -> QString {
if (settingsType == ::Settings::Main::Id()) {
return u"settings/log-out"_q;
} else if (settingsType == ::Settings::Chat::Id()) {
return u"chat/themes-create"_q;
}
return QString();
}();
if (!highlightId.isEmpty()
&& controller->takeHighlightControlId(highlightId)) {
showTopBarMenu(false); showTopBarMenu(false);
if (_topBarMenu) { if (_topBarMenu) {
const auto menu = _topBarMenu->menu(); const auto menu = _topBarMenu->menu();
for (const auto action : menu->actions()) { for (const auto action : menu->actions()) {
const auto controlId = "highlight-control-id"; const auto controlId = "highlight-control-id";
if (action->property(controlId).toString() == logoutId) { if (action->property(controlId).toString() == highlightId) {
if (const auto item = menu->itemForAction(action)) { if (const auto item = menu->itemForAction(action)) {
::Settings::HighlightWidget(item); ::Settings::HighlightWidget(item);
} }
@@ -545,6 +545,29 @@ void InnerWidget::enableBackButton() {
void InnerWidget::showFinished() { void InnerWidget::showFinished() {
_showFinished.fire({}); _showFinished.fire({});
const auto window = _controller->parentController();
const auto id = window->highlightControlId();
if (id.isEmpty()) {
return;
}
if (id == u"my-profile/posts"_q) {
window->setHighlightControlId(QString());
if (_albumsWrap) {
::Settings::HighlightWidget(_albumsWrap);
}
} else if (id == u"my-profile/posts/add-album"_q) {
window->setHighlightControlId(QString());
if (_albumsWrap) {
::Settings::HighlightWidget(_albumsWrap);
}
_controller->uiShow()->show(Box(
NewAlbumBox,
_controller,
_peer,
StoryId(),
[=](Data::StoryAlbum album) { albumAdded(album); }));
}
} }
void InnerWidget::finalizeTop() { void InnerWidget::finalizeTop() {
@@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_chat.h" #include "settings/settings_chat.h"
#include "settings/settings_experimental.h" #include "settings/settings_experimental.h"
#include "settings/settings_power_saving.h" #include "settings/settings_power_saving.h"
#include "ui/power_saving.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "storage/storage_domain.h" #include "storage/storage_domain.h"
#include "tray.h" #include "tray.h"
@@ -746,7 +747,7 @@ void BuildPerformanceSection(
.st = &st::settingsButtonNoIcon, .st = &st::settingsButtonNoIcon,
.onClick = [=] { .onClick = [=] {
if (controller) { if (controller) {
controller->window().show(Box(PowerSavingBox)); controller->window().show(Box(PowerSavingBox, PowerSaving::Flags()));
} }
}, },
.keywords = { u"power"_q, u"saving"_q, u"battery"_q, u"animation"_q }, .keywords = { u"power"_q, u"saving"_q, u"battery"_q, u"animation"_q },
@@ -40,7 +40,8 @@ SectionBuilder::SectionBuilder(BuildContext context)
} }
Ui::RpWidget *SectionBuilder::addControl(ControlArgs &&args) { Ui::RpWidget *SectionBuilder::addControl(ControlArgs &&args) {
return v::match(_context, [&](const WidgetContext &ctx) { const auto id = args.id;
const auto raw = v::match(_context, [&](const WidgetContext &ctx) {
if (!args.factory) { if (!args.factory) {
return static_cast<Ui::RpWidget*>(nullptr); return static_cast<Ui::RpWidget*>(nullptr);
} }
@@ -58,6 +59,10 @@ Ui::RpWidget *SectionBuilder::addControl(ControlArgs &&args) {
} }
return static_cast<Ui::RpWidget*>(nullptr); return static_cast<Ui::RpWidget*>(nullptr);
}); });
if (raw && !id.isEmpty()) {
registerHighlight(id, raw, {});
}
return raw;
} }
Ui::SettingsButton *SectionBuilder::addSettingsButton(ButtonArgs &&args) { Ui::SettingsButton *SectionBuilder::addSettingsButton(ButtonArgs &&args) {
@@ -461,6 +466,14 @@ Fn<void(Type)> SectionBuilder::showOther() const {
}); });
} }
HighlightRegistry *SectionBuilder::highlights() const {
return v::match(_context, [](const WidgetContext &ctx) {
return ctx.highlights;
}, [](const SearchContext &) -> HighlightRegistry* {
return nullptr;
});
}
void SectionBuilder::registerHighlight( void SectionBuilder::registerHighlight(
QString id, QString id,
QWidget *widget, QWidget *widget,
@@ -201,6 +201,7 @@ public:
[[nodiscard]] Ui::VerticalLayout *container() const; [[nodiscard]] Ui::VerticalLayout *container() const;
[[nodiscard]] Window::SessionController *controller() const; [[nodiscard]] Window::SessionController *controller() const;
[[nodiscard]] Fn<void(Type)> showOther() const; [[nodiscard]] Fn<void(Type)> showOther() const;
[[nodiscard]] HighlightRegistry *highlights() const;
private: private:
void registerHighlight( void registerHighlight(
@@ -30,7 +30,8 @@ namespace {
void BuildChatSectionContent( void BuildChatSectionContent(
SectionBuilder &builder, SectionBuilder &builder,
Window::SessionController *controller, Window::SessionController *controller,
Fn<void(Type)> showOther) { Fn<void(Type)> showOther,
HighlightRegistry *highlights) {
if (!controller) { if (!controller) {
builder.addSettingsButton({ builder.addSettingsButton({
.id = u"appearance/theme"_q, .id = u"appearance/theme"_q,
@@ -116,15 +117,15 @@ void BuildChatSectionContent(
auto updateOnTick = rpl::single( auto updateOnTick = rpl::single(
) | rpl::then(base::timer_each(60 * crl::time(1000))); ) | rpl::then(base::timer_each(60 * crl::time(1000)));
SetupThemeOptions(controller, container); SetupThemeOptions(controller, container, highlights);
SetupThemeSettings(controller, container); SetupThemeSettings(controller, container, highlights);
SetupCloudThemes(controller, container); SetupCloudThemes(controller, container, highlights);
SetupChatBackground(controller, container); SetupChatBackground(controller, container, highlights);
SetupChatListQuickAction(controller, container); SetupChatListQuickAction(controller, container);
SetupStickersEmoji(controller, container); SetupStickersEmoji(controller, container, highlights);
SetupMessages(controller, container); SetupMessages(controller, container, highlights);
Ui::AddDivider(container); Ui::AddDivider(container);
SetupSensitiveContent(controller, container, std::move(updateOnTick)); SetupSensitiveContent(controller, container, std::move(updateOnTick), highlights);
SetupArchive(controller, container, showOther); SetupArchive(controller, container, showOther);
} }
@@ -146,7 +147,7 @@ void ChatSection(
.highlights = highlights, .highlights = highlights,
}); });
BuildChatSectionContent(builder, controller, showOther); BuildChatSectionContent(builder, controller, showOther, highlights);
std::move(showFinished) | rpl::on_next([=] { std::move(showFinished) | rpl::on_next([=] {
for (const auto &[id, entry] : *highlights) { for (const auto &[id, entry] : *highlights) {
@@ -163,7 +164,7 @@ void ChatSection(
std::vector<SearchEntry> ChatSectionForSearch() { std::vector<SearchEntry> ChatSectionForSearch() {
std::vector<SearchEntry> entries; std::vector<SearchEntry> entries;
SectionBuilder builder(SearchContext{ .entries = &entries }); SectionBuilder builder(SearchContext{ .entries = &entries });
BuildChatSectionContent(builder, nullptr, nullptr); BuildChatSectionContent(builder, nullptr, nullptr, nullptr);
return entries; return entries;
} }
@@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_main.h" #include "settings/settings_main.h"
#include "settings/settings_notifications.h" #include "settings/settings_notifications.h"
#include "settings/settings_power_saving.h" #include "settings/settings_power_saving.h"
#include "ui/power_saving.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "settings/settings_privacy_security.h" #include "settings/settings_privacy_security.h"
#include "ui/basic_click_handlers.h" #include "ui/basic_click_handlers.h"
@@ -149,7 +150,7 @@ void BuildSectionButtons(
.title = tr::lng_settings_power_menu(), .title = tr::lng_settings_power_menu(),
.icon = { &st::menuIconPowerUsage }, .icon = { &st::menuIconPowerUsage },
.onClick = window .onClick = window
? Fn<void()>([=] { window->show(Box(PowerSavingBox)); }) ? Fn<void()>([=] { window->show(Box(PowerSavingBox, PowerSaving::Flags())); })
: Fn<void()>(nullptr), : Fn<void()>(nullptr),
.keywords = { u"battery"_q, u"animations"_q, u"power"_q, u"saving"_q }, .keywords = { u"battery"_q, u"animations"_q, u"power"_q, u"saving"_q },
}); });
@@ -298,20 +299,11 @@ void BuildHelpSection(
builder.addDivider(); builder.addDivider();
builder.addSkip(); builder.addSkip();
const auto faqClick = controller
? [=] {
UrlClickHandler::Open(
tr::lng_settings_faq_link(tr::now),
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(controller),
}));
}
: Fn<void()>();
builder.addSettingsButton({ builder.addSettingsButton({
.id = u"main/faq"_q, .id = u"main/faq"_q,
.title = tr::lng_settings_faq(), .title = tr::lng_settings_faq(),
.icon = { &st::menuIconFaq }, .icon = { &st::menuIconFaq },
.onClick = faqClick, .onClick = [=] { OpenFaq(controller); },
.keywords = { u"help"_q, u"support"_q, u"questions"_q }, .keywords = { u"help"_q, u"support"_q, u"questions"_q },
}); });
@@ -329,9 +321,7 @@ void BuildHelpSection(
.id = u"main/ask-question"_q, .id = u"main/ask-question"_q,
.title = tr::lng_settings_ask_question(), .title = tr::lng_settings_ask_question(),
.icon = { &st::menuIconDiscussion }, .icon = { &st::menuIconDiscussion },
.onClick = [] { .onClick = [=] { OpenAskQuestionConfirm(controller); },
UrlClickHandler::Open(tr::lng_telegram_features_url(tr::now));
},
.keywords = { u"contact"_q, u"feedback"_q }, .keywords = { u"contact"_q, u"feedback"_q },
}); });
@@ -395,7 +395,7 @@ void BuildPrivacySection(
.st = &st::settingsButtonNoIcon, .st = &st::settingsButtonNoIcon,
.label = rpl::duplicate(messagesLabel), .label = rpl::duplicate(messagesLabel),
.onClick = [=] { .onClick = [=] {
controller->show(Box(EditMessagesPrivacyBox, controller)); controller->show(Box(EditMessagesPrivacyBox, controller, QString()));
}, },
.keywords = { u"messages"_q, u"new"_q, u"unknown"_q }, .keywords = { u"messages"_q, u"new"_q, u"unknown"_q },
}); });
@@ -466,13 +466,13 @@ void BuildPrivacySection(
void BuildArchiveAndMuteSection( void BuildArchiveAndMuteSection(
SectionBuilder &builder, SectionBuilder &builder,
not_null<Window::SessionController*> controller) { not_null<Window::SessionController*> controller) {
SetupArchiveAndMute(controller, builder.container()); SetupArchiveAndMute(controller, builder.container(), builder.highlights());
} }
void BuildBotsAndWebsitesSection( void BuildBotsAndWebsitesSection(
SectionBuilder &builder, SectionBuilder &builder,
not_null<Window::SessionController*> controller) { not_null<Window::SessionController*> controller) {
SetupBotsAndWebsites(controller, builder.container()); SetupBotsAndWebsites(controller, builder.container(), builder.highlights());
} }
void BuildTopPeersSection( void BuildTopPeersSection(
@@ -53,11 +53,11 @@ BottomButton CreateBottomDisableButton(
Ui::AddSkip(content); Ui::AddSkip(content);
content->add(object_ptr<Button>( const auto button = content->add(object_ptr<Button>(
content, content,
std::move(buttonText), std::move(buttonText),
st::settingsAttentionButton st::settingsAttentionButton));
))->addClickHandler(std::move(callback)); button->addClickHandler(std::move(callback));
const auto divider = Ui::CreateChild<OneEdgeBoxContentDivider>( const auto divider = Ui::CreateChild<OneEdgeBoxContentDivider>(
parent.get()); parent.get());
@@ -81,6 +81,7 @@ BottomButton CreateBottomDisableButton(
return { return {
.content = base::make_weak(content), .content = base::make_weak(content),
.button = base::make_weak(button),
.isBottomFillerShown = divider->geometryValue( .isBottomFillerShown = divider->geometryValue(
) | rpl::map([](const QRect &r) { ) | rpl::map([](const QRect &r) {
return r.height() > 0; return r.height() > 0;
@@ -81,6 +81,7 @@ void AddSkipInsteadOfError(not_null<Ui::VerticalLayout*> content);
struct BottomButton { struct BottomButton {
base::weak_qptr<Ui::RpWidget> content; base::weak_qptr<Ui::RpWidget> content;
base::weak_qptr<Ui::RpWidget> button;
rpl::producer<bool> isBottomFillerShown; rpl::producer<bool> isBottomFillerShown;
}; };
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/core_cloud_password.h" #include "core/core_cloud_password.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "settings/cloud_password/settings_cloud_password_common.h" #include "settings/cloud_password/settings_cloud_password_common.h"
#include "settings/settings_common.h"
#include "settings/cloud_password/settings_cloud_password_email_confirm.h" #include "settings/cloud_password/settings_cloud_password_email_confirm.h"
#include "settings/cloud_password/settings_cloud_password_email.h" #include "settings/cloud_password/settings_cloud_password_email.h"
#include "settings/cloud_password/settings_cloud_password_hint.h" #include "settings/cloud_password/settings_cloud_password_hint.h"
@@ -66,6 +67,10 @@ private:
rpl::lifetime _requestLifetime; rpl::lifetime _requestLifetime;
QPointer<Ui::RpWidget> _changePasswordButton;
QPointer<Ui::RpWidget> _changeEmailButton;
QPointer<Ui::RpWidget> _disableButton;
}; };
rpl::producer<QString> Manage::title() { rpl::producer<QString> Manage::title() {
@@ -134,22 +139,24 @@ void Manage::setupContent() {
}); });
Ui::AddSkip(content); Ui::AddSkip(content);
AddButtonWithIcon( const auto changePasswordButton = AddButtonWithIcon(
content, content,
tr::lng_settings_cloud_password_manage_password_change(), tr::lng_settings_cloud_password_manage_password_change(),
st::settingsButton, st::settingsButton,
{ &st::menuIconPermissions } { &st::menuIconPermissions });
)->setClickedCallback([=] { _changePasswordButton = changePasswordButton;
changePasswordButton->setClickedCallback([=] {
showOtherAndRememberPassword(CloudPasswordInputId()); showOtherAndRememberPassword(CloudPasswordInputId());
}); });
AddButtonWithIcon( const auto changeEmailButton = AddButtonWithIcon(
content, content,
state->hasRecovery state->hasRecovery
? tr::lng_settings_cloud_password_manage_email_change() ? tr::lng_settings_cloud_password_manage_email_change()
: tr::lng_settings_cloud_password_manage_email_new(), : tr::lng_settings_cloud_password_manage_email_new(),
st::settingsButton, st::settingsButton,
{ &st::menuIconRecoveryEmail } { &st::menuIconRecoveryEmail });
)->setClickedCallback([=] { _changeEmailButton = changeEmailButton;
changeEmailButton->setClickedCallback([=] {
auto data = stepData(); auto data = stepData();
data.setOnlyRecoveryEmail = true; data.setOnlyRecoveryEmail = true;
setStepData(std::move(data)); setStepData(std::move(data));
@@ -158,6 +165,29 @@ void Manage::setupContent() {
}); });
Ui::AddSkip(content); Ui::AddSkip(content);
showFinishes() | rpl::take(1) | rpl::on_next([=] {
const auto id = controller()->highlightControlId();
if (id.isEmpty()) {
return;
}
if (id == u"2sv/change"_q) {
controller()->setHighlightControlId(QString());
if (_changePasswordButton) {
HighlightWidget(_changePasswordButton);
}
} else if (id == u"2sv/change-email"_q) {
controller()->setHighlightControlId(QString());
if (_changeEmailButton) {
HighlightWidget(_changeEmailButton);
}
} else if (id == u"2sv/disable"_q) {
controller()->setHighlightControlId(QString());
if (_disableButton) {
HighlightWidget(_disableButton);
}
}
}, lifetime());
using Divider = CloudPassword::OneEdgeBoxContentDivider; using Divider = CloudPassword::OneEdgeBoxContentDivider;
const auto divider = Ui::CreateChild<Divider>(this); const auto divider = Ui::CreateChild<Divider>(this);
divider->lower(); divider->lower();
@@ -222,6 +252,7 @@ base::weak_qptr<Ui::RpWidget> Manage::createPinnedToBottom(
std::move(callback)); std::move(callback));
_isBottomFillerShown = base::take(bottomButton.isBottomFillerShown); _isBottomFillerShown = base::take(bottomButton.isBottomFillerShown);
_disableButton = bottomButton.button.get();
return bottomButton.content; return bottomButton.content;
} }
@@ -719,7 +719,7 @@ void SetupAnimations(
container, container,
tr::lng_settings_power_menu(), tr::lng_settings_power_menu(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
))->setClickedCallback([=] { window->show(Box(PowerSavingBox)); }); ))->setClickedCallback([=] { window->show(Box(PowerSavingBox, PowerSaving::Flags())); });
} }
void ArchiveSettingsBox( void ArchiveSettingsBox(
@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "settings/settings_business.h" #include "settings/settings_business.h"
#include "base/call_delayed.h"
#include "api/api_chat_links.h" #include "api/api_chat_links.h"
#include "boxes/premium_preview_box.h" #include "boxes/premium_preview_box.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
@@ -720,7 +722,11 @@ base::weak_qptr<Ui::RpWidget> Business::createPinnedToTop(
void Business::showFinished() { void Business::showFinished() {
_showFinished.fire({}); _showFinished.fire({});
_controller->checkHighlightControl(u"business/sponsored"_q, _sponsoredButton); crl::on_main(this, [=] {
_controller->checkHighlightControl(
u"business/sponsored"_q,
_sponsoredButton);
});
} }
base::weak_qptr<Ui::RpWidget> Business::createPinnedToBottom( base::weak_qptr<Ui::RpWidget> Business::createPinnedToBottom(
+169 -25
View File
@@ -30,9 +30,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/widgets/fields/input_field.h" #include "ui/widgets/fields/input_field.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/color_editor.h" #include "ui/widgets/color_editor.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/labels.h"
#include "ui/chat/attach/attach_extensions.h" #include "ui/chat/attach/attach_extensions.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
@@ -83,6 +84,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_window.h" #include "styles/style_window.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include <QAction>
namespace Settings { namespace Settings {
namespace { namespace {
@@ -98,6 +101,7 @@ public:
void show(Type type); void show(Type type);
[[nodiscard]] Ui::RpWidget *editButton() const;
rpl::producer<QColor> selected() const; rpl::producer<QColor> selected() const;
private: private:
@@ -113,6 +117,7 @@ private:
rpl::producer<> clicks() const; rpl::producer<> clicks() const;
bool selected() const; bool selected() const;
QColor color() const; QColor color() const;
Ui::RpWidget *widget() const;
private: private:
void paint(); void paint();
@@ -217,6 +222,10 @@ QColor ColorsPalette::Button::color() const {
return _colors.front(); return _colors.front();
} }
Ui::RpWidget *ColorsPalette::Button::widget() const {
return const_cast<Ui::AbstractButton*>(&_widget);
}
void ColorsPalette::Button::paint() { void ColorsPalette::Button::paint() {
auto p = QPainter(&_widget); auto p = QPainter(&_widget);
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
@@ -246,6 +255,10 @@ ColorsPalette::ColorsPalette(not_null<Ui::VerticalLayout*> container)
}, inner->lifetime()); }, inner->lifetime());
} }
Ui::RpWidget *ColorsPalette::editButton() const {
return _buttons.empty() ? nullptr : _buttons.back()->widget();
}
void ColorsPalette::show(Type type) { void ColorsPalette::show(Type type) {
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type); const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
if (scheme == end(kSchemesList)) { if (scheme == end(kSchemesList)) {
@@ -384,7 +397,7 @@ void ColorsPalette::updateInnerGeometry() {
button->moveToLeft(int(base::SafeRound(x)), y); button->moveToLeft(int(base::SafeRound(x)), y);
x += size + skip; x += size + skip;
} }
inner->resize(inner->width(), y + size); inner->resize(inner->width(), y + size + st::defaultVerticalListSkip);
} }
} // namespace } // namespace
@@ -419,6 +432,9 @@ public:
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller); not_null<Window::SessionController*> controller);
[[nodiscard]] Ui::LinkButton *chooseFromGallery() const;
[[nodiscard]] Ui::LinkButton *chooseFromFile() const;
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
@@ -545,6 +561,14 @@ int BackgroundRow::resizeGetHeight(int newWidth) {
return st::settingsBackgroundThumb; return st::settingsBackgroundThumb;
} }
Ui::LinkButton *BackgroundRow::chooseFromGallery() const {
return _chooseFromGallery.data();
}
Ui::LinkButton *BackgroundRow::chooseFromFile() const {
return _chooseFromFile.data();
}
float64 BackgroundRow::radialProgress() const { float64 BackgroundRow::radialProgress() const {
return _controller->content()->chatBackgroundProgress(); return _controller->content()->chatBackgroundProgress();
} }
@@ -714,10 +738,21 @@ void ChooseFromFile(
void SetupStickersEmoji( void SetupStickersEmoji(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddSubsectionTitle(container, tr::lng_settings_stickers_emoji()); const auto title = Ui::AddSubsectionTitle(
container,
tr::lng_settings_stickers_emoji());
if (highlights) {
highlights->push_back({
u"chat/stickers-emoji"_q,
Builder::HighlightEntry{
title.get(),
SubsectionTitleHighlight() },
});
}
const auto session = &controller->session(); const auto session = &controller->session();
@@ -736,7 +771,7 @@ void SetupStickersEmoji(
st::settingsCheckbox); st::settingsCheckbox);
}; };
const auto add = [&](const QString &label, bool checked, auto &&handle) { const auto add = [&](const QString &label, bool checked, auto &&handle) {
inner->add( return inner->add(
checkbox(label, checked), checkbox(label, checked),
st::settingsCheckboxPadding st::settingsCheckboxPadding
)->checkedChanges( )->checkedChanges(
@@ -744,29 +779,49 @@ void SetupStickersEmoji(
std::move(handle), std::move(handle),
inner->lifetime()); inner->lifetime());
}; };
const auto addWithReturn = [&](
const QString &label,
bool checked,
auto &&handle) {
const auto result = inner->add(
checkbox(label, checked),
st::settingsCheckboxPadding);
result->checkedChanges(
) | rpl::on_next(
std::move(handle),
inner->lifetime());
return result;
};
const auto addSliding = [&]( const auto addSliding = [&](
const QString &label, const QString &label,
bool checked, bool checked,
auto &&handle, auto &&handle,
rpl::producer<bool> shown) { rpl::producer<bool> shown) {
inner->add( const auto wrap = inner->add(
object_ptr<Ui::SlideWrap<Ui::Checkbox>>( object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
inner, inner,
checkbox(label, checked), checkbox(label, checked),
st::settingsCheckboxPadding) st::settingsCheckboxPadding));
)->setDuration(0)->toggleOn(std::move(shown))->entity()->checkedChanges( wrap->setDuration(0)->toggleOn(std::move(shown))->entity()->checkedChanges(
) | rpl::on_next( ) | rpl::on_next(
std::move(handle), std::move(handle),
inner->lifetime()); inner->lifetime());
return wrap->entity();
}; };
add( const auto largeEmoji = addWithReturn(
tr::lng_settings_large_emoji(tr::now), tr::lng_settings_large_emoji(tr::now),
Core::App().settings().largeEmoji(), Core::App().settings().largeEmoji(),
[=](bool checked) { [=](bool checked) {
Core::App().settings().setLargeEmoji(checked); Core::App().settings().setLargeEmoji(checked);
Core::App().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
}); });
if (highlights) {
highlights->push_back({
u"chat/large-emoji"_q,
Builder::HighlightEntry{ largeEmoji, { .radius = st::boxRadius } },
});
}
add( add(
tr::lng_settings_replace_emojis(tr::now), tr::lng_settings_replace_emojis(tr::now),
@@ -789,7 +844,7 @@ void SetupStickersEmoji(
}); });
using namespace rpl::mappers; using namespace rpl::mappers;
addSliding( const auto suggestAnimated = addSliding(
tr::lng_settings_suggest_animated_emoji(tr::now), tr::lng_settings_suggest_animated_emoji(tr::now),
Core::App().settings().suggestAnimatedEmoji(), Core::App().settings().suggestAnimatedEmoji(),
[=](bool checked) { [=](bool checked) {
@@ -800,14 +855,26 @@ void SetupStickersEmoji(
Data::AmPremiumValue(session), Data::AmPremiumValue(session),
suggestEmoji->value(), suggestEmoji->value(),
_1 && _2)); _1 && _2));
if (highlights) {
highlights->push_back({
u"chat/suggest-animated-emoji"_q,
Builder::HighlightEntry{ suggestAnimated, { .radius = st::boxRadius } },
});
}
add( const auto suggestByEmoji = addWithReturn(
tr::lng_settings_suggest_by_emoji(tr::now), tr::lng_settings_suggest_by_emoji(tr::now),
Core::App().settings().suggestStickersByEmoji(), Core::App().settings().suggestStickersByEmoji(),
[=](bool checked) { [=](bool checked) {
Core::App().settings().setSuggestStickersByEmoji(checked); Core::App().settings().setSuggestStickersByEmoji(checked);
Core::App().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
}); });
if (highlights) {
highlights->push_back({
u"chat/suggest-by-emoji"_q,
Builder::HighlightEntry{ suggestByEmoji, { .radius = st::boxRadius } },
});
}
add( add(
tr::lng_settings_loop_stickers(tr::now), tr::lng_settings_loop_stickers(tr::now),
@@ -842,7 +909,8 @@ void SetupStickersEmoji(
void SetupMessages( void SetupMessages(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
Ui::AddDivider(container); Ui::AddDivider(container);
Ui::AddSkip(container); Ui::AddSkip(container);
@@ -904,6 +972,12 @@ void SetupMessages(
const auto react = addQuick( const auto react = addQuick(
Quick::React, Quick::React,
tr::lng_settings_chat_quick_action_react(tr::now)); tr::lng_settings_chat_quick_action_react(tr::now));
if (highlights) {
highlights->push_back({
u"chat/quick-reaction"_q,
Builder::HighlightEntry{ react, { .radius = st::boxRadius } },
});
}
const auto buttonRight = Ui::CreateSimpleCircleButton( const auto buttonRight = Ui::CreateSimpleCircleButton(
inner, inner,
@@ -996,6 +1070,14 @@ void SetupMessages(
buttonRight->setClickedCallback([=, show = controller->uiShow()] { buttonRight->setClickedCallback([=, show = controller->uiShow()] {
show->showBox(Box(ReactionsSettingsBox, controller)); show->showBox(Box(ReactionsSettingsBox, controller));
}); });
if (highlights) {
highlights->push_back({
u"chat/quick-reaction-choose"_q,
Builder::HighlightEntry{
buttonRight.get(),
{ .shape = HighlightShape::Ellipse } },
});
}
Ui::AddSkip(inner, st::settingsSendTypeSkip); Ui::AddSkip(inner, st::settingsSendTypeSkip);
@@ -1206,16 +1288,43 @@ void SetupAutoDownload(
void SetupChatBackground( void SetupChatBackground(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
Ui::AddDivider(container); Ui::AddDivider(container);
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddSubsectionTitle(container, tr::lng_settings_section_background()); const auto title = Ui::AddSubsectionTitle(
container,
tr::lng_settings_section_background());
container->add( const auto row = container->add(
object_ptr<BackgroundRow>(container, controller), object_ptr<BackgroundRow>(container, controller),
st::settingsBackgroundPadding); st::settingsBackgroundPadding);
if (highlights) {
highlights->push_back({
u"chat/wallpapers"_q,
Builder::HighlightEntry{
title.get(),
SubsectionTitleHighlight(),
},
});
highlights->push_back({
u"chat/wallpapers-set"_q,
Builder::HighlightEntry{
row->chooseFromGallery(),
SubsectionTitleHighlight(),
},
});
highlights->push_back({
u"chat/wallpapers-choose-photo"_q,
Builder::HighlightEntry{
row->chooseFromFile(),
SubsectionTitleHighlight(),
},
});
}
const auto skipTop = st::settingsCheckbox.margin.top(); const auto skipTop = st::settingsCheckbox.margin.top();
const auto skipBottom = st::settingsCheckbox.margin.bottom(); const auto skipBottom = st::settingsCheckbox.margin.bottom();
auto wrap = object_ptr<Ui::VerticalLayout>(container); auto wrap = object_ptr<Ui::VerticalLayout>(container);
@@ -1511,7 +1620,8 @@ void SetupChatListQuickAction(
void SetupDefaultThemes( void SetupDefaultThemes(
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
using Type = Window::Theme::EmbeddedType; using Type = Window::Theme::EmbeddedType;
using Scheme = Window::Theme::EmbeddedScheme; using Scheme = Window::Theme::EmbeddedScheme;
using Check = Window::Theme::CloudListCheck; using Check = Window::Theme::CloudListCheck;
@@ -1627,6 +1737,17 @@ void SetupDefaultThemes(
refreshColorizer(scheme.type); refreshColorizer(scheme.type);
} }
if (highlights) {
const auto add = st::roundRadiusSmall;
highlights->push_back({ u"chat/themes-edit"_q, {
palette->editButton(),
{
.margin = { -add, -add, -add, -add },
.shape = HighlightShape::Ellipse,
},
}});
}
Background()->updates( Background()->updates(
) | rpl::filter([](const BackgroundUpdate &update) { ) | rpl::filter([](const BackgroundUpdate &update) {
return (update.type == BackgroundUpdate::Type::ApplyingTheme); return (update.type == BackgroundUpdate::Type::ApplyingTheme);
@@ -1700,21 +1821,34 @@ void SetupDefaultThemes(
void SetupThemeOptions( void SetupThemeOptions(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
using namespace Window::Theme; using namespace Window::Theme;
Ui::AddSkip(container, st::settingsPrivacySkip); Ui::AddSkip(container, st::settingsPrivacySkip);
Ui::AddSubsectionTitle(container, tr::lng_settings_themes()); const auto title = Ui::AddSubsectionTitle(
container,
tr::lng_settings_themes());
if (highlights) {
highlights->push_back({
u"chat/themes"_q,
Builder::HighlightEntry{
title.get(),
SubsectionTitleHighlight(),
},
});
}
Ui::AddSkip(container, st::settingsThemesTopSkip); Ui::AddSkip(container, st::settingsThemesTopSkip);
SetupDefaultThemes(&controller->window(), container); SetupDefaultThemes(&controller->window(), container, highlights);
Ui::AddSkip(container); Ui::AddSkip(container);
} }
void SetupCloudThemes( void SetupCloudThemes(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
using namespace Window::Theme; using namespace Window::Theme;
using namespace rpl::mappers; using namespace rpl::mappers;
@@ -1806,7 +1940,8 @@ void SetupCloudThemes(
void SetupThemeSettings( void SetupThemeSettings(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
Ui::AddDivider(container); Ui::AddDivider(container);
Ui::AddSkip(container, st::settingsPrivacySkip); Ui::AddSkip(container, st::settingsPrivacySkip);
@@ -1826,13 +1961,13 @@ void SetupThemeSettings(
? tr::lng_settings_auto_night_mode_on() ? tr::lng_settings_auto_night_mode_on()
: tr::lng_settings_auto_night_mode_off(); : tr::lng_settings_auto_night_mode_off();
}) | rpl::flatten_latest(); }) | rpl::flatten_latest();
AddButtonWithLabel( const auto button = AddButtonWithLabel(
container, container,
tr::lng_settings_auto_night_mode(), tr::lng_settings_auto_night_mode(),
std::move(label), std::move(label),
st::settingsButton, st::settingsButton,
{ &st::menuIconNightMode } { &st::menuIconNightMode });
)->setClickedCallback([=] { button->setClickedCallback([=] {
const auto now = !settings->systemDarkModeEnabled(); const auto now = !settings->systemDarkModeEnabled();
if (now && Window::Theme::Background()->editingTheme()) { if (now && Window::Theme::Background()->editingTheme()) {
controller->show(Ui::MakeInformBox( controller->show(Ui::MakeInformBox(
@@ -1842,6 +1977,12 @@ void SetupThemeSettings(
Core::App().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
} }
}); });
if (highlights) {
highlights->push_back({
u"chat/auto-night-mode"_q,
Builder::HighlightEntry{ button.get(), {} },
});
}
} }
const auto family = container->lifetime().make_state< const auto family = container->lifetime().make_state<
@@ -2031,10 +2172,13 @@ rpl::producer<QString> Chat::title() {
void Chat::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { void Chat::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) {
const auto window = &_controller->window(); const auto window = &_controller->window();
addAction( const auto createTheme = addAction(
tr::lng_settings_bg_theme_create(tr::now), tr::lng_settings_bg_theme_create(tr::now),
[=] { window->show(Box(Window::Theme::CreateBox, window)); }, [=] { window->show(Box(Window::Theme::CreateBox, window)); },
&st::menuIconChangeColors); &st::menuIconChangeColors);
createTheme->setProperty(
"highlight-control-id",
u"chat/themes-create"_q);
} }
void Chat::setupContent(not_null<Window::SessionController*> controller) { void Chat::setupContent(not_null<Window::SessionController*> controller) {
+21 -8
View File
@@ -15,6 +15,11 @@ class Controller;
namespace Settings { namespace Settings {
namespace Builder {
struct HighlightEntry;
using HighlightRegistry = std::vector<std::pair<QString, HighlightEntry>>;
} // namespace Builder
void SetupDataStorage( void SetupDataStorage(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container);
@@ -23,7 +28,8 @@ void SetupAutoDownload(
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container);
void SetupDefaultThemes( void SetupDefaultThemes(
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupSupport( void SetupSupport(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container);
@@ -40,19 +46,23 @@ void PaintRoundColorButton(
void SetupThemeOptions( void SetupThemeOptions(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupThemeSettings( void SetupThemeSettings(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupCloudThemes( void SetupCloudThemes(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupChatBackground( void SetupChatBackground(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupChatListQuickAction( void SetupChatListQuickAction(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
@@ -60,11 +70,13 @@ void SetupChatListQuickAction(
void SetupStickersEmoji( void SetupStickersEmoji(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupMessages( void SetupMessages(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupArchive( void SetupArchive(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
@@ -74,7 +86,8 @@ void SetupArchive(
void SetupSensitiveContent( void SetupSensitiveContent(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
rpl::producer<> updateTrigger); rpl::producer<> updateTrigger,
Builder::HighlightRegistry *highlights = nullptr);
class Chat : public Section<Chat> { class Chat : public Section<Chat> {
public: public:
@@ -285,6 +285,11 @@ void ScrollToWidget(not_null<QWidget*> target) {
} }
} }
HighlightArgs SubsectionTitleHighlight() {
const auto radius = st::roundRadiusSmall;
return { .margin = { -radius, 0, -radius, 0 }, .radius = radius };
}
void AbstractSection::build( void AbstractSection::build(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
SectionBuilder builder) { SectionBuilder builder) {
@@ -88,6 +88,8 @@ struct HighlightDescriptor {
void HighlightWidget(QWidget *target, HighlightArgs &&args = {}); void HighlightWidget(QWidget *target, HighlightArgs &&args = {});
void ScrollToWidget(not_null<QWidget*> target); void ScrollToWidget(not_null<QWidget*> target);
[[nodiscard]] HighlightArgs SubsectionTitleHighlight();
using SectionBuilder = void(*)( using SectionBuilder = void(*)(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "settings/settings_global_ttl.h" #include "settings/settings_global_ttl.h"
#include "settings/settings_common.h"
#include "api/api_self_destruct.h" #include "api/api_self_destruct.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
@@ -210,6 +211,7 @@ private:
const std::shared_ptr<Main::SessionShow> _show; const std::shared_ptr<Main::SessionShow> _show;
not_null<Ui::VerticalLayout*> _buttons; not_null<Ui::VerticalLayout*> _buttons;
QPointer<Ui::SettingsButton> _customButton;
rpl::event_stream<> _showFinished; rpl::event_stream<> _showFinished;
rpl::lifetime _requestLifetime; rpl::lifetime _requestLifetime;
@@ -348,10 +350,11 @@ void GlobalTTL::setupContent() {
} }
const auto show = _controller->uiShow(); const auto show = _controller->uiShow();
content->add(object_ptr<Ui::SettingsButton>( _customButton = content->add(object_ptr<Ui::SettingsButton>(
content, content,
tr::lng_settings_ttl_after_custom(), tr::lng_settings_ttl_after_custom(),
st::settingsButtonNoIcon))->setClickedCallback([=] { st::settingsButtonNoIcon));
_customButton->setClickedCallback([=] {
struct Args { struct Args {
std::shared_ptr<Ui::Show> show; std::shared_ptr<Ui::Show> show;
TimeId startTtl; TimeId startTtl;
@@ -427,6 +430,12 @@ void GlobalTTL::setupContent() {
void GlobalTTL::showFinished() { void GlobalTTL::showFinished() {
_showFinished.fire({}); _showFinished.fire({});
if (_customButton) {
_controller->checkHighlightControl(
u"auto-delete/set-custom"_q,
_customButton,
{ .rippleShape = true });
}
} }
Type GlobalTTLId() { Type GlobalTTLId() {
@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/cloud_password/settings_cloud_password_common.h" #include "settings/cloud_password/settings_cloud_password_common.h"
#include "settings/cloud_password/settings_cloud_password_step.h" #include "settings/cloud_password/settings_cloud_password_step.h"
#include "settings/settings_common.h"
#include "storage/storage_domain.h" #include "storage/storage_domain.h"
#include "ui/vertical_list.h" #include "ui/vertical_list.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
@@ -411,6 +412,11 @@ private:
rpl::event_stream<> _showFinished; rpl::event_stream<> _showFinished;
rpl::event_stream<> _showBack; rpl::event_stream<> _showBack;
QPointer<Ui::RpWidget> _changeButton;
QPointer<Ui::RpWidget> _autoLockButton;
QPointer<Ui::RpWidget> _biometricsButton;
QPointer<Ui::RpWidget> _disableButton;
}; };
LocalPasscodeManage::LocalPasscodeManage( LocalPasscodeManage::LocalPasscodeManage(
@@ -449,12 +455,13 @@ void LocalPasscodeManage::setupContent() {
Ui::AddSkip(content); Ui::AddSkip(content);
AddButtonWithIcon( const auto changeButton = AddButtonWithIcon(
content, content,
tr::lng_passcode_change(), tr::lng_passcode_change(),
st::settingsButton, st::settingsButton,
{ &st::menuIconLock } { &st::menuIconLock });
)->addClickHandler([=] { _changeButton = changeButton;
changeButton->addClickHandler([=] {
showOther(LocalPasscodeChange::Id()); showOther(LocalPasscodeChange::Id());
}); });
@@ -477,15 +484,16 @@ void LocalPasscodeManage::setupContent() {
: tr::lng_hours(tr::now, lt_count, hours); : tr::lng_hours(tr::now, lt_count, hours);
}); });
AddButtonWithLabel( const auto autoLockButton = AddButtonWithLabel(
content, content,
(base::Platform::LastUserInputTimeSupported() (base::Platform::LastUserInputTimeSupported()
? tr::lng_passcode_autolock_away ? tr::lng_passcode_autolock_away
: tr::lng_passcode_autolock_inactive)(), : tr::lng_passcode_autolock_inactive)(),
std::move(autolockLabel), std::move(autolockLabel),
st::settingsButton, st::settingsButton,
{ &st::menuIconTimer } { &st::menuIconTimer });
)->addClickHandler([=] { _autoLockButton = autoLockButton;
autoLockButton->addClickHandler([=] {
const auto box = _controller->show(Box<AutoLockBox>()); const auto box = _controller->show(Box<AutoLockBox>());
box->boxClosing( box->boxClosing(
) | rpl::start_to_stream(state->autoLockBoxClosing, box->lifetime()); ) | rpl::start_to_stream(state->autoLockBoxClosing, box->lifetime());
@@ -553,7 +561,7 @@ void LocalPasscodeManage::setupContent() {
Ui::AddSkip(systemUnlockContent); Ui::AddSkip(systemUnlockContent);
AddButtonWithIcon( const auto biometricsButton = AddButtonWithIcon(
systemUnlockContent, systemUnlockContent,
(Platform::IsWindows() (Platform::IsWindows()
? tr::lng_settings_use_winhello() ? tr::lng_settings_use_winhello()
@@ -569,8 +577,9 @@ void LocalPasscodeManage::setupContent() {
? &st::menuIconTouchID ? &st::menuIconTouchID
: (type == UnlockType::Companion) : (type == UnlockType::Companion)
? &st::menuIconAppleWatch ? &st::menuIconAppleWatch
: &st::menuIconSystemPwd } : &st::menuIconSystemPwd });
)->toggleOn( _biometricsButton = biometricsButton;
biometricsButton->toggleOn(
rpl::single(Core::App().settings().systemUnlockEnabled()) rpl::single(Core::App().settings().systemUnlockEnabled())
)->toggledChanges( )->toggledChanges(
) | rpl::filter([=](bool value) { ) | rpl::filter([=](bool value) {
@@ -625,12 +634,39 @@ base::weak_qptr<Ui::RpWidget> LocalPasscodeManage::createPinnedToBottom(
std::move(callback)); std::move(callback));
_isBottomFillerShown = base::take(bottomButton.isBottomFillerShown); _isBottomFillerShown = base::take(bottomButton.isBottomFillerShown);
_disableButton = bottomButton.button.get();
return bottomButton.content; return bottomButton.content;
} }
void LocalPasscodeManage::showFinished() { void LocalPasscodeManage::showFinished() {
_showFinished.fire({}); _showFinished.fire({});
const auto id = _controller->highlightControlId();
if (id.isEmpty()) {
return;
}
if (id == u"passcode/change"_q) {
_controller->setHighlightControlId(QString());
if (_changeButton) {
HighlightWidget(_changeButton);
}
} else if (id == u"passcode/auto-lock"_q) {
_controller->setHighlightControlId(QString());
if (_autoLockButton) {
HighlightWidget(_autoLockButton);
}
} else if (id == u"passcode/biometrics"_q) {
_controller->setHighlightControlId(QString());
if (_biometricsButton) {
HighlightWidget(_biometricsButton);
}
} else if (id == u"passcode/disable"_q) {
_controller->setHighlightControlId(QString());
if (_disableButton) {
HighlightWidget(_disableButton);
}
}
} }
rpl::producer<> LocalPasscodeManage::sectionShowBack() { rpl::producer<> LocalPasscodeManage::sectionShowBack() {
@@ -769,4 +769,39 @@ void OpenFaq(base::weak_ptr<Window::SessionController> weak) {
})); }));
} }
void OpenAskQuestionConfirm(not_null<Window::SessionController*> window) {
const auto requestId = std::make_shared<mtpRequestId>();
const auto sure = [=](Fn<void()> close) {
if (*requestId) {
return;
}
*requestId = window->session().api().request(
MTPhelp_GetSupport()
).done(crl::guard(window, [=](const MTPhelp_Support &result) {
*requestId = 0;
result.match([&](const MTPDhelp_support &data) {
auto &owner = window->session().data();
if (const auto user = owner.processUser(data.vuser())) {
window->showPeerHistory(user);
}
});
close();
})).fail([=] {
*requestId = 0;
close();
}).send();
};
window->show(Ui::MakeConfirmBox({
.text = tr::lng_settings_ask_sure(),
.confirmed = sure,
.cancelled = [=](Fn<void()> close) {
OpenFaq(window);
close();
},
.confirmText = tr::lng_settings_ask_ok(),
.cancelText = tr::lng_settings_faq_button(),
.strictCancel = true,
}));
}
} // namespace Settings } // namespace Settings
@@ -41,6 +41,7 @@ void SetupValidatePasswordSuggestion(
Fn<void(Type)> showOther); Fn<void(Type)> showOther);
void OpenFaq(base::weak_ptr<Window::SessionController> weak); void OpenFaq(base::weak_ptr<Window::SessionController> weak);
void OpenAskQuestionConfirm(not_null<Window::SessionController*> window);
class Main : public Section<Main> { class Main : public Section<Main> {
public: public:
@@ -7,10 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "settings/settings_passkeys.h" #include "settings/settings_passkeys.h"
#include "core/application.h"
#include "settings/cloud_password/settings_cloud_password_common.h" #include "settings/cloud_password/settings_cloud_password_common.h"
#include "settings/settings_common.h"
#include "settings/settings_common_session.h" #include "settings/settings_common_session.h"
#include "data/components/passkeys.h" #include "data/components/passkeys.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "platform/platform_webauthn.h" #include "platform/platform_webauthn.h"
@@ -58,12 +61,12 @@ public:
} }
private: private:
void showFinished() override { void showFinished() override;
_showFinished.fire({});
}
void setupContent(not_null<Window::SessionController*> controller); void setupContent(not_null<Window::SessionController*> controller);
const not_null<Window::SessionController*> _controller;
QPointer<Ui::SettingsButton> _addButton;
Ui::RoundRect _bottomSkipRounding; Ui::RoundRect _bottomSkipRounding;
rpl::event_stream<> _showFinished; rpl::event_stream<> _showFinished;
@@ -181,6 +184,7 @@ void PasskeysNoneBox(
? tr::lng_settings_passkeys_none_button() ? tr::lng_settings_passkeys_none_button()
: tr::lng_settings_passkeys_none_button_unsupported(), : tr::lng_settings_passkeys_none_button_unsupported(),
st::defaultActiveButton); st::defaultActiveButton);
const auto createButton = button.data();
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->resizeToWidth(box->width() button->resizeToWidth(box->width()
- st.buttonPadding.left() - st.buttonPadding.left()
@@ -211,6 +215,21 @@ void PasskeysNoneBox(
anim::with_alpha(button->st().textFg->c, 0.5)); anim::with_alpha(button->st().textFg->c, 0.5));
} }
box->addButton(std::move(button)); box->addButton(std::move(button));
box->showFinishes(
) | rpl::take(1) | rpl::on_next([=] {
if (const auto window = Core::App().findWindow(box)) {
window->checkHighlightControl(
u"passkeys/create"_q,
createButton,
{
.color = &st::activeButtonFg,
.opacity = 0.6,
.rippleShape = true,
.scroll = false,
});
}
}, box->lifetime());
} }
} }
@@ -218,10 +237,21 @@ Passkeys::Passkeys(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Section(parent) : Section(parent)
, _controller(controller)
, _bottomSkipRounding(st::boxRadius, st::boxDividerBg) { , _bottomSkipRounding(st::boxRadius, st::boxDividerBg) {
setupContent(controller); setupContent(controller);
} }
void Passkeys::showFinished() {
_showFinished.fire({});
if (_addButton) {
_controller->checkHighlightControl(
u"passkeys/create"_q,
_addButton,
{ .rippleShape = true });
}
}
rpl::producer<QString> Passkeys::title() { rpl::producer<QString> Passkeys::title() {
return tr::lng_settings_passkeys_title(); return tr::lng_settings_passkeys_title();
} }
@@ -376,7 +406,8 @@ void Passkeys::setupContent(
tr::lng_settings_passkeys_button(), tr::lng_settings_passkeys_button(),
st::settingsButtonActive, st::settingsButtonActive,
{ &st::settingsIconPasskeys }))); { &st::settingsIconPasskeys })));
buttonWrap->entity()->setClickedCallback([=] { _addButton = buttonWrap->entity();
_addButton->setClickedCallback([=] {
controller->show(Box(PasskeysNoneBox, session)); controller->show(Box(PasskeysNoneBox, session));
}); });
buttonWrap->toggleOn(session->passkeys().requestList( buttonWrap->toggleOn(session->passkeys().requestList(
@@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/power_saving.h" #include "ui/power_saving.h"
#include "ui/vertical_list.h" #include "ui/vertical_list.h"
#include "settings/settings_common.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
@@ -27,7 +28,9 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
} // namespace } // namespace
void PowerSavingBox(not_null<Ui::GenericBox*> box) { void PowerSavingBox(
not_null<Ui::GenericBox*> box,
PowerSaving::Flags highlightFlags) {
box->setStyle(st::layerBox); box->setStyle(st::layerBox);
box->setTitle(tr::lng_settings_power_title()); box->setTitle(tr::lng_settings_power_title());
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);
@@ -53,12 +56,14 @@ void PowerSavingBox(not_null<Ui::GenericBox*> box) {
? tr::lng_settings_power_turn_off(tr::now) ? tr::lng_settings_power_turn_off(tr::now)
: QString(); : QString();
auto [checkboxes, getResult, changes] = CreateEditPowerSaving( auto [checkboxes, getResult, changes, highlightWidget] = CreateEditPowerSaving(
box, box,
PowerSaving::kAll & ~PowerSaving::Current(), PowerSaving::kAll & ~PowerSaving::Current(),
state->forceDisabledMessage.value()); state->forceDisabledMessage.value(),
highlightFlags);
const auto controlsRaw = checkboxes.data(); const auto controlsRaw = checkboxes.data();
const auto highlightWidgetRaw = highlightWidget.data();
box->addRow(std::move(checkboxes), style::margins()); box->addRow(std::move(checkboxes), style::margins());
auto automatic = (Ui::SettingsButton*)nullptr; auto automatic = (Ui::SettingsButton*)nullptr;
@@ -121,6 +126,13 @@ void PowerSavingBox(not_null<Ui::GenericBox*> box) {
box->closeBox(); box->closeBox();
}); });
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
if (highlightWidgetRaw) {
box->showFinishes(
) | rpl::take(1) | rpl::on_next([=] {
HighlightWidget(highlightWidgetRaw);
}, box->lifetime());
}
} }
EditFlagsDescriptor<PowerSaving::Flags> PowerSavingLabels() { EditFlagsDescriptor<PowerSaving::Flags> PowerSavingLabels() {
@@ -19,12 +19,15 @@ using Flags = base::flags<Flag>;
namespace Ui { namespace Ui {
class GenericBox; class GenericBox;
class RpWidget;
} // namespace Ui } // namespace Ui
namespace Settings { namespace Settings {
void PowerSavingBox(not_null<Ui::GenericBox*> box); void PowerSavingBox(
not_null<Ui::GenericBox*> box,
PowerSaving::Flags highlightFlags = PowerSaving::Flags());
[[nodiscard]] EditFlagsDescriptor<PowerSaving::Flags> PowerSavingLabels(); [[nodiscard]] EditFlagsDescriptor<PowerSaving::Flags> PowerSavingLabels();
} // namespace PowerSaving } // namespace Settings
@@ -1810,11 +1810,10 @@ void GiftsAutoSavePrivacyController::checkHighlightControls(
controller->checkHighlightControl( controller->checkHighlightControl(
u"privacy/show-icon"_q, u"privacy/show-icon"_q,
_showIconButton.data()); _showIconButton.data());
const auto radius = st::roundRadiusSmall;
controller->checkHighlightControl( controller->checkHighlightControl(
u"privacy/accepted-types"_q, u"privacy/accepted-types"_q,
_acceptedTypesTitle.data(), _acceptedTypesTitle.data(),
{ .margin = { -radius, 0, -radius, 0 }, .radius = radius }); SubsectionTitleHighlight());
} }
UserPrivacy::Key SavedMusicPrivacyController::key() const { UserPrivacy::Key SavedMusicPrivacyController::key() const {
@@ -261,7 +261,7 @@ void AddMessagesPrivacyButton(
st, st,
{}); {});
button->addClickHandler([=] { button->addClickHandler([=] {
controller->show(Box(EditMessagesPrivacyBox, controller)); controller->show(Box(EditMessagesPrivacyBox, controller, QString()));
}); });
if (!session->appConfig().newRequirePremiumFree()) { if (!session->appConfig().newRequirePremiumFree()) {
AddPremiumStar(button, session, rpl::duplicate(label), st.padding); AddPremiumStar(button, session, rpl::duplicate(label), st.padding);
@@ -743,19 +743,28 @@ auto ClearPaymentInfoBox(not_null<Main::Session*> session) {
void SetupBotsAndWebsites( void SetupBotsAndWebsites(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddSubsectionTitle(container, tr::lng_settings_security_bots()); Ui::AddSubsectionTitle(container, tr::lng_settings_security_bots());
const auto session = &controller->session(); const auto session = &controller->session();
container->add(object_ptr<Button>( const auto button = container->add(object_ptr<Button>(
container, container,
tr::lng_settings_clear_payment_info(), tr::lng_settings_clear_payment_info(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
))->addClickHandler([=] { ));
button->addClickHandler([=] {
controller->show(ClearPaymentInfoBox(session)); controller->show(ClearPaymentInfoBox(session));
}); });
if (highlights) {
highlights->push_back({
u"privacy/bots_payment"_q,
Builder::HighlightEntry{ button },
});
}
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddDivider(container); Ui::AddDivider(container);
} }
@@ -944,7 +953,8 @@ void SetupSecurity(
void SetupSensitiveContent( void SetupSensitiveContent(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
rpl::producer<> updateTrigger) { rpl::producer<> updateTrigger,
Builder::HighlightRegistry *highlights) {
using namespace rpl::mappers; using namespace rpl::mappers;
const auto wrap = container->add( const auto wrap = container->add(
@@ -965,11 +975,11 @@ void SetupSensitiveContent(
) | rpl::on_next([=] { ) | rpl::on_next([=] {
session->api().sensitiveContent().reload(); session->api().sensitiveContent().reload();
}, container->lifetime()); }, container->lifetime());
inner->add(object_ptr<Button>( const auto button = inner->add(object_ptr<Button>(
inner, inner,
tr::lng_settings_sensitive_disable_filtering(), tr::lng_settings_sensitive_disable_filtering(),
st::settingsButtonNoIcon st::settingsButtonNoIcon));
))->toggleOn(rpl::merge( button->toggleOn(rpl::merge(
session->api().sensitiveContent().enabled(), session->api().sensitiveContent().enabled(),
disable->events() | rpl::map_to(false) disable->events() | rpl::map_to(false)
))->toggledChanges( ))->toggledChanges(
@@ -988,6 +998,13 @@ void SetupSensitiveContent(
} }
}, container->lifetime()); }, container->lifetime());
if (highlights) {
highlights->push_back({
u"chat/show-18-content"_q,
Builder::HighlightEntry{ button },
});
}
Ui::AddSkip(inner); Ui::AddSkip(inner);
Ui::AddDividerText(inner, tr::lng_settings_sensitive_about()); Ui::AddDividerText(inner, tr::lng_settings_sensitive_about());
@@ -1111,7 +1128,8 @@ not_null<Ui::SettingsButton*> AddPrivacyButton(
void SetupArchiveAndMute( void SetupArchiveAndMute(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights) {
using namespace rpl::mappers; using namespace rpl::mappers;
const auto wrap = container->add( const auto wrap = container->add(
@@ -1127,11 +1145,12 @@ void SetupArchiveAndMute(
const auto privacy = &session->api().globalPrivacy(); const auto privacy = &session->api().globalPrivacy();
privacy->reload(); privacy->reload();
inner->add(object_ptr<Button>( const auto button = inner->add(object_ptr<Button>(
inner, inner,
tr::lng_settings_auto_archive(), tr::lng_settings_auto_archive(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
))->toggleOn( ));
button->toggleOn(
privacy->archiveAndMute() privacy->archiveAndMute()
)->toggledChanges( )->toggledChanges(
) | rpl::filter([=](bool toggled) { ) | rpl::filter([=](bool toggled) {
@@ -1140,6 +1159,13 @@ void SetupArchiveAndMute(
privacy->updateArchiveAndMute(toggled); privacy->updateArchiveAndMute(toggled);
}, container->lifetime()); }, container->lifetime());
if (highlights) {
highlights->push_back({
u"privacy/archive_and_mute"_q,
Builder::HighlightEntry{ button },
});
}
Ui::AddSkip(inner); Ui::AddSkip(inner);
Ui::AddDividerText(inner, tr::lng_settings_auto_archive_about()); Ui::AddDividerText(inner, tr::lng_settings_auto_archive_about());
@@ -12,6 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class EditPrivacyController; class EditPrivacyController;
namespace Settings::Builder {
struct HighlightEntry;
using HighlightRegistry = std::vector<std::pair<QString, HighlightEntry>>;
} // namespace Settings::Builder
namespace Ui { namespace Ui {
class BoxContent; class BoxContent;
} // namespace Ui } // namespace Ui
@@ -48,7 +53,8 @@ void AddPrivacyPremiumStar(
void SetupArchiveAndMute( void SetupArchiveAndMute(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupSecurity( void SetupSecurity(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
@@ -63,7 +69,8 @@ void SetupPrivacy(
void SetupBotsAndWebsites( void SetupBotsAndWebsites(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container,
Builder::HighlightRegistry *highlights = nullptr);
void SetupConfirmationExtensions( void SetupConfirmationExtensions(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
@@ -291,6 +291,7 @@ public:
not_null<Window::SessionController*> controller); not_null<Window::SessionController*> controller);
void setupContent(); void setupContent();
[[nodiscard]] Ui::RpWidget *terminateAllButton() const;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
@@ -367,6 +368,7 @@ public:
[[nodiscard]] rpl::producer<EntryData> showRequests() const; [[nodiscard]] rpl::producer<EntryData> showRequests() const;
[[nodiscard]] rpl::producer<uint64> terminateOne() const; [[nodiscard]] rpl::producer<uint64> terminateOne() const;
[[nodiscard]] rpl::producer<> terminateAll() const; [[nodiscard]] rpl::producer<> terminateAll() const;
[[nodiscard]] Ui::RpWidget *terminateAllButton() const;
private: private:
void setupContent(); void setupContent();
@@ -553,6 +555,10 @@ void Content::terminateAll() {
tr::lng_settings_disconnect_all_sure()); tr::lng_settings_disconnect_all_sure());
} }
Ui::RpWidget *Content::terminateAllButton() const {
return _inner ? _inner->terminateAllButton() : nullptr;
}
Content::Inner::Inner( Content::Inner::Inner(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
@@ -629,6 +635,10 @@ rpl::producer<EntryData> Content::Inner::showRequests() const {
return _list->showRequests(); return _list->showRequests();
} }
Ui::RpWidget *Content::Inner::terminateAllButton() const {
return _terminateAll.data();
}
Content::ListController::ListController( Content::ListController::ListController(
not_null<Main::Session*> session) not_null<Main::Session*> session)
: _session(session) { : _session(session) {
@@ -733,7 +743,8 @@ namespace Settings {
Websites::Websites( Websites::Websites(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Section(parent) { : Section(parent)
, _controller(controller) {
setupContent(controller); setupContent(controller);
} }
@@ -741,6 +752,12 @@ rpl::producer<QString> Websites::title() {
return tr::lng_settings_connected_title(); return tr::lng_settings_connected_title();
} }
void Websites::showFinished() {
_controller->checkHighlightControl(
u"websites/disconnect-all"_q,
_terminateAll.data());
}
void Websites::setupContent(not_null<Window::SessionController*> controller) { void Websites::setupContent(not_null<Window::SessionController*> controller) {
const auto container = Ui::CreateChild<Ui::VerticalLayout>(this); const auto container = Ui::CreateChild<Ui::VerticalLayout>(this);
Ui::AddSkip(container); Ui::AddSkip(container);
@@ -748,6 +765,8 @@ void Websites::setupContent(not_null<Window::SessionController*> controller) {
object_ptr<Content>(container, controller)); object_ptr<Content>(container, controller));
content->setupContent(); content->setupContent();
_terminateAll = content->terminateAllButton();
Ui::ResizeFitChild(this, container); Ui::ResizeFitChild(this, container);
} }
@@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_common_session.h" #include "settings/settings_common_session.h"
namespace Ui {
class RpWidget;
} // namespace Ui
namespace Settings { namespace Settings {
class Websites : public Section<Websites> { class Websites : public Section<Websites> {
@@ -18,10 +22,14 @@ public:
not_null<Window::SessionController*> controller); not_null<Window::SessionController*> controller);
[[nodiscard]] rpl::producer<QString> title() override; [[nodiscard]] rpl::producer<QString> title() override;
void showFinished() override;
private: private:
void setupContent(not_null<Window::SessionController*> controller); void setupContent(not_null<Window::SessionController*> controller);
const not_null<Window::SessionController*> _controller;
QPointer<Ui::RpWidget> _terminateAll;
}; };
} // namespace Settings } // namespace Settings
@@ -449,7 +449,10 @@ void UserpicButton::choosePhotoLocally() {
}, &st::menuIconProfile); }, &st::menuIconProfile);
} }
} }
_menu->popup(QCursor::pos()); const auto position = rect().contains(mapFromGlobal(QCursor::pos()))
? QCursor::pos()
: mapToGlobal(rect().center());
_menu->popup(position);
} }
auto UserpicButton::makeResetToOriginalAction() auto UserpicButton::makeResetToOriginalAction()
@@ -637,11 +637,13 @@ void MainMenu::parentResized() {
void MainMenu::showFinished() { void MainMenu::showFinished() {
_showFinished = true; _showFinished = true;
const auto radius = st::roundRadiusSmall;
_controller->checkHighlightControl( _controller->checkHighlightControl(
u"main-menu/emoji-status"_q, u"main-menu/emoji-status"_q,
_setEmojiStatus, _setEmojiStatus,
{ .margin = { -radius, 0, -radius, 0 }, .radius = radius }); Settings::SubsectionTitleHighlight());
_controller->checkHighlightControl(
u"main-menu/night-mode"_q,
_nightThemeToggle);
} }
void MainMenu::setupMenu() { void MainMenu::setupMenu() {