/* 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 "mtproto/sender.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" #include "window/window_lock_widgets.h" #include "core/core_cloud_password.h" namespace Main { class Account; } // namespace Main namespace Ui { class IconButton; class RoundButton; class LinkButton; class SlideAnimation; class CrossFadeAnimation; class FlatLabel; template class FadeWrap; } // namespace Ui namespace Window { class ConnectionState; } // namespace Window namespace Intro { class Widget : public Ui::RpWidget, private MTP::Sender, private base::Subscriber { Q_OBJECT public: Widget(QWidget *parent, not_null account); void showAnimated(const QPixmap &bgAnimCache, bool back = false); void setInnerFocus(); ~Widget(); protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void keyPressEvent(QKeyEvent *e) override; signals: void countryChanged(); private slots: void onCheckUpdateStatus(); // Internal interface. public: struct Data { QString country; QString phone; QByteArray phoneHash; enum class CallStatus { Waiting, Calling, Called, Disabled, }; CallStatus callStatus = CallStatus::Disabled; int callTimeout = 0; int codeLength = 5; bool codeByTelegram = false; Core::CloudPasswordCheckRequest pwdRequest; bool hasRecovery = false; QString pwdHint; bool pwdNotEmptyPassport = false; Window::TermsLock termsLock; base::Observable updated; }; enum class Direction { Back, Forward, Replace, }; class Step : public Ui::RpWidget, public RPCSender, protected base::Subscriber { public: Step( QWidget *parent, not_null account, not_null data, bool hasCover = false); Main::Account &account() const { return *_account; } virtual void finishInit() { } virtual void setInnerFocus() { setFocus(); } void setGoCallback( Fn callback); void setShowResetCallback(Fn callback); void setShowTermsCallback( Fn callback); void setAcceptTermsCallback( Fn callback)> callback); void prepareShowAnimated(Step *after); void showAnimated(Direction direction); void showFast(); bool animating() const; bool hasCover() const; virtual bool hasBack() const; virtual void activate(); virtual void cancelled(); virtual void finished(); virtual void submit() = 0; virtual rpl::producer nextButtonText() const; int contentLeft() const; int contentTop() const; void setErrorCentered(bool centered); void setErrorBelowLink(bool below); void showError(rpl::producer text); void hideError() { showError(rpl::single(QString())); } ~Step(); protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void setTitleText(rpl::producer titleText); void setDescriptionText(rpl::producer descriptionText); void setDescriptionText( rpl::producer richDescriptionText); bool paintAnimated(Painter &p, QRect clip); void fillSentCodeData(const MTPDauth_sentCode &type); void showDescription(); void hideDescription(); not_null getData() const { return _data; } void finish(const MTPUser &user, QImage &&photo = QImage()); void goBack() { if (_goCallback) { _goCallback(nullptr, Direction::Back); } } template void goNext() { if (_goCallback) { _goCallback( new StepType(parentWidget(), _account, _data), Direction::Forward); } } template void goReplace() { if (_goCallback) { _goCallback( new StepType(parentWidget(), _account, _data), Direction::Replace); } } void showResetButton() { if (_showResetCallback) _showResetCallback(); } void showTerms() { if (_showTermsCallback) _showTermsCallback(); } void acceptTerms(Fn callback) { if (_acceptTermsCallback) { _acceptTermsCallback(callback); } } private: struct CoverAnimation { CoverAnimation() = default; CoverAnimation(CoverAnimation &&other) = default; CoverAnimation &operator=(CoverAnimation &&other) = default; ~CoverAnimation(); std::unique_ptr title; std::unique_ptr description; // From content top till the next button top. QPixmap contentSnapshotWas; QPixmap contentSnapshotNow; }; void updateLabelsPosition(); void paintContentSnapshot(Painter &p, const QPixmap &snapshot, float64 alpha, float64 howMuchHidden); void refreshError(const QString &text); CoverAnimation prepareCoverAnimation(Step *step); QPixmap prepareContentSnapshot(); QPixmap prepareSlideAnimation(); void showFinished(); void prepareCoverMask(); void paintCover(Painter &p, int top); const not_null _account; const not_null _data; bool _hasCover = false; Fn _goCallback; Fn _showResetCallback; Fn _showTermsCallback; Fn callback)> _acceptTermsCallback; rpl::variable _titleText; object_ptr _title; rpl::variable _descriptionText; object_ptr> _description; bool _errorCentered = false; bool _errorBelowLink = false; rpl::variable _errorText; object_ptr> _error = { nullptr }; Ui::Animations::Simple _a_show; CoverAnimation _coverAnimation; std::unique_ptr _slideAnimation; QPixmap _coverMask; }; private: void setupConnectingWidget(); void refreshLang(); void animationCallback(); void createLanguageLink(); void updateControlsGeometry(); not_null getData() { return &_data; } void fixOrder(); void showControls(); void hideControls(); QRect calculateStepRect() const; void showResetButton(); void resetAccount(); void showTerms(); void acceptTerms(Fn callback); void hideAndDestroy(object_ptr> widget); Step *getStep(int skip = 0) { Assert(_stepHistory.size() + skip > 0); return _stepHistory.at(_stepHistory.size() - skip - 1); } void historyMove(Direction direction); void moveToStep(Step *step, Direction direction); void appendStep(Step *step); void getNearestDC(); void showTerms(Fn callback); not_null _account; Ui::Animations::Simple _a_show; bool _showBack = false; QPixmap _cacheUnder, _cacheOver; QVector _stepHistory; Data _data; Ui::Animations::Simple _coverShownAnimation; int _nextTopFrom = 0; int _controlsTopFrom = 0; object_ptr> _back; object_ptr> _update = { nullptr }; object_ptr> _settings; object_ptr _next; object_ptr> _changeLanguage = { nullptr }; object_ptr> _resetAccount = { nullptr }; object_ptr> _terms = { nullptr }; std::unique_ptr _connecting; mtpRequestId _resetRequest = 0; }; } // namespace Intro