Added step section of password input to cloud password settings.

This commit is contained in:
23rd 2022-05-06 03:32:21 +03:00
parent 5a4d1a1e85
commit 5e2acdeaa3
9 changed files with 234 additions and 6 deletions

View File

@ -1074,6 +1074,8 @@ PRIVATE
profile/profile_cover_drop_area.h
settings/cloud_password/settings_cloud_password_common.cpp
settings/cloud_password/settings_cloud_password_common.h
settings/cloud_password/settings_cloud_password_input.cpp
settings/cloud_password/settings_cloud_password_input.h
settings/cloud_password/settings_cloud_password_start.cpp
settings/cloud_password/settings_cloud_password_start.h
settings/settings_advanced.cpp

View File

@ -699,8 +699,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_cloud_password_reset_cancel" = "Cancel password reset";
"lng_cloud_password_enter_old" = "Enter current password";
"lng_cloud_password_enter_first" = "Enter a password";
"lng_cloud_password_enter_new" = "Enter new password";
"lng_cloud_password_confirm_new" = "Re-enter new password";
"lng_cloud_password_enter_new" = "Enter password";
"lng_cloud_password_confirm_new" = "Re-enter password";
"lng_cloud_password_hint" = "Enter password hint";
"lng_cloud_password_change_hint" = "Enter new password hint";
"lng_cloud_password_bad" = "Password and hint cannot be the same.";

View File

@ -5,5 +5,6 @@
<file alias="filters.tgs">../../animations/filters.tgs</file>
<file alias="local_passcode_enter.tgs">../../animations/local_passcode_enter.tgs</file>
<file alias="cloud_password/intro.tgs">../../animations/cloud_password/intro.tgs</file>
<file alias="cloud_password/password_input.tgs">../../animations/cloud_password/password_input.tgs</file>
</qresource>
</RCC>

View File

@ -244,6 +244,24 @@ rpl::producer<> AbstractStep::sectionShowBack() {
return _showBack.events();
}
void AbstractStep::setStepDataReference(std::any &data) {
_stepData = &data;
}
StepData AbstractStep::stepData() const {
if (!_stepData || !_stepData->has_value()) {
StepData();
}
const auto my = std::any_cast<StepData>(_stepData);
return my ? (*my) : StepData();
}
void AbstractStep::setStepData(StepData data) {
if (_stepData) {
*_stepData = data;
}
}
AbstractStep::~AbstractStep() = default;
} // namespace Settings::CloudPassword

View File

