mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 15:17:07 +02:00
Added step section of password input to cloud password settings.
This commit is contained in:
parent
5a4d1a1e85
commit
5e2acdeaa3
9 changed files with 234 additions and 6 deletions
Telegram
|
@ -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
|
||||
|
|
BIN
Telegram/Resources/animations/cloud_password/password_input.tgs
Normal file
BIN
Telegram/Resources/animations/cloud_password/password_input.tgs
Normal file
Binary file not shown.
|
@ -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.";
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue