diff --git a/Telegram/Resources/icons/fragment.png b/Telegram/Resources/icons/fragment.png new file mode 100644 index 000000000..d56b3eaac Binary files /dev/null and b/Telegram/Resources/icons/fragment.png differ diff --git a/Telegram/Resources/icons/fragment@2x.png b/Telegram/Resources/icons/fragment@2x.png new file mode 100644 index 000000000..453b4b2b8 Binary files /dev/null and b/Telegram/Resources/icons/fragment@2x.png differ diff --git a/Telegram/Resources/icons/fragment@3x.png b/Telegram/Resources/icons/fragment@3x.png new file mode 100644 index 000000000..154c121c5 Binary files /dev/null and b/Telegram/Resources/icons/fragment@3x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 5f642ad10..3f1ed5c03 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -323,6 +323,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_intro_qr_step3" = "Scan this image to Log In"; "lng_intro_qr_skip" = "Or log in using your phone number"; +"lng_intro_fragment_title" = "Enter code"; +"lng_intro_fragment_about" = "Get the code for {phone_number} in the Anonymous Numbers section on Fragment."; +"lng_intro_fragment_button" = "Open Fragment"; + "lng_phone_title" = "Your Phone Number"; "lng_phone_desc" = "Please confirm your country code and\nenter your mobile phone number."; "lng_phone_to_qr" = "Quick log in using QR code"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 2710e2fe7..5f736325b 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -293,6 +293,13 @@ membersAbout: FlatLabel(defaultFlatLabel) { style: boxLabelStyle; } +fragmentBoxButton: RoundButton(introNextButton) { + width: 256px; + icon: icon {{ "fragment", activeButtonFg }}; + iconOver: icon {{ "fragment", activeButtonFgOver }}; + iconPosition: point(-10px, 9px); +} + passcodeHeaderFont: font(19px); passcodeHeaderHeight: 80px; passcodeInput: InputField(introPhone) { diff --git a/Telegram/SourceFiles/intro/intro.style b/Telegram/SourceFiles/intro/intro.style index c05508bc5..f6381e444 100644 --- a/Telegram/SourceFiles/intro/intro.style +++ b/Telegram/SourceFiles/intro/intro.style @@ -85,6 +85,7 @@ introCoverDuration: 200; introNextButton: RoundButton(defaultActiveButton) { width: 300px; height: 42px; + radius: 6px; textTop: 11px; font: font(boxFontSize semibold); } diff --git a/Telegram/SourceFiles/intro/intro_code.cpp b/Telegram/SourceFiles/intro/intro_code.cpp index 2932decb5..3d4eab1ac 100644 --- a/Telegram/SourceFiles/intro/intro_code.cpp +++ b/Telegram/SourceFiles/intro/intro_code.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "intro/intro_signup.h" #include "intro/intro_password_check.h" +#include "core/file_utilities.h" #include "core/update_checker.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" @@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_account.h" #include "mtproto/mtp_instance.h" #include "styles/style_intro.h" +#include "styles/style_boxes.h" namespace Intro { namespace details { @@ -99,7 +101,9 @@ CodeWidget::CodeWidget( _code->setDigitsCountMax(getData()->codeLength); - setTitleText(rpl::single(Ui::FormatPhone(getData()->phone))); + setTitleText(getData()->codeByFragmentUrl.isEmpty() + ? rpl::single(Ui::FormatPhone(getData()->phone)) + : tr::lng_intro_fragment_title()); updateDescText(); } @@ -117,10 +121,19 @@ int CodeWidget::errorTop() const { void CodeWidget::updateDescText() { const auto byTelegram = getData()->codeByTelegram; + const auto isFragment = !getData()->codeByFragmentUrl.isEmpty(); setDescriptionText( - (byTelegram ? tr::lng_code_from_telegram : tr::lng_code_desc)( - Ui::Text::RichLangValue)); - if (getData()->codeByTelegram) { + isFragment + ? tr::lng_intro_fragment_about( + lt_phone_number, + rpl::single(TextWithEntities{ + .text = Ui::FormatPhone(getData()->phone) + }), + Ui::Text::RichLangValue) + : (byTelegram ? tr::lng_code_from_telegram : tr::lng_code_desc)( + Ui::Text::RichLangValue)); + if (isFragment) { + } else if (getData()->codeByTelegram) { _noTelegramCode->show(); _callTimer.cancel(); } else { @@ -300,7 +313,7 @@ void CodeWidget::codeSubmitFail(const MTP::Error &error) { void CodeWidget::codeChanged() { hideError(); - submit(); + submitCode(); } void CodeWidget::sendCall() { @@ -362,6 +375,14 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) { } void CodeWidget::submit() { + if (getData()->codeByFragmentUrl.isEmpty()) { + submitCode(); + } else { + File::OpenUrl(getData()->codeByFragmentUrl); + } +} + +void CodeWidget::submitCode() { const auto text = QString( _code->getLastText() ).remove( @@ -393,6 +414,18 @@ void CodeWidget::submit() { }).handleFloodErrors().send(); } +rpl::producer<QString> CodeWidget::nextButtonText() const { + return getData()->codeByFragmentUrl.isEmpty() + ? Step::nextButtonText() + : tr::lng_intro_fragment_button(); +} + +const style::RoundButton *CodeWidget::nextButtonStyle() const { + return !getData()->codeByFragmentUrl.isEmpty() + ? &st::fragmentBoxButton + : nullptr; +} + void CodeWidget::noTelegramCode() { if (_noTelegramCodeRequestId) { return; diff --git a/Telegram/SourceFiles/intro/intro_code.h b/Telegram/SourceFiles/intro/intro_code.h index d267c477d..95ae597a1 100644 --- a/Telegram/SourceFiles/intro/intro_code.h +++ b/Telegram/SourceFiles/intro/intro_code.h @@ -55,6 +55,8 @@ public: void finished() override; void cancelled() override; void submit() override; + rpl::producer<QString> nextButtonText() const override; + const style::RoundButton *nextButtonStyle() const override; void updateDescText(); @@ -83,6 +85,8 @@ private: void noTelegramCodeDone(const MTPauth_SentCode &result); void noTelegramCodeFail(const MTP::Error &result); + void submitCode(); + void stopCheck(); object_ptr<Ui::LinkButton> _noTelegramCode; diff --git a/Telegram/SourceFiles/intro/intro_step.cpp b/Telegram/SourceFiles/intro/intro_step.cpp index 9162775d1..68ff6b40f 100644 --- a/Telegram/SourceFiles/intro/intro_step.cpp +++ b/Telegram/SourceFiles/intro/intro_step.cpp @@ -119,6 +119,10 @@ rpl::producer<QString> Step::nextButtonText() const { return tr::lng_intro_next(); } +const style::RoundButton *Step::nextButtonStyle() const { + return nullptr; +} + void Step::goBack() { if (_goCallback) { _goCallback(nullptr, StackAction::Back, Animate::Back); diff --git a/Telegram/SourceFiles/intro/intro_step.h b/Telegram/SourceFiles/intro/intro_step.h index 2148e6e94..256396bf2 100644 --- a/Telegram/SourceFiles/intro/intro_step.h +++ b/Telegram/SourceFiles/intro/intro_step.h @@ -12,6 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "ui/effects/animations.h" +namespace style { +struct RoundButton; +} // namespace style; + namespace Main { class Account; } // namespace Main; @@ -77,6 +81,7 @@ public: virtual void submit() = 0; [[nodiscard]] virtual rpl::producer<QString> nextButtonText() const; + [[nodiscard]] virtual const style::RoundButton *nextButtonStyle() const; [[nodiscard]] int contentLeft() const; [[nodiscard]] int contentTop() const; diff --git a/Telegram/SourceFiles/intro/intro_widget.cpp b/Telegram/SourceFiles/intro/intro_widget.cpp index 6e1f427ad..e90cf82d0 100644 --- a/Telegram/SourceFiles/intro/intro_widget.cpp +++ b/Telegram/SourceFiles/intro/intro_widget.cpp @@ -74,6 +74,7 @@ Widget::Widget( : RpWidget(parent) , _account(account) , _data(details::Data{ .controller = controller }) +, _nextStyle(&st::introNextButton) , _back(this, object_ptr<Ui::IconButton>(this, st::introBackButton)) , _settings( this, @@ -83,7 +84,7 @@ Widget::Widget( st::defaultBoxButton)) , _next( this, - object_ptr<Ui::RoundButton>(this, nullptr, st::introNextButton)) + object_ptr<Ui::RoundButton>(this, nullptr, *_nextStyle)) , _connecting(std::make_unique<Window::ConnectionState>( this, account, @@ -127,10 +128,6 @@ Widget::Widget( _back->entity()->setClickedCallback([=] { backRequested(); }); _back->hide(anim::type::instant); - _next->entity()->setClickedCallback([=] { getStep()->submit(); }); - _next->entity()->setTextTransform( - Ui::RoundButton::TextTransform::NoTransform); - if (_changeLanguage) { _changeLanguage->finishAnimating(); } @@ -344,13 +341,31 @@ void Widget::historyMove(StackAction action, Animate animate) { if (_terms) { hideAndDestroy(std::exchange(_terms, { nullptr })); } + { + const auto st = getStep()->nextButtonStyle(); + const auto nextStyle = st ? st : &st::introNextButton; + if (_nextStyle != nextStyle) { + _nextStyle = nextStyle; + _next = nullptr; + _next.create( + this, + object_ptr<Ui::RoundButton>(this, nullptr, *nextStyle)); + showControls(); + updateControlsGeometry(); + } + } getStep()->finishInit(); getStep()->prepareShowAnimated(wasStep); if (wasStep->hasCover() != getStep()->hasCover()) { _nextTopFrom = wasStep->contentTop() + st::introNextTop; _controlsTopFrom = wasStep->hasCover() ? st::introCoverHeight : 0; - _coverShownAnimation.start([this] { updateControlsGeometry(); }, 0., 1., st::introCoverDuration, wasStep->hasCover() ? anim::linear : anim::easeOutCirc); + _coverShownAnimation.start( + [this] { updateControlsGeometry(); }, + 0., + 1., + st::introCoverDuration, + wasStep->hasCover() ? anim::linear : anim::easeOutCirc); } _stepLifetime.destroy(); @@ -665,6 +680,10 @@ void Widget::showControls() { } void Widget::setupNextButton() { + _next->entity()->setClickedCallback([=] { getStep()->submit(); }); + _next->entity()->setTextTransform( + Ui::RoundButton::TextTransform::NoTransform); + _next->entity()->setText(getStep()->nextButtonText( ) | rpl::filter([](const QString &text) { return !text.isEmpty(); @@ -757,13 +776,18 @@ void Widget::resizeEvent(QResizeEvent *e) { } void Widget::updateControlsGeometry() { - auto shown = _coverShownAnimation.value(1.); + const auto skip = st::introSettingsSkip; + const auto shown = _coverShownAnimation.value(1.); - auto controlsTopTo = getStep()->hasCover() ? st::introCoverHeight : 0; - auto controlsTop = anim::interpolate(_controlsTopFrom, controlsTopTo, shown); - _settings->moveToRight(st::introSettingsSkip, controlsTop + st::introSettingsSkip); + const auto controlsTop = anim::interpolate( + _controlsTopFrom, + getStep()->hasCover() ? st::introCoverHeight : 0, + shown); + _settings->moveToRight(skip, controlsTop + skip); if (_update) { - _update->moveToRight(st::introSettingsSkip + _settings->width() + st::introSettingsSkip, _settings->y()); + _update->moveToRight( + skip + _settings->width() + skip, + _settings->y()); } _back->moveToLeft(0, controlsTop); @@ -779,13 +803,19 @@ void Widget::updateControlsGeometry() { ? QRect(0, 0, width(), realNextTop) : QRect()); if (_changeLanguage) { - _changeLanguage->moveToLeft((width() - _changeLanguage->width()) / 2, _next->y() + _next->height() + _changeLanguage->height()); + _changeLanguage->moveToLeft( + (width() - _changeLanguage->width()) / 2, + _next->y() + _next->height() + _changeLanguage->height()); } if (_resetAccount) { - _resetAccount->moveToLeft((width() - _resetAccount->width()) / 2, height() - st::introResetBottom - _resetAccount->height()); + _resetAccount->moveToLeft( + (width() - _resetAccount->width()) / 2, + height() - st::introResetBottom - _resetAccount->height()); } if (_terms) { - _terms->moveToLeft((width() - _terms->width()) / 2, height() - st::introTermsBottom - _terms->height()); + _terms->moveToLeft( + (width() - _terms->width()) / 2, + height() - st::introTermsBottom - _terms->height()); } } diff --git a/Telegram/SourceFiles/intro/intro_widget.h b/Telegram/SourceFiles/intro/intro_widget.h index e40d914c9..ef224b831 100644 --- a/Telegram/SourceFiles/intro/intro_widget.h +++ b/Telegram/SourceFiles/intro/intro_widget.h @@ -186,6 +186,8 @@ private: int _nextTopFrom = 0; int _controlsTopFrom = 0; + const style::RoundButton *_nextStyle = nullptr; + object_ptr<Ui::FadeWrap<Ui::IconButton>> _back; object_ptr<Ui::FadeWrap<Ui::RoundButton>> _update = { nullptr }; object_ptr<Ui::FadeWrap<Ui::RoundButton>> _settings;