From 3967e58627385c710ce8f5a18d644930687d1b47 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 7 May 2022 03:58:41 +0300 Subject: [PATCH] Improved step section of password input for checking cloud password. --- .../settings_cloud_password_input.cpp | 110 +++++++++++++++--- 1 file changed, 95 insertions(+), 15 deletions(-) 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 80ba14bc76..1152ac1237 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp @@ -7,11 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "settings/cloud_password/settings_cloud_password_input.h" +#include "api/api_cloud_password.h" #include "base/qt_signal_producer.h" +#include "core/core_cloud_password.h" #include "lang/lang_keys.h" #include "lottie/lottie_icon.h" #include "settings/cloud_password/settings_cloud_password_common.h" #include "settings/cloud_password/settings_cloud_password_hint.h" +#include "settings/cloud_password/settings_cloud_password_manage.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/labels.h" @@ -65,6 +68,9 @@ public: [[nodiscard]] rpl::producer title() override; void setupContent(); +private: + rpl::lifetime _requestLifetime; + }; rpl::producer Input::title() { @@ -77,6 +83,10 @@ void Input::setupContent() { const auto currentStepDataPassword = base::take(currentStepData.password); setStepData(currentStepData); + const auto currentState = cloudPassword().stateCurrent(); + const auto hasPassword = currentState ? currentState->hasPassword : false; + const auto isCheck = stepData().currentPassword.isEmpty() && hasPassword; + const auto icon = CreateInteractiveLottieIcon( content, { @@ -92,41 +102,108 @@ void Input::setupContent() { content, QString(), rpl::never<>(), - tr::lng_settings_cloud_password_password_subtitle(), + isCheck + ? tr::lng_settings_cloud_password_check_subtitle() + : hasPassword + ? tr::lng_settings_cloud_password_manage_password_change() + : tr::lng_settings_cloud_password_password_subtitle(), tr::lng_cloud_password_about()); AddSkip(content, st::settingLocalPasscodeDescriptionBottomSkip); const auto newInput = AddPasswordField( content, - tr::lng_cloud_password_enter_new(), - currentStepDataPassword); - const auto reenterInput = AddPasswordField( - content, - tr::lng_cloud_password_confirm_new(), - currentStepDataPassword); - const auto error = AddError(content, reenterInput); + isCheck + ? tr::lng_cloud_password_enter_old() + : tr::lng_cloud_password_enter_new(), + currentStepDataPassword); + const auto reenterInput = isCheck + ? (Ui::PasswordInput*)(nullptr) + : AddPasswordField( + content, + tr::lng_cloud_password_confirm_new(), + currentStepDataPassword).get(); + const auto error = AddError(content, newInput); + if (reenterInput) { + QObject::connect(reenterInput, &Ui::MaskedInputField::changed, [=] { + error->hide(); + }); + } + + if (isCheck) { + const auto hint = currentState ? currentState->hint : QString(); + const auto hintInfo = Ui::CreateChild( + error->parentWidget(), + tr::lng_signin_hint(tr::now, lt_password_hint, hint), + st::defaultFlatLabel); + hintInfo->setVisible(!hint.isEmpty()); + error->geometryValue( + ) | rpl::start_with_next([=](const QRect &r) { + hintInfo->setGeometry(r); + }, hintInfo->lifetime()); + error->shownValue( + ) | rpl::start_with_next([=](bool shown) { + if (shown) { + hintInfo->hide(); + } else { + hintInfo->setVisible(!hint.isEmpty()); + } + }, hintInfo->lifetime()); + } if (!newInput->text().isEmpty()) { icon.icon->jumpTo(icon.icon->framesCount() / 2, icon.update); } - const auto button = AddDoneButton(content, tr::lng_continue()); + const auto checkPassword = [=](const QString &pass) { + if (_requestLifetime) { + return; + } + _requestLifetime = cloudPassword().check( + pass + ) | rpl::start_with_error_done([=](const QString &type) { + _requestLifetime.destroy(); + + newInput->setFocus(); + newInput->showError(); + newInput->selectAll(); + error->show(); + if (type == u"PASSWORD_HASH_INVALID"_q + || type == u"SRP_PASSWORD_CHANGED"_q) { + error->setText(tr::lng_cloud_password_wrong(tr::now)); + } else { + error->setText(Lang::Hard::ServerError()); + } + }, [=] { + _requestLifetime.destroy(); + + auto data = stepData(); + data.currentPassword = pass; + setStepData(std::move(data)); + showOther(CloudPasswordManageId()); + }); + }; + + const auto button = AddDoneButton( + content, + isCheck ? tr::lng_passcode_check_button() : tr::lng_continue()); button->setClickedCallback([=] { const auto newText = newInput->text(); - const auto reenterText = reenterInput->text(); + const auto reenterText = isCheck ? QString() : reenterInput->text(); if (newText.isEmpty()) { newInput->setFocus(); newInput->showError(); - } else if (reenterText.isEmpty()) { + } else if (reenterInput && reenterText.isEmpty()) { reenterInput->setFocus(); reenterInput->showError(); - } else if (newText != reenterText) { + } else if (reenterInput && (newText != reenterText)) { reenterInput->setFocus(); reenterInput->showError(); reenterInput->selectAll(); error->show(); error->setText(tr::lng_cloud_password_differ(tr::now)); + } else if (isCheck) { + checkPassword(newText); } else { auto data = stepData(); data.password = newText; @@ -148,17 +225,20 @@ void Input::setupContent() { }, content->lifetime()); const auto submit = [=] { - if (reenterInput->hasFocus()) { + if (!reenterInput || reenterInput->hasFocus()) { button->clicked({}, Qt::LeftButton); } else { reenterInput->setFocus(); } }; QObject::connect(newInput, &Ui::MaskedInputField::submitted, submit); - QObject::connect(reenterInput, &Ui::MaskedInputField::submitted, submit); + if (reenterInput) { + using namespace Ui; + QObject::connect(reenterInput, &MaskedInputField::submitted, submit); + } setFocusCallback([=] { - if (newInput->text().isEmpty()) { + if (isCheck || newInput->text().isEmpty()) { newInput->setFocus(); } else if (reenterInput->text().isEmpty()) { reenterInput->setFocus();