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