@ -19,6 +19,10 @@ class VerticalLayout;
namespace Settings::CloudPassword {
struct StepData {
QString password;
};
void SetupHeader(
not_null<Ui::VerticalLayout*> content,
const QString &lottie,
@ -79,6 +83,8 @@ public:
[[nodiscard]] rpl::producer<Type> sectionShowOther() override;
[[nodiscard]] rpl::producer<> sectionShowBack() override;
void setStepDataReference(std::any &data) override;
protected:
[[nodiscard]] not_null<Window::SessionController*> controller() const;
@ -89,6 +95,9 @@ protected:
[[nodiscard]] rpl::producer<> showFinishes() const;
StepData stepData() const;
void setStepData(StepData data);
private:
const not_null<Window::SessionController*> _controller;
@ -98,15 +107,17 @@ private:
rpl::event_stream<Type> _showOther;
rpl::event_stream<> _showBack;
std::any *_stepData;
};
template <typename SectionType>
class TypedAbstractStep : public AbstractStep {
public:
TypedAbstractStep(
QWidget *parent,
not_null<Window::SessionController*> controller)
: AbstractStep(parent, controller) {
using AbstractStep::AbstractStep;
void setStepDataReference(std::any &data) override final {
AbstractStep::setStepDataReference(data);
static_cast<SectionType*>(this)->setupContent();
}

View File

@ -0,0 +1,177 @@
/*
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_input.h"
#include "base/qt_signal_producer.h"
#include "lang/lang_keys.h"
#include "lottie/lottie_icon.h"
#include "settings/cloud_password/settings_cloud_password_common.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/labels.h"
#include "ui/wrap/vertical_layout.h"
#include "styles/style_boxes.h"
#include "styles/style_settings.h"
namespace Settings {
namespace CloudPassword {
namespace {
struct Icon {
not_null<Lottie::Icon*> icon;
Fn<void()> update;
};
Icon CreateInteractiveLottieIcon(
not_null<Ui::VerticalLayout*> container,
Lottie::IconDescriptor &&descriptor,
style::margins padding) {
auto object = object_ptr<Ui::RpWidget>(container);
const auto raw = object.data();
const auto width = descriptor.sizeOverride.width();
raw->resize(QRect(
QPoint(),
descriptor.sizeOverride).marginsAdded(padding).size());
auto owned = Lottie::MakeIcon(std::move(descriptor));
const auto icon = owned.get();
raw->lifetime().add([kept = std::move(owned)]{});
raw->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(raw);
const auto left = (raw->width() - width) / 2;
icon->paint(p, left, padding.top());
}, raw->lifetime());
container->add(std::move(object));
return { .icon = icon, .update = [=] { raw->update(); } };
}
} // namespace
class Input : public TypedAbstractStep<Input> {
public:
using TypedAbstractStep::TypedAbstractStep;
[[nodiscard]] rpl::producer<QString> title() override;
void setupContent();
};
rpl::producer<QString> Input::title() {
return tr::lng_settings_cloud_password_password_title();
}
void Input::setupContent() {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
auto currentStepData = stepData();
const auto currentStepDataPassword = base::take(currentStepData.password);
setStepData(currentStepData);
const auto icon = CreateInteractiveLottieIcon(
content,
{
.name = u"cloud_password/password_input"_q,
.sizeOverride = {
st::changePhoneIconSize,
st::changePhoneIconSize
},
},
st::settingLocalPasscodeIconPadding);
SetupHeader(
content,
QString(),
rpl::never<>(),
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);
if (!newInput->text().isEmpty()) {
icon.icon->jumpTo(icon.icon->framesCount() / 2, icon.update);
}
const auto button = AddDoneButton(content, tr::lng_continue());
button->setClickedCallback([=] {
const auto newText = newInput->text();
const auto reenterText = reenterInput->text();
if (newText.isEmpty()) {
newInput->setFocus();
newInput->showError();
} else if (reenterText.isEmpty()) {
reenterInput->setFocus();
reenterInput->showError();
} else if (newText != reenterText) {
reenterInput->setFocus();
reenterInput->showError();
reenterInput->selectAll();
error->show();
error->setText(tr::lng_cloud_password_differ(tr::now));
} else {
auto data = stepData();
data.password = newText;
setStepData(std::move(data));
}
});
base::qt_signal_producer(
newInput.get(),
&QLineEdit::textChanged // Covers Undo.
) | rpl::map([=] {
return newInput->text().isEmpty();
}) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool empty) {
const auto from = icon.icon->frameIndex();
const auto to = empty ? 0 : (icon.icon->framesCount() / 2 - 1);
icon.icon->animate(icon.update, from, to);
}, content->lifetime());
const auto submit = [=] {
if (reenterInput->hasFocus()) {
button->clicked({}, Qt::LeftButton);
} else {
reenterInput->setFocus();
}
};
QObject::connect(newInput, &Ui::MaskedInputField::submitted, submit);
QObject::connect(reenterInput, &Ui::MaskedInputField::submitted, submit);
setFocusCallback([=] {
if (newInput->text().isEmpty()) {
newInput->setFocus();
} else if (reenterInput->text().isEmpty()) {
reenterInput->setFocus();
} else {
newInput->setFocus();
}
});
Ui::ResizeFitChild(this, content);
}
} // namespace CloudPassword
Type CloudPasswordInputId() {
return CloudPassword::Input::Id();
}
} // namespace Settings

View File

@ -0,0 +1,17 @@
/*
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
*/
#pragma once
#include "settings/settings_type.h"
namespace Settings {
Type CloudPasswordInputId();
} // namespace Settings

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "settings/cloud_password/settings_cloud_password_common.h"
#include "settings/cloud_password/settings_cloud_password_input.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
#include "styles/style_settings.h"
@ -49,6 +50,7 @@ void Start::setupContent() {
content,
tr::lng_settings_cloud_password_password_subtitle()
)->setClickedCallback([=] {
showOther(CloudPasswordInputId());
});
Ui::ResizeFitChild(this, content);