/* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once #include "mtproto/sender.h" namespace Ui { class IconButton; class RoundButton; class LinkButton; class SlideAnimation; class CrossFadeAnimation; class FlatLabel; template class FadeWrap; } // namespace Ui namespace Intro { class Widget : public TWidget, 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(); #ifndef TDESKTOP_DISABLE_AUTOUPDATE private slots: void onCheckUpdateStatus(); #endif // TDESKTOP_DISABLE_AUTOUPDATE // 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; QByteArray pwdSalt; bool hasRecovery = false; QString pwdHint; 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 setInnerFocus() { setFocus(); } void setGoCallback(base::lambda callback); void setShowResetCallback(base::lambda 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(base::lambda textFactory); void hideError() { showError(base::lambda()); } ~Step(); protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void setTitleText(base::lambda richTitleTextFactory); void setDescriptionText(base::lambda richDescriptionTextFactory); bool paintAnimated(Painter &p, QRect clip); void fillSentCodeData(const MTPauth_SentCodeType &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(); } 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; base::lambda _goCallback; base::lambda _showResetCallback; object_ptr _title; base::lambda _titleTextFactory; object_ptr> _description; base::lambda _descriptionTextFactory; bool _errorCentered = false; bool _errorBelowLink = false; base::lambda _errorTextFactory; object_ptr> _error = { nullptr }; Animation _a_show; CoverAnimation _coverAnimation; std::unique_ptr _slideAnimation; QPixmap _coverMask; }; private: 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(); 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(); 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 }; mtpRequestId _resetRequest = 0; }; } // namespace Intro