From 1ae3122c205f4e5e48839db831c8e6baf8f86d38 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 28 May 2025 13:33:09 +0300 Subject: [PATCH] Added support of suggestion to validate cloud password to settings. --- Telegram/CMakeLists.txt | 2 + .../animations/cloud_password/validate.tgs | Bin 0 -> 15226 bytes Telegram/Resources/langs/lang.strings | 8 + .../Resources/qrc/telegram/animations.qrc | 1 + .../data/components/promo_suggestions.cpp | 5 + .../data/components/promo_suggestions.h | 2 + .../settings_cloud_password_common.h | 1 + .../settings_cloud_password_input.cpp | 155 ++++++++++++++---- .../settings_cloud_password_input.h | 1 + .../settings_cloud_password_validate_icon.cpp | 74 +++++++++ .../settings_cloud_password_validate_icon.h | 27 +++ .../SourceFiles/settings/settings_main.cpp | 78 ++++++++- 12 files changed, 324 insertions(+), 30 deletions(-) create mode 100644 Telegram/Resources/animations/cloud_password/validate.tgs create mode 100644 Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.cpp create mode 100644 Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 50dcfec3e6..92ce8f31a3 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1446,6 +1446,8 @@ PRIVATE settings/cloud_password/settings_cloud_password_start.h settings/cloud_password/settings_cloud_password_step.cpp settings/cloud_password/settings_cloud_password_step.h + settings/cloud_password/settings_cloud_password_validate_icon.cpp + settings/cloud_password/settings_cloud_password_validate_icon.h settings/settings_active_sessions.cpp settings/settings_active_sessions.h settings/settings_advanced.cpp diff --git a/Telegram/Resources/animations/cloud_password/validate.tgs b/Telegram/Resources/animations/cloud_password/validate.tgs new file mode 100644 index 0000000000000000000000000000000000000000..fd5161d885486ba3a015d7792a1f06aff63f542a GIT binary patch literal 15226 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../../animations/cloud_password/password_input.tgs ../../animations/cloud_password/hint.tgs ../../animations/cloud_password/email.tgs + ../../animations/cloud_password/validate.tgs ../../animations/ttl.tgs ../../animations/discussion.tgs ../../animations/stats.tgs diff --git a/Telegram/SourceFiles/data/components/promo_suggestions.cpp b/Telegram/SourceFiles/data/components/promo_suggestions.cpp index 99ec5f5b2f..33c0b860a5 100644 --- a/Telegram/SourceFiles/data/components/promo_suggestions.cpp +++ b/Telegram/SourceFiles/data/components/promo_suggestions.cpp @@ -306,4 +306,9 @@ std::optional PromoSuggestions::knownBirthdaysToday() const { return _contactBirthdaysToday; } +QString PromoSuggestions::SugValidatePassword() { + static const auto key = u"VALIDATE_PASSWORD"_q; + return key; +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/components/promo_suggestions.h b/Telegram/SourceFiles/data/components/promo_suggestions.h index 33f943a958..e57c1162cf 100644 --- a/Telegram/SourceFiles/data/components/promo_suggestions.h +++ b/Telegram/SourceFiles/data/components/promo_suggestions.h @@ -51,6 +51,8 @@ public: [[nodiscard]] auto knownBirthdaysToday() const -> std::optional>; + [[nodiscard]] static QString SugValidatePassword(); + private: void setTopPromoted( History *promoted, diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h index 586e58a9dd..a87c1aaed5 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h @@ -34,6 +34,7 @@ struct StepData { QString email; int unconfirmedEmailLengthCode; bool setOnlyRecoveryEmail = false; + bool suggestionValidate = false; struct ProcessRecover { bool setNewPassword = false; diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp index 0064dcbda7..7719fc2ddd 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp @@ -12,20 +12,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" #include "base/unixtime.h" #include "core/core_cloud_password.h" +#include "data/components/promo_suggestions.h" #include "lang/lang_keys.h" #include "lottie/lottie_icon.h" +#include "main/main_session.h" #include "settings/cloud_password/settings_cloud_password_common.h" #include "settings/cloud_password/settings_cloud_password_email_confirm.h" #include "settings/cloud_password/settings_cloud_password_hint.h" #include "settings/cloud_password/settings_cloud_password_manage.h" #include "settings/cloud_password/settings_cloud_password_step.h" +#include "settings/cloud_password/settings_cloud_password_validate_icon.h" +#include "ui/boxes/boost_box.h" // Ui::StartFireworks. #include "ui/boxes/confirm_box.h" +#include "ui/rect.h" #include "ui/text/format_values.h" +#include "ui/ui_utility.h" +#include "ui/vertical_list.h" #include "ui/widgets/buttons.h" #include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" -#include "ui/vertical_list.h" #include "window/window_session_controller.h" #include "styles/style_boxes.h" #include "styles/style_layers.h" @@ -53,6 +59,10 @@ RecreateResetPassword: – Continue to RecreateResetHint. – Clear password and Back to Settings. – Back to Settings. + +ValidatePassword: +- Submit to show good validate. +- Back to Main Settings. */ namespace Settings { @@ -72,9 +82,7 @@ Icon CreateInteractiveLottieIcon( const auto raw = object.data(); const auto width = descriptor.sizeOverride.width(); - raw->resize(QRect( - QPoint(), - descriptor.sizeOverride).marginsAdded(padding).size()); + raw->resize((Rect(descriptor.sizeOverride) + padding).size()); auto owned = Lottie::MakeIcon(std::move(descriptor)); const auto icon = owned.get(); @@ -118,7 +126,10 @@ public: using TypedAbstractStep::TypedAbstractStep; [[nodiscard]] rpl::producer title() override; + [[nodiscard]] QPointer createPinnedToTop( + not_null parent) override; void setupContent(); + void setupValidateGood(); protected: [[nodiscard]] rpl::producer> removeTypes() override; @@ -130,6 +141,8 @@ private: not_null info, Fn recoverCallback); + QWidget *_parent = nullptr; + rpl::variable> _removesFromStack; rpl::lifetime _requestLifetime; @@ -143,12 +156,58 @@ rpl::producer Input::title() { return tr::lng_settings_cloud_password_password_title(); } +QPointer Input::createPinnedToTop( + not_null parent) { + _parent = parent; + return nullptr; +} + +void Input::setupValidateGood() { + const auto content = Ui::CreateChild(this); + + if (_parent) { + Ui::StartFireworks(_parent); + } + + if (auto owned = CreateValidateGoodIcon(&controller()->session())) { + owned->setParent(content); + content->add( + object_ptr>( + content, + std::move(owned)), + QMargins(0, st::lineWidth * 75, 0, 0)); + } + + SetupHeader( + content, + QString(), + rpl::never<>(), + tr::lng_settings_suggestion_password_step_finish_title(), + tr::lng_settings_suggestion_password_step_finish_about()); + + const auto button = AddDoneButton(content, tr::lng_share_done()); + button->setClickedCallback([=] { + showBack(); + }); + + Ui::ToggleChildrenVisibility(this, true); + Ui::ResizeFitChild(this, content); + content->resizeToWidth(width()); + Ui::SendPendingMoveResizeEvents(content); +} + void Input::setupContent() { + if (QWidget::children().count() > 0) { + return; + } + const auto content = Ui::CreateChild(this); auto currentStepData = stepData(); const auto currentStepDataPassword = base::take(currentStepData.password); const auto currentStepProcessRecover = base::take( currentStepData.processRecover); + const auto currentStepValidate = base::take( + currentStepData.suggestionValidate); setStepData(currentStepData); const auto currentState = cloudPassword().stateCurrent(); @@ -167,11 +226,10 @@ void Input::setupContent() { const auto icon = CreateInteractiveLottieIcon( content, { - .name = u"cloud_password/password_input"_q, - .sizeOverride = { - st::settingsCloudPasswordIconSize, - st::settingsCloudPasswordIconSize - }, + .name = currentStepValidate + ? u"cloud_password/validate"_q + : u"cloud_password/password_input"_q, + .sizeOverride = Size(st::settingsCloudPasswordIconSize), }, st::settingLocalPasscodeIconPadding); @@ -179,12 +237,16 @@ void Input::setupContent() { content, QString(), rpl::never<>(), - isCheck + currentStepValidate + ? tr::lng_settings_suggestion_password_step_input_title() + : isCheck ? tr::lng_settings_cloud_password_check_subtitle() : hasPassword ? tr::lng_settings_cloud_password_manage_password_change() : tr::lng_settings_cloud_password_password_subtitle(), - isCheck + currentStepValidate + ? tr::lng_settings_suggestion_password_step_input_about() + : isCheck ? tr::lng_settings_cloud_password_manage_about1() : tr::lng_cloud_password_about()); @@ -340,7 +402,9 @@ void Input::setupContent() { Ui::AddSkip(content); } - if (!newInput->text().isEmpty()) { + if (currentStepValidate) { + icon.icon->animate(icon.update, 0, icon.icon->framesCount() - 1); + } else if (!newInput->text().isEmpty()) { icon.icon->jumpTo(icon.icon->framesCount() / 2, icon.update); } @@ -376,10 +440,18 @@ void Input::setupContent() { } } - auto data = stepData(); - data.currentPassword = pass; - setStepData(std::move(data)); - showOther(CloudPasswordManageId()); + if (currentStepValidate) { + controller()->session().promoSuggestions().dismiss( + Data::PromoSuggestions::SugValidatePassword()); + setupValidateGood(); + delete content; + } else { + auto data = stepData(); + data.currentPassword = pass; + setStepData(std::move(data)); + showOther(CloudPasswordManageId()); + } + }); }; @@ -412,17 +484,19 @@ void Input::setupContent() { } }); - base::qt_signal_producer( - newInput.get(), - &QLineEdit::textChanged // Covers Undo. - ) | rpl::map([=] { - return newInput->text().isEmpty(); - }) | rpl::distinct_until_changed( - ) | rpl::start_with_next([=](bool empty) { - const auto from = icon.icon->frameIndex(); - const auto to = empty ? 0 : (icon.icon->framesCount() / 2 - 1); - icon.icon->animate(icon.update, from, to); - }, content->lifetime()); + if (!currentStepValidate) { + base::qt_signal_producer( + newInput.get(), + &QLineEdit::textChanged // Covers Undo. + ) | rpl::map([=] { + return newInput->text().isEmpty(); + }) | rpl::distinct_until_changed( + ) | rpl::start_with_next([=](bool empty) { + const auto from = icon.icon->frameIndex(); + const auto to = empty ? 0 : (icon.icon->framesCount() / 2 - 1); + icon.icon->animate(icon.update, from, to); + }, content->lifetime()); + } const auto submit = [=] { if (!reenterInput || reenterInput->hasFocus()) { @@ -437,7 +511,7 @@ void Input::setupContent() { QObject::connect(reenterInput, &MaskedInputField::submitted, submit); } - setFocusCallback([=] { + setFocusCallback(crl::guard(content, [=] { if (isCheck || newInput->text().isEmpty()) { newInput->setFocus(); } else if (reenterInput->text().isEmpty()) { @@ -445,7 +519,7 @@ void Input::setupContent() { } else { newInput->setFocus(); } - }); + })); Ui::ResizeFitChild(this, content); } @@ -586,10 +660,33 @@ void Input::setupRecoverButton( }); } +class SuggestionInput : public Input { +public: + SuggestionInput( + QWidget *parent, + not_null controller) + : Input(parent, controller) + , _stepData(StepData{ .suggestionValidate = true }) { + setStepDataReference(_stepData); + } + + [[nodiscard]] static Type Id() { + return SectionFactory::Instance(); + } + +private: + std::any _stepData; + +}; + } // namespace CloudPassword Type CloudPasswordInputId() { return CloudPassword::Input::Id(); } +Type CloudPasswordSuggestionInputId() { + return CloudPassword::SuggestionInput::Id(); +} + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.h b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.h index 1103047df4..0c1ae4f89c 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.h +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.h @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Settings { Type CloudPasswordInputId(); +Type CloudPasswordSuggestionInputId(); } // namespace Settings diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.cpp new file mode 100644 index 0000000000..7ea244e8ff --- /dev/null +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.cpp @@ -0,0 +1,74 @@ +/* +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 +*/ +#include "settings/cloud_password/settings_cloud_password_validate_icon.h" + +#include "apiwrap.h" +#include "base/object_ptr.h" +#include "chat_helpers/stickers_emoji_pack.h" +#include "data/data_session.h" +#include "data/stickers/data_custom_emoji.h" +#include "data/stickers/data_stickers.h" +#include "main/main_session.h" +#include "ui/rect.h" +#include "ui/rp_widget.h" +#include "styles/style_settings.h" + +namespace Settings { +namespace { + +[[nodiscard]] DocumentData *EmojiValidateGood( + not_null session) { + auto emoji = TextWithEntities{ + .text = (QString(QChar(0xD83D)) + QChar(0xDC4D)), + }; + if (const auto e = Ui::Emoji::Find(emoji.text)) { + const auto sticker = session->emojiStickersPack().stickerForEmoji(e); + return sticker.document; + } + return nullptr; +} + +} // namespace + +object_ptr CreateValidateGoodIcon( + not_null session) { + const auto document = EmojiValidateGood(session); + if (!document) { + return nullptr; + } + + auto owned = object_ptr((QWidget*)nullptr); + const auto widget = owned.data(); + + struct State { + std::unique_ptr emoji; + }; + const auto state = widget->lifetime().make_state(); + const auto size = st::settingsCloudPasswordIconSize; + state->emoji = std::make_unique( + session->data().customEmojiManager().create( + document, + [=] { widget->update(); }, + Data::CustomEmojiManager::SizeTag::Normal, + size), + 1, + true); + widget->paintRequest() | rpl::start_with_next([=] { + auto p = QPainter(widget); + state->emoji->paint(p, Ui::Text::CustomEmojiPaintContext{ + .textColor = st::windowFg->c, + .now = crl::now(), + }); + }, widget->lifetime()); + const auto padding = st::settingLocalPasscodeIconPadding; + widget->resize((Rect(Size(size)) + padding).size()); + + return owned; +} + +} // namespace Settings diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.h b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.h new file mode 100644 index 0000000000..54280d7360 --- /dev/null +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_validate_icon.h @@ -0,0 +1,27 @@ +/* +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 + +template +class object_ptr; + +namespace Main { +class Session; +} // namespace Main + +namespace Ui { +class RpWidget; +} // namespace Ui + +namespace Settings { + +[[nodiscard]] object_ptr CreateValidateGoodIcon( + not_null session); + +} // namespace Settings + diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index 07ad5e1f99..496e5e2933 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "settings/settings_main.h" +#include "settings/cloud_password/settings_cloud_password_input.h" #include "api/api_credits.h" #include "core/application.h" #include "core/click_handler_types.h" @@ -467,7 +468,7 @@ void SetupValidatePhoneNumberSuggestion( yes->setClickedCallback([=] { controller->session().promoSuggestions().dismiss( kSugValidatePhone.utf8()); - mainWrap->toggle(false, anim::type::normal); + mainWrap->toggle(false, anim::type::normal); }); const auto no = Ui::CreateChild( wrap, @@ -522,6 +523,77 @@ void SetupValidatePhoneNumberSuggestion( Ui::AddSkip(content); } +void SetupValidatePasswordSuggestion( + not_null controller, + not_null container, + Fn showOther) { + if (!controller->session().promoSuggestions().current( + Data::PromoSuggestions::SugValidatePassword()) + || controller->session().promoSuggestions().current( + kSugValidatePhone.utf8())) { + return; + } + const auto mainWrap = container->add( + object_ptr>( + container, + object_ptr(container))); + const auto content = mainWrap->entity(); + Ui::AddSubsectionTitle( + content, + tr::lng_settings_suggestion_password_title(), + QMargins( + st::boxRowPadding.left() + - st::defaultSubsectionTitlePadding.left(), + 0, + 0, + 0)); + const auto label = content->add( + object_ptr( + content, + tr::lng_settings_suggestion_password_about(), + st::boxLabel), + st::boxRowPadding); + + Ui::AddSkip(content); + Ui::AddSkip(content); + + const auto wrap = content->add( + object_ptr( + content, + st::inviteLinkButton.height), + st::inviteLinkButtonsPadding); + const auto yes = Ui::CreateChild( + wrap, + tr::lng_settings_suggestion_password_yes(), + st::inviteLinkButton); + yes->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); + yes->setClickedCallback([=] { + controller->session().promoSuggestions().dismiss( + Data::PromoSuggestions::SugValidatePassword()); + mainWrap->toggle(false, anim::type::normal); + }); + const auto no = Ui::CreateChild( + wrap, + tr::lng_settings_suggestion_password_no(), + st::inviteLinkButton); + no->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); + no->setClickedCallback([=] { + showOther(Settings::CloudPasswordSuggestionInputId()); + }); + + wrap->widthValue() | rpl::start_with_next([=](int width) { + const auto buttonWidth = (width - st::inviteLinkButtonsSkip) / 2; + yes->setFullWidth(buttonWidth); + no->setFullWidth(buttonWidth); + yes->moveToLeft(0, 0, width); + no->moveToRight(0, 0, width); + }, wrap->lifetime()); + Ui::AddSkip(content); + Ui::AddSkip(content); + Ui::AddDivider(content); + Ui::AddSkip(content); +} + void SetupSections( not_null controller, not_null container, @@ -533,6 +605,10 @@ void SetupSections( controller, container, showOther); + SetupValidatePasswordSuggestion( + controller, + container, + showOther); const auto addSection = [&]( rpl::producer label,