Change phone number section instead of a box.

This commit is contained in:
John Preston 2022-04-13 12:05:10 +04:00
parent 2253cd86e5
commit 488f6412f2
29 changed files with 189 additions and 136 deletions

View file

@ -576,13 +576,24 @@ colorValueInput: InputField(defaultInputField) {
colorResultInput: InputField(colorValueInput) {
}
changePhoneDescription: FlatLabel(boxLabel) {
changePhoneButton: RoundButton(defaultActiveButton) {
width: 256px;
height: 42px;
textTop: 11px;
font: boxButtonFont;
}
changePhoneButtonPadding: margins(0px, 32px, 0px, 44px);
changePhoneTitle: FlatLabel(boxTitle) {
}
changePhoneTitlePadding: margins(0px, 8px, 0px, 8px);
changePhoneDescription: FlatLabel(defaultFlatLabel) {
minWidth: 332px;
align: align(top);
textFg: windowSubTextFg;
}
changePhoneIconTop: 16px;
changePhoneIconSize: 96px;
changePhoneDescriptionTop: 128px;
changePhoneDescriptionPadding: margins(0px, 1px, 0px, 8px);
changePhoneIconPadding: margins(0px, 39px, 0px, 5px);
changePhoneIconSize: 120px;
changePhoneLabel: FlatLabel(defaultFlatLabel) {
minWidth: 275px;
textFg: windowSubTextFg;

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/sent_code_field.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/toast/toast.h"
#include "ui/text/format_values.h" // Ui::FormatPhone
@ -21,8 +22,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "mtproto/sender.h"
#include "info/profile/info_profile_values.h"
#include "lottie/lottie_icon.h"
#include "mtproto/sender.h"
#include "apiwrap.h"
#include "window/window_session_controller.h"
#include "styles/style_layers.h"
@ -69,25 +71,7 @@ void CreateErrorLabel(
namespace Settings {
ChangePhone::ChangePhone(
QWidget *parent,
not_null<Window::SessionController*> controller)
: Section(parent) {
setupContent(controller);
}
rpl::producer<QString> ChangePhone::Title() {
return tr::lng_change_phone_button();
}
void ChangePhone::setupContent(
not_null<Window::SessionController*> controller) {
}
} // namespace Settings
class ChangePhoneBox::EnterPhone : public Ui::BoxContent {
class ChangePhone::EnterPhone : public Ui::BoxContent {
public:
EnterPhone(QWidget*, not_null<Window::SessionController*> controller);
@ -118,7 +102,7 @@ private:
};
class ChangePhoneBox::EnterCode : public Ui::BoxContent {
class ChangePhone::EnterCode : public Ui::BoxContent {
public:
EnterCode(
QWidget*,
@ -161,14 +145,14 @@ private:
};
ChangePhoneBox::EnterPhone::EnterPhone(
ChangePhone::EnterPhone::EnterPhone(
QWidget*,
not_null<Window::SessionController*> controller)
: _controller(controller)
, _api(&controller->session().mtp()) {
}
void ChangePhoneBox::EnterPhone::prepare() {
void ChangePhone::EnterPhone::prepare() {
setTitle(tr::lng_change_phone_title());
const auto phoneValue = QString();
@ -204,7 +188,7 @@ void ChangePhoneBox::EnterPhone::prepare() {
addButton(tr::lng_cancel(), [this] { closeBox(); });
}
void ChangePhoneBox::EnterPhone::submit() {
void ChangePhone::EnterPhone::submit() {
if (_requestId) {
return;
}
@ -223,7 +207,7 @@ void ChangePhoneBox::EnterPhone::submit() {
}).handleFloodErrors().send();
}
void ChangePhoneBox::EnterPhone::sendPhoneDone(
void ChangePhone::EnterPhone::sendPhoneDone(
const MTPauth_SentCode &result,
const QString &phoneNumber) {
using CodeData = const MTPDauth_sentCode&;
@ -276,7 +260,7 @@ void ChangePhoneBox::EnterPhone::sendPhoneDone(
Ui::LayerOption::KeepOther);
}
void ChangePhoneBox::EnterPhone::sendPhoneFail(
void ChangePhone::EnterPhone::sendPhoneFail(
const MTP::Error &error,
const QString &phoneNumber) {
if (MTP::IsFloodError(error)) {
@ -298,7 +282,7 @@ void ChangePhoneBox::EnterPhone::sendPhoneFail(
}
}
void ChangePhoneBox::EnterPhone::showError(const QString &text) {
void ChangePhone::EnterPhone::showError(const QString &text) {
CreateErrorLabel(
this,
_error,
@ -310,7 +294,7 @@ void ChangePhoneBox::EnterPhone::showError(const QString &text) {
}
}
ChangePhoneBox::EnterCode::EnterCode(
ChangePhone::EnterCode::EnterCode(
QWidget*,
not_null<Window::SessionController*> controller,
const QString &phone,
@ -326,7 +310,7 @@ ChangePhoneBox::EnterCode::EnterCode(
, _call([this] { sendCall(); }, [this] { updateCall(); }) {
}
void ChangePhoneBox::EnterCode::prepare() {
void ChangePhone::EnterCode::prepare() {
setTitle(tr::lng_change_phone_title());
const auto descriptionText = tr::lng_change_phone_code_description(
@ -364,13 +348,13 @@ void ChangePhoneBox::EnterCode::prepare() {
addButton(tr::lng_cancel(), [=] { closeBox(); });
}
int ChangePhoneBox::EnterCode::countHeight() {
int ChangePhone::EnterCode::countHeight() {
const auto errorSkip = st::boxLittleSkip
+ st::changePhoneError.style.font->height;
return _code->bottomNoMargins() + errorSkip + 3 * st::boxLittleSkip;
}
void ChangePhoneBox::EnterCode::submit() {
void ChangePhone::EnterCode::submit() {
if (_requestId) {
return;
}
@ -400,7 +384,7 @@ void ChangePhoneBox::EnterCode::submit() {
})).handleFloodErrors().send();
}
void ChangePhoneBox::EnterCode::sendCall() {
void ChangePhone::EnterCode::sendCall() {
_api.request(MTPauth_ResendCode(
MTP_string(_phone),
MTP_string(_hash)
@ -409,7 +393,7 @@ void ChangePhoneBox::EnterCode::sendCall() {
}).send();
}
void ChangePhoneBox::EnterCode::updateCall() {
void ChangePhone::EnterCode::updateCall() {
const auto text = _call.getText();
if (text.isEmpty()) {
_callLabel.destroy();
@ -424,7 +408,7 @@ void ChangePhoneBox::EnterCode::updateCall() {
}
}
void ChangePhoneBox::EnterCode::showError(const QString &text) {
void ChangePhone::EnterCode::showError(const QString &text) {
CreateErrorLabel(
this,
_error,
@ -436,7 +420,7 @@ void ChangePhoneBox::EnterCode::showError(const QString &text) {
}
}
void ChangePhoneBox::EnterCode::sendCodeFail(const MTP::Error &error) {
void ChangePhone::EnterCode::sendCodeFail(const MTP::Error &error) {
if (MTP::IsFloodError(error)) {
showError(tr::lng_flood_error(tr::now));
} else if (error.type() == qstr("PHONE_CODE_EMPTY")
@ -452,66 +436,81 @@ void ChangePhoneBox::EnterCode::sendCodeFail(const MTP::Error &error) {
}
}
ChangePhoneBox::ChangePhoneBox(
QWidget*,
ChangePhone::ChangePhone(
QWidget *parent,
not_null<Window::SessionController*> controller)
: _controller(controller)
, _icon(Lottie::MakeIcon({
.name = u"change_number"_q,
.sizeOverride = {
st::changePhoneIconSize,
st::changePhoneIconSize,
},
})) {
: Section(parent)
, _controller(controller) {
setupContent();
}
void ChangePhoneBox::showFinished() {
animateIcon();
rpl::producer<QString> ChangePhone::title() {
return Info::Profile::PhoneValue(
_controller->session().user()
) | rpl::map([](const TextWithEntities &text) {
return text.text;
});
}
void ChangePhoneBox::animateIcon() {
_icon->animate([=] { update(); }, 0, _icon->framesCount());
}
void ChangePhone::setupContent() {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
void ChangePhoneBox::prepare() {
setTitle(tr::lng_change_phone_title());
addButton(tr::lng_change_phone_button(), [=, controller = _controller] {
auto icon = CreateLottieIcon(content, {
.name = u"change_number"_q,
.sizeOverride = {
st::changePhoneIconSize,
st::changePhoneIconSize,
},
}, st::changePhoneIconPadding);
content->add(std::move(icon.widget));
_animate = std::move(icon.animate);
content->add(
object_ptr<Ui::CenterWrap<>>(
content,
object_ptr<Ui::FlatLabel>(
content,
tr::lng_change_phone_button(),
st::changePhoneTitle)),
st::changePhoneTitlePadding);
content->add(
object_ptr<Ui::CenterWrap<>>(
content,
object_ptr<Ui::FlatLabel>(
content,
tr::lng_change_phone_about(Ui::Text::RichLangValue),
st::changePhoneDescription)),
st::changePhoneDescriptionPadding);
const auto button = content->add(
object_ptr<Ui::CenterWrap<Ui::RoundButton>>(
content,
object_ptr<Ui::RoundButton>(
content,
tr::lng_change_phone_button(),
st::changePhoneButton)),
st::changePhoneButtonPadding)->entity();
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setClickedCallback([=] {
auto callback = [=] {
controller->show(
Box<EnterPhone>(controller),
_controller->show(
Box<EnterPhone>(_controller),
Ui::LayerOption::CloseOther);
};
controller->show(
_controller->show(
Ui::MakeConfirmBox({
.text = tr::lng_change_phone_warning(),
.confirmed = std::move(callback),
}),
Ui::LayerOption::CloseOther);
});
addButton(tr::lng_cancel(), [this] {
closeBox();
});
const auto label = Ui::CreateChild<Ui::FlatLabel>(
this,
tr::lng_change_phone_about(Ui::Text::RichLangValue),
st::changePhoneDescription);
label->moveToLeft(
(st::boxWideWidth - label->width()) / 2,
st::changePhoneDescriptionTop);
setDimensions(
st::boxWideWidth,
label->bottomNoMargins() + st::boxLittleSkip);
Ui::ResizeFitChild(this, content);
}
void ChangePhoneBox::paintEvent(QPaintEvent *e) {
BoxContent::paintEvent(e);
Painter p(this);
const auto left = (width() - st::changePhoneIconSize) / 2;
_icon->paint(p, left, st::changePhoneIconTop);
if (!_icon->animating() && _icon->frameIndex() > 0) {
animateIcon();
}
void ChangePhone::showFinished() {
_animate();
}
} // namespace Settings

View file

@ -26,36 +26,18 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
void showFinished() override;
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);
class EnterPhone;
class EnterCode;
void setupContent();
const not_null<Window::SessionController*> _controller;
Fn<void()> _animate;
};
} // namespace Settings
class ChangePhoneBox : public Ui::BoxContent {
public:
ChangePhoneBox(
QWidget*,
not_null<Window::SessionController*> controller);
void showFinished() override;
protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
private:
void animateIcon();
class EnterPhone;
class EnterCode;
const not_null<Window::SessionController*> _controller;
const std::unique_ptr<Lottie::Icon> _icon;
};

View file

@ -1163,7 +1163,7 @@ Sessions::Sessions(
setupContent(controller);
}
rpl::producer<QString> Sessions::Title() {
rpl::producer<QString> Sessions::title() {
return tr::lng_settings_sessions_title();
}

View file

@ -22,7 +22,7 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);

View file

@ -54,6 +54,8 @@ public:
bool hasTopBarShadow() const;
virtual void setInnerFocus();
virtual void showFinished() {
}
// When resizing the widget with top edge moved up or down and we
// want to add this top movement to the scroll position, so inner

View file

@ -777,6 +777,7 @@ void WrapWidget::showFinishedHook() {
// Restore shadow visibility after showChildren() call.
_topShadow->toggle(_topShadow->toggled(), anim::type::instant);
_topBarSurrogate.destroy();
_content->showFinished();
}
bool WrapWidget::showInternal(

View file

@ -83,6 +83,10 @@ void Widget::saveChanges(FnMut<void()> done) {
_inner->sectionSaveChanges(std::move(done));
}
void Widget::showFinished() {
_inner->showFinished();
}
rpl::producer<bool> Widget::desiredShadowVisibility() const {
return (_type == ::Settings::Main::Id()
|| _type == ::Settings::Information::Id())
@ -91,7 +95,7 @@ rpl::producer<bool> Widget::desiredShadowVisibility() const {
}
rpl::producer<QString> Widget::title() {
return _type()->title();
return _inner->title();
}
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {

View file

@ -65,6 +65,8 @@ public:
void saveChanges(FnMut<void()> done) override;
void showFinished() override;
rpl::producer<bool> desiredShadowVisibility() const override;
rpl::producer<QString> title() override;

View file

@ -741,7 +741,7 @@ Advanced::Advanced(
setupContent(controller);
}
rpl::producer<QString> Advanced::Title() {
rpl::producer<QString> Advanced::title() {
return tr::lng_settings_advanced();
}

View file

@ -38,7 +38,7 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
rpl::producer<Type> sectionShowOther() override;

View file

@ -56,7 +56,7 @@ Calls::Calls(
Calls::~Calls() = default;
rpl::producer<QString> Calls::Title() {
rpl::producer<QString> Calls::title() {
return tr::lng_settings_section_call_settings();
}

View file

@ -38,7 +38,7 @@ public:
Calls(QWidget *parent, not_null<Window::SessionController*> controller);
~Calls();
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
void sectionSaveChanges(FnMut<void()> done) override;

View file

@ -1607,7 +1607,7 @@ Chat::Chat(QWidget *parent, not_null<Window::SessionController*> controller)
setupContent(controller);
}
rpl::producer<QString> Chat::Title() {
rpl::producer<QString> Chat::title() {
return tr::lng_settings_section_chat_settings();
}

View file

@ -35,7 +35,7 @@ class Chat : public Section<Chat> {
public:
Chat(QWidget *parent, not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);

View file

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "main/main_session.h"
#include "main/main_domain.h"
#include "lottie/lottie_icon.h"
#include "base/options.h"
#include "styles/style_layers.h"
#include "styles/style_settings.h"
@ -245,6 +246,40 @@ not_null<Ui::FlatLabel*> AddSubsectionTitle(
st::settingsSubsectionTitlePadding + addPadding);
}
LottieIcon CreateLottieIcon(
not_null<QWidget*> parent,
Lottie::IconDescriptor &&descriptor,
style::margins padding) {
auto object = object_ptr<Ui::RpWidget>(parent);
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)]{});
const auto animate = [=] {
icon->animate([=] { raw->update(); }, 0, icon->framesCount());
};
raw->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(raw);
const auto left = (raw->width() - width) / 2;
icon->paint(p, left, padding.top());
if (!icon->animating() && icon->frameIndex() > 0) {
animate();
}
}, raw->lifetime());
return { .widget = std::move(object), .animate = std::move(animate) };
}
void FillMenu(
not_null<Window::SessionController*> controller,
Type type,

View file

@ -33,6 +33,10 @@ struct FlatLabel;
struct SettingsButton;
} // namespace style
namespace Lottie {
struct IconDescriptor;
} // namespace Lottie
namespace Settings {
extern const char kOptionMonoSettingsIcons[];
@ -45,7 +49,6 @@ struct SectionMeta {
[[nodiscard]] virtual object_ptr<AbstractSection> create(
not_null<QWidget*> parent,
not_null<Window::SessionController*> controller) const = 0;
[[nodiscard]] virtual rpl::producer<QString> title() const = 0;
};
template <typename SectionType>
@ -56,9 +59,6 @@ struct SectionMetaImplementation : SectionMeta {
) const final override {
return object_ptr<SectionType>(parent, controller);
}
rpl::producer<QString> title() const final override {
return SectionType::Title();
}
[[nodiscard]] static not_null<SectionMeta*> Meta() {
static SectionMetaImplementation result;
@ -74,9 +74,12 @@ public:
[[nodiscard]] virtual rpl::producer<Type> sectionShowOther() {
return nullptr;
}
[[nodiscard]] virtual rpl::producer<QString> title() = 0;
virtual void sectionSaveChanges(FnMut<void()> done) {
done();
}
virtual void showFinished() {
}
};
template <typename SectionType>
@ -171,6 +174,15 @@ not_null<Ui::FlatLabel*> AddSubsectionTitle(
style::margins addPadding = {},
const style::FlatLabel *st = nullptr);
struct LottieIcon {
object_ptr<Ui::RpWidget> widget;
Fn<void()> animate;
};
[[nodiscard]] LottieIcon CreateLottieIcon(
not_null<QWidget*> parent,
Lottie::IconDescriptor &&descriptor,
style::margins padding = {});
void FillMenu(
not_null<Window::SessionController*> controller,
Type type,

View file

@ -146,7 +146,7 @@ Experimental::Experimental(
setupContent(controller);
}
rpl::producer<QString> Experimental::Title() {
rpl::producer<QString> Experimental::title() {
return tr::lng_settings_experimental();
}

View file

@ -17,7 +17,7 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);

View file

@ -580,7 +580,7 @@ Folders::~Folders() {
}
}
rpl::producer<QString> Folders::Title() {
rpl::producer<QString> Folders::title() {
return tr::lng_filters_title();
}

View file

@ -18,7 +18,7 @@ public:
not_null<Window::SessionController*> controller);
~Folders();
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);

View file

@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_domain.h"
#include "mtproto/mtproto_dc_options.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "window/window_peer_menu.h"
#include "apiwrap.h"
#include "api/api_peer_photo.h"
@ -285,12 +286,16 @@ void SetupRows(
[=] { controller->show(Box<EditNameBox>(self)); },
{ &st::settingsIconUser, kIconLightBlue });
const auto showChangePhone = [=] {
controller->showSettings(ChangePhone::Id());
controller->window().activate();
};
AddRow(
container,
tr::lng_settings_phone_label(),
Info::Profile::PhoneValue(self),
tr::lng_profile_copy_phone(tr::now),
[=] { controller->show(Box<ChangePhoneBox>(controller)); },
showChangePhone,
{ &st::settingsIconCalls, kIconGreen });
auto username = Info::Profile::UsernameValue(self);
@ -798,7 +803,7 @@ Information::Information(
setupContent(controller);
}
rpl::producer<QString> Information::Title() {
rpl::producer<QString> Information::title() {
return tr::lng_settings_section_info();
}

View file

@ -21,7 +21,7 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);

View file

@ -530,7 +530,7 @@ Main::Main(
setupContent(controller);
}
rpl::producer<QString> Main::Title() {
rpl::producer<QString> Main::title() {
return tr::lng_menu_settings();
}

View file

@ -36,7 +36,7 @@ class Main : public Section<Main> {
public:
Main(QWidget *parent, not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
rpl::producer<Type> sectionShowOther() override;

View file

@ -1143,7 +1143,7 @@ Notifications::Notifications(
setupContent(controller);
}
rpl::producer<QString> Notifications::Title() {
rpl::producer<QString> Notifications::title() {
return tr::lng_settings_section_notify();
}

View file

@ -17,7 +17,7 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
private:
void setupContent(not_null<Window::SessionController*> controller);

View file

@ -965,7 +965,7 @@ PrivacySecurity::PrivacySecurity(
setupContent(controller);
}
rpl::producer<QString> PrivacySecurity::Title() {
rpl::producer<QString> PrivacySecurity::title() {
return tr::lng_settings_section_privacy();
}

View file

@ -40,7 +40,7 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
[[nodiscard]] static rpl::producer<QString> Title();
[[nodiscard]] rpl::producer<QString> title() override;
rpl::producer<Type> sectionShowOther() override;