mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-28 18:23:38 +00:00
Initial layout of the passport authorization form.
This commit is contained in:
parent
ddb4527159
commit
07e8a2bd85
@ -1502,6 +1502,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_terms_decline" = "Decline";
|
||||
"lng_terms_signup_sorry" = "We're very sorry, but this means you can't sign up for Telegram.\n\nUnlike others, we don't use your data for ad targeting or other commercial purposes. Telegram only stores the information it needs to function as a feature-rich cloud service. You can adjust how we use your data in Privacy & Security settings.\n\nBut if you're generally not OK with Telegram's modest needs, it won't be possible for us to provide this service.";
|
||||
|
||||
"lng_passport_title" = "Telegram passport";
|
||||
"lng_passport_request" = "{domain} requests access to your personal data\nto sign you up for their services";
|
||||
"lng_passport_password_request" = "Please provide the password for\naccessing your personal data.";
|
||||
"lng_passport_password_placeholder" = "Enter password";
|
||||
"lng_passport_password_wrong" = "Wrong password";
|
||||
"lng_passport_header" = "Requested information";
|
||||
"lng_passport_identity_title" = "Identity document";
|
||||
"lng_passport_identity_description" = "Upload scan of your passport or other ID";
|
||||
"lng_passport_identity_passport" = "Passport";
|
||||
"lng_passport_identity_card" = "Identity card";
|
||||
"lng_passport_identity_license" = "Driver's license";
|
||||
"lng_passport_address_title" = "Residential address";
|
||||
"lng_passport_address_description" = "Upload proof of your address";
|
||||
"lng_passport_phone_title" = "Phone number";
|
||||
"lng_passport_email_title" = "E-mail";
|
||||
"lng_passport_email_description" = "Specify your e-mail address";
|
||||
"lng_passport_accept_allow" = "You accept {policy} and allow their {bot} to send messages to you.";
|
||||
"lng_passport_accept" = "You accept {policy}.";
|
||||
"lng_passport_policy" = "{domain} privacy policy";
|
||||
"lng_passport_authorize" = "Authorize";
|
||||
"lng_passport_form_error" = "Could not get authorization form.";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||
|
@ -223,6 +223,10 @@ inline int FillRandom(base::byte_span bytes) {
|
||||
return RAND_bytes(reinterpret_cast<unsigned char*>(bytes.data()), bytes.size());
|
||||
}
|
||||
|
||||
inline void AddRandomSeed(base::const_byte_span bytes) {
|
||||
RAND_seed(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
} // namespace openssl
|
||||
|
||||
namespace bytes {
|
||||
|
@ -76,6 +76,8 @@ void BoxContent::finishPrepare() {
|
||||
|
||||
void BoxContent::finishScrollCreate() {
|
||||
Expects(_scroll != nullptr);
|
||||
|
||||
_scroll->show();
|
||||
updateScrollAreaGeometry();
|
||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(_scroll, SIGNAL(innerResized()), this, SLOT(onInnerResize()));
|
||||
|
@ -323,7 +323,9 @@ void PasscodeBox::save(bool force) {
|
||||
if (!_oldPasscode->isHidden()) {
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
}
|
||||
auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt | MTPDaccount_passwordInputSettings::Flag::f_new_password_hash | MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_password_hash
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
if (_oldPasscode->isHidden() || _newPasscode->isHidden()) {
|
||||
flags |= MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
}
|
||||
|
@ -923,6 +923,7 @@ bool Messenger::openLocalUrl(const QString &url) {
|
||||
scope,
|
||||
callback,
|
||||
publicKey));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
Telegram/SourceFiles/passport/passport.style
Normal file
39
Telegram/SourceFiles/passport/passport.style
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
using "basic.style";
|
||||
|
||||
using "ui/widgets/widgets.style";
|
||||
using "boxes/boxes.style";
|
||||
using "intro/intro.style";
|
||||
|
||||
passportPasswordPadding: margins(20px, 30px, 20px, 40px);
|
||||
passportPasswordForgotSkip: 5px;
|
||||
passportPasswordAboutSkip: 15px;
|
||||
passportPasswordLabel: FlatLabel(boxLabel) {
|
||||
minWidth: 275px;
|
||||
}
|
||||
passportPasswordHintLabel: passportPasswordLabel;
|
||||
passportErrorLabel: FlatLabel(passportPasswordLabel) {
|
||||
textFg: boxTextFgError;
|
||||
}
|
||||
|
||||
passportRowPadding: margins(20px, 10px, 20px, 10px);
|
||||
passportRowSkip: 5px;
|
||||
passportRowRipple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
passportRowCheckbox: IconButton(defaultIconButton) {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
iconPosition: point(10px, 13px);
|
||||
icon: icon {{ "send_control_save", menuIconFg }};
|
||||
iconOver: icon {{ "send_control_save", menuIconFgOver }};
|
||||
rippleAreaPosition: point(0px, 0px);
|
||||
rippleAreaSize: 38px;
|
||||
ripple: passportRowRipple;
|
||||
}
|
261
Telegram/SourceFiles/passport/passport_form_box.cpp
Normal file
261
Telegram/SourceFiles/passport/passport_form_box.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
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_form_box.h"
|
||||
|
||||
#include "passport/passport_form_controller.h"
|
||||
#include "passport/passport_form_row.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_passport.h"
|
||||
|
||||
namespace Passport {
|
||||
|
||||
class FormBox::CheckWidget : public Ui::RpWidget {
|
||||
public:
|
||||
CheckWidget(QWidget *parent, not_null<FormController*> controller);
|
||||
|
||||
void setInnerFocus();
|
||||
void submit();
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
private:
|
||||
void showError(const QString &error);
|
||||
void hideError();
|
||||
|
||||
not_null<FormController*> _controller;
|
||||
|
||||
object_ptr<Ui::PasswordInput> _password;
|
||||
object_ptr<Ui::FlatLabel> _hint = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _error = { nullptr };
|
||||
object_ptr<Ui::LinkButton> _forgot;
|
||||
object_ptr<Ui::FlatLabel> _about;
|
||||
|
||||
};
|
||||
|
||||
class FormBox::Inner : public Ui::RpWidget {
|
||||
public:
|
||||
Inner(QWidget *parent, not_null<FormController*> controller);
|
||||
|
||||
void refresh();
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
not_null<FormController*> _controller;
|
||||
std::vector<object_ptr<FormRow>> _rows;
|
||||
|
||||
};
|
||||
|
||||
FormBox::CheckWidget::CheckWidget(
|
||||
QWidget *parent,
|
||||
not_null<FormController*> controller)
|
||||
: RpWidget(parent)
|
||||
, _controller(controller)
|
||||
, _password(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
langFactory(lng_passport_password_placeholder))
|
||||
, _forgot(this, lang(lng_signin_recover), st::boxLinkButton)
|
||||
, _about(
|
||||
this,
|
||||
lang(lng_passport_password_request),
|
||||
Ui::FlatLabel::InitType::Simple,
|
||||
st::passportPasswordLabel) {
|
||||
connect(_password, &Ui::PasswordInput::submitted, this, [=] {
|
||||
submit();
|
||||
});
|
||||
connect(_password, &Ui::PasswordInput::changed, this, [=] {
|
||||
hideError();
|
||||
});
|
||||
if (const auto hint = _controller->passwordHint(); !hint.isEmpty()) {
|
||||
_hint.create(
|
||||
this,
|
||||
hint,
|
||||
Ui::FlatLabel::InitType::Simple,
|
||||
st::passportPasswordHintLabel);
|
||||
}
|
||||
_controller->passwordError(
|
||||
) | rpl::start_with_next([=](const QString &error) {
|
||||
showError(error);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void FormBox::CheckWidget::showError(const QString &error) {
|
||||
_password->showError();
|
||||
_error.create(
|
||||
this,
|
||||
error,
|
||||
Ui::FlatLabel::InitType::Simple,
|
||||
st::passportErrorLabel);
|
||||
_error->show();
|
||||
if (_hint) {
|
||||
_hint->hide();
|
||||
}
|
||||
resizeToWidth(width());
|
||||
}
|
||||
|
||||
void FormBox::CheckWidget::hideError() {
|
||||
_error.destroy();
|
||||
if (_hint) {
|
||||
_hint->show();
|
||||
}
|
||||
}
|
||||
|
||||
void FormBox::CheckWidget::submit() {
|
||||
_controller->submitPassword(_password->getLastText());
|
||||
}
|
||||
|
||||
void FormBox::CheckWidget::setInnerFocus() {
|
||||
_password->setFocusFast();
|
||||
}
|
||||
|
||||
int FormBox::CheckWidget::resizeGetHeight(int newWidth) {
|
||||
const auto padding = st::passportPasswordPadding;
|
||||
const auto availableWidth = newWidth
|
||||
- st::boxPadding.left()
|
||||
- st::boxPadding.right();
|
||||
auto top = padding.top();
|
||||
|
||||
_about->resizeToWidth(availableWidth);
|
||||
_about->moveToLeft(padding.left(), top);
|
||||
top += _about->height();
|
||||
|
||||
_password->resize(availableWidth, _password->height());
|
||||
_password->moveToLeft(padding.left(), top);
|
||||
top += _password->height();
|
||||
|
||||
if (_error) {
|
||||
_error->resizeToWidth(availableWidth);
|
||||
_error->moveToLeft(padding.left(), top);
|
||||
}
|
||||
if (_hint) {
|
||||
_hint->resizeToWidth(availableWidth);
|
||||
_hint->moveToLeft(padding.left(), top);
|
||||
top += _hint->height();
|
||||
} else {
|
||||
top += st::passportPasswordHintLabel.style.font->height;
|
||||
}
|
||||
_forgot->moveToLeft(padding.left(), top);
|
||||
top += _forgot->height();
|
||||
return top + padding.bottom();
|
||||
}
|
||||
|
||||
FormBox::Inner::Inner(
|
||||
QWidget *parent,
|
||||
not_null<FormController*> controller)
|
||||
: RpWidget(parent)
|
||||
, _controller(controller) {
|
||||
refresh();
|
||||
}
|
||||
|
||||
void FormBox::Inner::refresh() {
|
||||
auto index = 0;
|
||||
_controller->fillRows([&](
|
||||
QString title,
|
||||
QString description,
|
||||
bool ready) {
|
||||
if (_rows.size() <= index) {
|
||||
_rows.push_back(object_ptr<FormRow>(this, title, description));
|
||||
}
|
||||
_rows[index++]->setReady(ready);
|
||||
});
|
||||
while (_rows.size() > index) {
|
||||
_rows.pop_back();
|
||||
}
|
||||
resizeToWidth(width());
|
||||
}
|
||||
|
||||
int FormBox::Inner::resizeGetHeight(int newWidth) {
|
||||
auto result = 0;
|
||||
for (auto &row : _rows) {
|
||||
row->resizeToWidth(newWidth);
|
||||
row->moveToLeft(0, result);
|
||||
result += row->height();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FormBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
}
|
||||
|
||||
FormBox::FormBox(QWidget*, not_null<FormController*> controller)
|
||||
: _controller(controller) {
|
||||
}
|
||||
|
||||
void FormBox::prepare() {
|
||||
setTitle(langFactory(lng_passport_title));
|
||||
|
||||
addButton(langFactory(lng_create_group_next), [=] {
|
||||
submitPassword();
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [=] {
|
||||
closeBox();
|
||||
});
|
||||
|
||||
_passwordCheck = setInnerWidget(
|
||||
object_ptr<CheckWidget>(this, _controller));
|
||||
_passwordCheck->resizeToWidth(st::boxWideWidth);
|
||||
|
||||
_innerCached.create(this, _controller);
|
||||
_innerCached->resizeToWidth(st::boxWideWidth);
|
||||
const auto desiredHeight = std::min(
|
||||
std::max(_innerCached->height(), _passwordCheck->height()),
|
||||
st::boxMaxListHeight);
|
||||
setDimensions(st::boxWideWidth, desiredHeight);
|
||||
_innerCached->hide();
|
||||
|
||||
_controller->secretReadyEvents(
|
||||
) | rpl::start_with_next([=] {
|
||||
showForm();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void FormBox::setInnerFocus() {
|
||||
if (_passwordCheck) {
|
||||
_passwordCheck->setInnerFocus();
|
||||
} else {
|
||||
_inner->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void FormBox::submitPassword() {
|
||||
Expects(_passwordCheck != nullptr);
|
||||
|
||||
_passwordCheck->submit();
|
||||
}
|
||||
|
||||
void FormBox::showForm() {
|
||||
clearButtons();
|
||||
addButton(langFactory(lng_passport_authorize), [=] {
|
||||
submitForm();
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [=] {
|
||||
closeBox();
|
||||
});
|
||||
|
||||
_inner = setInnerWidget(std::move(_innerCached));
|
||||
_inner->show();
|
||||
}
|
||||
|
||||
void FormBox::submitForm() {
|
||||
|
||||
}
|
||||
|
||||
} // namespace Passport
|
39
Telegram/SourceFiles/passport/passport_form_box.h
Normal file
39
Telegram/SourceFiles/passport/passport_form_box.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
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 "boxes/abstract_box.h"
|
||||
|
||||
namespace Passport {
|
||||
|
||||
class FormController;
|
||||
|
||||
class FormBox : public BoxContent {
|
||||
public:
|
||||
FormBox(QWidget*, not_null<FormController*> controller);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
void setInnerFocus() override;
|
||||
|
||||
private:
|
||||
class CheckWidget;
|
||||
class Inner;
|
||||
|
||||
void submitPassword();
|
||||
void showForm();
|
||||
void submitForm();
|
||||
|
||||
not_null<FormController*> _controller;
|
||||
object_ptr<Inner> _innerCached = { nullptr };
|
||||
QPointer<CheckWidget> _passwordCheck;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Passport
|
@ -7,8 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "passport/passport_form_controller.h"
|
||||
|
||||
#include "passport/passport_form_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "base/openssl_help.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
namespace Passport {
|
||||
@ -42,6 +44,95 @@ void FormController::show() {
|
||||
requestPassword();
|
||||
}
|
||||
|
||||
void FormController::submitPassword(const QString &password) {
|
||||
Expects(!_password.salt.isEmpty());
|
||||
|
||||
if (_passwordCheckRequestId) {
|
||||
return;
|
||||
}
|
||||
const auto data = _password.salt + password.toUtf8() + _password.salt;
|
||||
const auto hash = hashSha256(data.constData(), data.size());
|
||||
_passwordCheckRequestId = request(MTPaccount_GetPasswordSettings(
|
||||
MTP_bytes(gsl::as_bytes(gsl::make_span(hash)))
|
||||
)).handleFloodErrors(
|
||||
).done([=](const MTPaccount_PasswordSettings &result) {
|
||||
Expects(result.type() == mtpc_account_passwordSettings);
|
||||
|
||||
_passwordCheckRequestId = 0;
|
||||
const auto &data = result.c_account_passwordSettings();
|
||||
_passwordEmail = qs(data.vemail);
|
||||
_secret = byteVectorFromMTP(data.vsecure_secret);
|
||||
_secretReady.fire({});
|
||||
}).fail([=](const RPCError &error) {
|
||||
_passwordCheckRequestId = 0;
|
||||
if (MTP::isFloodError(error)) {
|
||||
_passwordError.fire(lang(lng_flood_error));
|
||||
} else if (error.type() == qstr("PASSWORD_HASH_INVALID")) {
|
||||
_passwordError.fire(lang(lng_passport_password_wrong));
|
||||
} else {
|
||||
_passwordError.fire_copy(error.type());
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
rpl::producer<QString> FormController::passwordError() const {
|
||||
return _passwordError.events();
|
||||
}
|
||||
|
||||
QString FormController::passwordHint() const {
|
||||
return _password.hint;
|
||||
}
|
||||
|
||||
rpl::producer<> FormController::secretReadyEvents() const {
|
||||
return _secretReady.events();
|
||||
}
|
||||
|
||||
QString FormController::defaultEmail() const {
|
||||
return _passwordEmail;
|
||||
}
|
||||
|
||||
QString FormController::defaultPhoneNumber() const {
|
||||
if (const auto self = App::self()) {
|
||||
return self->phone();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void FormController::fillRows(
|
||||
base::lambda<void(
|
||||
QString title,
|
||||
QString description,
|
||||
bool ready)> callback) {
|
||||
for (const auto &field : _form.fields) {
|
||||
switch (field.type) {
|
||||
case Field::Type::Identity:
|
||||
callback(
|
||||
lang(lng_passport_identity_title),
|
||||
lang(lng_passport_identity_description),
|
||||
false);
|
||||
break;
|
||||
case Field::Type::Address:
|
||||
callback(
|
||||
lang(lng_passport_address_title),
|
||||
lang(lng_passport_address_description),
|
||||
false);
|
||||
break;
|
||||
case Field::Type::Phone:
|
||||
callback(
|
||||
lang(lng_passport_phone_title),
|
||||
App::self()->phone(),
|
||||
true);
|
||||
break;
|
||||
case Field::Type::Email:
|
||||
callback(
|
||||
lang(lng_passport_email_title),
|
||||
lang(lng_passport_email_description),
|
||||
false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FormController::requestForm() {
|
||||
auto scope = QVector<MTPstring>();
|
||||
scope.reserve(_request.scope.size());
|
||||
@ -51,7 +142,7 @@ void FormController::requestForm() {
|
||||
auto normalizedKey = _request.publicKey;
|
||||
normalizedKey.replace("\r\n", "\n");
|
||||
const auto bytes = normalizedKey.toUtf8();
|
||||
request(MTPaccount_GetAuthorizationForm(
|
||||
_formRequestId = request(MTPaccount_GetAuthorizationForm(
|
||||
MTP_flags(MTPaccount_GetAuthorizationForm::Flag::f_origin
|
||||
| MTPaccount_GetAuthorizationForm::Flag::f_public_key),
|
||||
MTP_int(_request.botId),
|
||||
@ -61,6 +152,7 @@ void FormController::requestForm() {
|
||||
MTPstring(), // bundle_id
|
||||
MTP_bytes(bytes)
|
||||
)).done([=](const MTPaccount_AuthorizationForm &result) {
|
||||
_formRequestId = 0;
|
||||
formDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
formFail(error);
|
||||
@ -117,7 +209,9 @@ auto FormController::convertValue(
|
||||
|
||||
void FormController::formDone(const MTPaccount_AuthorizationForm &result) {
|
||||
parseForm(result);
|
||||
showForm();
|
||||
if (!_passwordRequestId) {
|
||||
showForm();
|
||||
}
|
||||
}
|
||||
|
||||
void FormController::parseForm(const MTPaccount_AuthorizationForm &result) {
|
||||
@ -160,57 +254,57 @@ void FormController::showForm() {
|
||||
Ui::show(Box<InformBox>("Could not get authorization bot."));
|
||||
return;
|
||||
}
|
||||
auto text = QString("Auth request:\n");
|
||||
for (const auto &field : _form.fields) {
|
||||
switch (field.type) {
|
||||
case Field::Type::Identity: text += "- identity\n"; break;
|
||||
case Field::Type::Address: text += "- address\n"; break;
|
||||
case Field::Type::Email: text += "- email\n"; break;
|
||||
case Field::Type::Phone: text += "- phone\n"; break;
|
||||
}
|
||||
}
|
||||
if (_form.requestWrite) {
|
||||
text += "and bot @" + _bot->username + " requests write permission.";
|
||||
} else {
|
||||
text += "and bot @" + _bot->username + " does not request write permission.";
|
||||
}
|
||||
Ui::show(Box<InformBox>(text));
|
||||
// Ui::show(Box<FormBox>(this));
|
||||
Ui::show(Box<FormBox>(this));
|
||||
}
|
||||
|
||||
void FormController::formFail(const RPCError &error) {
|
||||
// #TODO langs
|
||||
Ui::show(Box<InformBox>("Could not get authorization form."));
|
||||
Ui::show(Box<InformBox>(lang(lng_passport_form_error)));
|
||||
}
|
||||
|
||||
void FormController::requestPassword() {
|
||||
request(MTPaccount_GetPassword(
|
||||
_passwordRequestId = request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
_passwordRequestId = 0;
|
||||
passwordDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
formFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void FormController::passwordDone(const MTPaccount_Password &result) {
|
||||
switch (result.type()) {
|
||||
case mtpc_account_noPassword:
|
||||
createPassword(result.c_account_noPassword());
|
||||
parsePassword(result.c_account_noPassword());
|
||||
break;
|
||||
|
||||
case mtpc_account_password:
|
||||
checkPassword(result.c_account_password());
|
||||
parsePassword(result.c_account_password());
|
||||
break;
|
||||
}
|
||||
if (!_formRequestId) {
|
||||
showForm();
|
||||
}
|
||||
}
|
||||
|
||||
void FormController::passwordFail(const RPCError &error) {
|
||||
Ui::show(Box<InformBox>("Could not get authorization form."));
|
||||
}
|
||||
|
||||
void FormController::createPassword(const MTPDaccount_noPassword &result) {
|
||||
Ui::show(Box<InformBox>("You need 2fa password!")); // #TODO
|
||||
void FormController::parsePassword(const MTPDaccount_noPassword &result) {
|
||||
_password.unconfirmedPattern = qs(result.vemail_unconfirmed_pattern);
|
||||
_password.newSalt = result.vnew_salt.v;
|
||||
openssl::AddRandomSeed(
|
||||
gsl::as_bytes(gsl::make_span(result.vsecret_random.v)));
|
||||
}
|
||||
|
||||
void FormController::checkPassword(const MTPDaccount_password &result) {
|
||||
void FormController::parsePassword(const MTPDaccount_password &result) {
|
||||
_password.hint = qs(result.vhint);
|
||||
_password.hasRecovery = mtpIsTrue(result.vhas_recovery);
|
||||
_password.salt = result.vcurrent_salt.v;
|
||||
_password.unconfirmedPattern = qs(result.vemail_unconfirmed_pattern);
|
||||
_password.newSalt = result.vnew_salt.v;
|
||||
openssl::AddRandomSeed(
|
||||
gsl::as_bytes(gsl::make_span(result.vsecret_random.v)));
|
||||
}
|
||||
|
||||
} // namespace Passport
|
||||
|
@ -31,12 +31,32 @@ struct FormRequest {
|
||||
|
||||
class FormController : private MTP::Sender {
|
||||
public:
|
||||
struct PasswordCheckResult {
|
||||
QByteArray secret;
|
||||
|
||||
};
|
||||
|
||||
FormController(
|
||||
not_null<Window::Controller*> controller,
|
||||
const FormRequest &request);
|
||||
|
||||
void show();
|
||||
|
||||
void submitPassword(const QString &password);
|
||||
rpl::producer<QString> passwordError() const;
|
||||
QString passwordHint() const;
|
||||
|
||||
rpl::producer<> secretReadyEvents() const;
|
||||
|
||||
QString defaultEmail() const;
|
||||
QString defaultPhoneNumber() const;
|
||||
|
||||
void fillRows(
|
||||
base::lambda<void(
|
||||
QString title,
|
||||
QString description,
|
||||
bool ready)> callback);
|
||||
|
||||
private:
|
||||
struct File {
|
||||
uint64 id = 0;
|
||||
@ -76,6 +96,13 @@ private:
|
||||
bool requestWrite = false;
|
||||
std::vector<Field> fields;
|
||||
};
|
||||
struct PasswordSettings {
|
||||
QByteArray salt;
|
||||
QByteArray newSalt;
|
||||
QString hint;
|
||||
QString unconfirmedPattern;
|
||||
bool hasRecovery = false;
|
||||
};
|
||||
Value convertValue(const MTPSecureValue &value) const;
|
||||
|
||||
void requestForm();
|
||||
@ -88,16 +115,26 @@ private:
|
||||
|
||||
void passwordDone(const MTPaccount_Password &result);
|
||||
void passwordFail(const RPCError &error);
|
||||
void createPassword(const MTPDaccount_noPassword &settings);
|
||||
void checkPassword(const MTPDaccount_password &settings);
|
||||
void parsePassword(const MTPDaccount_noPassword &settings);
|
||||
void parsePassword(const MTPDaccount_password &settings);
|
||||
|
||||
not_null<Window::Controller*> _controller;
|
||||
FormRequest _request;
|
||||
UserData *_bot = nullptr;
|
||||
QString _origin;
|
||||
|
||||
mtpRequestId _formRequestId = 0;
|
||||
mtpRequestId _passwordRequestId = 0;
|
||||
mtpRequestId _passwordCheckRequestId = 0;
|
||||
|
||||
PasswordSettings _password;
|
||||
Form _form;
|
||||
|
||||
base::byte_vector _secret;
|
||||
QString _passwordEmail;
|
||||
rpl::event_stream<> _secretReady;
|
||||
rpl::event_stream<QString> _passwordError;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Passport
|
||||
|
96
Telegram/SourceFiles/passport/passport_form_row.cpp
Normal file
96
Telegram/SourceFiles/passport/passport_form_row.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
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_form_row.h"
|
||||
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_passport.h"
|
||||
|
||||
namespace Passport {
|
||||
|
||||
FormRow::FormRow(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &description)
|
||||
: RippleButton(parent, st::passportRowRipple)
|
||||
, _title(
|
||||
st::semiboldTextStyle,
|
||||
title,
|
||||
Ui::NameTextOptions(),
|
||||
st::boxWideWidth / 2)
|
||||
, _description(
|
||||
st::defaultTextStyle,
|
||||
description,
|
||||
Ui::NameTextOptions(),
|
||||
st::boxWideWidth / 2) {
|
||||
}
|
||||
|
||||
void FormRow::setReady(bool ready) {
|
||||
if (ready) {
|
||||
_checkbox.create(this, object_ptr<Ui::IconButton>(
|
||||
this,
|
||||
st::passportRowCheckbox));
|
||||
_checkbox->show(anim::type::instant);
|
||||
_checkbox->entity()->addClickHandler([=] {
|
||||
_checkbox->hide(anim::type::normal);
|
||||
});
|
||||
} else {
|
||||
_checkbox.destroy();
|
||||
}
|
||||
resizeToWidth(width());
|
||||
}
|
||||
|
||||
int FormRow::resizeGetHeight(int newWidth) {
|
||||
const auto availableWidth = countAvailableWidth(newWidth);
|
||||
_titleHeight = _title.countHeight(availableWidth);
|
||||
_descriptionHeight = _description.countHeight(availableWidth);
|
||||
const auto result = st::passportRowPadding.top()
|
||||
+ _titleHeight
|
||||
+ st::passportRowSkip
|
||||
+ _descriptionHeight
|
||||
+ st::passportRowPadding.bottom();
|
||||
if (_checkbox) {
|
||||
const auto right = st::passportRowPadding.right();
|
||||
_checkbox->moveToRight(
|
||||
right,
|
||||
(result - _checkbox->height()) / 2,
|
||||
newWidth);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int FormRow::countAvailableWidth(int newWidth) const {
|
||||
return newWidth
|
||||
- st::passportRowPadding.left()
|
||||
- st::passportRowPadding.right()
|
||||
- (_checkbox ? _checkbox->width() : 0);
|
||||
}
|
||||
|
||||
int FormRow::countAvailableWidth() const {
|
||||
return countAvailableWidth(width());
|
||||
}
|
||||
|
||||
void FormRow::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
const auto ms = getms();
|
||||
paintRipple(p, 0, 0, ms);
|
||||
|
||||
const auto left = st::passportRowPadding.left();
|
||||
const auto availableWidth = countAvailableWidth();
|
||||
auto top = st::passportRowPadding.top();
|
||||
|
||||
_title.drawLeft(p, left, top, availableWidth, width());
|
||||
top += _titleHeight + st::passportRowSkip;
|
||||
|
||||
_description.drawLeft(p, left, top, availableWidth, width());
|
||||
top += _descriptionHeight + st::passportRowPadding.bottom();
|
||||
}
|
||||
|
||||
} // namespace Passport
|
45
Telegram/SourceFiles/passport/passport_form_row.h
Normal file
45
Telegram/SourceFiles/passport/passport_form_row.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
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/widgets/buttons.h"
|
||||
|
||||
namespace Ui {
|
||||
template <typename Widget>
|
||||
class FadeWrapScaled;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Passport {
|
||||
|
||||
class FormRow : public Ui::RippleButton {
|
||||
public:
|
||||
FormRow(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &description);
|
||||
|
||||
void setReady(bool ready);
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
int countAvailableWidth() const;
|
||||
int countAvailableWidth(int newWidth) const;
|
||||
|
||||
Text _title;
|
||||
Text _description;
|
||||
int _titleHeight = 0;
|
||||
int _descriptionHeight = 0;
|
||||
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _checkbox = { nullptr };
|
||||
|
||||
};
|
||||
|
||||
} // namespace Passport
|
@ -33,6 +33,7 @@
|
||||
'<(src_loc)/media/view/mediaview.style',
|
||||
'<(src_loc)/media/player/media_player.style',
|
||||
'<(src_loc)/overview/overview.style',
|
||||
'<(src_loc)/passport/passport.style',
|
||||
'<(src_loc)/profile/profile.style',
|
||||
'<(src_loc)/settings/settings.style',
|
||||
'<(src_loc)/chat_helpers/chat_helpers.style',
|
||||
|
@ -454,8 +454,12 @@
|
||||
<(src_loc)/mtproto/type_utils.h
|
||||
<(src_loc)/overview/overview_layout.cpp
|
||||
<(src_loc)/overview/overview_layout.h
|
||||
<(src_loc)/passport/passport_form_box.cpp
|
||||
<(src_loc)/passport/passport_form_box.h
|
||||
<(src_loc)/passport/passport_form_controller.cpp
|
||||
<(src_loc)/passport/passport_form_controller.h
|
||||
<(src_loc)/passport/passport_form_row.cpp
|
||||
<(src_loc)/passport/passport_form_row.h
|
||||
<(src_loc)/platform/linux/linux_desktop_environment.cpp
|
||||
<(src_loc)/platform/linux/linux_desktop_environment.h
|
||||
<(src_loc)/platform/linux/linux_gdk_helper.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user