2022-05-06 03:22:48 +00:00
|
|
|
|
/*
|
|
|
|
|
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_email.h"
|
|
|
|
|
|
|
|
|
|
#include "api/api_cloud_password.h"
|
2022-05-08 20:04:46 +00:00
|
|
|
|
#include "core/core_cloud_password.h"
|
2022-05-06 03:22:48 +00:00
|
|
|
|
#include "lang/lang_keys.h"
|
|
|
|
|
#include "settings/cloud_password/settings_cloud_password_common.h"
|
2022-05-07 02:45:52 +00:00
|
|
|
|
#include "settings/cloud_password/settings_cloud_password_email_confirm.h"
|
2022-05-06 23:47:57 +00:00
|
|
|
|
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
2022-05-06 03:22:48 +00:00
|
|
|
|
#include "ui/boxes/confirm_box.h"
|
|
|
|
|
#include "ui/widgets/buttons.h"
|
2023-08-31 11:21:24 +00:00
|
|
|
|
#include "ui/widgets/fields/input_field.h"
|
2022-05-06 03:22:48 +00:00
|
|
|
|
#include "ui/wrap/padding_wrap.h"
|
|
|
|
|
#include "ui/wrap/vertical_layout.h"
|
|
|
|
|
#include "window/window_session_controller.h"
|
|
|
|
|
#include "styles/style_boxes.h"
|
|
|
|
|
#include "styles/style_layers.h"
|
|
|
|
|
#include "styles/style_settings.h"
|
|
|
|
|
|
2022-05-09 19:03:56 +00:00
|
|
|
|
/*
|
|
|
|
|
Available actions for follow states.
|
|
|
|
|
|
|
|
|
|
CreateEmail:
|
|
|
|
|
– Continue to EmailConfirm.
|
|
|
|
|
+ Continue to Manage if Email is confirmed already.
|
|
|
|
|
– Warn and Skip to Manage.
|
|
|
|
|
– Back to CreateHint.
|
|
|
|
|
|
|
|
|
|
ChangeEmail from ChangePassword:
|
|
|
|
|
– Continue to EmailConfirm.
|
|
|
|
|
+ Continue to Manage if Email is confirmed already.
|
|
|
|
|
– Warn and Skip to Manage.
|
|
|
|
|
– Back to ChangeHint.
|
|
|
|
|
|
|
|
|
|
ChangeEmail from Manage:
|
|
|
|
|
– Continue to EmailConfirm.
|
|
|
|
|
+ Continue to Manage if Email is confirmed already.
|
|
|
|
|
– Back to Manage.
|
|
|
|
|
*/
|
|
|
|
|
|
2022-05-06 03:22:48 +00:00
|
|
|
|
namespace Settings {
|
|
|
|
|
namespace CloudPassword {
|
|
|
|
|
|
|
|
|
|
class Email : public TypedAbstractStep<Email> {
|
|
|
|
|
public:
|
|
|
|
|
using TypedAbstractStep::TypedAbstractStep;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] rpl::producer<QString> title() override;
|
|
|
|
|
void setupContent();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
rpl::lifetime _requestLifetime;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
rpl::producer<QString> Email::title() {
|
|
|
|
|
return tr::lng_settings_cloud_password_email_title();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Email::setupContent() {
|
|
|
|
|
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
|
|
|
|
auto currentStepData = stepData();
|
|
|
|
|
const auto currentStepDataEmail = base::take(currentStepData.email);
|
2022-05-08 20:04:46 +00:00
|
|
|
|
const auto setOnly = base::take(currentStepData.setOnlyRecoveryEmail);
|
2022-05-06 03:22:48 +00:00
|
|
|
|
setStepData(currentStepData);
|
|
|
|
|
|
2022-05-08 20:04:46 +00:00
|
|
|
|
const auto state = cloudPassword().stateCurrent();
|
|
|
|
|
const auto hasRecovery = state && state->hasRecovery;
|
|
|
|
|
|
2022-05-06 03:22:48 +00:00
|
|
|
|
SetupHeader(
|
|
|
|
|
content,
|
|
|
|
|
u"cloud_password/email"_q,
|
|
|
|
|
showFinishes(),
|
2022-05-08 20:04:46 +00:00
|
|
|
|
hasRecovery
|
|
|
|
|
? tr::lng_settings_cloud_password_manage_email_change()
|
|
|
|
|
: tr::lng_settings_cloud_password_email_subtitle(),
|
2022-05-06 03:22:48 +00:00
|
|
|
|
tr::lng_settings_cloud_password_email_about());
|
|
|
|
|
|
|
|
|
|
AddSkip(content, st::settingLocalPasscodeDescriptionBottomSkip);
|
|
|
|
|
|
|
|
|
|
const auto wrap = AddWrappedField(
|
|
|
|
|
content,
|
|
|
|
|
tr::lng_cloud_password_email(),
|
|
|
|
|
currentStepDataEmail);
|
|
|
|
|
const auto newInput = wrap->entity();
|
2022-05-09 16:36:22 +00:00
|
|
|
|
const auto error = AddError(content, nullptr);
|
2023-08-31 11:21:24 +00:00
|
|
|
|
newInput->changes(
|
|
|
|
|
) | rpl::start_with_next([=] {
|
2022-05-09 16:36:22 +00:00
|
|
|
|
error->hide();
|
2023-08-31 11:21:24 +00:00
|
|
|
|
}, newInput->lifetime());
|
2022-05-06 03:22:48 +00:00
|
|
|
|
AddSkipInsteadOfField(content);
|
|
|
|
|
|
|
|
|
|
const auto send = [=](Fn<void()> close) {
|
|
|
|
|
Expects(!_requestLifetime);
|
|
|
|
|
|
|
|
|
|
const auto data = stepData();
|
|
|
|
|
|
2022-05-08 20:04:46 +00:00
|
|
|
|
_requestLifetime = (setOnly
|
|
|
|
|
? cloudPassword().setEmail(data.currentPassword, data.email)
|
|
|
|
|
: cloudPassword().set(
|
|
|
|
|
data.currentPassword,
|
|
|
|
|
data.password,
|
|
|
|
|
data.hint,
|
|
|
|
|
!data.email.isEmpty(),
|
|
|
|
|
data.email)
|
2022-05-06 03:22:48 +00:00
|
|
|
|
) | rpl::start_with_next_error_done([=](Api::CloudPassword::SetOk d) {
|
|
|
|
|
_requestLifetime.destroy();
|
|
|
|
|
|
|
|
|
|
auto data = stepData();
|
|
|
|
|
data.unconfirmedEmailLengthCode = d.unconfirmedEmailLengthCode;
|
|
|
|
|
setStepData(std::move(data));
|
2022-05-07 02:45:52 +00:00
|
|
|
|
showOther(CloudPasswordEmailConfirmId());
|
2022-05-09 16:36:22 +00:00
|
|
|
|
}, [=](const QString &type) {
|
2022-05-06 03:22:48 +00:00
|
|
|
|
_requestLifetime.destroy();
|
|
|
|
|
|
2022-05-09 16:36:22 +00:00
|
|
|
|
if (MTP::IsFloodError(type)) {
|
|
|
|
|
error->show();
|
|
|
|
|
error->setText(tr::lng_flood_error(tr::now));
|
2022-05-09 23:47:16 +00:00
|
|
|
|
} else if (AbstractStep::isPasswordInvalidError(type)) {
|
2022-05-09 16:36:22 +00:00
|
|
|
|
} else if (type == u"EMAIL_INVALID"_q) {
|
|
|
|
|
error->show();
|
|
|
|
|
error->setText(tr::lng_cloud_password_bad_email(tr::now));
|
|
|
|
|
newInput->setFocus();
|
|
|
|
|
newInput->showError();
|
|
|
|
|
newInput->selectAll();
|
|
|
|
|
}
|
2022-05-06 03:22:48 +00:00
|
|
|
|
}, [=] {
|
|
|
|
|
_requestLifetime.destroy();
|
|
|
|
|
|
|
|
|
|
auto empty = StepData();
|
2022-05-06 23:47:57 +00:00
|
|
|
|
empty.currentPassword = stepData().password.isEmpty()
|
|
|
|
|
? stepData().currentPassword
|
|
|
|
|
: stepData().password;
|
2022-05-06 03:22:48 +00:00
|
|
|
|
setStepData(std::move(empty));
|
2022-05-06 23:47:57 +00:00
|
|
|
|
showOther(CloudPasswordManageId());
|
2022-05-06 03:22:48 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (close) {
|
|
|
|
|
_requestLifetime.add(close);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto confirm = [=](const QString &email) {
|
|
|
|
|
if (_requestLifetime) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto data = stepData();
|
|
|
|
|
data.email = email;
|
|
|
|
|
setStepData(std::move(data));
|
|
|
|
|
|
|
|
|
|
if (!email.isEmpty()) {
|
|
|
|
|
send(nullptr);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
controller()->show(Ui::MakeConfirmBox({
|
|
|
|
|
.text = { tr::lng_cloud_password_about_recover() },
|
|
|
|
|
.confirmed = crl::guard(this, send),
|
|
|
|
|
.confirmText = tr::lng_cloud_password_skip_email(),
|
|
|
|
|
.confirmStyle = &st::attentionBoxButton,
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2022-05-08 21:49:54 +00:00
|
|
|
|
const auto skip = AddLinkButton(
|
|
|
|
|
wrap,
|
|
|
|
|
tr::lng_cloud_password_skip_email());
|
2022-05-06 03:22:48 +00:00
|
|
|
|
skip->setClickedCallback([=] {
|
|
|
|
|
confirm(QString());
|
|
|
|
|
});
|
2022-05-08 20:04:46 +00:00
|
|
|
|
skip->setVisible(!setOnly);
|
2022-05-06 03:22:48 +00:00
|
|
|
|
|
|
|
|
|
const auto button = AddDoneButton(
|
|
|
|
|
content,
|
|
|
|
|
tr::lng_settings_cloud_password_save());
|
|
|
|
|
button->setClickedCallback([=] {
|
|
|
|
|
const auto newText = newInput->getLastText();
|
|
|
|
|
if (newText.isEmpty()) {
|
|
|
|
|
newInput->setFocus();
|
|
|
|
|
newInput->showError();
|
|
|
|
|
} else {
|
|
|
|
|
confirm(newText);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const auto submit = [=] { button->clicked({}, Qt::LeftButton); };
|
2023-08-31 11:21:24 +00:00
|
|
|
|
newInput->submits() | rpl::start_with_next(submit, newInput->lifetime());
|
2022-05-06 03:22:48 +00:00
|
|
|
|
|
|
|
|
|
setFocusCallback([=] { newInput->setFocus(); });
|
|
|
|
|
|
|
|
|
|
Ui::ResizeFitChild(this, content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace CloudPassword
|
|
|
|
|
|
|
|
|
|
Type CloudPasswordEmailId() {
|
|
|
|
|
return CloudPassword::Email::Id();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Settings
|