Rewrite settings_passkeys to new builder pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John Preston
2026-01-14 17:24:08 +04:00
parent d966dc2343
commit 86398de8bd
6 changed files with 146 additions and 90 deletions
+2 -2
View File
@@ -1588,8 +1588,8 @@ PRIVATE
settings/sections/settings_privacy_security.h settings/sections/settings_privacy_security.h
settings/sections/settings_notifications_type.cpp settings/sections/settings_notifications_type.cpp
settings/sections/settings_notifications_type.h settings/sections/settings_notifications_type.h
settings/settings_passkeys.cpp settings/sections/settings_passkeys.cpp
settings/settings_passkeys.h settings/sections/settings_passkeys.h
settings/settings_power_saving.cpp settings/settings_power_saving.cpp
settings/settings_power_saving.h settings/settings_power_saving.h
settings/settings_premium.cpp settings/settings_premium.cpp
@@ -44,7 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/sections/settings_business.h" #include "settings/sections/settings_business.h"
#include "settings/sections/settings_calls.h" #include "settings/sections/settings_calls.h"
#include "settings/sections/settings_chat.h" #include "settings/sections/settings_chat.h"
#include "settings/settings_passkeys.h" #include "settings/sections/settings_passkeys.h"
#include "data/components/passkeys.h" #include "data/components/passkeys.h"
#include "calls/calls_box_controller.h" #include "calls/calls_box_controller.h"
#include "settings/sections/settings_credits.h" #include "settings/sections/settings_credits.h"
@@ -5,76 +5,81 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "settings/settings_passkeys.h" #include "settings/sections/settings_passkeys.h"
#include "base/unixtime.h"
#include "core/application.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/components/passkeys.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "window/window_controller.h" #include "data/stickers/data_custom_emoji.h"
#include "window/window_session_controller.h" #include "lang/lang_keys.h"
#include "lottie/lottie_icon.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "platform/platform_webauthn.h" #include "platform/platform_webauthn.h"
#include "ui/layers/generic_box.h" #include "settings/cloud_password/settings_cloud_password_common.h"
#include "settings/sections/settings_privacy_security.h"
#include "settings/settings_builder.h"
#include "settings/settings_common.h"
#include "settings/settings_common_session.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/text/custom_emoji_instance.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/vertical_list.h" #include "ui/vertical_list.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/menu/menu_add_action_callback.h" #include "ui/widgets/menu/menu_add_action_callback.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "lang/lang_keys.h" #include "ui/wrap/vertical_layout.h"
#include "lottie/lottie_icon.h" #include "window/window_controller.h"
#include "base/unixtime.h" #include "window/window_session_controller.h"
#include "data/stickers/data_custom_emoji.h"
#include "ui/text/custom_emoji_instance.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_channel_earn.h" #include "styles/style_channel_earn.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include "styles/style_premium.h" #include "styles/style_premium.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "styles/style_menu_icons.h"
namespace Settings { namespace Settings {
namespace {
class Passkeys : public Section<Passkeys> { using namespace Builder;
public:
Passkeys(
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] rpl::producer<QString> title() override; void BuildPasskeysSection(SectionBuilder &builder) {
builder.add(nullptr, [] {
return SearchEntry{
.id = u"passkeys/create"_q,
.title = tr::lng_settings_passkeys_button(tr::now),
.keywords = { u"add"_q, u"register"_q, u"create"_q },
};
});
builder.add(nullptr, [] {
return SearchEntry{
.id = u"passkeys/list"_q,
.title = tr::lng_settings_passkeys_title(tr::now),
.keywords = { u"passkeys"_q, u"biometric"_q, u"authentication"_q },
};
});
}
[[nodiscard]] rpl::producer<> showFinishes() const { const auto kMeta = BuildHelper({
return _showFinished.events(); .id = Passkeys::Id(),
} .parentId = PrivacySecurity::Id(),
.title = &tr::lng_settings_passkeys_title,
.icon = &st::menuIconPermissions,
}, [](SectionBuilder &builder) {
BuildPasskeysSection(builder);
});
const Ui::RoundRect *bottomSkipRounding() const override { } // namespace
return &_bottomSkipRounding;
}
private:
void showFinished() override;
void setupContent();
QPointer<Ui::SettingsButton> _addButton;
Ui::RoundRect _bottomSkipRounding;
rpl::event_stream<> _showFinished;
};
void PasskeysNoneBox( void PasskeysNoneBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session) { not_null<::Main::Session*> session) {
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);
box->setNoContentMargin(true); box->setNoContentMargin(true);
box->setCloseByEscape(true); box->setCloseByEscape(true);
@@ -236,11 +241,13 @@ Passkeys::Passkeys(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Section(parent, controller) : Section(parent, controller)
, _container(Ui::CreateChild<Ui::VerticalLayout>(this))
, _bottomSkipRounding(st::boxRadius, st::boxDividerBg) { , _bottomSkipRounding(st::boxRadius, st::boxDividerBg) {
setupContent(); setupContent();
} }
void Passkeys::showFinished() { void Passkeys::showFinished() {
Section::showFinished();
_showFinished.fire({}); _showFinished.fire({});
if (_addButton) { if (_addButton) {
controller()->checkHighlightControl( controller()->checkHighlightControl(
@@ -255,30 +262,29 @@ rpl::producer<QString> Passkeys::title() {
} }
void Passkeys::setupContent() { void Passkeys::setupContent() {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
const auto session = &controller()->session(); const auto session = &controller()->session();
CloudPassword::SetupHeader( CloudPassword::SetupHeader(
content, _container,
u"passkeys"_q, u"passkeys"_q,
showFinishes(), _showFinished.events(),
rpl::single(QString()), rpl::single(QString()),
tr::lng_settings_passkeys_about()); tr::lng_settings_passkeys_about());
Ui::AddSkip(content); Ui::AddSkip(_container);
const auto container = content->add( const auto passkeysListContainer = _container->add(
object_ptr<Ui::VerticalLayout>(content)); object_ptr<Ui::VerticalLayout>(_container));
const auto &st = st::peerListBoxItem; const auto &st = st::peerListBoxItem;
const auto nameStyle = &st.nameStyle; const auto nameStyle = &st.nameStyle;
const auto rebuild = [=] { const auto rebuild = [=] {
while (container->count()) { while (passkeysListContainer->count()) {
delete container->widgetAt(0); delete passkeysListContainer->widgetAt(0);
} }
for (const auto &passkey : session->passkeys().list()) { for (const auto &passkey : session->passkeys().list()) {
const auto button = container->add( const auto button = passkeysListContainer->add(
object_ptr<Ui::AbstractButton>(container)); object_ptr<Ui::AbstractButton>(passkeysListContainer));
button->resize(button->width(), st.height); button->resize(button->width(), st.height);
const auto menu = Ui::CreateChild<Ui::IconButton>( const auto menu = Ui::CreateChild<Ui::IconButton>(
button, button,
@@ -391,15 +397,15 @@ void Passkeys::setupContent() {
}); });
button->showChildren(); button->showChildren();
} }
container->showChildren(); passkeysListContainer->showChildren();
container->resizeToWidth(content->width()); passkeysListContainer->resizeToWidth(_container->width());
}; };
const auto buttonWrap = content->add( const auto buttonWrap = _container->add(
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>( object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
content, _container,
CreateButtonWithIcon( CreateButtonWithIcon(
content, _container,
tr::lng_settings_passkeys_button(), tr::lng_settings_passkeys_button(),
st::settingsButtonActive, st::settingsButtonActive,
{ &st::settingsIconPasskeys }))); { &st::settingsIconPasskeys })));
@@ -412,12 +418,12 @@ void Passkeys::setupContent() {
buttonWrap->finishAnimating(); buttonWrap->finishAnimating();
session->passkeys().requestList( session->passkeys().requestList(
) | rpl::on_next(rebuild, content->lifetime()); ) | rpl::on_next(rebuild, _container->lifetime());
rebuild(); rebuild();
Ui::AddSkip(content); Ui::AddSkip(_container);
const auto label = Ui::AddDividerText( const auto label = Ui::AddDividerText(
content, _container,
tr::lng_settings_passkeys_button_about( tr::lng_settings_passkeys_button_about(
lt_link, lt_link,
tr::lng_channel_earn_about_link( tr::lng_channel_earn_about_link(
@@ -433,11 +439,27 @@ void Passkeys::setupContent() {
controller()->show(Box(PasskeysNoneBox, session)); controller()->show(Box(PasskeysNoneBox, session));
return false; return false;
}); });
Ui::ResizeFitChild(this, content);
widthValue(
) | rpl::on_next([=](int width) {
_container->resizeToWidth(width);
}, _container->lifetime());
_container->heightValue(
) | rpl::on_next([=](int height) {
resize(width(), height);
}, _container->lifetime());
build(_container, Builder::PasskeysSection);
} }
Type PasskeysId() { Type PasskeysId() {
return Passkeys::Id(); return Passkeys::Id();
} }
namespace Builder {
SectionBuildMethod PasskeysSection = kMeta.build;
} // namespace Builder
} // namespace Settings } // namespace Settings
@@ -0,0 +1,62 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "settings/settings_common_session.h"
#include "settings/settings_type.h"
namespace Ui {
class GenericBox;
class SettingsButton;
class VerticalLayout;
} // namespace Ui
namespace Main {
class Session;
} // namespace Main
namespace Settings {
class Passkeys : public Section<Passkeys> {
public:
Passkeys(
QWidget *parent,
not_null<Window::SessionController*> controller);
void showFinished() override;
[[nodiscard]] rpl::producer<QString> title() override;
const Ui::RoundRect *bottomSkipRounding() const override {
return &_bottomSkipRounding;
}
private:
void setupContent();
const not_null<Ui::VerticalLayout*> _container;
QPointer<Ui::SettingsButton> _addButton;
Ui::RoundRect _bottomSkipRounding;
rpl::event_stream<> _showFinished;
};
void PasskeysNoneBox(
not_null<Ui::GenericBox*> box,
not_null<::Main::Session*> session);
Type PasskeysId();
namespace Builder {
extern SectionBuildMethod PasskeysSection;
} // namespace Builder
} // namespace Settings
@@ -47,7 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/sections/settings_blocked_peers.h" #include "settings/sections/settings_blocked_peers.h"
#include "settings/sections/settings_global_ttl.h" #include "settings/sections/settings_global_ttl.h"
#include "settings/sections/settings_local_passcode.h" #include "settings/sections/settings_local_passcode.h"
#include "settings/settings_passkeys.h" #include "settings/sections/settings_passkeys.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "settings/settings_privacy_controllers.h" #include "settings/settings_privacy_controllers.h"
#include "settings/settings_websites.h" #include "settings/settings_websites.h"
@@ -1,28 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "settings/settings_type.h"
namespace Ui {
class GenericBox;
} // namespace Ui
namespace Main {
class Session;
} // namespace Main
namespace Settings {
void PasskeysNoneBox(
not_null<Ui::GenericBox*> box,
not_null<::Main::Session*> session);
Type PasskeysId();
} // namespace Settings