diff --git a/Telegram/Resources/animations/passkeys.tgs b/Telegram/Resources/animations/passkeys.tgs new file mode 100644 index 0000000000..62e11b2540 Binary files /dev/null and b/Telegram/Resources/animations/passkeys.tgs differ diff --git a/Telegram/Resources/qrc/telegram/animations.qrc b/Telegram/Resources/qrc/telegram/animations.qrc index 5a52c5f380..34e0b4591e 100644 --- a/Telegram/Resources/qrc/telegram/animations.qrc +++ b/Telegram/Resources/qrc/telegram/animations.qrc @@ -50,6 +50,7 @@ ../../animations/rtmp.tgs ../../animations/show_or_premium_lastseen.tgs ../../animations/show_or_premium_readtime.tgs + ../../animations/passkeys.tgs ../../animations/profile/profile_muting.tgs ../../animations/profile/profile_unmuting.tgs diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 6460e3c3d7..d0a7275782 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -715,6 +715,10 @@ settingsCreditsButton: SettingsButton(settingsButton) { settingsButtonIconGift: icon {{ "settings/gift", menuIconColor }}; settingsButtonIconEarn: icon {{ "settings/earn", menuIconColor }}; +settingsIconPasskeysAboutIcon1: icon {{ "menu/permissions", boxTextFg }}; +settingsIconPasskeysAboutIcon2: icon {{ "menu/passcode_winhello", boxTextFg }}; +settingsIconPasskeysAboutIcon3: icon {{ "menu/lock", boxTextFg }}; + settingsAgeVerifyBox: Box(filterInviteBox) { buttonPadding: margins(24px, 24px, 24px, 24px); } diff --git a/Telegram/SourceFiles/settings/settings_passkeys.cpp b/Telegram/SourceFiles/settings/settings_passkeys.cpp index 3fe0c507e3..b82fd35231 100644 --- a/Telegram/SourceFiles/settings/settings_passkeys.cpp +++ b/Telegram/SourceFiles/settings/settings_passkeys.cpp @@ -7,13 +7,157 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "settings/settings_passkeys.h" +#include "data/components/passkeys.h" +#include "data/data_session.h" +#include "window/window_session_controller.h" +#include "main/main_session.h" +#include "platform/platform_webauthn.h" +#include "ui/layers/generic_box.h" +#include "ui/painter.h" +#include "ui/rect.h" +#include "ui/text/text_utilities.h" #include "ui/vertical_list.h" +#include "ui/widgets/buttons.h" #include "ui/wrap/vertical_layout.h" #include "lang/lang_keys.h" +#include "lottie/lottie_icon.h" +#include "styles/style_channel_earn.h" +#include "styles/style_chat.h" +#include "styles/style_layers.h" +#include "styles/style_premium.h" #include "styles/style_settings.h" namespace Settings { +void PasskeysNoneBox( + not_null box, + not_null session) { + box->setWidth(st::boxWideWidth); + box->setNoContentMargin(true); + box->setCloseByEscape(true); + box->addTopButton(st::boxTitleClose, [=] { box->closeBox(); }); + + const auto content = box->verticalLayout().get(); + + Ui::AddSkip(content); + { + const auto &size = st::settingsCloudPasswordIconSize; + auto icon = CreateLottieIcon( + content, + { .name = u"passkeys"_q, .sizeOverride = { size, size } }, + st::settingLocalPasscodeIconPadding); + const auto animate = std::move(icon.animate); + box->addRow(std::move(icon.widget), style::al_top); + box->showFinishes() | rpl::take(1) | rpl::start_with_next([=] { + animate(anim::repeat::once); + }, content->lifetime()); + } + Ui::AddSkip(content); + Ui::AddSkip(content); + box->addRow( + object_ptr( + content, + tr::lng_settings_passkeys_none_title(), + st::boxTitle), + style::al_top); + Ui::AddSkip(content); + box->addRow( + object_ptr( + content, + tr::lng_settings_passkeys_none_about(), + st::channelEarnLearnDescription), + style::al_top); + Ui::AddSkip(content); + Ui::AddSkip(content); + Ui::AddSkip(content); + { + const auto padding = QMargins( + st::settingsButton.padding.left(), + st::boxRowPadding.top(), + st::boxRowPadding.right(), + st::boxRowPadding.bottom()); + const auto addEntry = [&]( + rpl::producer title, + rpl::producer about, + const style::icon &icon) { + const auto top = content->add( + object_ptr( + content, + std::move(title), + st::channelEarnSemiboldLabel), + padding); + Ui::AddSkip(content, st::channelEarnHistoryThreeSkip); + content->add( + object_ptr( + content, + std::move(about), + st::channelEarnHistoryRecipientLabel), + padding); + const auto left = Ui::CreateChild( + box->verticalLayout().get()); + left->paintRequest( + ) | rpl::start_with_next([=] { + auto p = Painter(left); + icon.paint(p, 0, 0, left->width()); + }, left->lifetime()); + left->resize(icon.size()); + top->geometryValue( + ) | rpl::start_with_next([=](const QRect &g) { + left->moveToLeft( + (g.left() - left->width()) / 2, + g.top() + st::channelEarnHistoryThreeSkip); + }, left->lifetime()); + }; + addEntry( + tr::lng_settings_passkeys_none_info1_title(), + tr::lng_settings_passkeys_none_info1_about(), + st::settingsIconPasskeysAboutIcon1); + Ui::AddSkip(content); + Ui::AddSkip(content); + addEntry( + tr::lng_settings_passkeys_none_info2_title(), + tr::lng_settings_passkeys_none_info2_about(), + st::settingsIconPasskeysAboutIcon2); + Ui::AddSkip(content); + Ui::AddSkip(content); + addEntry( + tr::lng_settings_passkeys_none_info3_title(), + tr::lng_settings_passkeys_none_info3_about(), + st::settingsIconPasskeysAboutIcon3); + Ui::AddSkip(content); + Ui::AddSkip(content); + } + Ui::AddSkip(content); + Ui::AddSkip(content); + { + const auto &st = st::premiumPreviewDoubledLimitsBox; + box->setStyle(st); + auto button = object_ptr( + box, + tr::lng_settings_passkeys_none_button(), + st::defaultActiveButton); + button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); + button->resizeToWidth(box->width() + - st.buttonPadding.left() + - st.buttonPadding.left()); + button->setClickedCallback([=] { + session->passkeys().initRegistration([=]( + const Data::Passkey::RegisterData &data) { + Platform::WebAuthn::RegisterKey(data, [=]( + Platform::WebAuthn::RegisterResult result) { + if (!result.success) { + return; + } + session->passkeys().registerPasskey(result, [=] { + box->closeBox(); + }); + }); + }); + }); + box->addButton(std::move(button)); + } +} + Passkeys::Passkeys( QWidget *parent, not_null controller) diff --git a/Telegram/SourceFiles/settings/settings_passkeys.h b/Telegram/SourceFiles/settings/settings_passkeys.h index 182e6b713b..999a768030 100644 --- a/Telegram/SourceFiles/settings/settings_passkeys.h +++ b/Telegram/SourceFiles/settings/settings_passkeys.h @@ -9,8 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_common_session.h" +namespace Ui { +class GenericBox; +} // namespace Ui + namespace Settings { +void PasskeysNoneBox( + not_null box, + not_null session); + class Passkeys : public Section { public: Passkeys(