mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +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;
|
QString email;
|
||||||
int unconfirmedEmailLengthCode;
|
int unconfirmedEmailLengthCode;
|
||||||
bool setOnlyRecoveryEmail = false;
|
bool setOnlyRecoveryEmail = false;
|
||||||
|
|
||||||
|
struct ProcessRecover {
|
||||||
|
bool setNewPassword = false;
|
||||||
|
QString checkedCode;
|
||||||
|
QString emailPattern;
|
||||||
|
};
|
||||||
|
ProcessRecover processRecover;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetupHeader(
|
void SetupHeader(
|
||||||
|
|
|
@ -67,6 +67,8 @@ void EmailConfirm::setupContent() {
|
||||||
// we should forget the current password.
|
// we should forget the current password.
|
||||||
const auto currentPassword = base::take(currentStepData.currentPassword);
|
const auto currentPassword = base::take(currentStepData.currentPassword);
|
||||||
const auto typedPassword = base::take(currentStepData.password);
|
const auto typedPassword = base::take(currentStepData.password);
|
||||||
|
const auto recoverEmailPattern = base::take(
|
||||||
|
currentStepData.processRecover.emailPattern);
|
||||||
setStepData(currentStepData);
|
setStepData(currentStepData);
|
||||||
|
|
||||||
const auto state = cloudPassword().stateCurrent();
|
const auto state = cloudPassword().stateCurrent();
|
||||||
|
@ -77,7 +79,9 @@ void EmailConfirm::setupContent() {
|
||||||
}
|
}
|
||||||
cloudPassword().state(
|
cloudPassword().state(
|
||||||
) | rpl::start_with_next([=](const Core::CloudPasswordState &state) {
|
) | rpl::start_with_next([=](const Core::CloudPasswordState &state) {
|
||||||
if (!_requestLifetime && state.unconfirmedPattern.isEmpty()) {
|
if (!_requestLifetime
|
||||||
|
&& state.unconfirmedPattern.isEmpty()
|
||||||
|
&& recoverEmailPattern.isEmpty()) {
|
||||||
setStepData(StepData());
|
setStepData(StepData());
|
||||||
showBack();
|
showBack();
|
||||||
}
|
}
|
||||||
|
@ -87,12 +91,16 @@ void EmailConfirm::setupContent() {
|
||||||
content,
|
content,
|
||||||
u"cloud_password/email"_q,
|
u"cloud_password/email"_q,
|
||||||
showFinishes(),
|
showFinishes(),
|
||||||
tr::lng_cloud_password_confirm(),
|
state->unconfirmedPattern.isEmpty()
|
||||||
|
? tr::lng_settings_cloud_password_email_recovery_subtitle()
|
||||||
|
: tr::lng_cloud_password_confirm(),
|
||||||
rpl::single(
|
rpl::single(
|
||||||
tr::lng_cloud_password_waiting_code(
|
tr::lng_cloud_password_waiting_code(
|
||||||
tr::now,
|
tr::now,
|
||||||
lt_email,
|
lt_email,
|
||||||
state->unconfirmedPattern)));
|
state->unconfirmedPattern.isEmpty()
|
||||||
|
? recoverEmailPattern
|
||||||
|
: state->unconfirmedPattern)));
|
||||||
|
|
||||||
AddSkip(content, st::settingLocalPasscodeDescriptionBottomSkip);
|
AddSkip(content, st::settingLocalPasscodeDescriptionBottomSkip);
|
||||||
|
|
||||||
|
@ -147,16 +155,19 @@ void EmailConfirm::setupContent() {
|
||||||
newInput->hideError();
|
newInput->hideError();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
resend->setVisible(recoverEmailPattern.isEmpty());
|
||||||
|
|
||||||
const auto button = AddDoneButton(
|
const auto button = AddDoneButton(
|
||||||
content,
|
content,
|
||||||
tr::lng_settings_cloud_password_email_confirm());
|
recoverEmailPattern.isEmpty()
|
||||||
|
? tr::lng_settings_cloud_password_email_confirm()
|
||||||
|
: tr::lng_passcode_check_button());
|
||||||
button->setClickedCallback([=] {
|
button->setClickedCallback([=] {
|
||||||
const auto newText = newInput->getDigitsOnly();
|
const auto newText = newInput->getDigitsOnly();
|
||||||
if (newText.isEmpty()) {
|
if (newText.isEmpty()) {
|
||||||
newInput->setFocus();
|
newInput->setFocus();
|
||||||
newInput->showError();
|
newInput->showError();
|
||||||
} else if (!_requestLifetime) {
|
} else if (!_requestLifetime && recoverEmailPattern.isEmpty()) {
|
||||||
_requestLifetime = cloudPassword().confirmEmail(
|
_requestLifetime = cloudPassword().confirmEmail(
|
||||||
newText
|
newText
|
||||||
) | rpl::start_with_error_done([=](const QString &type) {
|
) | rpl::start_with_error_done([=](const QString &type) {
|
||||||
|
@ -193,6 +204,44 @@ void EmailConfirm::setupContent() {
|
||||||
showOther(CloudPasswordManageId());
|
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 "settings/cloud_password/settings_cloud_password_hint.h"
|
||||||
|
|
||||||
|
#include "api/api_cloud_password.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "settings/cloud_password/settings_cloud_password_common.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_email.h"
|
||||||
|
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
@ -28,6 +30,9 @@ public:
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
void setupContent();
|
void setupContent();
|
||||||
|
|
||||||
|
private:
|
||||||
|
rpl::lifetime _requestLifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rpl::producer<QString> Hint::title() {
|
rpl::producer<QString> Hint::title() {
|
||||||
|
@ -61,10 +66,37 @@ void Hint::setupContent() {
|
||||||
AddSkipInsteadOfField(content);
|
AddSkipInsteadOfField(content);
|
||||||
|
|
||||||
const auto save = [=](const QString &hint) {
|
const auto save = [=](const QString &hint) {
|
||||||
auto data = stepData();
|
if (currentStepData.processRecover.setNewPassword) {
|
||||||
data.hint = hint;
|
if (_requestLifetime) {
|
||||||
setStepData(std::move(data));
|
return;
|
||||||
showOther(CloudPasswordEmailId());
|
}
|
||||||
|
_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(
|
AddLinkButton(
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "lottie/lottie_icon.h"
|
#include "lottie/lottie_icon.h"
|
||||||
#include "settings/cloud_password/settings_cloud_password_common.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_hint.h"
|
||||||
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
@ -68,11 +69,18 @@ public:
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
void setupContent();
|
void setupContent();
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<std::vector<Type>> removeFromStack() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
rpl::variable<std::vector<Type>> _removesFromStack;
|
||||||
rpl::lifetime _requestLifetime;
|
rpl::lifetime _requestLifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rpl::producer<std::vector<Type>> Input::removeFromStack() {
|
||||||
|
return _removesFromStack.value();
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> Input::title() {
|
rpl::producer<QString> Input::title() {
|
||||||
return tr::lng_settings_cloud_password_password_title();
|
return tr::lng_settings_cloud_password_password_title();
|
||||||
}
|
}
|
||||||
|
@ -81,11 +89,22 @@ void Input::setupContent() {
|
||||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||||
auto currentStepData = stepData();
|
auto currentStepData = stepData();
|
||||||
const auto currentStepDataPassword = base::take(currentStepData.password);
|
const auto currentStepDataPassword = base::take(currentStepData.password);
|
||||||
|
const auto currentStepProcessRecover = base::take(
|
||||||
|
currentStepData.processRecover);
|
||||||
setStepData(currentStepData);
|
setStepData(currentStepData);
|
||||||
|
|
||||||
const auto currentState = cloudPassword().stateCurrent();
|
const auto currentState = cloudPassword().stateCurrent();
|
||||||
const auto hasPassword = currentState ? currentState->hasPassword : false;
|
const auto hasPassword = !currentStepProcessRecover.setNewPassword
|
||||||
const auto isCheck = stepData().currentPassword.isEmpty() && hasPassword;
|
&& (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(
|
const auto icon = CreateInteractiveLottieIcon(
|
||||||
content,
|
content,
|
||||||
|
@ -131,6 +150,8 @@ void Input::setupContent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCheck) {
|
if (isCheck) {
|
||||||
|
AddSkipInsteadOfField(content);
|
||||||
|
|
||||||
const auto hint = currentState ? currentState->hint : QString();
|
const auto hint = currentState ? currentState->hint : QString();
|
||||||
const auto hintInfo = Ui::CreateChild<Ui::FlatLabel>(
|
const auto hintInfo = Ui::CreateChild<Ui::FlatLabel>(
|
||||||
error->parentWidget(),
|
error->parentWidget(),
|
||||||
|
@ -149,6 +170,44 @@ void Input::setupContent() {
|
||||||
hintInfo->setVisible(!hint.isEmpty());
|
hintInfo->setVisible(!hint.isEmpty());
|
||||||
}
|
}
|
||||||
}, hintInfo->lifetime());
|
}, 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()) {
|
if (!newInput->text().isEmpty()) {
|
||||||
|
@ -168,7 +227,9 @@ void Input::setupContent() {
|
||||||
newInput->showError();
|
newInput->showError();
|
||||||
newInput->selectAll();
|
newInput->selectAll();
|
||||||
error->show();
|
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) {
|
|| type == u"SRP_PASSWORD_CHANGED"_q) {
|
||||||
error->setText(tr::lng_cloud_password_wrong(tr::now));
|
error->setText(tr::lng_cloud_password_wrong(tr::now));
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,6 +267,7 @@ void Input::setupContent() {
|
||||||
checkPassword(newText);
|
checkPassword(newText);
|
||||||
} else {
|
} else {
|
||||||
auto data = stepData();
|
auto data = stepData();
|
||||||
|
data.processRecover = currentStepProcessRecover;
|
||||||
data.password = newText;
|
data.password = newText;
|
||||||
setStepData(std::move(data));
|
setStepData(std::move(data));
|
||||||
showOther(CloudPasswordHintId());
|
showOther(CloudPasswordHintId());
|
||||||
|
|
Loading…
Add table
Reference in a new issue