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 ×tampLinkBase = 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