diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 776536aa4c..bc686b183b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1541,10 +1541,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_passport_country" = "Country"; "lng_passport_document_number" = "Card Number"; "lng_passport_expiry_date" = "Expiry date"; +"lng_passport_address" = "Address"; "lng_passport_street" = "Street"; "lng_passport_city" = "City"; "lng_passport_state" = "State"; "lng_passport_postcode" = "Postcode"; +"lng_passport_use_existing" = "USE {existing}"; +"lng_passport_use_existing_phone" = "Use the same phone number as on Telegram."; +"lng_passport_new_phone" = "Or enter a new phone number"; +"lng_passport_new_phone_code" = "Note: You will receive a confirmation code on the phone number you provide."; +"lng_passport_use_existing_email" = "Use the same email as on Telegram."; +"lng_passport_new_email" = "Or enter a new email"; +"lng_passport_new_email_code" = "Note: You will receive a confirmation code on the email address you provide."; +"lng_passport_email_enter_code" = "Please enter the confirmation code we've just sent to {email}."; // Wnd specific diff --git a/Telegram/SourceFiles/passport/passport.style b/Telegram/SourceFiles/passport/passport.style index a73b4e69c3..fec484ace9 100644 --- a/Telegram/SourceFiles/passport/passport.style +++ b/Telegram/SourceFiles/passport/passport.style @@ -115,10 +115,13 @@ passportFormUserpic: UserpicButton(passportPasswordUserpic) { } passportFormUserpicPadding: margins(0px, 5px, 0px, 10px); passportFormDividerHeight: 13px; -passportFormPolicy: FlatLabel(defaultFlatLabel) { +passportFormLabel: FlatLabel(defaultFlatLabel) { minWidth: 285px; align: align(topleft); textFg: windowSubTextFg; +} +passportFormLabelPadding: margins(22px, 7px, 22px, 14px); +passportFormPolicy: FlatLabel(passportFormLabel) { style: TextStyle(defaultTextStyle) { linkFont: font(fsize semibold underline); linkFontOver: font(fsize semibold underline); @@ -128,6 +131,8 @@ passportFormPolicy: FlatLabel(defaultFlatLabel) { } } passportFormPolicyPadding: margins(22px, 7px, 22px, 28px); +passportContactNewFieldPadding: margins(22px, 0px, 22px, 28px); +passportContactFieldPadding: margins(22px, 14px, 22px, 28px); passportRowPadding: margins(22px, 8px, 25px, 8px); passportRowSkip: 2px; @@ -180,6 +185,9 @@ passportDetailsField: InputField(defaultInputField) { heightMin: 32px; font: normalFont; } +passportContactField: InputField(defaultInputField) { + font: normalFont; +} passportDetailsFieldLeft: 116px; passportDetailsFieldTop: 2px; passportDetailsFieldSkipMin: 12px; diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.cpp b/Telegram/SourceFiles/passport/passport_panel_controller.cpp index ee3b2cea03..3145cd7d68 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_controller.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "passport/passport_panel_edit_document.h" +#include "passport/passport_panel_edit_contact.h" #include "passport/passport_panel.h" #include "boxes/confirm_box.h" #include "layout.h" @@ -41,6 +42,7 @@ PanelEditDocument::Scheme GetDocumentScheme(Scope::Type type) { switch (type) { case Scope::Type::Identity: { auto result = Scheme(); + result.rowsHeader = lang(lng_passport_personal_details); result.rows = { { Scheme::ValueType::Fields, @@ -90,6 +92,7 @@ PanelEditDocument::Scheme GetDocumentScheme(Scope::Type type) { case Scope::Type::Address: { auto result = Scheme(); + result.rowsHeader = lang(lng_passport_address); result.rows = { { Scheme::ValueType::Fields, @@ -134,6 +137,48 @@ PanelEditDocument::Scheme GetDocumentScheme(Scope::Type type) { Unexpected("Type in GetDocumentScheme()."); } +PanelEditContact::Scheme GetContactScheme(Scope::Type type) { + using Scheme = PanelEditContact::Scheme; + switch (type) { + case Scope::Type::Phone: { + auto result = Scheme(); + result.aboutExisting = lang(lng_passport_use_existing_phone); + result.newHeader = lang(lng_passport_new_phone); + result.aboutNew = lang(lng_passport_new_phone_code); + result.validate = [](const QString &value) { + return QRegularExpression( + "^\\d{2,12}$" + ).match(value).hasMatch(); + }; + result.preprocess = [](const QString &value) { + return App::formatPhone(value); + }; + result.postprocess = [](QString value) { + return value.replace(QRegularExpression("[^\\d]"), QString()); + }; + return result; + } break; + + case Scope::Type::Email: { + auto result = Scheme(); + result.aboutExisting = lang(lng_passport_use_existing_email); + result.newHeader = lang(lng_passport_new_email); + result.newPlaceholder = langFactory(lng_passport_email_title); + result.aboutNew = lang(lng_passport_new_email_code); + result.validate = [](const QString &value) { + const auto at = value.indexOf('@'); + const auto dot = value.lastIndexOf('.'); + return (at > 0) && (dot > at); + }; + result.preprocess = result.postprocess = [](const QString &value) { + return value.trimmed(); + }; + return result; + } break; + } + Unexpected("Type in GetContactScheme()."); +} + } // namespace BoxPointer::BoxPointer(QPointer value) @@ -324,6 +369,16 @@ ScanInfo PanelController::collectScanInfo(const EditFile &file) const { file.deleted }; } +QString PanelController::getDefaultContactValue(Scope::Type type) const { + switch (type) { + case Scope::Type::Phone: + return _form->defaultPhoneNumber(); + case Scope::Type::Email: + return _form->defaultEmail(); + } + Unexpected("Type in PanelController::getDefaultContactValue()."); +} + void PanelController::showAskPassword() { ensurePanelCreated(); _panel->showAskPassword(); @@ -376,8 +431,19 @@ void PanelController::editScope(int index) { this, std::move(GetDocumentScheme(_editScope->type)), _editScope->fields->data.parsed); + case Scope::Type::Phone: + case Scope::Type::Email: { + const auto &fields = _editScope->fields->data.parsed.fields; + const auto valueIt = fields.find("value"); + return object_ptr( + _panel.get(), + this, + std::move(GetContactScheme(_editScope->type)), + (valueIt == end(fields)) ? QString() : valueIt->second, + getDefaultContactValue(_editScope->type)); + } break; } - return { nullptr }; + Unexpected("Type in PanelController::editScope()."); }(); if (content) { _panel->setBackAllowed(true); diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.h b/Telegram/SourceFiles/passport/passport_panel_controller.h index 1791d5eb73..9f9f984712 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.h +++ b/Telegram/SourceFiles/passport/passport_panel_controller.h @@ -83,6 +83,7 @@ private: std::vector valueFiles(const Value &value) const; ScanInfo collectScanInfo(const EditFile &file) const; + QString getDefaultContactValue(Scope::Type type) const; not_null _form; std::vector _scopes; diff --git a/Telegram/SourceFiles/passport/passport_panel_details_row.cpp b/Telegram/SourceFiles/passport/passport_panel_details_row.cpp index c40b5c0f71..abc674ce4c 100644 --- a/Telegram/SourceFiles/passport/passport_panel_details_row.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_details_row.cpp @@ -12,6 +12,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Passport { +int PanelLabel::naturalWidth() const { + return -1; +} + +void PanelLabel::resizeEvent(QResizeEvent *e) { + _background->lower(); + _background->setGeometry(rect()); + return PaddingWrap::resizeEvent(e); +} + PanelDetailsRow::PanelDetailsRow( QWidget *parent, const QString &label, diff --git a/Telegram/SourceFiles/passport/passport_panel_details_row.h b/Telegram/SourceFiles/passport/passport_panel_details_row.h index 55b6dc4133..de9cb1fdcf 100644 --- a/Telegram/SourceFiles/passport/passport_panel_details_row.h +++ b/Telegram/SourceFiles/passport/passport_panel_details_row.h @@ -8,6 +8,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/rp_widget.h" +#include "ui/wrap/padding_wrap.h" +#include "ui/widgets/labels.h" +#include "boxes/abstract_box.h" namespace Ui { class InputField; @@ -15,6 +18,20 @@ class InputField; namespace Passport { +class PanelLabel : public Ui::PaddingWrap { +public: + using PaddingWrap::PaddingWrap; + + int naturalWidth() const override; + +protected: + void resizeEvent(QResizeEvent *e) override; + +private: + object_ptr _background = object_ptr(this); + +}; + class PanelDetailsRow : public Ui::RpWidget { public: PanelDetailsRow( diff --git a/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp b/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp new file mode 100644 index 0000000000..2603ae2a66 --- /dev/null +++ b/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp @@ -0,0 +1,151 @@ +/* +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 "passport/passport_panel_edit_contact.h" + +#include "passport/passport_panel_controller.h" +#include "passport/passport_panel_details_row.h" +#include "info/profile/info_profile_button.h" +#include "info/profile/info_profile_values.h" +#include "ui/widgets/input_fields.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/shadow.h" +#include "ui/wrap/vertical_layout.h" +#include "boxes/abstract_box.h" +#include "lang/lang_keys.h" +#include "styles/style_passport.h" + +namespace Passport { + +PanelEditContact::PanelEditContact( + QWidget*, + not_null controller, + Scheme scheme, + const QString &data, + const QString &existing) +: _controller(controller) +, _scheme(std::move(scheme)) +, _content(this) +, _bottomShadow(this) +, _done( + this, + langFactory(lng_passport_save_value), + st::passportPanelSaveValue) { + setupControls(data, existing); +} + +void PanelEditContact::setupControls( + const QString &data, + const QString &existing) { + widthValue( + ) | rpl::start_with_next([=](int width) { + _content->resizeToWidth(width); + }, _content->lifetime()); + + _content->add(object_ptr( + _content, + st::passportFormDividerHeight)); + if (!existing.isEmpty()) { + _content->add( + object_ptr( + _content, + Lang::Viewer( + lng_passport_use_existing__tagged + ) | rpl::map([=] { + return lng_passport_use_existing( + lt_existing, + (_scheme.preprocess + ? _scheme.preprocess(existing) + : existing)); + }), + st::passportUploadButton), + st::passportUploadButtonPadding + )->addClickHandler([=] { + save(existing); + }); + _content->add( + object_ptr( + _content, + object_ptr( + _content, + _scheme.aboutExisting, + Ui::FlatLabel::InitType::Simple, + st::passportFormLabel), + st::passportFormLabelPadding)); + _content->add( + object_ptr( + _content, + _scheme.newHeader, + Ui::FlatLabel::InitType::Simple, + st::passportFormHeader), + st::passportDetailsHeaderPadding); + _field = _content->add( + object_ptr( + _content, + st::passportDetailsField), + st::passportContactNewFieldPadding); + } else { + _field = _content->add( + object_ptr( + _content, + st::passportContactField, + _scheme.newPlaceholder), + st::passportContactFieldPadding); + } + _content->add( + object_ptr( + _content, + object_ptr( + _content, + _scheme.aboutNew, + Ui::FlatLabel::InitType::Simple, + st::passportFormLabel), + st::passportFormLabelPadding)); + + _done->addClickHandler([=] { + crl::on_main(this, [=] { + save(); + }); + }); +} + +void PanelEditContact::focusInEvent(QFocusEvent *e) { + _field->setFocusFast(); +} + +void PanelEditContact::resizeEvent(QResizeEvent *e) { + updateControlsGeometry(); +} + +void PanelEditContact::updateControlsGeometry() { + const auto submitTop = height() - _done->height(); + _bottomShadow->resizeToWidth(width()); + _bottomShadow->moveToLeft(0, submitTop - st::lineWidth); + _done->resizeToWidth(width()); + _done->moveToLeft(0, submitTop); +} + +void PanelEditContact::save() { + const auto result = _field->getLastText(); + const auto processed = _scheme.postprocess + ? _scheme.postprocess(result) + : result; + if (_scheme.validate && !_scheme.validate(processed)) { + _field->showError(); + return; + } + save(processed); +} + +void PanelEditContact::save(const QString &value) { + auto data = ValueMap(); + data.fields["value"] = value; + _controller->saveScope(std::move(data), {}); +} + +} // namespace Passport diff --git a/Telegram/SourceFiles/passport/passport_panel_edit_contact.h b/Telegram/SourceFiles/passport/passport_panel_edit_contact.h new file mode 100644 index 0000000000..5935df90dc --- /dev/null +++ b/Telegram/SourceFiles/passport/passport_panel_edit_contact.h @@ -0,0 +1,72 @@ +/* +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 "ui/rp_widget.h" + +namespace Ui { +class InputField; +class PlainShadow; +class RoundButton; +class VerticalLayout; +} // namespace Ui + +namespace Passport { + +class PanelController; + +class PanelEditContact : public Ui::RpWidget { +public: + struct Scheme { + enum class ValueType { + Phone, + Text, + }; + ValueType type = ValueType::Phone; + + QString aboutExisting; + QString newHeader; + base::lambda newPlaceholder; + QString aboutNew; + base::lambda validate; + base::lambda preprocess; + base::lambda postprocess; + + }; + + PanelEditContact( + QWidget *parent, + not_null controller, + Scheme scheme, + const QString &data, + const QString &existing); + +protected: + void focusInEvent(QFocusEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + +private: + void setupControls( + const QString &data, + const QString &existing); + void updateControlsGeometry(); + + void save(); + void save(const QString &value); + + not_null _controller; + Scheme _scheme; + + object_ptr _content; + QPointer _field; + object_ptr _bottomShadow; + object_ptr _done; + +}; + +} // namespace Passport diff --git a/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp b/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp index d5df557327..dbe062f09f 100644 --- a/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp @@ -100,7 +100,7 @@ not_null PanelEditDocument::setupContent( inner->add( object_ptr( inner, - lang(lng_passport_personal_details), + _scheme.rowsHeader, Ui::FlatLabel::InitType::Simple, st::passportFormHeader), st::passportDetailsHeaderPadding); diff --git a/Telegram/SourceFiles/passport/passport_panel_edit_document.h b/Telegram/SourceFiles/passport/passport_panel_edit_document.h index 4b04cd05fb..06db0d2ca2 100644 --- a/Telegram/SourceFiles/passport/passport_panel_edit_document.h +++ b/Telegram/SourceFiles/passport/passport_panel_edit_document.h @@ -39,6 +39,7 @@ public: base::lambda validate; }; std::vector rows; + QString rowsHeader; }; diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 80f7637b5c..6e97a3c4af 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -466,6 +466,8 @@ <(src_loc)/passport/passport_panel_controller.h <(src_loc)/passport/passport_panel_details_row.cpp <(src_loc)/passport/passport_panel_details_row.h +<(src_loc)/passport/passport_panel_edit_contact.cpp +<(src_loc)/passport/passport_panel_edit_contact.h <(src_loc)/passport/passport_panel_edit_document.cpp <(src_loc)/passport/passport_panel_edit_document.h <(src_loc)/passport/passport_panel_edit_scans.cpp