/* 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 "window/window_lock_widgets.h" #include "core/core_cloud_password.h" 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); 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; bool phoneIsRegistered = false; enum class CallStatus { Waiting, Calling, Called, Disabled, }; CallStatus callStatus = CallStatus::Disabled; int callTimeout = 0; QString code; 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 TWidget, public RPCSender, protected base::Subscriber { public: Step(QWidget *parent, Data *data, bool hasCover = false); 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 QString nextButtonText() const; int contentLeft() const; int contentTop() const; void setErrorCentered(bool centered); void setErrorBelowLink(bool below); void showError(Fn textFactory); void hideError() { showError(Fn()); } ~Step(); protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void setTitleText(Fn richTitleTextFactory); void setDescriptionText(Fn richDescriptionTextFactory); bool paintAnimated(Painter &p, QRect clip); void fillSentCodeData(const MTPDauth_sentCode &type); void showDescription(); void hideDescription(); Data *getData() const { return _data; } void finish(const MTPUser &user, QImage &&photo = QImage()); void goBack() { if (_goCallback) _goCallback(nullptr, Direction::Back); } void goNext(Step *step) { if (_goCallback) _goCallback(step, Direction::Forward); } void goReplace(Step *step) { if (_goCallback) _goCallback(step, 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(); void refreshTitle(); void refreshDescription(); void refreshLang(); CoverAnimation prepareCoverAnimation(Step *step); QPixmap prepareContentSnapshot(); QPixmap prepareSlideAnimation(); void showFinished(); void prepareCoverMask(); void paintCover(Painter &p, int top); Data *_data = nullptr; bool _hasCover = false; Fn _goCallback; Fn _showResetCallback; Fn _showTermsCallback; Fn callback)> _acceptTermsCallback; object_ptr _title; Fn _titleTextFactory; object_ptr> _description; Fn _descriptionTextFactory; bool _errorCentered = false; bool _errorBelowLink = false; Fn _errorTextFactory; object_ptr> _error = { nullptr }; Animation _a_show; CoverAnimation _coverAnimation; std::unique_ptr _slideAnimation; QPixmap _coverMask; }; private: void setupConnectingWidget(); void refreshLang(); void animationCallback(); void createLanguageLink(); void updateControlsGeometry(); Data *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); Animation _a_show; bool _showBack = false; QPixmap _cacheUnder, _cacheOver; QVector _stepHistory; Data _data; Animation _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