mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Added ability to recover cloud password with email from settings.
This commit is contained in:
parent
4d5cb6398e
commit
031525e7e3
4 changed files with 162 additions and 12 deletions
|
@ -34,6 +34,13 @@ struct StepData {
|
|||
QString email;
|
||||
int unconfirmedEmailLengthCode;
|
||||
bool setOnlyRecoveryEmail = false;
|
||||
|
||||
struct ProcessRecover {
|
||||
bool setNewPassword = false;
|
||||
QString checkedCode;
|
||||
QString emailPattern;
|
||||
};
|
||||
ProcessRecover processRecover;
|
||||
};
|
||||
|
||||
void SetupHeader(
|
||||
|
|
|
@ -67,6 +67,8 @@ void EmailConfirm::setupContent() {
|
|||
// we should forget the current password.
|
||||
const auto currentPassword = base::take(currentStepData.currentPassword);
|
||||
const auto typedPassword = base::take(currentStepData.password);
|
||||
const auto recoverEmailPattern = base::take(
|
||||
currentStepData.processRecover.emailPattern);
|
||||
setStepData(currentStepData);
|
||||
|
||||
const auto state = cloudPassword().stateCurrent();
|
||||
|
@ -77,7 +79,9 @@ void EmailConfirm::setupContent() {
|
|||
}
|
||||
cloudPassword().state(
|
||||
) | rpl::start_with_next([=](const Core::CloudPasswordState &state) {
|
||||
if (!_requestLifetime && state.unconfirmedPattern.isEmpty()) {
|
||||
if (!_requestLifetime
|
||||
&& state.unconfirmedPattern.isEmpty()
|
||||
&& recoverEmailPattern.isEmpty()) {
|
||||
setStepData(StepData());
|
||||
showBack();
|
||||
}
|
||||
|
@ -87,12 +91,16 @@ void EmailConfirm::setupContent() {
|
|||
content,
|
||||
u"cloud_password/email"_q,
|
||||
showFinishes(),
|
||||
tr::lng_cloud_password_confirm(),
|
||||
state->unconfirmedPattern.isEmpty()
|
||||
? tr::lng_settings_cloud_password_email_recovery_subtitle()
|
||||
: tr::lng_cloud_password_confirm(),
|
||||
rpl::single(
|
||||
tr::lng_cloud_password_waiting_code(
|
||||
tr::now,
|
||||
lt_email,
|
||||
state->unconfirmedPattern)));
|
||||
state->unconfirmedPattern.isEmpty()
|
||||
? recoverEmailPattern
|
||||
: state->unconfirmedPattern)));
|
||||
|
||||
AddSkip(content, st::settingLocalPasscodeDescriptionBottomSkip);
|
||||
|
||||
|
@ -147,16 +155,19 @@ void EmailConfirm::setupContent() {
|
|||
newInput->hideError();
|
||||
});
|
||||
});
|
||||
resend->setVisible(recoverEmailPattern.isEmpty());
|
||||
|
||||
const auto button = AddDoneButton(
|
||||
content,
|
||||
tr::lng_settings_cloud_password_email_confirm());
|
||||
recoverEmailPattern.isEmpty()
|
||||
? tr::lng_settings_cloud_password_email_confirm()
|
||||
: tr::lng_passcode_check_button());
|
||||
button->setClickedCallback([=] {
|
||||
const auto newText = newInput->getDigitsOnly();
|
||||
if (newText.isEmpty()) {
|
||||
newInput->setFocus();
|
||||
newInput->showError();
|
||||
} else if (!_requestLifetime) {
|
||||
} else if (!_requestLifetime && recoverEmailPattern.isEmpty()) {
|
||||
_requestLifetime = cloudPassword().confirmEmail(
|
||||
newText
|
||||
) | rpl::start_with_error_done([=](const QString &type) {
|
||||
|
@ -193,6 +204,44 @@ void EmailConfirm::setupContent() {
|
|||
showOther(CloudPasswordManageId());
|
||||
}
|
||||
});
|
||||
} else if (!_requestLifetime) {
|
||||
_requestLifetime = cloudPassword().checkRecoveryEmailAddressCode(
|
||||
newText
|
||||
) | rpl::start_with_error_done([=](const QString &type) {
|
||||
_requestLifetime.destroy();
|
||||
|
||||
newInput->setFocus();
|
||||
newInput->showError();
|
||||
error->show();
|
||||
|
||||
if (MTP::IsFloodError(type)) {
|
||||
error->setText(tr::lng_flood_error(tr::now));
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == u"PASSWORD_RECOVERY_NA"_q) {
|
||||
setStepData(StepData());
|
||||
showBack();
|
||||
} else if (type == u"PASSWORD_RECOVERY_EXPIRED"_q) {
|
||||
setStepData(StepData());
|
||||
showBack();
|
||||
} else if (type == u"CODE_INVALID"_q) {
|
||||
error->setText(tr::lng_signin_wrong_code(tr::now));
|
||||
} else {
|
||||
error->setText(Logs::DebugEnabled()
|
||||
// internal server error
|
||||
? type
|
||||
: Lang::Hard::ServerError());
|
||||
}
|
||||
}, [=] {
|
||||
_requestLifetime.destroy();
|
||||
|
||||
auto empty = StepData();
|
||||
empty.processRecover.checkedCode = newText;
|
||||
empty.processRecover.setNewPassword = true;
|
||||
setStepData(std::move(empty));
|
||||
showOther(CloudPasswordInputId());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -7,9 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "settings/cloud_password/settings_cloud_password_hint.h"
|
||||
|
||||
#include "api/api_cloud_password.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "settings/cloud_password/settings_cloud_password_common.h"
|
||||
#include "settings/cloud_password/settings_cloud_password_email.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"
|
||||
|
@ -28,6 +30,9 @@ public:
|
|||
[[nodiscard]] rpl::producer<QString> title() override;
|
||||
void setupContent();
|
||||
|
||||
private:
|
||||
rpl::lifetime _requestLifetime;
|
||||
|
||||
};
|
||||
|
||||
rpl::producer<QString> Hint::title() {
|
||||
|
@ -61,10 +66,37 @@ void Hint::setupContent() {
|
|||
AddSkipInsteadOfField(content);
|
||||
|
||||
const auto save = [=](const QString &hint) {
|
||||
auto data = stepData();
|
||||
data.hint = hint;
|
||||
setStepData(std::move(data));
|
||||
showOther(CloudPasswordEmailId());
|
||||
if (currentStepData.processRecover.setNewPassword) {
|
||||
if (_requestLifetime) {
|
||||
return;
|
||||
}
|
||||
_requestLifetime = cloudPassword().recoverPassword(
|
||||
currentStepData.processRecover.checkedCode,
|
||||
currentStepData.password,
|
||||
hint
|
||||
) | rpl::start_with_error_done([=](const QString &type) {
|
||||
_requestLifetime.destroy();
|
||||
|
||||
error->show();
|
||||
if (MTP::IsFloodError(type)) {
|
||||
error->setText(tr::lng_flood_error(tr::now));
|
||||
} else {
|
||||
error->setText(Lang::Hard::ServerError());
|
||||
}
|
||||
}, [=] {
|
||||
_requestLifetime.destroy();
|
||||
|
||||
auto empty = StepData();
|
||||
empty.currentPassword = stepData().password;
|
||||
setStepData(std::move(empty));
|
||||
showOther(CloudPasswordManageId());
|
||||
});
|
||||
} else {
|
||||
auto data = stepData();
|
||||
data.hint = hint;
|
||||
setStepData(std::move(data));
|
||||
showOther(CloudPasswordEmailId());
|
||||
}
|
||||
};
|
||||
|
||||
AddLinkButton(
|
||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#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_email_confirm.h"
|
||||
#include "settings/cloud_password/settings_cloud_password_hint.h"
|
||||
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
@ -68,11 +69,18 @@ public:
|
|||
[[nodiscard]] rpl::producer<QString> title() override;
|
||||
void setupContent();
|
||||
|
||||
[[nodiscard]] rpl::producer<std::vector<Type>> removeFromStack() override;
|
||||
|
||||
private:
|
||||
rpl::variable<std::vector<Type>> _removesFromStack;
|
||||
rpl::lifetime _requestLifetime;
|
||||
|
||||
};
|
||||
|
||||
rpl::producer<std::vector<Type>> Input::removeFromStack() {
|
||||
return _removesFromStack.value();
|
||||
}
|
||||
|
||||
rpl::producer<QString> Input::title() {
|
||||
return tr::lng_settings_cloud_password_password_title();
|
||||
}
|
||||
|
@ -81,11 +89,22 @@ void Input::setupContent() {
|
|||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
auto currentStepData = stepData();
|
||||
const auto currentStepDataPassword = base::take(currentStepData.password);
|
||||
const auto currentStepProcessRecover = base::take(
|
||||
currentStepData.processRecover);
|
||||
setStepData(currentStepData);
|
||||
|
||||
const auto currentState = cloudPassword().stateCurrent();
|
||||
const auto hasPassword = currentState ? currentState->hasPassword : false;
|
||||
const auto isCheck = stepData().currentPassword.isEmpty() && hasPassword;
|
||||
const auto hasPassword = !currentStepProcessRecover.setNewPassword
|
||||
&& (currentState ? currentState->hasPassword : false);
|
||||
const auto isCheck = currentStepData.currentPassword.isEmpty()
|
||||
&& hasPassword
|
||||
&& !currentStepProcessRecover.setNewPassword;
|
||||
|
||||
if (currentStepProcessRecover.setNewPassword) {
|
||||
_removesFromStack = std::vector<Type>{
|
||||
CloudPasswordEmailConfirmId()
|
||||
};
|
||||
}
|
||||
|
||||
const auto icon = CreateInteractiveLottieIcon(
|
||||
content,
|
||||
|
@ -131,6 +150,8 @@ void Input::setupContent() {
|
|||
}
|
||||
|
||||
if (isCheck) {
|
||||
AddSkipInsteadOfField(content);
|
||||
|
||||
const auto hint = currentState ? currentState->hint : QString();
|
||||
const auto hintInfo = Ui::CreateChild<Ui::FlatLabel>(
|
||||
error->parentWidget(),
|
||||
|
@ -149,6 +170,44 @@ void Input::setupContent() {
|
|||
hintInfo->setVisible(!hint.isEmpty());
|
||||
}
|
||||
}, hintInfo->lifetime());
|
||||
|
||||
const auto recover = Ui::CreateChild<Ui::LinkButton>(
|
||||
content,
|
||||
tr::lng_signin_recover(tr::now));
|
||||
|
||||
rpl::merge(
|
||||
content->geometryValue(),
|
||||
newInput->geometryValue()
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto topLeft = newInput->mapTo(content, newInput->pos());
|
||||
recover->moveToLeft(
|
||||
newInput->pos().x(),
|
||||
topLeft.y() + newInput->height() + st::passcodeTextLine);
|
||||
}, recover->lifetime());
|
||||
recover->setClickedCallback([=] {
|
||||
if (_requestLifetime) {
|
||||
return;
|
||||
}
|
||||
_requestLifetime = cloudPassword().requestPasswordRecovery(
|
||||
) | rpl::start_with_next_error([=](const QString &pattern) {
|
||||
_requestLifetime.destroy();
|
||||
|
||||
auto data = stepData();
|
||||
data.processRecover = currentStepProcessRecover;
|
||||
data.processRecover.emailPattern = pattern;
|
||||
setStepData(std::move(data));
|
||||
showOther(CloudPasswordEmailConfirmId());
|
||||
}, [=](const QString &type) {
|
||||
_requestLifetime.destroy();
|
||||
|
||||
error->show();
|
||||
if (MTP::IsFloodError(type)) {
|
||||
error->setText(tr::lng_flood_error(tr::now));
|
||||
} else {
|
||||
error->setText(Lang::Hard::ServerError());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!newInput->text().isEmpty()) {
|
||||
|
@ -168,7 +227,9 @@ void Input::setupContent() {
|
|||
newInput->showError();
|
||||
newInput->selectAll();
|
||||
error->show();
|
||||
if (type == u"PASSWORD_HASH_INVALID"_q
|
||||
if (MTP::IsFloodError(type)) {
|
||||
error->setText(tr::lng_flood_error(tr::now));
|
||||
} else if (type == u"PASSWORD_HASH_INVALID"_q
|
||||
|| type == u"SRP_PASSWORD_CHANGED"_q) {
|
||||
error->setText(tr::lng_cloud_password_wrong(tr::now));
|
||||
} else {
|
||||
|
@ -206,6 +267,7 @@ void Input::setupContent() {
|
|||
checkPassword(newText);
|
||||
} else {
|
||||
auto data = stepData();
|
||||
data.processRecover = currentStepProcessRecover;
|
||||
data.password = newText;
|
||||
setStepData(std::move(data));
|
||||
showOther(CloudPasswordHintId());
|
||||
|
|
Loading…
Add table
Reference in a new issue