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 "history/view/history_view_object.h"
11 #include "ui/rect_part.h"
12 
13 class History;
14 struct HistoryMessageEdited;
15 struct TextSelection;
16 
17 namespace base {
18 template <typename Enum>
19 class enum_mask;
20 } // namespace base
21 
22 namespace Storage {
23 enum class SharedMediaType : signed char;
24 using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
25 } // namespace Storage
26 
27 namespace Lottie {
28 class SinglePlayer;
29 struct ColorReplacements;
30 } // namespace Lottie
31 
32 namespace Ui {
33 struct BubbleSelectionInterval;
34 struct ChatPaintContext;
35 } // namespace Ui
36 
37 namespace HistoryView {
38 
39 enum class PointState : char;
40 enum class CursorState : char;
41 enum class InfoDisplayType : char;
42 struct TextState;
43 struct StateRequest;
44 class Element;
45 
46 using PaintContext = Ui::ChatPaintContext;
47 
48 enum class MediaInBubbleState {
49 	None,
50 	Top,
51 	Middle,
52 	Bottom,
53 };
54 
55 [[nodiscard]] QString DocumentTimestampLinkBase(
56 	not_null<DocumentData*> document,
57 	FullMsgId context);
58 [[nodiscard]] TextWithEntities AddTimestampLinks(
59 	TextWithEntities text,
60 	TimeId duration,
61 	const QString &base);
62 
63 class Media : public Object {
64 public:
Media(not_null<Element * > parent)65 	explicit Media(not_null<Element*> parent) : _parent(parent) {
66 	}
67 
68 	[[nodiscard]] not_null<History*> history() const;
69 
selectedText(TextSelection selection)70 	[[nodiscard]] virtual TextForMimeData selectedText(
71 			TextSelection selection) const {
72 		return TextForMimeData();
73 	}
74 
75 	[[nodiscard]] virtual bool isDisplayed() const;
updateNeedBubbleState()76 	virtual void updateNeedBubbleState() {
77 	}
hasTextForCopy()78 	[[nodiscard]] virtual bool hasTextForCopy() const {
79 		return false;
80 	}
hideMessageText()81 	[[nodiscard]] virtual bool hideMessageText() const {
82 		return true;
83 	}
allowsFastShare()84 	[[nodiscard]] virtual bool allowsFastShare() const {
85 		return false;
86 	}
refreshParentId(not_null<HistoryItem * > realParent)87 	virtual void refreshParentId(not_null<HistoryItem*> realParent) {
88 	}
drawHighlight(Painter & p,const PaintContext & context,int top)89 	virtual void drawHighlight(
90 		Painter &p,
91 		const PaintContext &context,
92 		int top) const {
93 	}
94 	virtual void draw(Painter &p, const PaintContext &context) const = 0;
95 	[[nodiscard]] virtual PointState pointState(QPoint point) const;
96 	[[nodiscard]] virtual TextState textState(
97 		QPoint point,
98 		StateRequest request) const = 0;
updatePressed(QPoint point)99 	virtual void updatePressed(QPoint point) {
100 	}
101 
102 	[[nodiscard]] virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
103 
104 	// if we are in selecting items mode perhaps we want to
105 	// toggle selection instead of activating the pressed link
106 	[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
107 		const ClickHandlerPtr &p) const = 0;
108 
109 	// if we press and drag on this media should we drag the item
dragItem()110 	[[nodiscard]] virtual bool dragItem() const {
111 		return false;
112 	}
113 
adjustSelection(TextSelection selection,TextSelectType type)114 	[[nodiscard]] virtual TextSelection adjustSelection(
115 			TextSelection selection,
116 			TextSelectType type) const {
117 		return selection;
118 	}
fullSelectionLength()119 	[[nodiscard]] virtual uint16 fullSelectionLength() const {
120 		return 0;
121 	}
122 	[[nodiscard]] TextSelection skipSelection(
123 		TextSelection selection) const;
124 	[[nodiscard]] TextSelection unskipSelection(
125 		TextSelection selection) const;
126 
127 	[[nodiscard]] virtual auto getBubbleSelectionIntervals(
128 		TextSelection selection) const
129 	-> std::vector<Ui::BubbleSelectionInterval>;
130 
131 	// if we press and drag this link should we drag the item
132 	[[nodiscard]] virtual bool dragItemByHandler(
133 		const ClickHandlerPtr &p) const = 0;
134 
clickHandlerActiveChanged(const ClickHandlerPtr & p,bool active)135 	virtual void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
136 	}
clickHandlerPressedChanged(const ClickHandlerPtr & p,bool pressed)137 	virtual void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
138 	}
139 
uploading()140 	[[nodiscard]] virtual bool uploading() const {
141 		return false;
142 	}
143 
getPhoto()144 	[[nodiscard]] virtual PhotoData *getPhoto() const {
145 		return nullptr;
146 	}
getDocument()147 	[[nodiscard]] virtual DocumentData *getDocument() const {
148 		return nullptr;
149 	}
150 
playAnimation()151 	void playAnimation() {
152 		playAnimation(false);
153 	}
autoplayAnimation()154 	void autoplayAnimation() {
155 		playAnimation(true);
156 	}
stopAnimation()157 	virtual void stopAnimation() {
158 	}
stickerClearLoopPlayed()159 	virtual void stickerClearLoopPlayed() {
160 	}
161 	virtual std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie(
162 		not_null<DocumentData*> data,
163 		const Lottie::ColorReplacements *replacements);
checkAnimation()164 	virtual void checkAnimation() {
165 	}
166 
sizeForGroupingOptimal(int maxWidth)167 	[[nodiscard]] virtual QSize sizeForGroupingOptimal(int maxWidth) const {
168 		Unexpected("Grouping method call.");
169 	}
sizeForGrouping(int width)170 	[[nodiscard]] virtual QSize sizeForGrouping(int width) const {
171 		Unexpected("Grouping method call.");
172 	}
drawGrouped(Painter & p,const PaintContext & context,const QRect & geometry,RectParts sides,RectParts corners,float64 highlightOpacity,not_null<uint64 * > cacheKey,not_null<QPixmap * > cache)173 	virtual void drawGrouped(
174 			Painter &p,
175 			const PaintContext &context,
176 			const QRect &geometry,
177 			RectParts sides,
178 			RectParts corners,
179 			float64 highlightOpacity,
180 			not_null<uint64*> cacheKey,
181 			not_null<QPixmap*> cache) const {
182 		Unexpected("Grouping method call.");
183 	}
184 	[[nodiscard]] virtual TextState getStateGrouped(
185 		const QRect &geometry,
186 		RectParts sides,
187 		QPoint point,
188 		StateRequest request) const;
189 
animating()190 	[[nodiscard]] virtual bool animating() const {
191 		return false;
192 	}
193 
getCaption()194 	[[nodiscard]] virtual TextWithEntities getCaption() const {
195 		return TextWithEntities();
196 	}
197 	[[nodiscard]] virtual bool needsBubble() const = 0;
198 	[[nodiscard]] virtual bool customInfoLayout() const = 0;
bubbleMargins()199 	[[nodiscard]] virtual QMargins bubbleMargins() const {
200 		return QMargins();
201 	}
202 
overrideEditedDate()203 	[[nodiscard]] virtual bool overrideEditedDate() const {
204 		return false;
205 	}
displayedEditBadge()206 	[[nodiscard]] virtual HistoryMessageEdited *displayedEditBadge() const {
207 		Unexpected("displayedEditBadge() on non-grouped media.");
208 	}
209 
210 	// An attach media in a web page can provide an
211 	// additional text to be displayed below the attach.
212 	// For example duration / progress for video messages.
additionalInfoString()213 	[[nodiscard]] virtual QString additionalInfoString() const {
214 		return QString();
215 	}
216 
setInBubbleState(MediaInBubbleState state)217 	void setInBubbleState(MediaInBubbleState state) {
218 		_inBubbleState = state;
219 	}
inBubbleState()220 	[[nodiscard]] MediaInBubbleState inBubbleState() const {
221 		return _inBubbleState;
222 	}
isBubbleTop()223 	[[nodiscard]] bool isBubbleTop() const {
224 		return (_inBubbleState == MediaInBubbleState::Top)
225 			|| (_inBubbleState == MediaInBubbleState::None);
226 	}
isBubbleBottom()227 	[[nodiscard]] bool isBubbleBottom() const {
228 		return (_inBubbleState == MediaInBubbleState::Bottom)
229 			|| (_inBubbleState == MediaInBubbleState::None);
230 	}
231 	[[nodiscard]] bool isRoundedInBubbleBottom() const;
skipBubbleTail()232 	[[nodiscard]] virtual bool skipBubbleTail() const {
233 		return false;
234 	}
235 
236 	// Sometimes webpages can force the bubble to fit their size instead of
237 	// allowing message text to be as wide as possible (like wallpapers).
enforceBubbleWidth()238 	[[nodiscard]] virtual bool enforceBubbleWidth() const {
239 		return false;
240 	}
241 
242 	// Sometimes click on media in message is overloaded by the message:
243 	// (for example it can open a link or a game instead of opening media)
244 	// But the overloading click handler should be used only when media
245 	// is already loaded (not a photo or GIF waiting for load with auto
246 	// load being disabled - in such case media should handle the click).
isReadyForOpen()247 	[[nodiscard]] virtual bool isReadyForOpen() const {
248 		return true;
249 	}
250 
251 	struct BubbleRoll {
252 		float64 rotate = 0.;
253 		float64 scale = 1.;
254 
255 		explicit operator bool() const {
256 			return (rotate != 0.) || (scale != 1.);
257 		}
258 	};
bubbleRoll()259 	[[nodiscard]] virtual BubbleRoll bubbleRoll() const {
260 		return BubbleRoll();
261 	}
bubbleRollRepaintMargins()262 	[[nodiscard]] virtual QMargins bubbleRollRepaintMargins() const {
263 		return QMargins();
264 	}
paintBubbleFireworks(Painter & p,const QRect & bubble,crl::time ms)265 	virtual void paintBubbleFireworks(
266 		Painter &p,
267 		const QRect &bubble,
268 		crl::time ms) const {
269 	}
customHighlight()270 	[[nodiscard]] virtual bool customHighlight() const {
271 		return false;
272 	}
273 
hasHeavyPart()274 	virtual bool hasHeavyPart() const {
275 		return false;
276 	}
unloadHeavyPart()277 	virtual void unloadHeavyPart() {
278 	}
279 
280 	// Should be called only by Data::Session.
updateSharedContactUserId(UserId userId)281 	virtual void updateSharedContactUserId(UserId userId) {
282 	}
parentTextUpdated()283 	virtual void parentTextUpdated() {
284 	}
285 
286 	virtual ~Media() = default;
287 
288 protected:
289 	[[nodiscard]] QSize countCurrentSize(int newWidth) override;
290 	[[nodiscard]] Ui::Text::String createCaption(
291 		not_null<HistoryItem*> item,
292 		TimeId timestampLinksDuration = 0,
293 		const QString &timestampLinkBase = QString()) const;
294 
playAnimation(bool autoplay)295 	virtual void playAnimation(bool autoplay) {
296 	}
297 
298 	[[nodiscard]] bool usesBubblePattern(const PaintContext &context) const;
299 
300 	const not_null<Element*> _parent;
301 	MediaInBubbleState _inBubbleState = MediaInBubbleState::None;
302 
303 };
304 
305 } // namespace HistoryView
306