mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-30 14:08:41 +00:00
Added support of setting up of login email from intro.
This commit is contained in:
@@ -1123,6 +1123,8 @@ PRIVATE
|
|||||||
inline_bots/inline_results_widget.h
|
inline_bots/inline_results_widget.h
|
||||||
intro/intro_code.cpp
|
intro/intro_code.cpp
|
||||||
intro/intro_code.h
|
intro/intro_code.h
|
||||||
|
intro/intro_email.cpp
|
||||||
|
intro/intro_email.h
|
||||||
intro/intro_password_check.cpp
|
intro/intro_password_check.cpp
|
||||||
intro/intro_password_check.h
|
intro/intro_password_check.h
|
||||||
intro/intro_phone.cpp
|
intro/intro_phone.cpp
|
||||||
|
@@ -377,6 +377,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_intro_fragment_about" = "Get the code for {phone_number} in the Anonymous Numbers section on Fragment.";
|
"lng_intro_fragment_about" = "Get the code for {phone_number} in the Anonymous Numbers section on Fragment.";
|
||||||
"lng_intro_fragment_button" = "Open Fragment";
|
"lng_intro_fragment_button" = "Open Fragment";
|
||||||
|
|
||||||
|
"lng_intro_email_setup_title" = "Choose a login email";
|
||||||
|
"lng_intro_email_confirm_subtitle" = "Please check your email {email} (don't forget the spam folder) and enter the code we just sent you.";
|
||||||
|
|
||||||
"lng_phone_title" = "Your Phone Number";
|
"lng_phone_title" = "Your Phone Number";
|
||||||
"lng_phone_desc" = "Please confirm your country code\nand enter your phone number.";
|
"lng_phone_desc" = "Please confirm your country code\nand enter your phone number.";
|
||||||
"lng_phone_to_qr" = "Quick log in using QR code";
|
"lng_phone_to_qr" = "Quick log in using QR code";
|
||||||
|
@@ -84,16 +84,19 @@ void CodeWidget::updateDescText() {
|
|||||||
const auto byTelegram = getData()->codeByTelegram;
|
const auto byTelegram = getData()->codeByTelegram;
|
||||||
const auto isFragment = !getData()->codeByFragmentUrl.isEmpty();
|
const auto isFragment = !getData()->codeByFragmentUrl.isEmpty();
|
||||||
_isFragment = isFragment;
|
_isFragment = isFragment;
|
||||||
setDescriptionText(
|
setDescriptionText(isEmailVerification()
|
||||||
isFragment
|
? tr::lng_intro_email_confirm_subtitle(
|
||||||
? tr::lng_intro_fragment_about(
|
lt_email,
|
||||||
lt_phone_number,
|
rpl::single(Ui::Text::WrapEmailPattern(getData()->emailPattern)),
|
||||||
rpl::single(TextWithEntities{
|
Ui::Text::WithEntities)
|
||||||
.text = Ui::FormatPhone(getData()->phone)
|
: isFragment
|
||||||
}),
|
? tr::lng_intro_fragment_about(
|
||||||
Ui::Text::RichLangValue)
|
lt_phone_number,
|
||||||
: (byTelegram ? tr::lng_code_from_telegram : tr::lng_code_desc)(
|
rpl::single(
|
||||||
Ui::Text::RichLangValue));
|
TextWithEntities::Simple(Ui::FormatPhone(getData()->phone))),
|
||||||
|
Ui::Text::RichLangValue)
|
||||||
|
: (byTelegram ? tr::lng_code_from_telegram : tr::lng_code_desc)(
|
||||||
|
Ui::Text::RichLangValue));
|
||||||
if (getData()->codeByTelegram) {
|
if (getData()->codeByTelegram) {
|
||||||
_noTelegramCode->show();
|
_noTelegramCode->show();
|
||||||
_callTimer.cancel();
|
_callTimer.cancel();
|
||||||
@@ -350,11 +353,13 @@ void CodeWidget::submitCode(const QString &text) {
|
|||||||
_code->setEnabled(false);
|
_code->setEnabled(false);
|
||||||
getData()->pwdState = Core::CloudPasswordState();
|
getData()->pwdState = Core::CloudPasswordState();
|
||||||
_sentRequest = api().request(MTPauth_SignIn(
|
_sentRequest = api().request(MTPauth_SignIn(
|
||||||
MTP_flags(MTPauth_SignIn::Flag::f_phone_code),
|
MTP_flags(isEmailVerification()
|
||||||
|
? MTPauth_SignIn::Flag::f_email_verification
|
||||||
|
: MTPauth_SignIn::Flag::f_phone_code),
|
||||||
MTP_string(getData()->phone),
|
MTP_string(getData()->phone),
|
||||||
MTP_bytes(getData()->phoneHash),
|
MTP_bytes(getData()->phoneHash),
|
||||||
MTP_string(_sentCode),
|
MTP_string(_sentCode),
|
||||||
MTPEmailVerification()
|
MTP_emailVerificationCode(MTP_string(_sentCode))
|
||||||
)).done([=](const MTPauth_Authorization &result) {
|
)).done([=](const MTPauth_Authorization &result) {
|
||||||
codeSubmitDone(result);
|
codeSubmitDone(result);
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
@@ -362,6 +367,10 @@ void CodeWidget::submitCode(const QString &text) {
|
|||||||
}).handleFloodErrors().send();
|
}).handleFloodErrors().send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CodeWidget::isEmailVerification() const {
|
||||||
|
return !getData()->emailPattern.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> CodeWidget::nextButtonText() const {
|
rpl::producer<QString> CodeWidget::nextButtonText() const {
|
||||||
return _isFragment.value(
|
return _isFragment.value(
|
||||||
) | rpl::map([=](bool isFragment) {
|
) | rpl::map([=](bool isFragment) {
|
||||||
|
@@ -54,6 +54,8 @@ private:
|
|||||||
|
|
||||||
int errorTop() const override;
|
int errorTop() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] bool isEmailVerification() const;
|
||||||
|
|
||||||
void updateCallText();
|
void updateCallText();
|
||||||
void refreshLang();
|
void refreshLang();
|
||||||
void updateControlsGeometry();
|
void updateControlsGeometry();
|
||||||
|
173
Telegram/SourceFiles/intro/intro_email.cpp
Normal file
173
Telegram/SourceFiles/intro/intro_email.cpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
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 "intro/intro_email.h"
|
||||||
|
|
||||||
|
#include "intro/intro_code.h"
|
||||||
|
#include "intro/intro_code_input.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "lottie/lottie_icon.h"
|
||||||
|
#include "settings/cloud_password/settings_cloud_password_common.h"
|
||||||
|
#include "settings/settings_common.h" // CreateLottieIcon.
|
||||||
|
#include "ui/rect.h"
|
||||||
|
#include "ui/vertical_list.h"
|
||||||
|
#include "ui/widgets/fields/input_field.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
#include "window/window_controller.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
#include "styles/style_intro.h"
|
||||||
|
#include "styles/style_settings.h"
|
||||||
|
|
||||||
|
namespace Intro {
|
||||||
|
namespace details {
|
||||||
|
|
||||||
|
EmailWidget::EmailWidget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Main::Account*> account,
|
||||||
|
not_null<Data*> data)
|
||||||
|
: Step(parent, account, data)
|
||||||
|
, _inner(this) {
|
||||||
|
const auto content = _inner.get();
|
||||||
|
widthValue() | rpl::start_with_next([=](int w) {
|
||||||
|
content->resizeToWidth(st::introNextButton.width);
|
||||||
|
content->moveToLeft((w - content->width()) / 2, contentTop());
|
||||||
|
}, content->lifetime());
|
||||||
|
|
||||||
|
content->add(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
content,
|
||||||
|
tr::lng_intro_email_setup_title(),
|
||||||
|
st::introTitle),
|
||||||
|
style::margins(),
|
||||||
|
style::al_left);
|
||||||
|
Ui::AddSkip(content, st::lineWidth * 2);
|
||||||
|
content->add(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
content,
|
||||||
|
tr::lng_settings_cloud_login_email_about(),
|
||||||
|
st::introDescription),
|
||||||
|
style::margins(),
|
||||||
|
style::al_left);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto lottie = u"cloud_password/email"_q;
|
||||||
|
const auto size = st::settingsCloudPasswordIconSize / 3 * 2;
|
||||||
|
auto icon = Settings::CreateLottieIcon(
|
||||||
|
content,
|
||||||
|
{ .name = lottie, .sizeOverride = Size(size) },
|
||||||
|
style::margins());
|
||||||
|
content->add(std::move(icon.widget));
|
||||||
|
_showFinished.events(
|
||||||
|
) | rpl::start_with_next([animate = std::move(icon.animate)] {
|
||||||
|
animate(anim::repeat::once);
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto wrap = Settings::CloudPassword::AddWrappedField(
|
||||||
|
content,
|
||||||
|
tr::lng_settings_cloud_login_email_placeholder(),
|
||||||
|
QString());
|
||||||
|
const auto newInput = wrap->entity();
|
||||||
|
Ui::AddSkip(content);
|
||||||
|
const auto error = Settings::CloudPassword::AddError(content, nullptr);
|
||||||
|
newInput->changes() | rpl::start_with_next([=] {
|
||||||
|
error->hide();
|
||||||
|
}, newInput->lifetime());
|
||||||
|
newInput->setText(getData()->email);
|
||||||
|
if (newInput->hasText()) {
|
||||||
|
newInput->selectAll();
|
||||||
|
}
|
||||||
|
_setFocus.events() | rpl::start_with_next([=] {
|
||||||
|
newInput->setFocus();
|
||||||
|
}, newInput->lifetime());
|
||||||
|
|
||||||
|
_submitCallback = [=] {
|
||||||
|
const auto send = [=](const QString &email) {
|
||||||
|
getData()->email = email;
|
||||||
|
|
||||||
|
const auto done = [=](int length, const QString &pattern) {
|
||||||
|
_sentRequest = 0;
|
||||||
|
getData()->codeLength = length;
|
||||||
|
getData()->emailPattern = pattern;
|
||||||
|
goNext<CodeWidget>();
|
||||||
|
};
|
||||||
|
const auto fail = [=](const QString &type) {
|
||||||
|
_sentRequest = 0;
|
||||||
|
|
||||||
|
newInput->setFocus();
|
||||||
|
newInput->showError();
|
||||||
|
newInput->selectAll();
|
||||||
|
error->show();
|
||||||
|
|
||||||
|
if (MTP::IsFloodError(type)) {
|
||||||
|
error->setText(tr::lng_flood_error(tr::now));
|
||||||
|
} else if (type == u"EMAIL_NOT_ALLOWED"_q) {
|
||||||
|
error->setText(
|
||||||
|
tr::lng_settings_error_email_not_alowed(tr::now));
|
||||||
|
} else if (type == u"EMAIL_INVALID"_q) {
|
||||||
|
error->setText(tr::lng_cloud_password_bad_email(tr::now));
|
||||||
|
} else if (type == u"EMAIL_HASH_EXPIRED"_q) {
|
||||||
|
// Show box?
|
||||||
|
error->setText(Lang::Hard::EmailConfirmationExpired());
|
||||||
|
} else {
|
||||||
|
error->setText(Lang::Hard::ServerError());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_sentRequest = api().request(MTPaccount_SendVerifyEmailCode(
|
||||||
|
MTP_emailVerifyPurposeLoginSetup(
|
||||||
|
MTP_string(getData()->phone),
|
||||||
|
MTP_bytes(getData()->phoneHash)),
|
||||||
|
MTP_string(email)
|
||||||
|
)).done([=](const MTPaccount_SentEmailCode &result) {
|
||||||
|
done(
|
||||||
|
result.data().vlength().v,
|
||||||
|
qs(result.data().vemail_pattern()));
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
fail(error.type());
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
const auto newText = newInput->getLastText();
|
||||||
|
if (newText.isEmpty()) {
|
||||||
|
newInput->setFocus();
|
||||||
|
newInput->showError();
|
||||||
|
} else {
|
||||||
|
send(newText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailWidget::submit() {
|
||||||
|
if (_submitCallback) {
|
||||||
|
_submitCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailWidget::setInnerFocus() {
|
||||||
|
_setFocus.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailWidget::activate() {
|
||||||
|
Step::activate();
|
||||||
|
showChildren();
|
||||||
|
setInnerFocus();
|
||||||
|
_showFinished.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailWidget::finished() {
|
||||||
|
Step::finished();
|
||||||
|
cancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailWidget::cancelled() {
|
||||||
|
api().request(base::take(_sentRequest)).cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace details
|
||||||
|
} // namespace Intro
|
50
Telegram/SourceFiles/intro/intro_email.h
Normal file
50
Telegram/SourceFiles/intro/intro_email.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
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 "intro/intro_step.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class VerticalLayout;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace MTP {
|
||||||
|
class Sender;
|
||||||
|
} // namespace MTP
|
||||||
|
|
||||||
|
namespace Intro {
|
||||||
|
namespace details {
|
||||||
|
|
||||||
|
class EmailWidget final : public Step {
|
||||||
|
public:
|
||||||
|
EmailWidget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Main::Account*> account,
|
||||||
|
not_null<Data*> data);
|
||||||
|
|
||||||
|
void setInnerFocus() override;
|
||||||
|
void activate() override;
|
||||||
|
void finished() override;
|
||||||
|
void cancelled() override;
|
||||||
|
void submit() override;
|
||||||
|
|
||||||
|
bool hasBack() const override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
object_ptr<Ui::VerticalLayout> _inner;
|
||||||
|
Fn<void()> _submitCallback = nullptr;
|
||||||
|
rpl::event_stream<> _showFinished;
|
||||||
|
rpl::event_stream<> _setFocus;
|
||||||
|
mtpRequestId _sentRequest = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace details
|
||||||
|
} // namespace Intro
|
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "intro/intro_code.h"
|
#include "intro/intro_code.h"
|
||||||
|
#include "intro/intro_email.h"
|
||||||
#include "intro/intro_qr.h"
|
#include "intro/intro_qr.h"
|
||||||
#include "styles/style_intro.h"
|
#include "styles/style_intro.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
@@ -237,6 +238,9 @@ void PhoneWidget::phoneSubmitDone(const MTPauth_SentCode &result) {
|
|||||||
fillSentCodeData(data);
|
fillSentCodeData(data);
|
||||||
getData()->phone = DigitsOnly(_sentPhone);
|
getData()->phone = DigitsOnly(_sentPhone);
|
||||||
getData()->phoneHash = qba(data.vphone_code_hash());
|
getData()->phoneHash = qba(data.vphone_code_hash());
|
||||||
|
if (getData()->emailStatus == EmailStatus::SetupRequired) {
|
||||||
|
return goNext<EmailWidget>();
|
||||||
|
}
|
||||||
const auto next = data.vnext_type();
|
const auto next = data.vnext_type();
|
||||||
if (next && next->type() == mtpc_auth_codeTypeCall) {
|
if (next && next->type() == mtpc_auth_codeTypeCall) {
|
||||||
getData()->callStatus = CallStatus::Waiting;
|
getData()->callStatus = CallStatus::Waiting;
|
||||||
|
@@ -375,7 +375,7 @@ void Step::fillSentCodeData(const MTPDauth_sentCode &data) {
|
|||||||
}, [&](const MTPDauth_sentCodeTypeSmsPhrase &) {
|
}, [&](const MTPDauth_sentCodeTypeSmsPhrase &) {
|
||||||
bad("SmsPhrase");
|
bad("SmsPhrase");
|
||||||
}, [&](const MTPDauth_sentCodeTypeSetUpEmailRequired &) {
|
}, [&](const MTPDauth_sentCodeTypeSetUpEmailRequired &) {
|
||||||
bad("SetUpEmailRequired");
|
getData()->emailStatus = EmailStatus::SetupRequired;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,11 @@ enum class CallStatus {
|
|||||||
Disabled,
|
Disabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class EmailStatus {
|
||||||
|
None,
|
||||||
|
SetupRequired,
|
||||||
|
};
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
// Required for the UserpicButton.
|
// Required for the UserpicButton.
|
||||||
const not_null<Window::Controller*> controller;
|
const not_null<Window::Controller*> controller;
|
||||||
@@ -58,6 +63,10 @@ struct Data {
|
|||||||
bool codeByTelegram = false;
|
bool codeByTelegram = false;
|
||||||
QString codeByFragmentUrl;
|
QString codeByFragmentUrl;
|
||||||
|
|
||||||
|
EmailStatus emailStatus = EmailStatus::None;
|
||||||
|
QString email;
|
||||||
|
QString emailPattern;
|
||||||
|
|
||||||
Core::CloudPasswordState pwdState;
|
Core::CloudPasswordState pwdState;
|
||||||
|
|
||||||
Window::TermsLock termsLock;
|
Window::TermsLock termsLock;
|
||||||
|
Reference in New Issue
Block a user