Added ability to reset cloud password without recovery email.
This commit is contained in:
parent
fedd8bece3
commit
bcbf009a62
|
@ -564,6 +564,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_cloud_password_skip_hint" = "Skip hint";
|
"lng_settings_cloud_password_skip_hint" = "Skip hint";
|
||||||
"lng_settings_cloud_password_save" = "Save and Finish";
|
"lng_settings_cloud_password_save" = "Save and Finish";
|
||||||
"lng_settings_cloud_password_email_confirm" = "Confirm and Finish";
|
"lng_settings_cloud_password_email_confirm" = "Confirm and Finish";
|
||||||
|
"lng_settings_cloud_password_reset_in" = "You can reset your password in {duration}.";
|
||||||
|
|
||||||
"lng_clear_payment_info_title" = "Clear payment info";
|
"lng_clear_payment_info_title" = "Clear payment info";
|
||||||
"lng_clear_payment_info_sure" = "Are you sure you want to clear your payment and shipping info?";
|
"lng_clear_payment_info_sure" = "Are you sure you want to clear your payment and shipping info?";
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "settings/cloud_password/settings_cloud_password_email_confirm.h"
|
#include "settings/cloud_password/settings_cloud_password_email_confirm.h"
|
||||||
|
|
||||||
#include "api/api_cloud_password.h"
|
#include "api/api_cloud_password.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
#include "core/core_cloud_password.h"
|
#include "core/core_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"
|
||||||
|
@ -17,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
||||||
#include "settings/cloud_password/settings_cloud_password_start.h"
|
#include "settings/cloud_password/settings_cloud_password_start.h"
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/sent_code_field.h"
|
#include "ui/widgets/sent_code_field.h"
|
||||||
#include "ui/wrap/padding_wrap.h"
|
#include "ui/wrap/padding_wrap.h"
|
||||||
|
@ -155,7 +157,65 @@ void EmailConfirm::setupContent() {
|
||||||
newInput->hideError();
|
newInput->hideError();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
resend->setVisible(recoverEmailPattern.isEmpty());
|
|
||||||
|
if (!recoverEmailPattern.isEmpty()) {
|
||||||
|
resend->setText(tr::lng_signin_try_password(tr::now));
|
||||||
|
|
||||||
|
resend->setClickedCallback([=] {
|
||||||
|
const auto reset = [=](Fn<void()> close) {
|
||||||
|
if (_requestLifetime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_requestLifetime = cloudPassword().resetPassword(
|
||||||
|
) | rpl::start_with_next_error_done([=](
|
||||||
|
Api::CloudPassword::ResetRetryDate retryDate) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
const auto left = std::max(
|
||||||
|
retryDate - base::unixtime::now(),
|
||||||
|
60);
|
||||||
|
controller()->show(Ui::MakeInformBox(
|
||||||
|
tr::lng_cloud_password_reset_later(
|
||||||
|
tr::now,
|
||||||
|
lt_duration,
|
||||||
|
Ui::FormatResetCloudPasswordIn(left))));
|
||||||
|
}, [=](const QString &type) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
}, [=] {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
|
||||||
|
cloudPassword().reload();
|
||||||
|
using PasswordState = Core::CloudPasswordState;
|
||||||
|
_requestLifetime = cloudPassword().state(
|
||||||
|
) | rpl::filter([=](const PasswordState &s) {
|
||||||
|
return s.pendingResetDate != 0;
|
||||||
|
}) | rpl::take(
|
||||||
|
1
|
||||||
|
) | rpl::start_with_next([=](const PasswordState &s) {
|
||||||
|
const auto left = (s.pendingResetDate
|
||||||
|
- base::unixtime::now());
|
||||||
|
if (left > 0) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
controller()->show(Ui::MakeInformBox(
|
||||||
|
tr::lng_settings_cloud_password_reset_in(
|
||||||
|
tr::now,
|
||||||
|
lt_duration,
|
||||||
|
Ui::FormatResetCloudPasswordIn(left))));
|
||||||
|
setStepData(StepData());
|
||||||
|
showBack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_requestLifetime.add(close);
|
||||||
|
};
|
||||||
|
|
||||||
|
controller()->show(Ui::MakeConfirmBox({
|
||||||
|
.text = tr::lng_cloud_password_reset_with_email(),
|
||||||
|
.confirmed = reset,
|
||||||
|
.confirmText = tr::lng_cloud_password_reset_ok(),
|
||||||
|
.confirmStyle = &st::attentionBoxButton,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const auto button = AddDoneButton(
|
const auto button = AddDoneButton(
|
||||||
content,
|
content,
|
||||||
|
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "api/api_cloud_password.h"
|
#include "api/api_cloud_password.h"
|
||||||
#include "base/qt_signal_producer.h"
|
#include "base/qt_signal_producer.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
#include "core/core_cloud_password.h"
|
#include "core/core_cloud_password.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "lottie/lottie_icon.h"
|
#include "lottie/lottie_icon.h"
|
||||||
|
@ -17,12 +19,14 @@ 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 "settings/cloud_password/settings_cloud_password_manage.h"
|
#include "settings/cloud_password/settings_cloud_password_manage.h"
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/text/format_values.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"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_settings.h"
|
#include "styles/style_settings.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
@ -93,6 +97,12 @@ public:
|
||||||
[[nodiscard]] rpl::producer<std::vector<Type>> removeFromStack() override;
|
[[nodiscard]] rpl::producer<std::vector<Type>> removeFromStack() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setupRecoverButton(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<Ui::LinkButton*> button,
|
||||||
|
not_null<Ui::FlatLabel*> info,
|
||||||
|
Fn<void()> recoverCallback);
|
||||||
|
|
||||||
rpl::variable<std::vector<Type>> _removesFromStack;
|
rpl::variable<std::vector<Type>> _removesFromStack;
|
||||||
rpl::lifetime _requestLifetime;
|
rpl::lifetime _requestLifetime;
|
||||||
|
|
||||||
|
@ -192,12 +202,15 @@ void Input::setupContent() {
|
||||||
}
|
}
|
||||||
}, hintInfo->lifetime());
|
}, hintInfo->lifetime());
|
||||||
|
|
||||||
const auto recover = AddLinkButton(content, newInput);
|
auto recoverCallback = [=] {
|
||||||
recover->setText(tr::lng_signin_recover(tr::now));
|
|
||||||
recover->setClickedCallback([=] {
|
|
||||||
if (_requestLifetime) {
|
if (_requestLifetime) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto state = cloudPassword().stateCurrent();
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state->hasRecovery) {
|
||||||
_requestLifetime = cloudPassword().requestPasswordRecovery(
|
_requestLifetime = cloudPassword().requestPasswordRecovery(
|
||||||
) | rpl::start_with_next_error([=](const QString &pattern) {
|
) | rpl::start_with_next_error([=](const QString &pattern) {
|
||||||
_requestLifetime.destroy();
|
_requestLifetime.destroy();
|
||||||
|
@ -217,7 +230,44 @@ void Input::setupContent() {
|
||||||
error->setText(Lang::Hard::ServerError());
|
error->setText(Lang::Hard::ServerError());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const auto callback = [=](Fn<void()> close) {
|
||||||
|
if (_requestLifetime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
_requestLifetime = cloudPassword().resetPassword(
|
||||||
|
) | rpl::start_with_error_done([=](const QString &type) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
}, [=] {
|
||||||
|
_requestLifetime.destroy();
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
controller()->show(Ui::MakeConfirmBox({
|
||||||
|
.text = tr::lng_cloud_password_reset_no_email(),
|
||||||
|
.confirmed = callback,
|
||||||
|
.confirmText = tr::lng_cloud_password_reset_ok(),
|
||||||
|
.cancelText = tr::lng_cancel(),
|
||||||
|
.confirmStyle = &st::attentionBoxButton,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto recover = AddLinkButton(content, newInput);
|
||||||
|
const auto resetInfo = Ui::CreateChild<Ui::FlatLabel>(
|
||||||
|
content,
|
||||||
|
QString(),
|
||||||
|
st::boxDividerLabel);
|
||||||
|
recover->geometryValue(
|
||||||
|
) | rpl::start_with_next([=](const QRect &r) {
|
||||||
|
resetInfo->moveToLeft(r.x(), r.y() + st::passcodeTextLine);
|
||||||
|
}, resetInfo->lifetime());
|
||||||
|
|
||||||
|
setupRecoverButton(
|
||||||
|
content,
|
||||||
|
recover,
|
||||||
|
resetInfo,
|
||||||
|
std::move(recoverCallback));
|
||||||
} else if (currentStepProcessRecover.setNewPassword && reenterInput) {
|
} else if (currentStepProcessRecover.setNewPassword && reenterInput) {
|
||||||
const auto skip = AddLinkButton(content, reenterInput);
|
const auto skip = AddLinkButton(content, reenterInput);
|
||||||
skip->setText(tr::lng_settings_auto_night_disable(tr::now));
|
skip->setText(tr::lng_settings_auto_night_disable(tr::now));
|
||||||
|
@ -278,6 +328,14 @@ void Input::setupContent() {
|
||||||
}, [=] {
|
}, [=] {
|
||||||
_requestLifetime.destroy();
|
_requestLifetime.destroy();
|
||||||
|
|
||||||
|
if (const auto state = cloudPassword().stateCurrent()) {
|
||||||
|
if (state->pendingResetDate > 0) {
|
||||||
|
auto lifetime = rpl::lifetime();
|
||||||
|
lifetime = cloudPassword().cancelResetPassword(
|
||||||
|
) | rpl::start_with_next([] {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto data = stepData();
|
auto data = stepData();
|
||||||
data.currentPassword = pass;
|
data.currentPassword = pass;
|
||||||
setStepData(std::move(data));
|
setStepData(std::move(data));
|
||||||
|
@ -352,6 +410,142 @@ void Input::setupContent() {
|
||||||
Ui::ResizeFitChild(this, content);
|
Ui::ResizeFitChild(this, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Input::setupRecoverButton(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<Ui::LinkButton*> button,
|
||||||
|
not_null<Ui::FlatLabel*> info,
|
||||||
|
Fn<void()> recoverCallback) {
|
||||||
|
|
||||||
|
struct Status {
|
||||||
|
enum class SuggestAction {
|
||||||
|
Recover,
|
||||||
|
Reset,
|
||||||
|
CancelReset,
|
||||||
|
};
|
||||||
|
SuggestAction suggest = SuggestAction::Recover;
|
||||||
|
TimeId left = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
base::Timer timer;
|
||||||
|
rpl::variable<Status> status;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto state = container->lifetime().make_state<State>();
|
||||||
|
|
||||||
|
const auto updateStatus = [=] {
|
||||||
|
const auto passwordState = cloudPassword().stateCurrent();
|
||||||
|
const auto date = passwordState ? passwordState->pendingResetDate : 0;
|
||||||
|
const auto left = (date - base::unixtime::now());
|
||||||
|
state->status = Status{
|
||||||
|
.suggest = ((left > 0)
|
||||||
|
? Status::SuggestAction::CancelReset
|
||||||
|
: date
|
||||||
|
? Status::SuggestAction::Reset
|
||||||
|
: Status::SuggestAction::Recover),
|
||||||
|
.left = left,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
state->timer.setCallback(updateStatus);
|
||||||
|
updateStatus();
|
||||||
|
|
||||||
|
state->status.value(
|
||||||
|
) | rpl::start_with_next([=](const Status &status) {
|
||||||
|
switch (status.suggest) {
|
||||||
|
case Status::SuggestAction::Recover: {
|
||||||
|
info->setText(QString());
|
||||||
|
button->setText(tr::lng_signin_recover(tr::now));
|
||||||
|
} break;
|
||||||
|
case Status::SuggestAction::Reset: {
|
||||||
|
info->setText(QString());
|
||||||
|
button->setText(tr::lng_cloud_password_reset_ready(tr::now));
|
||||||
|
} break;
|
||||||
|
case Status::SuggestAction::CancelReset: {
|
||||||
|
info->setText(
|
||||||
|
tr::lng_settings_cloud_password_reset_in(
|
||||||
|
tr::now,
|
||||||
|
lt_duration,
|
||||||
|
Ui::FormatResetCloudPasswordIn(status.left)));
|
||||||
|
button->setText(
|
||||||
|
tr::lng_cloud_password_reset_cancel_title(tr::now));
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}, container->lifetime());
|
||||||
|
|
||||||
|
cloudPassword().state(
|
||||||
|
) | rpl::start_with_next([=](const Core::CloudPasswordState &passState) {
|
||||||
|
updateStatus();
|
||||||
|
state->timer.cancel();
|
||||||
|
if (passState.pendingResetDate) {
|
||||||
|
state->timer.callEach(999);
|
||||||
|
}
|
||||||
|
}, container->lifetime());
|
||||||
|
|
||||||
|
button->setClickedCallback([=] {
|
||||||
|
const auto passState = cloudPassword().stateCurrent();
|
||||||
|
if (_requestLifetime || !passState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateStatus();
|
||||||
|
const auto suggest = state->status.current().suggest;
|
||||||
|
if (suggest == Status::SuggestAction::Recover) {
|
||||||
|
recoverCallback();
|
||||||
|
} else if (suggest == Status::SuggestAction::CancelReset) {
|
||||||
|
const auto cancel = [=](Fn<void()> close) {
|
||||||
|
if (_requestLifetime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
_requestLifetime = cloudPassword().cancelResetPassword(
|
||||||
|
) | rpl::start_with_error_done([=](const QString &error) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
}, [=] {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
controller()->show(Ui::MakeConfirmBox({
|
||||||
|
.text = tr::lng_cloud_password_reset_cancel_sure(),
|
||||||
|
.confirmed = cancel,
|
||||||
|
.confirmText = tr::lng_box_yes(),
|
||||||
|
.cancelText = tr::lng_box_no(),
|
||||||
|
}));
|
||||||
|
} else if (suggest == Status::SuggestAction::Reset) {
|
||||||
|
_requestLifetime = cloudPassword().resetPassword(
|
||||||
|
) | rpl::start_with_next_error_done([=](
|
||||||
|
Api::CloudPassword::ResetRetryDate retryDate) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
const auto left = std::max(
|
||||||
|
retryDate - base::unixtime::now(),
|
||||||
|
60);
|
||||||
|
controller()->show(Ui::MakeInformBox(
|
||||||
|
tr::lng_cloud_password_reset_later(
|
||||||
|
tr::now,
|
||||||
|
lt_duration,
|
||||||
|
Ui::FormatResetCloudPasswordIn(left))));
|
||||||
|
}, [=](const QString &type) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
}, [=] {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
|
||||||
|
cloudPassword().reload();
|
||||||
|
using PasswordState = Core::CloudPasswordState;
|
||||||
|
_requestLifetime = cloudPassword().state(
|
||||||
|
) | rpl::filter([=](const PasswordState &s) {
|
||||||
|
return !s.hasPassword;
|
||||||
|
}) | rpl::take(
|
||||||
|
1
|
||||||
|
) | rpl::start_with_next([=](const PasswordState &s) {
|
||||||
|
_requestLifetime.destroy();
|
||||||
|
controller()->show(Ui::MakeInformBox(
|
||||||
|
tr::lng_cloud_password_removed()));
|
||||||
|
setStepData(StepData());
|
||||||
|
showBack();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace CloudPassword
|
} // namespace CloudPassword
|
||||||
|
|
||||||
Type CloudPasswordInputId() {
|
Type CloudPasswordInputId() {
|
||||||
|
|
|
@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "settings/settings_local_passcode.h"
|
#include "settings/settings_local_passcode.h"
|
||||||
#include "settings/settings_privacy_controllers.h"
|
#include "settings/settings_privacy_controllers.h"
|
||||||
#include "base/timer_rpl.h"
|
#include "base/timer_rpl.h"
|
||||||
#include "base/unixtime.h"
|
|
||||||
#include "boxes/edit_privacy_box.h"
|
#include "boxes/edit_privacy_box.h"
|
||||||
#include "boxes/passcode_box.h"
|
#include "boxes/passcode_box.h"
|
||||||
#include "boxes/auto_lock_box.h"
|
#include "boxes/auto_lock_box.h"
|
||||||
|
@ -457,7 +456,6 @@ void SetupCloudPassword(
|
||||||
rpl::duplicate(noconfirmed),
|
rpl::duplicate(noconfirmed),
|
||||||
_1 && !_2));
|
_1 && !_2));
|
||||||
disable->entity()->addClickHandler(remove);
|
disable->entity()->addClickHandler(remove);
|
||||||
#endif
|
|
||||||
|
|
||||||
auto resetAt = session->api().cloudPassword().state(
|
auto resetAt = session->api().cloudPassword().state(
|
||||||
) | rpl::map([](const State &state) {
|
) | rpl::map([](const State &state) {
|
||||||
|
@ -574,7 +572,6 @@ void SetupCloudPassword(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#if 0
|
|
||||||
const auto abort = container->add(
|
const auto abort = container->add(
|
||||||
object_ptr<Ui::SlideWrap<Button>>(
|
object_ptr<Ui::SlideWrap<Button>>(
|
||||||
container,
|
container,
|
||||||
|
|
|
@ -436,4 +436,8 @@ QString FormatMuteForTiny(float64 sec) {
|
||||||
: QString();
|
: QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FormatResetCloudPasswordIn(float64 sec) {
|
||||||
|
return (sec >= 3600) ? FormatTTL(sec) : FormatDurationText(sec);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -31,6 +31,7 @@ inline constexpr auto FileStatusSizeFailed = 0x7FFFFFF2;
|
||||||
[[nodiscard]] QString FormatTTLTiny(float64 ttl);
|
[[nodiscard]] QString FormatTTLTiny(float64 ttl);
|
||||||
[[nodiscard]] QString FormatMuteFor(float64 sec);
|
[[nodiscard]] QString FormatMuteFor(float64 sec);
|
||||||
[[nodiscard]] QString FormatMuteForTiny(float64 sec);
|
[[nodiscard]] QString FormatMuteForTiny(float64 sec);
|
||||||
|
[[nodiscard]] QString FormatResetCloudPasswordIn(float64 sec);
|
||||||
|
|
||||||
struct CurrencyRule {
|
struct CurrencyRule {
|
||||||
const char *international = "";
|
const char *international = "";
|
||||||
|
|
Loading…
Reference in New Issue