history_view_element.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "history/view/history_view_object.h"
  9. #include "base/runtime_composer.h"
  10. #include "base/flags.h"
  11. #include "base/weak_ptr.h"
  12. class History;
  13. class HistoryBlock;
  14. class HistoryItem;
  15. struct HistoryMessageReply;
  16. struct PreparedServiceText;
  17. namespace Data {
  18. struct Reaction;
  19. struct ReactionId;
  20. } // namespace Data
  21. namespace Window {
  22. class SessionController;
  23. } // namespace Window
  24. namespace Ui {
  25. class PathShiftGradient;
  26. struct BubblePattern;
  27. struct ChatPaintContext;
  28. class ChatStyle;
  29. struct ReactionFlyAnimationArgs;
  30. class ReactionFlyAnimation;
  31. class RippleAnimation;
  32. } // namespace Ui
  33. namespace HistoryView::Reactions {
  34. struct ButtonParameters;
  35. class InlineList;
  36. } // namespace HistoryView::Reactions
  37. namespace HistoryView {
  38. using PaintContext = Ui::ChatPaintContext;
  39. enum class PointState : char;
  40. enum class InfoDisplayType : char;
  41. struct StateRequest;
  42. struct TextState;
  43. class Media;
  44. class Reply;
  45. enum class Context : char {
  46. History,
  47. Replies,
  48. Pinned,
  49. AdminLog,
  50. ContactPreview,
  51. SavedSublist,
  52. TTLViewer,
  53. ShortcutMessages,
  54. ScheduledTopic,
  55. ChatPreview,
  56. };
  57. enum class OnlyEmojiAndSpaces : char {
  58. Unknown,
  59. Yes,
  60. No,
  61. };
  62. struct SelectionModeResult {
  63. bool inSelectionMode = false;
  64. float64 progress = 0.0;
  65. };
  66. class Element;
  67. class ElementDelegate {
  68. public:
  69. virtual Context elementContext() = 0;
  70. virtual bool elementUnderCursor(not_null<const Element*> view) = 0;
  71. virtual SelectionModeResult elementInSelectionMode(
  72. const Element *view) = 0;
  73. virtual bool elementIntersectsRange(
  74. not_null<const Element*> view,
  75. int from,
  76. int till) = 0;
  77. virtual void elementStartStickerLoop(not_null<const Element*> view) = 0;
  78. virtual void elementShowPollResults(
  79. not_null<PollData*> poll,
  80. FullMsgId context) = 0;
  81. virtual void elementOpenPhoto(
  82. not_null<PhotoData*> photo,
  83. FullMsgId context) = 0;
  84. virtual void elementOpenDocument(
  85. not_null<DocumentData*> document,
  86. FullMsgId context,
  87. bool showInMediaView = false) = 0;
  88. virtual void elementCancelUpload(const FullMsgId &context) = 0;
  89. virtual void elementShowTooltip(
  90. const TextWithEntities &text,
  91. Fn<void()> hiddenCallback) = 0;
  92. virtual bool elementAnimationsPaused() = 0;
  93. virtual bool elementHideReply(not_null<const Element*> view) = 0;
  94. virtual bool elementShownUnread(not_null<const Element*> view) = 0;
  95. virtual void elementSendBotCommand(
  96. const QString &command,
  97. const FullMsgId &context) = 0;
  98. virtual void elementSearchInList(
  99. const QString &query,
  100. const FullMsgId &context) = 0;
  101. virtual void elementHandleViaClick(not_null<UserData*> bot) = 0;
  102. virtual bool elementIsChatWide() = 0;
  103. virtual not_null<Ui::PathShiftGradient*> elementPathShiftGradient() = 0;
  104. virtual void elementReplyTo(const FullReplyTo &to) = 0;
  105. virtual void elementStartInteraction(not_null<const Element*> view) = 0;
  106. virtual void elementStartPremium(
  107. not_null<const Element*> view,
  108. Element *replacing) = 0;
  109. virtual void elementCancelPremium(not_null<const Element*> view) = 0;
  110. virtual void elementStartEffect(
  111. not_null<const Element*> view,
  112. Element *replacing) = 0;
  113. virtual QString elementAuthorRank(not_null<const Element*> view) = 0;
  114. virtual bool elementHideTopicButton(not_null<const Element*> view) = 0;
  115. virtual ~ElementDelegate() {
  116. }
  117. };
  118. [[nodiscard]] std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
  119. not_null<const Ui::ChatStyle*> st,
  120. Fn<void()> update);
  121. class DefaultElementDelegate : public ElementDelegate {
  122. public:
  123. bool elementUnderCursor(not_null<const Element*> view) override;
  124. SelectionModeResult elementInSelectionMode(const Element *view) override;
  125. bool elementIntersectsRange(
  126. not_null<const Element*> view,
  127. int from,
  128. int till) override;
  129. void elementStartStickerLoop(not_null<const Element*> view) override;
  130. void elementShowPollResults(
  131. not_null<PollData*> poll,
  132. FullMsgId context) override;
  133. void elementOpenPhoto(
  134. not_null<PhotoData*> photo,
  135. FullMsgId context) override;
  136. void elementOpenDocument(
  137. not_null<DocumentData*> document,
  138. FullMsgId context,
  139. bool showInMediaView = false) override;
  140. void elementCancelUpload(const FullMsgId &context) override;
  141. void elementShowTooltip(
  142. const TextWithEntities &text,
  143. Fn<void()> hiddenCallback) override;
  144. bool elementHideReply(not_null<const Element*> view) override;
  145. bool elementShownUnread(not_null<const Element*> view) override;
  146. void elementSendBotCommand(
  147. const QString &command,
  148. const FullMsgId &context) override;
  149. void elementSearchInList(
  150. const QString &query,
  151. const FullMsgId &context) override;
  152. void elementHandleViaClick(not_null<UserData*> bot) override;
  153. bool elementIsChatWide() override;
  154. void elementReplyTo(const FullReplyTo &to) override;
  155. void elementStartInteraction(not_null<const Element*> view) override;
  156. void elementStartPremium(
  157. not_null<const Element*> view,
  158. Element *replacing) override;
  159. void elementCancelPremium(not_null<const Element*> view) override;
  160. void elementStartEffect(
  161. not_null<const Element*> view,
  162. Element *replacing) override;
  163. QString elementAuthorRank(not_null<const Element*> view) override;
  164. bool elementHideTopicButton(not_null<const Element*> view) override;
  165. };
  166. class SimpleElementDelegate : public DefaultElementDelegate {
  167. public:
  168. SimpleElementDelegate(
  169. not_null<Window::SessionController*> controller,
  170. Fn<void()> update);
  171. ~SimpleElementDelegate();
  172. bool elementAnimationsPaused() override;
  173. not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
  174. protected:
  175. [[nodiscard]] not_null<Window::SessionController*> controller() const {
  176. return _controller;
  177. }
  178. private:
  179. const not_null<Window::SessionController*> _controller;
  180. const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
  181. };
  182. TextSelection UnshiftItemSelection(
  183. TextSelection selection,
  184. uint16 byLength);
  185. TextSelection ShiftItemSelection(
  186. TextSelection selection,
  187. uint16 byLength);
  188. TextSelection UnshiftItemSelection(
  189. TextSelection selection,
  190. const Ui::Text::String &byText);
  191. TextSelection ShiftItemSelection(
  192. TextSelection selection,
  193. const Ui::Text::String &byText);
  194. QString DateTooltipText(not_null<Element*> view);
  195. // Any HistoryView::Element can have this Component for
  196. // displaying the unread messages bar above the message.
  197. struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
  198. void init(const QString &string);
  199. static int height();
  200. static int marginTop();
  201. void paint(
  202. Painter &p,
  203. const PaintContext &context,
  204. int y,
  205. int w,
  206. bool chatWide) const;
  207. QString text;
  208. int width = 0;
  209. rpl::lifetime lifetime;
  210. };
  211. // Any HistoryView::Element can have this Component for
  212. // displaying the day mark above the message.
  213. struct DateBadge : public RuntimeComponent<DateBadge, Element> {
  214. void init(const QString &date);
  215. int height() const;
  216. void paint(
  217. Painter &p,
  218. not_null<const Ui::ChatStyle*> st,
  219. int y,
  220. int w,
  221. bool chatWide) const;
  222. QString text;
  223. int width = 0;
  224. };
  225. // Any HistoryView::Element can have this Component for
  226. // displaying some text in layout of a service message above the message.
  227. struct ServicePreMessage
  228. : public RuntimeComponent<ServicePreMessage, Element> {
  229. void init(PreparedServiceText string);
  230. int resizeToWidth(int newWidth, bool chatWide);
  231. void paint(
  232. Painter &p,
  233. const PaintContext &context,
  234. QRect g,
  235. bool chatWide) const;
  236. [[nodiscard]] ClickHandlerPtr textState(
  237. QPoint point,
  238. const StateRequest &request,
  239. QRect g) const;
  240. Ui::Text::String text;
  241. int width = 0;
  242. int height = 0;
  243. };
  244. struct FakeBotAboutTop : public RuntimeComponent<FakeBotAboutTop, Element> {
  245. void init();
  246. Ui::Text::String text;
  247. int maxWidth = 0;
  248. int height = 0;
  249. };
  250. struct PurchasedTag : public RuntimeComponent<PurchasedTag, Element> {
  251. Ui::Text::String text;
  252. };
  253. struct TopicButton {
  254. std::unique_ptr<Ui::RippleAnimation> ripple;
  255. ClickHandlerPtr link;
  256. Ui::Text::String name;
  257. QPoint lastPoint;
  258. int nameVersion = 0;
  259. };
  260. struct SelectedQuote {
  261. HistoryItem *item = nullptr;
  262. TextWithEntities text;
  263. int offset = 0;
  264. bool overflown = false;
  265. explicit operator bool() const {
  266. return item && !text.empty();
  267. }
  268. friend inline bool operator==(SelectedQuote, SelectedQuote) = default;
  269. };
  270. class Element
  271. : public Object
  272. , public RuntimeComposer<Element>
  273. , public ClickHandlerHost
  274. , public base::has_weak_ptr {
  275. public:
  276. enum class Flag : uint16 {
  277. ServiceMessage = 0x0001,
  278. NeedsResize = 0x0002,
  279. AttachedToPrevious = 0x0004,
  280. AttachedToNext = 0x0008,
  281. BubbleAttachedToPrevious = 0x0010,
  282. BubbleAttachedToNext = 0x0020,
  283. HiddenByGroup = 0x0040,
  284. SpecialOnlyEmoji = 0x0080,
  285. CustomEmojiRepainting = 0x0100,
  286. ScheduledUntilOnline = 0x0200,
  287. TopicRootReply = 0x0400,
  288. MediaOverriden = 0x0800,
  289. HeavyCustomEmoji = 0x1000,
  290. };
  291. using Flags = base::flags<Flag>;
  292. friend inline constexpr auto is_flag_type(Flag) { return true; }
  293. Element(
  294. not_null<ElementDelegate*> delegate,
  295. not_null<HistoryItem*> data,
  296. Element *replacing,
  297. Flag serviceFlag);
  298. [[nodiscard]] virtual bool embedReactionsInBubble() const;
  299. [[nodiscard]] not_null<ElementDelegate*> delegate() const;
  300. [[nodiscard]] not_null<HistoryItem*> data() const;
  301. [[nodiscard]] not_null<History*> history() const;
  302. [[nodiscard]] Media *media() const;
  303. [[nodiscard]] Context context() const;
  304. void refreshDataId();
  305. [[nodiscard]] uint8 colorIndex() const;
  306. [[nodiscard]] uint8 contentColorIndex() const;
  307. [[nodiscard]] QDateTime dateTime() const;
  308. [[nodiscard]] int y() const;
  309. void setY(int y);
  310. [[nodiscard]] virtual int marginTop() const = 0;
  311. [[nodiscard]] virtual int marginBottom() const = 0;
  312. void setPendingResize();
  313. [[nodiscard]] bool pendingResize() const;
  314. [[nodiscard]] bool isUnderCursor() const;
  315. [[nodiscard]] bool isLastAndSelfMessage() const;
  316. [[nodiscard]] bool isAttachedToPrevious() const;
  317. [[nodiscard]] bool isAttachedToNext() const;
  318. [[nodiscard]] bool isBubbleAttachedToPrevious() const;
  319. [[nodiscard]] bool isBubbleAttachedToNext() const;
  320. [[nodiscard]] bool isTopicRootReply() const;
  321. [[nodiscard]] int skipBlockWidth() const;
  322. [[nodiscard]] int skipBlockHeight() const;
  323. [[nodiscard]] virtual int infoWidth() const;
  324. [[nodiscard]] virtual int bottomInfoFirstLineWidth() const;
  325. [[nodiscard]] virtual bool bottomInfoIsWide() const;
  326. [[nodiscard]] bool isHiddenByGroup() const;
  327. [[nodiscard]] virtual bool isHidden() const;
  328. [[nodiscard]] bool isIsolatedEmoji() const {
  329. return (_flags & Flag::SpecialOnlyEmoji)
  330. && _text.isIsolatedEmoji();
  331. }
  332. [[nodiscard]] bool isOnlyCustomEmoji() const {
  333. return (_flags & Flag::SpecialOnlyEmoji)
  334. && _text.isOnlyCustomEmoji();
  335. }
  336. [[nodiscard]] HistoryItem *textItem() const;
  337. [[nodiscard]] Ui::Text::IsolatedEmoji isolatedEmoji() const;
  338. [[nodiscard]] Ui::Text::OnlyCustomEmoji onlyCustomEmoji() const;
  339. [[nodiscard]] OnlyEmojiAndSpaces isOnlyEmojiAndSpaces() const;
  340. // For blocks context this should be called only from recountAttachToPreviousInBlocks().
  341. void setAttachToPrevious(bool attachToNext, Element *previous = nullptr);
  342. // For blocks context this should be called only from recountAttachToPreviousInBlocks()
  343. // of the next item or when the next item is removed through nextInBlocksRemoved() call.
  344. void setAttachToNext(bool attachToNext, Element *next = nullptr);
  345. // For blocks context this should be called only from recountDisplayDate().
  346. void setDisplayDate(bool displayDate);
  347. void setServicePreMessage(PreparedServiceText text);
  348. bool computeIsAttachToPrevious(not_null<Element*> previous);
  349. void createUnreadBar(rpl::producer<QString> text);
  350. void destroyUnreadBar();
  351. [[nodiscard]] int displayedDateHeight() const;
  352. [[nodiscard]] bool displayDate() const;
  353. [[nodiscard]] bool isInOneDayWithPrevious() const;
  354. virtual void draw(Painter &p, const PaintContext &context) const = 0;
  355. [[nodiscard]] virtual PointState pointState(QPoint point) const = 0;
  356. [[nodiscard]] virtual TextState textState(
  357. QPoint point,
  358. StateRequest request) const = 0;
  359. virtual void updatePressed(QPoint point) = 0;
  360. virtual void drawInfo(
  361. Painter &p,
  362. const PaintContext &context,
  363. int right,
  364. int bottom,
  365. int width,
  366. InfoDisplayType type) const;
  367. virtual TextState bottomInfoTextState(
  368. int right,
  369. int bottom,
  370. QPoint point,
  371. InfoDisplayType type) const;
  372. virtual TextForMimeData selectedText(TextSelection selection) const = 0;
  373. virtual SelectedQuote selectedQuote(
  374. TextSelection selection) const = 0;
  375. virtual TextSelection selectionFromQuote(
  376. const SelectedQuote &quote) const = 0;
  377. [[nodiscard]] virtual TextSelection adjustSelection(
  378. TextSelection selection,
  379. TextSelectType type) const;
  380. [[nodiscard]] static SelectedQuote FindSelectedQuote(
  381. const Ui::Text::String &text,
  382. TextSelection selection,
  383. not_null<HistoryItem*> item);
  384. [[nodiscard]] static TextSelection FindSelectionFromQuote(
  385. const Ui::Text::String &text,
  386. const SelectedQuote &quote);
  387. [[nodiscard]] virtual auto reactionButtonParameters(
  388. QPoint position,
  389. const TextState &reactionState) const -> Reactions::ButtonParameters;
  390. [[nodiscard]] virtual int reactionsOptimalWidth() const;
  391. // ClickHandlerHost interface.
  392. void clickHandlerActiveChanged(
  393. const ClickHandlerPtr &handler,
  394. bool active) override;
  395. void clickHandlerPressedChanged(
  396. const ClickHandlerPtr &handler,
  397. bool pressed) override;
  398. // hasFromPhoto() returns true even if we don't display the photo
  399. // but we need to skip a place at the left side for this photo
  400. [[nodiscard]] virtual bool hasFromPhoto() const;
  401. [[nodiscard]] virtual bool displayFromPhoto() const;
  402. [[nodiscard]] virtual bool hasFromName() const;
  403. [[nodiscard]] bool displayReply() const;
  404. [[nodiscard]] virtual bool displayFromName() const;
  405. [[nodiscard]] virtual TopicButton *displayedTopicButton() const;
  406. [[nodiscard]] virtual bool displayForwardedFrom() const;
  407. [[nodiscard]] virtual bool hasOutLayout() const;
  408. [[nodiscard]] bool hasRightLayout() const;
  409. [[nodiscard]] virtual bool drawBubble() const;
  410. [[nodiscard]] virtual bool hasBubble() const;
  411. [[nodiscard]] virtual bool unwrapped() const;
  412. [[nodiscard]] virtual int minWidthForMedia() const {
  413. return 0;
  414. }
  415. [[nodiscard]] virtual std::optional<QSize> rightActionSize() const;
  416. virtual void drawRightAction(
  417. Painter &p,
  418. const PaintContext &context,
  419. int left,
  420. int top,
  421. int outerWidth) const;
  422. [[nodiscard]] virtual ClickHandlerPtr rightActionLink(
  423. std::optional<QPoint> pressPoint) const;
  424. [[nodiscard]] virtual TimeId displayedEditDate() const;
  425. [[nodiscard]] virtual bool hasVisibleText() const;
  426. [[nodiscard]] int textualMaxWidth() const;
  427. virtual void applyGroupAdminChanges(
  428. const base::flat_set<UserId> &changes) {
  429. }
  430. [[nodiscard]] virtual bool toggleSelectionByHandlerClick(
  431. const ClickHandlerPtr &handler) const;
  432. [[nodiscard]] virtual bool allowTextSelectionByHandler(
  433. const ClickHandlerPtr &handler) const;
  434. [[nodiscard]] bool usesBubblePattern(const PaintContext &context) const;
  435. struct VerticalRepaintRange {
  436. int top = 0;
  437. int height = 0;
  438. };
  439. [[nodiscard]] virtual VerticalRepaintRange verticalRepaintRange() const;
  440. [[nodiscard]] virtual bool isSignedAuthorElided() const;
  441. virtual void itemDataChanged();
  442. void itemTextUpdated();
  443. void blockquoteExpandChanged();
  444. [[nodiscard]] virtual bool hasHeavyPart() const;
  445. virtual void unloadHeavyPart();
  446. void checkHeavyPart();
  447. void paintCustomHighlight(
  448. Painter &p,
  449. const PaintContext &context,
  450. int y,
  451. int height,
  452. not_null<const HistoryItem*> item) const;
  453. // Legacy blocks structure.
  454. [[nodiscard]] HistoryBlock *block();
  455. [[nodiscard]] const HistoryBlock *block() const;
  456. void attachToBlock(not_null<HistoryBlock*> block, int index);
  457. void removeFromBlock();
  458. void refreshInBlock();
  459. void setIndexInBlock(int index);
  460. [[nodiscard]] int indexInBlock() const;
  461. [[nodiscard]] Element *previousInBlocks() const;
  462. [[nodiscard]] Element *previousDisplayedInBlocks() const;
  463. [[nodiscard]] Element *nextInBlocks() const;
  464. [[nodiscard]] Element *nextDisplayedInBlocks() const;
  465. void previousInBlocksChanged();
  466. void nextInBlocksRemoved();
  467. [[nodiscard]] virtual QRect effectIconGeometry() const;
  468. [[nodiscard]] virtual QRect innerGeometry() const = 0;
  469. void customEmojiRepaint();
  470. void prepareCustomEmojiPaint(
  471. Painter &p,
  472. const PaintContext &context,
  473. const Ui::Text::String &text) const;
  474. void prepareCustomEmojiPaint(
  475. Painter &p,
  476. const PaintContext &context,
  477. const Reactions::InlineList &reactions) const;
  478. void clearCustomEmojiRepaint() const;
  479. void hideSpoilers();
  480. void repaint() const;
  481. [[nodiscard]] ClickHandlerPtr fromPhotoLink() const {
  482. return fromLink();
  483. }
  484. [[nodiscard]] bool markSponsoredViewed(int shownFromTop) const;
  485. virtual void animateReaction(Ui::ReactionFlyAnimationArgs &&args) = 0;
  486. void animateUnreadReactions();
  487. [[nodiscard]] auto takeReactionAnimations()
  488. -> base::flat_map<
  489. Data::ReactionId,
  490. std::unique_ptr<Ui::ReactionFlyAnimation>>;
  491. virtual void animateEffect(Ui::ReactionFlyAnimationArgs &&args);
  492. void animateUnreadEffect();
  493. [[nodiscard]] virtual auto takeEffectAnimation()
  494. -> std::unique_ptr<Ui::ReactionFlyAnimation>;
  495. void overrideMedia(std::unique_ptr<Media> media);
  496. [[nodiscard]] not_null<PurchasedTag*> enforcePurchasedTag();
  497. [[nodiscard]] static int AdditionalSpaceForSelectionCheckbox(
  498. not_null<const Element*> view,
  499. QRect countedGeometry = QRect());
  500. virtual bool consumeHorizontalScroll(QPoint position, int delta) {
  501. return false;
  502. }
  503. virtual ~Element();
  504. static void Hovered(Element *view);
  505. [[nodiscard]] static Element *Hovered();
  506. static void Pressed(Element *view);
  507. [[nodiscard]] static Element *Pressed();
  508. static void HoveredLink(Element *view);
  509. [[nodiscard]] static Element *HoveredLink();
  510. static void PressedLink(Element *view);
  511. [[nodiscard]] static Element *PressedLink();
  512. static void Moused(Element *view);
  513. [[nodiscard]] static Element *Moused();
  514. static void ClearGlobal();
  515. protected:
  516. void paintHighlight(
  517. Painter &p,
  518. const PaintContext &context,
  519. int geometryHeight) const;
  520. [[nodiscard]] ClickHandlerPtr fromLink() const;
  521. virtual void refreshDataIdHook();
  522. [[nodiscard]] const Ui::Text::String &text() const;
  523. [[nodiscard]] int textHeightFor(int textWidth);
  524. void validateText();
  525. void validateTextSkipBlock(bool has, int width, int height);
  526. void clearSpecialOnlyEmoji();
  527. void checkSpecialOnlyEmoji();
  528. void setupReactions(Element *replacing);
  529. void refreshReactions();
  530. bool updateReactions();
  531. std::unique_ptr<Reactions::InlineList> _reactions;
  532. private:
  533. // This should be called only from previousInBlocksChanged()
  534. // to add required bits to the Composer mask
  535. // after that always use Has<DateBadge>().
  536. void recountDisplayDateInBlocks();
  537. // This should be called only from previousInBlocksChanged() or when
  538. // DateBadge or UnreadBar bit is changed in the Composer mask
  539. // then the result should be cached in a client side flag
  540. // HistoryView::Element::Flag::AttachedToPrevious.
  541. void recountAttachToPreviousInBlocks();
  542. [[nodiscard]] bool countIsTopicRootReply() const;
  543. QSize countOptimalSize() final override;
  544. QSize countCurrentSize(int newWidth) final override;
  545. virtual QSize performCountOptimalSize() = 0;
  546. virtual QSize performCountCurrentSize(int newWidth) = 0;
  547. void refreshMedia(Element *replacing);
  548. void setTextWithLinks(
  549. const TextWithEntities &text,
  550. const std::vector<ClickHandlerPtr> &links = {});
  551. void setReactions(std::unique_ptr<Reactions::InlineList> list);
  552. struct TextWithLinks {
  553. TextWithEntities text;
  554. std::vector<ClickHandlerPtr> links;
  555. };
  556. [[nodiscard]] TextWithLinks contextDependentServiceText();
  557. const not_null<ElementDelegate*> _delegate;
  558. const not_null<HistoryItem*> _data;
  559. HistoryBlock *_block = nullptr;
  560. std::unique_ptr<Media> _media;
  561. mutable ClickHandlerPtr _fromLink;
  562. const QDateTime _dateTime;
  563. HistoryItem *_textItem = nullptr;
  564. mutable Ui::Text::String _text;
  565. mutable int _textWidth = -1;
  566. mutable int _textHeight = 0;
  567. int _y = 0;
  568. int _indexInBlock = -1;
  569. mutable Flags _flags = Flag(0);
  570. Context _context = Context();
  571. };
  572. [[nodiscard]] int FindViewY(
  573. not_null<Element*> view,
  574. uint16 symbol,
  575. int yfrom = 0);
  576. [[nodiscard]] Window::SessionController *ExtractController(
  577. const ClickContext &context);
  578. } // namespace HistoryView