1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9 
10 #include "base/object_ptr.h"
11 #include "mtproto/sender.h"
12 #include "ui/rp_widget.h"
13 #include "ui/effects/animations.h"
14 
15 namespace Main {
16 class Account;
17 } // namespace Main;
18 
19 namespace Ui {
20 class SlideAnimation;
21 class CrossFadeAnimation;
22 class FlatLabel;
23 template <typename Widget>
24 class FadeWrap;
25 } // namespace Ui
26 
27 namespace Intro {
28 namespace details {
29 
30 struct Data;
31 enum class StackAction;
32 enum class Animate;
33 
34 class Step : public Ui::RpWidget {
35 public:
36 	Step(
37 		QWidget *parent,
38 		not_null<Main::Account*> account,
39 		not_null<Data*> data,
40 		bool hasCover = false);
41 	~Step();
42 
account()43 	[[nodiscard]] Main::Account &account() const {
44 		return *_account;
45 	}
46 
47 	// It should not be called in StartWidget, in other steps it should be
48 	// present and not changing.
49 	[[nodiscard]] MTP::Sender &api() const;
50 	void apiClear();
51 
finishInit()52 	virtual void finishInit() {
53 	}
setInnerFocus()54 	virtual void setInnerFocus() {
55 		setFocus();
56 	}
57 
58 	void setGoCallback(
59 		Fn<void(Step *step, StackAction action, Animate animate)> callback);
60 	void setShowResetCallback(Fn<void()> callback);
61 	void setShowTermsCallback(Fn<void()> callback);
62 	void setCancelNearestDcCallback(Fn<void()> callback);
63 	void setAcceptTermsCallback(
64 		Fn<void(Fn<void()> callback)> callback);
65 
66 	void prepareShowAnimated(Step *after);
67 	void showAnimated(Animate animate);
68 	void showFast();
69 	[[nodiscard]] bool animating() const;
70 	void setShowAnimationClipping(QRect clipping);
71 
72 	[[nodiscard]] bool hasCover() const;
73 	[[nodiscard]] virtual bool hasBack() const;
74 	virtual void activate();
75 	virtual void cancelled();
76 	virtual void finished();
77 
78 	virtual void submit() = 0;
79 	[[nodiscard]] virtual rpl::producer<QString> nextButtonText() const;
80 
81 	[[nodiscard]] int contentLeft() const;
82 	[[nodiscard]] int contentTop() const;
83 
84 	void setErrorCentered(bool centered);
85 	void showError(rpl::producer<QString> text);
hideError()86 	void hideError() {
87 		showError(rpl::single(QString()));
88 	}
89 
90 protected:
91 	void paintEvent(QPaintEvent *e) override;
92 	void resizeEvent(QResizeEvent *e) override;
93 
94 	void setTitleText(rpl::producer<QString> titleText);
95 	void setDescriptionText(rpl::producer<QString> descriptionText);
96 	void setDescriptionText(
97 		rpl::producer<TextWithEntities> richDescriptionText);
98 	bool paintAnimated(Painter &p, QRect clip);
99 
100 	void fillSentCodeData(const MTPDauth_sentCode &type);
101 
102 	void showDescription();
103 	void hideDescription();
104 
getData()105 	[[nodiscard]] not_null<Data*> getData() const {
106 		return _data;
107 	}
108 	void finish(const MTPUser &user, QImage &&photo = QImage());
109 	void createSession(
110 		const MTPUser &user,
111 		QImage photo,
112 		const QVector<MTPDialogFilter> &filters);
113 
114 	void goBack();
115 
116 	template <typename StepType>
goNext()117 	void goNext() {
118 		goNext(new StepType(parentWidget(), _account, _data));
119 	}
120 
121 	template <typename StepType>
goReplace(Animate animate)122 	void goReplace(Animate animate) {
123 		goReplace(new StepType(parentWidget(), _account, _data), animate);
124 	}
125 
showResetButton()126 	void showResetButton() {
127 		if (_showResetCallback) _showResetCallback();
128 	}
showTerms()129 	void showTerms() {
130 		if (_showTermsCallback) _showTermsCallback();
131 	}
acceptTerms(Fn<void ()> callback)132 	void acceptTerms(Fn<void()> callback) {
133 		if (_acceptTermsCallback) {
134 			_acceptTermsCallback(callback);
135 		}
136 	}
cancelNearestDcRequest()137 	void cancelNearestDcRequest() {
138 		if (_cancelNearestDcCallback) _cancelNearestDcCallback();
139 	}
140 
141 	virtual int errorTop() const;
142 
143 private:
144 	struct CoverAnimation {
145 		CoverAnimation() = default;
146 		CoverAnimation(CoverAnimation &&other) = default;
147 		CoverAnimation &operator=(CoverAnimation &&other) = default;
148 		~CoverAnimation();
149 
150 		std::unique_ptr<Ui::CrossFadeAnimation> title;
151 		std::unique_ptr<Ui::CrossFadeAnimation> description;
152 
153 		// From content top till the next button top.
154 		QPixmap contentSnapshotWas;
155 		QPixmap contentSnapshotNow;
156 
157 		QRect clipping;
158 	};
159 	void updateLabelsPosition();
160 	void paintContentSnapshot(
161 		Painter &p,
162 		const QPixmap &snapshot,
163 		float64 alpha,
164 		float64 howMuchHidden);
165 	void refreshError(const QString &text);
166 
167 	void goNext(Step *step);
168 	void goReplace(Step *step, Animate animate);
169 
170 	[[nodiscard]] CoverAnimation prepareCoverAnimation(Step *step);
171 	[[nodiscard]] QPixmap prepareContentSnapshot();
172 	[[nodiscard]] QPixmap prepareSlideAnimation();
173 	void showFinished();
174 
175 	void prepareCoverMask();
176 	void paintCover(Painter &p, int top);
177 
178 	const not_null<Main::Account*> _account;
179 	const not_null<Data*> _data;
180 	mutable std::optional<MTP::Sender> _api;
181 
182 	bool _hasCover = false;
183 	Fn<void(Step *step, StackAction action, Animate animate)> _goCallback;
184 	Fn<void()> _showResetCallback;
185 	Fn<void()> _showTermsCallback;
186 	Fn<void()> _cancelNearestDcCallback;
187 	Fn<void(Fn<void()> callback)> _acceptTermsCallback;
188 
189 	rpl::variable<QString> _titleText;
190 	object_ptr<Ui::FlatLabel> _title;
191 	rpl::variable<TextWithEntities> _descriptionText;
192 	object_ptr<Ui::FadeWrap<Ui::FlatLabel>> _description;
193 
194 	bool _errorCentered = false;
195 	rpl::variable<QString> _errorText;
196 	object_ptr<Ui::FadeWrap<Ui::FlatLabel>> _error = { nullptr };
197 
198 	Ui::Animations::Simple _a_show;
199 	CoverAnimation _coverAnimation;
200 	std::unique_ptr<Ui::SlideAnimation> _slideAnimation;
201 	QPixmap _coverMask;
202 
203 };
204 
205 
206 } // namespace details
207 } // namespace Intro
208