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 "layout/layout_item_base.h"
11 #include "layout/layout_document_generic_preview.h"
12 #include "media/clip/media_clip_reader.h"
13 #include "core/click_handler_types.h"
14 #include "ui/effects/animations.h"
15 #include "ui/effects/radial_animation.h"
16 #include "styles/style_overview.h"
17 
18 class Image;
19 
20 namespace style {
21 struct RoundCheckbox;
22 } // namespace style
23 
24 namespace Data {
25 class Media;
26 class PhotoMedia;
27 class DocumentMedia;
28 } // namespace Data
29 
30 namespace Overview {
31 namespace Layout {
32 
33 class Checkbox;
34 class ItemBase;
35 class Delegate;
36 
37 class PaintContext : public PaintContextBase {
38 public:
PaintContext(crl::time ms,bool selecting)39 	PaintContext(crl::time ms, bool selecting) : PaintContextBase(ms, selecting) {
40 	}
41 	bool isAfterDate = false;
42 
43 };
44 
45 class ItemBase : public LayoutItemBase, public base::has_weak_ptr {
46 public:
47 	ItemBase(not_null<Delegate*> delegate, not_null<HistoryItem*> parent);
48 	~ItemBase();
49 
50 	virtual void paint(
51 		Painter &p,
52 		const QRect &clip,
53 		TextSelection selection,
54 		const PaintContext *context) = 0;
55 
56 	QDateTime dateTime() const;
57 
getItem()58 	HistoryItem *getItem() const {
59 		return _parent;
60 	}
61 
62 	void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
63 	void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
64 
65 	void invalidateCache();
66 
clearHeavyPart()67 	virtual void clearHeavyPart() {
68 	}
69 
70 protected:
parent()71 	[[nodiscard]] not_null<HistoryItem*> parent() const {
72 		return _parent;
73 	}
delegate()74 	[[nodiscard]] not_null<Delegate*> delegate() const {
75 		return _delegate;
76 	}
77 	void paintCheckbox(
78 		Painter &p,
79 		QPoint position,
80 		bool selected,
81 		const PaintContext *context);
82 	virtual const style::RoundCheckbox &checkboxStyle() const;
83 
84 private:
85 	void ensureCheckboxCreated();
86 
87 	const not_null<Delegate*> _delegate;
88 	const not_null<HistoryItem*> _parent;
89 	const QDateTime _dateTime;
90 	std::unique_ptr<Checkbox> _check;
91 
92 };
93 
94 class RadialProgressItem : public ItemBase {
95 public:
RadialProgressItem(not_null<Delegate * > delegate,not_null<HistoryItem * > parent)96 	RadialProgressItem(
97 		not_null<Delegate*> delegate,
98 		not_null<HistoryItem*> parent)
99 	: ItemBase(delegate, parent) {
100 	}
101 	RadialProgressItem(const RadialProgressItem &other) = delete;
102 
103 	void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
104 
105 	~RadialProgressItem();
106 
107 protected:
108 	ClickHandlerPtr _openl, _savel, _cancell;
109 	void setLinks(
110 		ClickHandlerPtr &&openl,
111 		ClickHandlerPtr &&savel,
112 		ClickHandlerPtr &&cancell);
113 	void setDocumentLinks(
114 		not_null<DocumentData*> document,
115 		bool forceOpen = false);
116 
117 	void radialAnimationCallback(crl::time now) const;
118 
119 	void ensureRadial();
120 	void checkRadialFinished() const;
121 
isRadialAnimation()122 	bool isRadialAnimation() const {
123 		if (_radial) {
124 			if (_radial->animating()) {
125 				return true;
126 			}
127 			checkRadialFinished();
128 		}
129 		return false;
130 	}
131 
132 	virtual float64 dataProgress() const = 0;
133 	virtual bool dataFinished() const = 0;
134 	virtual bool dataLoaded() const = 0;
iconAnimated()135 	virtual bool iconAnimated() const {
136 		return false;
137 	}
138 
139 	mutable std::unique_ptr<Ui::RadialAnimation> _radial;
140 	Ui::Animations::Simple _a_iconOver;
141 
142 };
143 
144 class StatusText {
145 public:
146 	// duration = -1 - no duration, duration = -2 - "GIF" duration
147 	void update(int newSize, int fullSize, int duration, crl::time realDuration);
148 	void setSize(int newSize);
149 
size()150 	int size() const {
151 		return _size;
152 	}
text()153 	QString text() const {
154 		return _text;
155 	}
156 
157 private:
158 	// >= 0 will contain download / upload string, _size = loaded bytes
159 	// < 0 will contain played string, _size = -(seconds + 1) played
160 	// 0x7FFFFFF0 will contain status for not yet downloaded file
161 	// 0x7FFFFFF1 will contain status for already downloaded file
162 	// 0x7FFFFFF2 will contain status for failed to download / upload file
163 	int _size = 0;
164 	QString _text;
165 
166 };
167 
168 struct Info : public RuntimeComponent<Info, LayoutItemBase> {
169 	int top = 0;
170 };
171 
172 class Photo final : public ItemBase {
173 public:
174 	Photo(
175 		not_null<Delegate*> delegate,
176 		not_null<HistoryItem*> parent,
177 		not_null<PhotoData*> photo);
178 
179 	void initDimensions() override;
180 	int32 resizeGetHeight(int32 width) override;
181 	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
182 	TextState getState(
183 		QPoint point,
184 		StateRequest request) const override;
185 
186 	void clearHeavyPart() override;
187 
188 private:
189 	void ensureDataMediaCreated() const;
190 	void setPixFrom(not_null<Image*> image);
191 
192 	const not_null<PhotoData*> _data;
193 	mutable std::shared_ptr<Data::PhotoMedia> _dataMedia;
194 	ClickHandlerPtr _link;
195 
196 	QPixmap _pix;
197 	bool _goodLoaded = false;
198 
199 };
200 
201 class Gif final : public RadialProgressItem {
202 public:
203 	Gif(
204 		not_null<Delegate*> delegate,
205 		not_null<HistoryItem*> parent,
206 		not_null<DocumentData*> gif);
207 	~Gif();
208 
209 	void initDimensions() override;
210 	int32 resizeGetHeight(int32 width) override;
211 	void paint(
212 		Painter &p,
213 		const QRect &clip,
214 		TextSelection selection,
215 		const PaintContext *context) override;
216 	TextState getState(
217 		QPoint point,
218 		StateRequest request) const override;
219 
220 	void clearHeavyPart() override;
221 	void setPosition(int32 position) override;
222 
223 protected:
224 	float64 dataProgress() const override;
225 	bool dataFinished() const override;
226 	bool dataLoaded() const override;
227 	bool iconAnimated() const override;
228 
229 private:
230 	QSize countFrameSize() const;
231 	int contentWidth() const;
232 	int contentHeight() const;
233 
234 	void validateThumbnail(
235 		Image *image,
236 		QSize size,
237 		QSize frame,
238 		bool good);
239 	void prepareThumbnail(QSize size, QSize frame);
240 
241 	void update();
242 
243 	void ensureDataMediaCreated() const;
244 	void updateStatusText();
245 
246 	void clipCallback(Media::Clip::Notification notification);
247 
248 	Media::Clip::ReaderPointer _gif;
249 
250 	const not_null<DocumentData*> _data;
251 	mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
252 	StatusText _status;
253 
254 	QPixmap _thumb;
255 	bool _thumbGood = false;
256 
257 };
258 
259 class Video final : public RadialProgressItem {
260 public:
261 	Video(
262 		not_null<Delegate*> delegate,
263 		not_null<HistoryItem*> parent,
264 		not_null<DocumentData*> video);
265 	~Video();
266 
267 	void initDimensions() override;
268 	int32 resizeGetHeight(int32 width) override;
269 	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
270 	TextState getState(
271 		QPoint point,
272 		StateRequest request) const override;
273 
274 	void clearHeavyPart() override;
275 
276 protected:
277 	float64 dataProgress() const override;
278 	bool dataFinished() const override;
279 	bool dataLoaded() const override;
280 	bool iconAnimated() const override;
281 
282 private:
283 	void ensureDataMediaCreated() const;
284 	void updateStatusText();
285 
286 	const not_null<DocumentData*> _data;
287 	mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
288 	StatusText _status;
289 
290 	QString _duration;
291 	QPixmap _pix;
292 	bool _pixBlurred = true;
293 
294 };
295 
296 class Voice final : public RadialProgressItem {
297 public:
298 	Voice(
299 		not_null<Delegate*> delegate,
300 		not_null<HistoryItem*> parent,
301 		not_null<DocumentData*> voice,
302 		const style::OverviewFileLayout &st);
303 
304 	void initDimensions() override;
305 	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
306 	TextState getState(
307 		QPoint point,
308 		StateRequest request) const override;
309 
310 	void clearHeavyPart() override;
311 
312 protected:
313 	float64 dataProgress() const override;
314 	bool dataFinished() const override;
315 	bool dataLoaded() const override;
316 	bool iconAnimated() const override;
317 	const style::RoundCheckbox &checkboxStyle() const override;
318 
319 private:
320 	void ensureDataMediaCreated() const;
321 	int duration() const;
322 
323 	not_null<DocumentData*> _data;
324 	mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
325 	StatusText _status;
326 	ClickHandlerPtr _namel;
327 
328 	const style::OverviewFileLayout &_st;
329 
330 	Ui::Text::String _name, _details;
331 	int _nameVersion;
332 
333 	void updateName();
334 	bool updateStatusText();
335 
336 };
337 
338 class Document final : public RadialProgressItem {
339 public:
340 	Document(
341 		not_null<Delegate*> delegate,
342 		not_null<HistoryItem*> parent,
343 		not_null<DocumentData*> document,
344 		const style::OverviewFileLayout &st);
345 
346 	void initDimensions() override;
347 	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
348 	TextState getState(
349 		QPoint point,
350 		StateRequest request) const override;
351 
352 	void clearHeavyPart() override;
353 
354 protected:
355 	float64 dataProgress() const override;
356 	bool dataFinished() const override;
357 	bool dataLoaded() const override;
358 	bool iconAnimated() const override;
359 	const style::RoundCheckbox &checkboxStyle() const override;
360 
361 private:
362 	[[nodiscard]] bool downloadInCorner() const;
363 	void drawCornerDownload(Painter &p, bool selected, const PaintContext *context) const;
364 	[[nodiscard]] TextState cornerDownloadTextState(
365 		QPoint point,
366 		StateRequest request) const;
367 
368 	void ensureDataMediaCreated() const;
369 
370 	not_null<DocumentData*> _data;
371 	mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
372 	StatusText _status;
373 	ClickHandlerPtr _msgl, _namel;
374 
375 	const style::OverviewFileLayout &_st;
376 	const ::Layout::DocumentGenericPreview _generic;
377 
378 	bool _thumbLoaded = false;
379 	QPixmap _thumb;
380 
381 	Ui::Text::String _name;
382 	QString _date, _ext;
383 	int32 _datew, _extw;
384 	int32 _thumbw;
385 
386 	bool withThumb() const;
387 	bool updateStatusText();
388 
389 };
390 
391 class Link final : public ItemBase {
392 public:
393 	Link(
394 		not_null<Delegate*> delegate,
395 		not_null<HistoryItem*> parent,
396 		Data::Media *media);
397 
398 	void initDimensions() override;
399 	int32 resizeGetHeight(int32 width) override;
400 	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
401 	TextState getState(
402 		QPoint point,
403 		StateRequest request) const override;
404 
405 	void clearHeavyPart() override;
406 
407 protected:
408 	const style::RoundCheckbox &checkboxStyle() const override;
409 
410 private:
411 	void ensurePhotoMediaCreated();
412 	void ensureDocumentMediaCreated();
413 	void validateThumbnail();
414 
415 	ClickHandlerPtr _photol;
416 
417 	QString _title, _letter;
418 	int _titlew = 0;
419 	WebPageData *_page = nullptr;
420 	std::shared_ptr<Data::PhotoMedia> _photoMedia;
421 	std::shared_ptr<Data::DocumentMedia> _documentMedia;
422 	int _pixw = 0;
423 	int _pixh = 0;
424 	Ui::Text::String _text = { st::msgMinWidth };
425 	QPixmap _thumbnail;
426 	bool _thumbnailBlurred = true;
427 
428 	struct LinkEntry {
LinkEntryLinkEntry429 		LinkEntry() : width(0) {
430 		}
431 		LinkEntry(const QString &url, const QString &text);
432 		QString text;
433 		int32 width;
434 		std::shared_ptr<TextClickHandler> lnk;
435 	};
436 	QVector<LinkEntry> _links;
437 
438 };
439 
440 } // namespace Layout
441 } // namespace Overview
442