diff --git a/Telegram/Resources/icons/passport_password_setup.png b/Telegram/Resources/icons/passport_password_setup.png new file mode 100644 index 000000000..fa56c7512 Binary files /dev/null and b/Telegram/Resources/icons/passport_password_setup.png differ diff --git a/Telegram/Resources/icons/passport_password_setup@2x.png b/Telegram/Resources/icons/passport_password_setup@2x.png new file mode 100644 index 000000000..77fa1391d Binary files /dev/null and b/Telegram/Resources/icons/passport_password_setup@2x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 90be90624..fe64ace2e 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1516,6 +1516,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_passport_title" = "Telegram passport"; "lng_passport_request1" = "{bot} requests access to your personal data"; "lng_passport_request2" = "to sign you up for their services"; +"lng_passport_create_password" = "Please create a password which will be used\nto encrypt your personal data."; +"lng_passport_about_password" = "This password will also be required whenever\nyou log in to a new device."; +"lng_passport_password_create" = "Create a password"; +"lng_passport_link_sent" = "Confirmation link was sent to your email\n{email}"; +"lng_passport_stop_password_sure" = "Are you sure you want to stop your password setup?"; "lng_passport_password_placeholder" = "Your password"; "lng_passport_next" = "Next"; "lng_passport_password_wrong" = "The password you entered is not valid."; diff --git a/Telegram/SourceFiles/boxes/abstract_box.cpp b/Telegram/SourceFiles/boxes/abstract_box.cpp index a475ffeae..9b1687580 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.cpp +++ b/Telegram/SourceFiles/boxes/abstract_box.cpp @@ -227,8 +227,9 @@ void BoxContent::paintEvent(QPaintEvent *e) { } } -AbstractBox::AbstractBox(QWidget *parent, object_ptr content) -: LayerWidget(parent) +AbstractBox::AbstractBox(not_null layer, object_ptr content) +: LayerWidget(layer) +, _layer(layer) , _content(std::move(content)) { subscribe(Lang::Current().updated(), [this] { refreshLang(); }); _content->setParent(this); @@ -330,6 +331,13 @@ bool AbstractBox::hasTitle() const { return (_title != nullptr) || !_additionalTitle.isEmpty(); } +void AbstractBox::showBox( + object_ptr box, + LayerOptions options, + anim::type animated) { + _layer->showBox(std::move(box), options, animated); +} + void AbstractBox::updateSize() { setDimensions(width(), _maxContentHeight); } diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index 8983812f1..84f4f6ea2 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -23,6 +23,8 @@ class FlatLabel; class FadeShadow; } // namespace Ui +class BoxContent; + class BoxContentDelegate { public: virtual void setLayerType(bool layerType) = 0; @@ -34,11 +36,25 @@ public: virtual QPointer addLeftButton(base::lambda textFactory, base::lambda clickCallback, const style::RoundButton &st) = 0; virtual void updateButtonsPositions() = 0; + virtual void showBox( + object_ptr box, + LayerOptions options, + anim::type animated) = 0; virtual void setDimensions(int newWidth, int maxHeight) = 0; virtual void setNoContentMargin(bool noContentMargin) = 0; virtual bool isBoxShown() const = 0; virtual void closeBox() = 0; + template + QPointer show( + object_ptr content, + LayerOptions options = LayerOption::KeepOther, + anim::type animated = anim::type::normal) { + auto result = QPointer(content.data()); + showBox(std::move(content), options, animated); + return result; + } + }; class BoxContent : public Ui::RpWidget, protected base::Subscriber { @@ -163,6 +179,10 @@ protected: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; + not_null getDelegate() const { + return _delegate; + } + private slots: void onScroll(); void onInnerResize(); @@ -179,10 +199,6 @@ private: void updateShadowsVisibility(); object_ptr doTakeInnerWidget(); - BoxContentDelegate *getDelegate() const { - Expects(_delegate != nullptr); - return _delegate; - } BoxContentDelegate *_delegate = nullptr; bool _preparing = false; @@ -205,13 +221,19 @@ class AbstractBox , public BoxContentDelegate , protected base::Subscriber { public: - AbstractBox(QWidget *parent, object_ptr content); + AbstractBox( + not_null layer, + object_ptr content); void parentResized() override; void setLayerType(bool layerType) override; void setTitle(base::lambda titleFactory) override; void setAdditionalTitle(base::lambda additionalFactory) override; + void showBox( + object_ptr box, + LayerOptions options, + anim::type animated) override; void clearButtons() override; QPointer addButton(base::lambda textFactory, base::lambda clickCallback, const style::RoundButton &st) override; @@ -262,6 +284,7 @@ private: int countRealHeight() const; void updateSize(); + not_null _layer; int _fullHeight = 0; bool _noContentMargin = false; diff --git a/Telegram/SourceFiles/boxes/passcode_box.cpp b/Telegram/SourceFiles/boxes/passcode_box.cpp index 2926864a3..6eb117381 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.cpp +++ b/Telegram/SourceFiles/boxes/passcode_box.cpp @@ -190,7 +190,7 @@ void PasscodeBox::setPasswordDone(const MTPBool &result) { _setRequest = 0; emit reloadPassword(); auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated)); - Ui::show(Box(text)); + getDelegate()->show(Box(text), LayerOption::CloseOther); } void PasscodeBox::closeReplacedBy() { @@ -244,7 +244,9 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) { _recoverEmail->showError(); update(); } else if (err == qstr("EMAIL_UNCONFIRMED")) { - Ui::show(Box(lang(lng_cloud_password_almost))); + getDelegate()->show( + Box(lang(lng_cloud_password_almost)), + LayerOption::CloseOther); emit reloadPassword(); } return true; @@ -307,9 +309,9 @@ void PasscodeBox::save(bool force) { } if (!_recoverEmail->isHidden() && email.isEmpty() && !force) { _skipEmailWarning = true; - _replacedBy = Ui::show(Box(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, base::lambda_guarded(this, [this] { + _replacedBy = getDelegate()->show(Box(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, base::lambda_guarded(this, [this] { save(true); - })), LayerOption::KeepOther); + }))); } else { QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt); QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized); @@ -407,9 +409,7 @@ void PasscodeBox::recoverExpired() { void PasscodeBox::recover() { if (_pattern == "-") return; - const auto box = Ui::show( - Box(_pattern), - LayerOption::KeepOther); + const auto box = getDelegate()->show(Box(_pattern)); connect(box, &RecoverBox::reloadPassword, this, &PasscodeBox::reloadPassword); connect(box, &RecoverBox::recoveryExpired, this, &PasscodeBox::recoverExpired); _replacedBy = box; @@ -494,7 +494,9 @@ void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &resul _submitRequest = 0; emit reloadPassword(); - Ui::show(Box(lang(lng_cloud_password_removed))); + getDelegate()->show( + Box(lang(lng_cloud_password_removed)), + LayerOption::CloseOther); } bool RecoverBox::codeSubmitFail(const RPCError &error) { @@ -512,7 +514,9 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) { const QString &err = error.type(); if (err == qstr("PASSWORD_EMPTY")) { emit reloadPassword(); - Ui::show(Box(lang(lng_cloud_password_removed))); + getDelegate()->show( + Box(lang(lng_cloud_password_removed)), + LayerOption::CloseOther); return true; } else if (err == qstr("PASSWORD_RECOVERY_NA")) { closeBox(); diff --git a/Telegram/SourceFiles/passport/passport.style b/Telegram/SourceFiles/passport/passport.style index 627c0b1d4..9fa1d40ce 100644 --- a/Telegram/SourceFiles/passport/passport.style +++ b/Telegram/SourceFiles/passport/passport.style @@ -26,6 +26,9 @@ passportPasswordLabelBold: FlatLabel(passportPasswordLabel) { linkFontOver: font(boxFontSize semibold underline); } } +passportPasswordSetupLabel: FlatLabel(passportPasswordLabel) { + minWidth: 0px; +} passportPasswordHintLabel: passportPasswordLabel; passportErrorLabel: FlatLabel(passportPasswordLabel) { textFg: boxTextFgError; @@ -223,3 +226,8 @@ passportDetailsSkip: 30px; passportDetailsGenderSkip: 30px; passportRequestTypeSkip: 16px; + +passportPasswordAbout1Padding: margins(10px, 28px, 10px, 0px); +passportPasswordAbout2Padding: margins(10px, 0px, 10px, 28px); +passportPasswordIconHeight: 224px; +passportPasswordIcon: icon {{ "passport_password_setup", windowSubTextFg }}; diff --git a/Telegram/SourceFiles/passport/passport_form_controller.cpp b/Telegram/SourceFiles/passport/passport_form_controller.cpp index 3fb2e78c4..b5f8c7df5 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_form_controller.cpp @@ -388,6 +388,34 @@ void FormController::submitPassword(const QString &password) { }).send(); } +void FormController::reloadPassword() { + requestPassword(); +} + +void FormController::cancelPassword() { + if (_passwordRequestId) { + return; + } + _passwordRequestId = request(MTPaccount_UpdatePasswordSettings( + MTP_bytes(QByteArray()), + MTP_account_passwordInputSettings( + MTP_flags(MTPDaccount_passwordInputSettings::Flag::f_email), + MTP_bytes(QByteArray()), // new_salt + MTP_bytes(QByteArray()), // new_password_hash + MTP_string(QString()), // hint + MTP_string(QString()), // email + MTP_bytes(QByteArray()), // new_secure_salt + MTP_bytes(QByteArray()), // new_secure_secret + MTP_long(0)) // new_secure_secret_hash + )).done([=](const MTPBool &result) { + _passwordRequestId = 0; + reloadPassword(); + }).fail([=](const RPCError &error) { + _passwordRequestId = 0; + reloadPassword(); + }).send(); +} + void FormController::validateSecureSecret( bytes::const_span salt, bytes::const_span encryptedSecret, @@ -525,8 +553,8 @@ rpl::producer FormController::passwordError() const { return _passwordError.events(); } -QString FormController::passwordHint() const { - return _password.hint; +const PasswordSettings &FormController::passwordSettings() const { + return _password; } void FormController::uploadScan( @@ -1702,6 +1730,9 @@ void FormController::formFail(const QString &error) { } void FormController::requestPassword() { + if (_passwordRequestId) { + return; + } _passwordRequestId = request(MTPaccount_GetPassword( )).done([=](const MTPaccount_Password &result) { _passwordRequestId = 0; @@ -1733,14 +1764,13 @@ void FormController::showForm() { } if (!_password.salt.empty()) { _view->showAskPassword(); - } else if (!_password.unconfirmedPattern.isEmpty()) { - _view->showPasswordUnconfirmed(); } else { _view->showNoPassword(); } } void FormController::parsePassword(const MTPDaccount_noPassword &result) { + _password = PasswordSettings(); _password.unconfirmedPattern = qs(result.vemail_unconfirmed_pattern); _password.newSalt = bytes::make_vector(result.vnew_salt.v); _password.newSecureSalt = bytes::make_vector(result.vnew_secure_salt.v); @@ -1748,6 +1778,7 @@ void FormController::parsePassword(const MTPDaccount_noPassword &result) { } void FormController::parsePassword(const MTPDaccount_password &result) { + _password = PasswordSettings(); _password.hint = qs(result.vhint); _password.hasRecovery = mtpIsTrue(result.vhas_recovery); _password.salt = bytes::make_vector(result.vcurrent_salt.v); diff --git a/Telegram/SourceFiles/passport/passport_form_controller.h b/Telegram/SourceFiles/passport/passport_form_controller.h index 45f9d6e81..215d7e503 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.h +++ b/Telegram/SourceFiles/passport/passport_form_controller.h @@ -217,7 +217,9 @@ public: std::vector> submitGetErrors(); void submitPassword(const QString &password); rpl::producer passwordError() const; - QString passwordHint() const; + const PasswordSettings &passwordSettings() const; + void reloadPassword(); + void cancelPassword(); bool canAddScan(not_null value) const; void uploadScan(not_null value, QByteArray &&content); diff --git a/Telegram/SourceFiles/passport/passport_form_view_controller.h b/Telegram/SourceFiles/passport/passport_form_view_controller.h index 6ef43feab..4a46b4e19 100644 --- a/Telegram/SourceFiles/passport/passport_form_view_controller.h +++ b/Telegram/SourceFiles/passport/passport_form_view_controller.h @@ -42,11 +42,13 @@ class ViewController { public: virtual void showAskPassword() = 0; virtual void showNoPassword() = 0; - virtual void showPasswordUnconfirmed() = 0; virtual void showCriticalError(const QString &error) = 0; virtual void editScope(int index) = 0; - virtual void showBox(object_ptr box) = 0; + virtual void showBox( + object_ptr box, + LayerOptions options, + anim::type animated) = 0; virtual void showToast(const QString &text) = 0; virtual void suggestReset(base::lambda callback) = 0; @@ -56,9 +58,12 @@ public: } template - QPointer show(object_ptr content) { - auto result = QPointer(content.data()); - showBox(std::move(content)); + QPointer show( + object_ptr box, + LayerOptions options = LayerOption::KeepOther, + anim::type animated = anim::type::normal) { + auto result = QPointer(box.data()); + showBox(std::move(box), options, animated); return result; } diff --git a/Telegram/SourceFiles/passport/passport_panel.cpp b/Telegram/SourceFiles/passport/passport_panel.cpp index 7a47f254b..f7d464b00 100644 --- a/Telegram/SourceFiles/passport/passport_panel.cpp +++ b/Telegram/SourceFiles/passport/passport_panel.cpp @@ -226,12 +226,6 @@ void Panel::showNoPassword() { setBackAllowed(false); } -void Panel::showPasswordUnconfirmed() { - showInner( - base::make_unique_q(_body, _controller)); - setBackAllowed(false); -} - void Panel::showCriticalError(const QString &error) { auto container = base::make_unique_q>( _body, @@ -258,12 +252,12 @@ void Panel::showEditValue(object_ptr from) { showInner(base::unique_qptr(from.data())); } -void Panel::showBox(object_ptr box) { +void Panel::showBox( + object_ptr box, + LayerOptions options, + anim::type animated) { ensureLayerCreated(); - _layer->showBox( - std::move(box), - LayerOption::KeepOther, - anim::type::normal); + _layer->showBox(std::move(box), options, animated); } void Panel::ensureLayerCreated() { diff --git a/Telegram/SourceFiles/passport/passport_panel.h b/Telegram/SourceFiles/passport/passport_panel.h index abb705f82..73ce87413 100644 --- a/Telegram/SourceFiles/passport/passport_panel.h +++ b/Telegram/SourceFiles/passport/passport_panel.h @@ -37,11 +37,13 @@ public: void showAskPassword(); void showNoPassword(); - void showPasswordUnconfirmed(); void showForm(); void showCriticalError(const QString &error); void showEditValue(object_ptr form); - void showBox(object_ptr box); + void showBox( + object_ptr box, + LayerOptions options, + anim::type animated); rpl::producer<> backRequests() const; void setBackAllowed(bool allowed); diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.cpp b/Telegram/SourceFiles/passport/passport_panel_controller.cpp index 38ebb4e52..f9b036e0a 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_controller.cpp @@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_panel_edit_contact.h" #include "passport/passport_panel_edit_scans.h" #include "passport/passport_panel.h" +#include "base/openssl_help.h" +#include "boxes/passcode_box.h" #include "boxes/confirm_box.h" #include "ui/toast/toast.h" #include "ui/countryinput.h" @@ -403,7 +405,11 @@ rpl::producer PanelController::passwordError() const { } QString PanelController::passwordHint() const { - return _form->passwordHint(); + return _form->passwordSettings().hint; +} + +QString PanelController::unconfirmedEmailPattern() const { + return _form->passwordSettings().unconfirmedPattern; } QString PanelController::defaultEmail() const { @@ -414,6 +420,40 @@ QString PanelController::defaultPhoneNumber() const { return _form->defaultPhoneNumber(); } +void PanelController::setupPassword() { + Expects(_panel != nullptr); + + const auto &settings = _form->passwordSettings(); + Assert(settings.salt.empty()); + + constexpr auto kRandomPart = 8; + auto newSalt = QByteArray( + reinterpret_cast(settings.newSalt.data()), + settings.newSalt.size()); + newSalt.resize(newSalt.size() + kRandomPart); + bytes::set_random( + bytes::make_span(newSalt).subspan(settings.newSalt.size())); + const auto currentSalt = QByteArray(); + const auto hasRecovery = false; + const auto hint = QString(); + auto box = show(Box( + newSalt, + currentSalt, + hasRecovery, + hint)); + box->connect(box, &PasscodeBox::reloadPassword, _panel.get(), [=] { + _form->reloadPassword(); + }); +} + +void PanelController::cancelPasswordSubmit() { + const auto box = std::make_shared>(); + *box = show(Box( + lang(lng_passport_stop_password_sure), + lang(lng_passport_stop), + [=] { if (*box) (*box)->closeBox(); _form->cancelPassword(); })); +} + bool PanelController::canAddScan() const { Expects(_editScope != nullptr); Expects(_editDocument != nullptr); @@ -683,11 +723,6 @@ void PanelController::showNoPassword() { _panel->showNoPassword(); } -void PanelController::showPasswordUnconfirmed() { - ensurePanelCreated(); - _panel->showPasswordUnconfirmed(); -} - void PanelController::showCriticalError(const QString &error) { ensurePanelCreated(); _panel->showCriticalError(error); @@ -1060,8 +1095,11 @@ void PanelController::cancelAuth() { _form->cancel(); } -void PanelController::showBox(object_ptr box) { - _panel->showBox(std::move(box)); +void PanelController::showBox( + object_ptr box, + LayerOptions options, + anim::type animated) { + _panel->showBox(std::move(box), options, animated); } void PanelController::showToast(const QString &text) { diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.h b/Telegram/SourceFiles/passport/passport_panel_controller.h index 1adb33197..f2bf6fa19 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.h +++ b/Telegram/SourceFiles/passport/passport_panel_controller.h @@ -69,6 +69,10 @@ public: void submitPassword(const QString &password); rpl::producer passwordError() const; QString passwordHint() const; + QString unconfirmedEmailPattern() const; + + void setupPassword(); + void cancelPasswordSubmit(); bool canAddScan() const; void uploadScan(QByteArray &&content); @@ -88,7 +92,6 @@ public: void showAskPassword() override; void showNoPassword() override; - void showPasswordUnconfirmed() override; void showCriticalError(const QString &error) override; void fillRows( @@ -106,7 +109,10 @@ public: const ValueMap &filesData) const; void cancelEditScope(); - void showBox(object_ptr box) override; + void showBox( + object_ptr box, + LayerOptions options, + anim::type animated) override; void showToast(const QString &text) override; void suggestReset(base::lambda callback) override; diff --git a/Telegram/SourceFiles/passport/passport_panel_form.cpp b/Telegram/SourceFiles/passport/passport_panel_form.cpp index af3258b03..f52dbad9a 100644 --- a/Telegram/SourceFiles/passport/passport_panel_form.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_form.cpp @@ -220,25 +220,25 @@ not_null PanelForm::setupContent() { _userpic->move((width - _userpic->width()) / 2, _userpic->y()); }, _userpic->lifetime()); - auto about1 = object_ptr( - inner, - lng_passport_request1(lt_bot, App::peerName(bot)), - Ui::FlatLabel::InitType::Simple, - st::passportPasswordLabelBold); - _about1 = about1.data(); - inner->add( - object_ptr(inner, std::move(about1)), - st::passportFormAbout1Padding); + _about1 = inner->add( + object_ptr>( + inner, + object_ptr( + inner, + lng_passport_request1(lt_bot, App::peerName(bot)), + Ui::FlatLabel::InitType::Simple, + st::passportPasswordLabelBold)), + st::passportFormAbout1Padding)->entity(); - auto about2 = object_ptr( - inner, - lang(lng_passport_request2), - Ui::FlatLabel::InitType::Simple, - st::passportPasswordLabel); - _about2 = about2.data(); - inner->add( - object_ptr(inner, std::move(about2)), - st::passportFormAbout2Padding); + _about2 = inner->add( + object_ptr>( + inner, + object_ptr( + inner, + lang(lng_passport_request2), + Ui::FlatLabel::InitType::Simple, + st::passportPasswordLabel)), + st::passportFormAbout2Padding)->entity(); inner->add(object_ptr( inner, diff --git a/Telegram/SourceFiles/passport/passport_panel_password.cpp b/Telegram/SourceFiles/passport/passport_panel_password.cpp index b5b8684a1..5596c01ae 100644 --- a/Telegram/SourceFiles/passport/passport_panel_password.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_password.cpp @@ -11,8 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" +#include "ui/wrap/vertical_layout.h" +#include "ui/wrap/padding_wrap.h" #include "ui/special_buttons.h" #include "lang/lang_keys.h" +#include "info/profile/info_profile_icon.h" #include "styles/style_passport.h" #include "styles/style_boxes.h" @@ -148,14 +151,96 @@ PanelNoPassword::PanelNoPassword( QWidget *parent, not_null controller) : RpWidget(parent) -, _controller(controller) { +, _controller(controller) +, _inner(Ui::CreateChild(this)) { + setupContent(); } -PanelPasswordUnconfirmed::PanelPasswordUnconfirmed( - QWidget *parent, - not_null controller) -: RpWidget(parent) -, _controller(controller) { +void PanelNoPassword::setupContent() { + widthValue( + ) | rpl::start_with_next([=](int newWidth) { + _inner->resizeToWidth(newWidth); + }, _inner->lifetime()); + + const auto about1 = _inner->add( + object_ptr>( + _inner, + object_ptr( + _inner, + lng_passport_request1( + lt_bot, + App::peerName(_controller->bot())), + Ui::FlatLabel::InitType::Simple, + st::passportPasswordLabelBold)), + st::passportPasswordAbout1Padding)->entity(); + + const auto about2 = _inner->add( + object_ptr>( + _inner, + object_ptr( + _inner, + lang(lng_passport_request2), + Ui::FlatLabel::InitType::Simple, + st::passportPasswordLabel)), + st::passportPasswordAbout2Padding)->entity(); + + const auto iconWrap = _inner->add( + object_ptr>( + _inner, + object_ptr( + _inner, + st::passportPasswordIconHeight))); + iconWrap->entity()->resizeToWidth(st::passportPasswordIcon.width()); + Ui::CreateChild( + iconWrap->entity(), + st::passportPasswordIcon, + QPoint(0, 0)); + + const auto about3 = _inner->add( + object_ptr>( + _inner, + object_ptr( + _inner, + lang(lng_passport_create_password), + Ui::FlatLabel::InitType::Simple, + st::passportPasswordSetupLabel)), + st::passportFormAbout2Padding)->entity(); + + refreshBottom(); +} + +void PanelNoPassword::refreshBottom() { + const auto pattern = _controller->unconfirmedEmailPattern(); + _about.reset(_inner->add( + object_ptr>( + _inner, + object_ptr( + _inner, + (pattern.isEmpty() + ? lang(lng_passport_about_password) + : lng_passport_link_sent(lt_email, pattern)), + Ui::FlatLabel::InitType::Simple, + st::passportPasswordSetupLabel)), + st::passportFormAbout2Padding)->entity()); + const auto button = _inner->add( + object_ptr>( + _inner, + object_ptr( + _inner, + langFactory(pattern.isEmpty() + ? lng_passport_password_create + : lng_cancel), + st::defaultBoxButton))); + if (pattern.isEmpty()) { + button->entity()->addClickHandler([=] { + _controller->setupPassword(); + }); + } else { + button->entity()->addClickHandler([=] { + _controller->cancelPasswordSubmit(); + }); + } + _button.reset(button); } } // namespace Passport diff --git a/Telegram/SourceFiles/passport/passport_panel_password.h b/Telegram/SourceFiles/passport/passport_panel_password.h index 2a6233d52..14de59bfd 100644 --- a/Telegram/SourceFiles/passport/passport_panel_password.h +++ b/Telegram/SourceFiles/passport/passport_panel_password.h @@ -15,6 +15,7 @@ class FlatLabel; class LinkButton; class RoundButton; class UserpicButton; +class VerticalLayout; } // namespace Ui namespace Passport { @@ -58,18 +59,14 @@ public: not_null controller); private: + void setupContent(); + void refreshBottom(); + not_null _controller; -}; - -class PanelPasswordUnconfirmed : public Ui::RpWidget { -public: - PanelPasswordUnconfirmed( - QWidget *parent, - not_null controller); - -private: - not_null _controller; + not_null _inner; + base::unique_qptr _about; + base::unique_qptr _button; }; diff --git a/Telegram/SourceFiles/ui/wrap/padding_wrap.cpp b/Telegram/SourceFiles/ui/wrap/padding_wrap.cpp index 100a986e1..33ec9ba23 100644 --- a/Telegram/SourceFiles/ui/wrap/padding_wrap.cpp +++ b/Telegram/SourceFiles/ui/wrap/padding_wrap.cpp @@ -67,4 +67,35 @@ int PaddingWrap::resizeGetHeight(int newWidth) { return heightNoMargins(); } +CenterWrap::CenterWrap( + QWidget *parent, + object_ptr &&child) +: Parent(parent, std::move(child)) { + if (const auto weak = wrapped()) { + wrappedSizeUpdated(weak->size()); + } +} + +int CenterWrap::naturalWidth() const { + return -1; +} + +int CenterWrap::resizeGetHeight(int newWidth) { + updateWrappedPosition(newWidth); + return heightNoMargins(); +} + +void CenterWrap::wrappedSizeUpdated(QSize size) { + updateWrappedPosition(width()); +} + +void CenterWrap::updateWrappedPosition(int forWidth) { + if (const auto weak = wrapped()) { + const auto margins = weak->getMargins(); + weak->moveToLeft( + (forWidth - weak->width()) / 2 + margins.left(), + margins.top()); + } +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/wrap/padding_wrap.h b/Telegram/SourceFiles/ui/wrap/padding_wrap.h index 4f529a505..24bf1a888 100644 --- a/Telegram/SourceFiles/ui/wrap/padding_wrap.h +++ b/Telegram/SourceFiles/ui/wrap/padding_wrap.h @@ -54,6 +54,42 @@ public: }; +template +class CenterWrap; + +template <> +class CenterWrap : public Wrap { + using Parent = Wrap; + +public: + CenterWrap( + QWidget *parent, + object_ptr &&child); + + int naturalWidth() const override; + +protected: + int resizeGetHeight(int newWidth) override; + void wrappedSizeUpdated(QSize size) override; + +private: + void updateWrappedPosition(int forWidth); + +}; + +template +class CenterWrap : public Wrap> { + using Parent = Wrap>; + +public: + CenterWrap( + QWidget *parent, + object_ptr &&child) + : Parent(parent, std::move(child)) { + } + +}; + class FixedHeightWidget : public RpWidget { public: FixedHeightWidget(QWidget *parent, int height) diff --git a/Telegram/SourceFiles/ui/wrap/wrap.h b/Telegram/SourceFiles/ui/wrap/wrap.h index be855168f..221dae1a3 100644 --- a/Telegram/SourceFiles/ui/wrap/wrap.h +++ b/Telegram/SourceFiles/ui/wrap/wrap.h @@ -183,24 +183,4 @@ private: }; -class IgnoreNaturalWidth : public Wrap { - using Parent = Wrap; - -public: - IgnoreNaturalWidth(QWidget *parent, object_ptr &&child) - : Parent(parent, std::move(child)) { - if (auto weak = wrapped()) { - auto margins = weak->getMargins(); - resizeToWidth(weak->width() - - margins.left() - - margins.right()); - } - } - - int naturalWidth() const override { - return -1; - } - -}; - } // namespace Ui diff --git a/Telegram/SourceFiles/window/layer_widget.cpp b/Telegram/SourceFiles/window/layer_widget.cpp index 3a8ce5008..f5ef4d5d9 100644 --- a/Telegram/SourceFiles/window/layer_widget.cpp +++ b/Telegram/SourceFiles/window/layer_widget.cpp @@ -686,7 +686,7 @@ LayerWidget *LayerStackWidget::pushBox( if (_layers.size() > 1) { if (!_background->animating()) { - layer->show(); + layer->setVisible(true); showFinished(); } } else {