history_item_components.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  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 "data/data_cloud_file.h"
  9. #include "history/history_item.h"
  10. #include "spellcheck/spellcheck_types.h" // LanguageId.
  11. #include "ui/empty_userpic.h"
  12. #include "ui/effects/animations.h"
  13. #include "ui/effects/ripple_animation.h"
  14. #include "ui/chat/message_bubble.h"
  15. struct WebPageData;
  16. class VoiceSeekClickHandler;
  17. class ReplyKeyboard;
  18. namespace Ui {
  19. struct ChatPaintContext;
  20. class ChatStyle;
  21. struct PeerUserpicView;
  22. } // namespace Ui
  23. namespace Ui::Text {
  24. struct GeometryDescriptor;
  25. } // namespace Ui::Text
  26. namespace Data {
  27. class Session;
  28. class Story;
  29. class SavedSublist;
  30. struct UnavailableReason;
  31. } // namespace Data
  32. namespace Media::Player {
  33. class RoundPainter;
  34. } // namespace Media::Player
  35. namespace Images {
  36. struct CornersMaskRef;
  37. } // namespace Images
  38. namespace HistoryView {
  39. class Element;
  40. class Document;
  41. class TranscribeButton;
  42. } // namespace HistoryView
  43. namespace style {
  44. struct BotKeyboardButton;
  45. } // namespace style
  46. extern const char kOptionFastButtonsMode[];
  47. [[nodiscard]] bool FastButtonsMode();
  48. struct HistoryMessageVia : public RuntimeComponent<HistoryMessageVia, HistoryItem> {
  49. void create(not_null<Data::Session*> owner, UserId userId);
  50. void resize(int32 availw) const;
  51. UserData *bot = nullptr;
  52. mutable QString text;
  53. mutable int width = 0;
  54. mutable int maxWidth = 0;
  55. ClickHandlerPtr link;
  56. };
  57. struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, HistoryItem> {
  58. static constexpr auto kMaxRecentRepliers = 3;
  59. struct Part {
  60. QString text;
  61. int textWidth = 0;
  62. int count = -1;
  63. };
  64. std::vector<PeerId> recentRepliers;
  65. Part views;
  66. Part replies;
  67. Part repliesSmall;
  68. ChannelId commentsMegagroupId = 0;
  69. MsgId commentsRootId = 0;
  70. MsgId commentsInboxReadTillId = 0;
  71. MsgId commentsMaxId = 0;
  72. int forwardsCount = 0;
  73. };
  74. struct HistoryMessageSigned : public RuntimeComponent<HistoryMessageSigned, HistoryItem> {
  75. QString author;
  76. UserData *viaBusinessBot = nullptr;
  77. bool isAnonymousRank = false;
  78. };
  79. struct HistoryMessageEdited : public RuntimeComponent<HistoryMessageEdited, HistoryItem> {
  80. TimeId date = 0;
  81. };
  82. class HiddenSenderInfo {
  83. public:
  84. HiddenSenderInfo(
  85. const QString &name,
  86. bool external,
  87. std::optional<uint8> colorIndex = {});
  88. QString name;
  89. QString firstName;
  90. QString lastName;
  91. uint8 colorIndex = 0;
  92. Ui::EmptyUserpic emptyUserpic;
  93. mutable Data::CloudImage customUserpic;
  94. [[nodiscard]] static ClickHandlerPtr ForwardClickHandler();
  95. [[nodiscard]] const Ui::Text::String &nameText() const;
  96. [[nodiscard]] bool paintCustomUserpic(
  97. Painter &p,
  98. Ui::PeerUserpicView &view,
  99. int x,
  100. int y,
  101. int outerWidth,
  102. int size) const;
  103. inline bool operator==(const HiddenSenderInfo &other) const {
  104. return name == other.name;
  105. }
  106. inline bool operator!=(const HiddenSenderInfo &other) const {
  107. return !(*this == other);
  108. }
  109. private:
  110. mutable Ui::Text::String _nameText;
  111. };
  112. struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded, HistoryItem> {
  113. void create(
  114. const HistoryMessageVia *via,
  115. not_null<const HistoryItem*> item) const;
  116. [[nodiscard]] bool forwardOfForward() const {
  117. return savedFromSender || savedFromHiddenSenderInfo;
  118. }
  119. TimeId originalDate = 0;
  120. PeerData *originalSender = nullptr;
  121. std::unique_ptr<HiddenSenderInfo> originalHiddenSenderInfo;
  122. QString originalPostAuthor;
  123. QString psaType;
  124. MsgId originalId = 0;
  125. mutable Ui::Text::String text = { 1 };
  126. PeerData *savedFromPeer = nullptr;
  127. MsgId savedFromMsgId = 0;
  128. PeerData *savedFromSender = nullptr;
  129. std::unique_ptr<HiddenSenderInfo> savedFromHiddenSenderInfo;
  130. bool savedFromOutgoing = false;
  131. bool imported = false;
  132. bool story = false;
  133. };
  134. struct HistoryMessageSavedMediaData : public RuntimeComponent<HistoryMessageSavedMediaData, HistoryItem> {
  135. TextWithEntities text;
  136. std::unique_ptr<Data::Media> media;
  137. };
  138. struct HistoryMessageSaved : public RuntimeComponent<HistoryMessageSaved, HistoryItem> {
  139. Data::SavedSublist *sublist = nullptr;
  140. };
  141. class ReplyToMessagePointer final {
  142. public:
  143. ReplyToMessagePointer(HistoryItem *item = nullptr) : _data(item) {
  144. }
  145. ReplyToMessagePointer(ReplyToMessagePointer &&other)
  146. : _data(base::take(other._data)) {
  147. }
  148. ReplyToMessagePointer &operator=(ReplyToMessagePointer &&other) {
  149. _data = base::take(other._data);
  150. return *this;
  151. }
  152. ReplyToMessagePointer &operator=(HistoryItem *item) {
  153. _data = item;
  154. return *this;
  155. }
  156. [[nodiscard]] bool empty() const {
  157. return !_data;
  158. }
  159. [[nodiscard]] HistoryItem *get() const {
  160. return _data;
  161. }
  162. explicit operator bool() const {
  163. return !empty();
  164. }
  165. [[nodiscard]] HistoryItem *operator->() const {
  166. return _data;
  167. }
  168. [[nodiscard]] HistoryItem &operator*() const {
  169. return *_data;
  170. }
  171. private:
  172. HistoryItem *_data = nullptr;
  173. };
  174. class ReplyToStoryPointer final {
  175. public:
  176. ReplyToStoryPointer(Data::Story *story = nullptr) : _data(story) {
  177. }
  178. ReplyToStoryPointer(ReplyToStoryPointer &&other)
  179. : _data(base::take(other._data)) {
  180. }
  181. ReplyToStoryPointer &operator=(ReplyToStoryPointer &&other) {
  182. _data = base::take(other._data);
  183. return *this;
  184. }
  185. ReplyToStoryPointer &operator=(Data::Story *item) {
  186. _data = item;
  187. return *this;
  188. }
  189. [[nodiscard]] bool empty() const {
  190. return !_data;
  191. }
  192. [[nodiscard]] Data::Story *get() const {
  193. return _data;
  194. }
  195. explicit operator bool() const {
  196. return !empty();
  197. }
  198. [[nodiscard]] Data::Story *operator->() const {
  199. return _data;
  200. }
  201. [[nodiscard]] Data::Story &operator*() const {
  202. return *_data;
  203. }
  204. private:
  205. Data::Story *_data = nullptr;
  206. };
  207. struct ReplyFields {
  208. [[nodiscard]] ReplyFields clone(not_null<HistoryItem*> parent) const;
  209. TextWithEntities quote;
  210. std::unique_ptr<Data::Media> externalMedia;
  211. PeerId externalSenderId = 0;
  212. QString externalSenderName;
  213. QString externalPostAuthor;
  214. PeerId externalPeerId = 0;
  215. MsgId messageId = 0;
  216. MsgId topMessageId = 0;
  217. StoryId storyId = 0;
  218. uint32 quoteOffset : 30 = 0;
  219. uint32 manualQuote : 1 = 0;
  220. uint32 topicPost : 1 = 0;
  221. };
  222. [[nodiscard]] ReplyFields ReplyFieldsFromMTP(
  223. not_null<HistoryItem*> item,
  224. const MTPMessageReplyHeader &reply);
  225. [[nodiscard]] FullReplyTo ReplyToFromMTP(
  226. not_null<History*> history,
  227. const MTPInputReplyTo &reply);
  228. struct HistoryMessageReply
  229. : public RuntimeComponent<HistoryMessageReply, HistoryItem> {
  230. HistoryMessageReply();
  231. HistoryMessageReply(const HistoryMessageReply &other) = delete;
  232. HistoryMessageReply(HistoryMessageReply &&other) = delete;
  233. HistoryMessageReply &operator=(
  234. const HistoryMessageReply &other) = delete;
  235. HistoryMessageReply &operator=(HistoryMessageReply &&other);
  236. ~HistoryMessageReply();
  237. void set(ReplyFields fields);
  238. void updateFields(
  239. not_null<HistoryItem*> holder,
  240. MsgId messageId,
  241. MsgId topMessageId,
  242. bool topicPost);
  243. void updateData(not_null<HistoryItem*> holder, bool force = false);
  244. // Must be called before destructor.
  245. void clearData(not_null<HistoryItem*> holder);
  246. [[nodiscard]] bool external() const;
  247. [[nodiscard]] bool displayAsExternal(
  248. not_null<HistoryItem*> holder) const;
  249. void itemRemoved(
  250. not_null<HistoryItem*> holder,
  251. not_null<HistoryItem*> removed);
  252. void storyRemoved(
  253. not_null<HistoryItem*> holder,
  254. not_null<Data::Story*> removed);
  255. [[nodiscard]] const ReplyFields &fields() const {
  256. return _fields;
  257. }
  258. [[nodiscard]] PeerId externalPeerId() const {
  259. return _fields.externalPeerId;
  260. }
  261. [[nodiscard]] MsgId messageId() const {
  262. return _fields.messageId;
  263. }
  264. [[nodiscard]] StoryId storyId() const {
  265. return _fields.storyId;
  266. }
  267. [[nodiscard]] MsgId topMessageId() const {
  268. return _fields.topMessageId;
  269. }
  270. [[nodiscard]] bool topicPost() const {
  271. return _fields.topicPost;
  272. }
  273. [[nodiscard]] bool manualQuote() const {
  274. return _fields.manualQuote;
  275. }
  276. [[nodiscard]] bool unavailable() const {
  277. return _unavailable;
  278. }
  279. [[nodiscard]] bool displaying() const {
  280. return _displaying;
  281. }
  282. [[nodiscard]] bool multiline() const {
  283. return _multiline;
  284. }
  285. [[nodiscard]] bool acquireResolve();
  286. void setTopMessageId(MsgId topMessageId);
  287. void refreshReplyToMedia();
  288. DocumentId replyToDocumentId = 0;
  289. WebPageId replyToWebPageId = 0;
  290. ReplyToMessagePointer resolvedMessage;
  291. ReplyToStoryPointer resolvedStory;
  292. private:
  293. ReplyFields _fields;
  294. uint8 _unavailable : 1 = 0;
  295. uint8 _displaying : 1 = 0;
  296. uint8 _multiline : 1 = 0;
  297. uint8 _pendingResolve : 1 = 0;
  298. uint8 _requestedResolve : 1 = 0;
  299. };
  300. struct HistoryMessageTranslation
  301. : public RuntimeComponent<HistoryMessageTranslation, HistoryItem> {
  302. TextWithEntities text;
  303. LanguageId to;
  304. bool requested = false;
  305. bool failed = false;
  306. bool used = false;
  307. };
  308. struct HistoryMessageReplyMarkup
  309. : public RuntimeComponent<HistoryMessageReplyMarkup, HistoryItem> {
  310. using Button = HistoryMessageMarkupButton;
  311. void createForwarded(const HistoryMessageReplyMarkup &original);
  312. void updateData(HistoryMessageMarkupData &&markup);
  313. [[nodiscard]] bool hiddenBy(Data::Media *media) const;
  314. HistoryMessageMarkupData data;
  315. std::unique_ptr<ReplyKeyboard> inlineKeyboard;
  316. };
  317. class ReplyMarkupClickHandler : public ClickHandler {
  318. public:
  319. ReplyMarkupClickHandler(
  320. not_null<Data::Session*> owner,
  321. int row,
  322. int column,
  323. FullMsgId context);
  324. QString tooltip() const override;
  325. void setFullDisplayed(bool full) {
  326. _fullDisplayed = full;
  327. }
  328. // Copy to clipboard support.
  329. QString copyToClipboardText() const override;
  330. QString copyToClipboardContextItemText() const override;
  331. // Finds the corresponding button in the items markup struct.
  332. // If the button is not found it returns nullptr.
  333. // Note: it is possible that we will point to the different button
  334. // than the one was used when constructing the handler, but not a big deal.
  335. const HistoryMessageMarkupButton *getButton() const;
  336. const HistoryMessageMarkupButton *getUrlButton() const;
  337. // We hold only FullMsgId, not HistoryItem*, because all click handlers
  338. // are activated async and the item may be already destroyed.
  339. void setMessageId(const FullMsgId &msgId) {
  340. _itemId = msgId;
  341. }
  342. void onClick(ClickContext context) const override;
  343. private:
  344. const not_null<Data::Session*> _owner;
  345. FullMsgId _itemId;
  346. int _row = 0;
  347. int _column = 0;
  348. bool _fullDisplayed = true;
  349. // Returns the full text of the corresponding button.
  350. QString buttonText() const;
  351. };
  352. class ReplyKeyboard {
  353. private:
  354. struct Button;
  355. public:
  356. class Style {
  357. public:
  358. Style(const style::BotKeyboardButton &st) : _st(&st) {
  359. }
  360. virtual void startPaint(
  361. QPainter &p,
  362. const Ui::ChatStyle *st) const = 0;
  363. virtual const style::TextStyle &textStyle() const = 0;
  364. int buttonSkip() const;
  365. int buttonPadding() const;
  366. int buttonHeight() const;
  367. [[nodiscard]] virtual Images::CornersMaskRef buttonRounding(
  368. Ui::BubbleRounding outer,
  369. RectParts sides) const = 0;
  370. virtual void repaint(not_null<const HistoryItem*> item) const = 0;
  371. virtual ~Style() {
  372. }
  373. protected:
  374. virtual void paintButtonBg(
  375. QPainter &p,
  376. const Ui::ChatStyle *st,
  377. const QRect &rect,
  378. Ui::BubbleRounding rounding,
  379. float64 howMuchOver) const = 0;
  380. virtual void paintButtonIcon(
  381. QPainter &p,
  382. const Ui::ChatStyle *st,
  383. const QRect &rect,
  384. int outerWidth,
  385. HistoryMessageMarkupButton::Type type) const = 0;
  386. virtual void paintButtonLoading(
  387. QPainter &p,
  388. const Ui::ChatStyle *st,
  389. const QRect &rect,
  390. int outerWidth,
  391. Ui::BubbleRounding rounding) const = 0;
  392. virtual int minButtonWidth(
  393. HistoryMessageMarkupButton::Type type) const = 0;
  394. private:
  395. const style::BotKeyboardButton *_st;
  396. void paintButton(
  397. Painter &p,
  398. const Ui::ChatStyle *st,
  399. int outerWidth,
  400. const ReplyKeyboard::Button &button,
  401. Ui::BubbleRounding rounding) const;
  402. friend class ReplyKeyboard;
  403. };
  404. ReplyKeyboard(
  405. not_null<const HistoryItem*> item,
  406. std::unique_ptr<Style> &&s);
  407. ReplyKeyboard(const ReplyKeyboard &other) = delete;
  408. ReplyKeyboard &operator=(const ReplyKeyboard &other) = delete;
  409. bool isEnoughSpace(int width, const style::BotKeyboardButton &st) const;
  410. void setStyle(std::unique_ptr<Style> &&s);
  411. void resize(int width, int height);
  412. // what width and height will best fit this keyboard
  413. int naturalWidth() const;
  414. int naturalHeight() const;
  415. void paint(
  416. Painter &p,
  417. const Ui::ChatStyle *st,
  418. Ui::BubbleRounding rounding,
  419. int outerWidth,
  420. const QRect &clip) const;
  421. ClickHandlerPtr getLink(QPoint point) const;
  422. ClickHandlerPtr getLinkByIndex(int index) const;
  423. void clickHandlerActiveChanged(
  424. const ClickHandlerPtr &p,
  425. bool active);
  426. void clickHandlerPressedChanged(
  427. const ClickHandlerPtr &p,
  428. bool pressed,
  429. Ui::BubbleRounding rounding);
  430. void clearSelection();
  431. void updateMessageId();
  432. private:
  433. friend class Style;
  434. struct Button {
  435. Button();
  436. Button(Button &&other);
  437. Button &operator=(Button &&other);
  438. ~Button();
  439. Ui::Text::String text = { 1 };
  440. QRect rect;
  441. int characters = 0;
  442. float64 howMuchOver = 0.;
  443. HistoryMessageMarkupButton::Type type;
  444. std::shared_ptr<ReplyMarkupClickHandler> link;
  445. mutable std::unique_ptr<Ui::RippleAnimation> ripple;
  446. };
  447. struct ButtonCoords {
  448. int i, j;
  449. };
  450. void startAnimation(int i, int j, int direction);
  451. [[nodiscard]] bool hasFastButtonMode() const;
  452. ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p);
  453. bool selectedAnimationCallback(crl::time now);
  454. const not_null<const HistoryItem*> _item;
  455. int _width = 0;
  456. std::vector<std::vector<Button>> _rows;
  457. base::flat_map<int, crl::time> _animations;
  458. Ui::Animations::Basic _selectedAnimation;
  459. std::unique_ptr<Style> _st;
  460. ClickHandlerPtr _savedPressed;
  461. ClickHandlerPtr _savedActive;
  462. mutable QPoint _savedCoords;
  463. };
  464. // Special type of Component for the channel actions log.
  465. struct HistoryMessageLogEntryOriginal
  466. : public RuntimeComponent<HistoryMessageLogEntryOriginal, HistoryItem> {
  467. HistoryMessageLogEntryOriginal();
  468. HistoryMessageLogEntryOriginal(HistoryMessageLogEntryOriginal &&other);
  469. HistoryMessageLogEntryOriginal &operator=(HistoryMessageLogEntryOriginal &&other);
  470. ~HistoryMessageLogEntryOriginal();
  471. WebPageData *page = nullptr;
  472. };
  473. struct MessageFactcheck {
  474. TextWithEntities text;
  475. QString country;
  476. uint64 hash = 0;
  477. bool needCheck = false;
  478. [[nodiscard]] bool empty() const {
  479. return text.empty() && country.isEmpty() && !hash;
  480. }
  481. explicit operator bool() const {
  482. return !empty();
  483. }
  484. };
  485. [[nodiscard]] MessageFactcheck FromMTP(
  486. not_null<HistoryItem*> item,
  487. const tl::conditional<MTPFactCheck> &factcheck);
  488. [[nodiscard]] MessageFactcheck FromMTP(
  489. not_null<Main::Session*> session,
  490. const tl::conditional<MTPFactCheck> &factcheck);
  491. struct HistoryMessageFactcheck
  492. : public RuntimeComponent<HistoryMessageFactcheck, HistoryItem> {
  493. MessageFactcheck data;
  494. WebPageData *page = nullptr;
  495. bool requested = false;
  496. };
  497. struct HistoryMessageRestrictions
  498. : public RuntimeComponent<HistoryMessageRestrictions, HistoryItem> {
  499. std::vector<Data::UnavailableReason> reasons;
  500. };
  501. struct HistoryServiceData
  502. : public RuntimeComponent<HistoryServiceData, HistoryItem> {
  503. std::vector<ClickHandlerPtr> textLinks;
  504. };
  505. struct HistoryServiceDependentData {
  506. PeerId peerId = 0;
  507. HistoryItem *msg = nullptr;
  508. ClickHandlerPtr lnk;
  509. MsgId msgId = 0;
  510. MsgId topId = 0;
  511. bool topicPost = false;
  512. bool pendingResolve = false;
  513. bool requestedResolve = false;
  514. };
  515. struct HistoryServicePinned
  516. : public RuntimeComponent<HistoryServicePinned, HistoryItem>
  517. , public HistoryServiceDependentData {
  518. };
  519. struct HistoryServiceTopicInfo
  520. : public RuntimeComponent<HistoryServiceTopicInfo, HistoryItem>
  521. , public HistoryServiceDependentData {
  522. QString title;
  523. DocumentId iconId = 0;
  524. bool closed = false;
  525. bool reopened = false;
  526. bool reiconed = false;
  527. bool renamed = false;
  528. bool hidden = false;
  529. bool unhidden = false;
  530. [[nodiscard]] bool created() const {
  531. return !closed
  532. && !reopened
  533. && !reiconed
  534. && !renamed
  535. && !hidden
  536. && !unhidden;
  537. }
  538. };
  539. struct HistoryServiceGameScore
  540. : public RuntimeComponent<HistoryServiceGameScore, HistoryItem>
  541. , public HistoryServiceDependentData {
  542. int score = 0;
  543. };
  544. struct HistoryServicePayment
  545. : public RuntimeComponent<HistoryServicePayment, HistoryItem>
  546. , public HistoryServiceDependentData {
  547. QString slug;
  548. TextWithEntities amount;
  549. ClickHandlerPtr invoiceLink;
  550. bool recurringInit = false;
  551. bool recurringUsed = false;
  552. bool isCreditsCurrency = false;
  553. };
  554. struct HistoryServiceSameBackground
  555. : public RuntimeComponent<HistoryServiceSameBackground, HistoryItem>
  556. , public HistoryServiceDependentData {
  557. };
  558. struct HistoryServiceGiveawayResults
  559. : public RuntimeComponent<HistoryServiceGiveawayResults, HistoryItem>
  560. , public HistoryServiceDependentData {
  561. };
  562. struct HistoryServiceCustomLink
  563. : public RuntimeComponent<HistoryServiceCustomLink, HistoryItem> {
  564. ClickHandlerPtr link;
  565. };
  566. struct HistoryServicePaymentRefund
  567. : public RuntimeComponent<HistoryServicePaymentRefund, HistoryItem> {
  568. ClickHandlerPtr link;
  569. PeerData *peer = nullptr;
  570. QString transactionId;
  571. QString currency;
  572. uint64 amount = 0;
  573. };
  574. enum class HistorySelfDestructType {
  575. Photo,
  576. Video,
  577. };
  578. struct TimeToLiveSingleView {
  579. friend inline auto operator<=>(
  580. TimeToLiveSingleView,
  581. TimeToLiveSingleView) = default;
  582. friend inline bool operator==(
  583. TimeToLiveSingleView,
  584. TimeToLiveSingleView) = default;
  585. };
  586. struct HistoryServiceSelfDestruct
  587. : public RuntimeComponent<HistoryServiceSelfDestruct, HistoryItem> {
  588. using Type = HistorySelfDestructType;
  589. Type type = Type::Photo;
  590. std::variant<crl::time, TimeToLiveSingleView> timeToLive = crl::time();
  591. std::variant<crl::time, TimeToLiveSingleView> destructAt = crl::time();
  592. };
  593. struct HistoryServiceOngoingCall
  594. : public RuntimeComponent<HistoryServiceOngoingCall, HistoryItem> {
  595. CallId id = 0;
  596. ClickHandlerPtr link;
  597. rpl::lifetime lifetime;
  598. };
  599. struct HistoryServiceChatThemeChange
  600. : public RuntimeComponent<HistoryServiceChatThemeChange, HistoryItem> {
  601. ClickHandlerPtr link;
  602. };
  603. struct HistoryServiceTTLChange
  604. : public RuntimeComponent<HistoryServiceTTLChange, HistoryItem> {
  605. ClickHandlerPtr link;
  606. };
  607. class FileClickHandler;
  608. struct HistoryDocumentThumbed : public RuntimeComponent<HistoryDocumentThumbed, HistoryView::Document> {
  609. std::shared_ptr<FileClickHandler> linksavel;
  610. std::shared_ptr<FileClickHandler> linkopenwithl;
  611. std::shared_ptr<FileClickHandler> linkcancell;
  612. mutable QImage thumbnail;
  613. mutable QString link;
  614. int thumbw = 0;
  615. mutable int linkw = 0;
  616. mutable Ui::BubbleRounding rounding;
  617. mutable bool blurred : 1 = false;
  618. };
  619. struct HistoryDocumentCaptioned : public RuntimeComponent<HistoryDocumentCaptioned, HistoryView::Document> {
  620. HistoryDocumentCaptioned();
  621. Ui::Text::String caption;
  622. };
  623. struct HistoryDocumentNamed : public RuntimeComponent<HistoryDocumentNamed, HistoryView::Document> {
  624. Ui::Text::String name;
  625. };
  626. struct HistoryDocumentVoicePlayback {
  627. HistoryDocumentVoicePlayback(const HistoryView::Document *that);
  628. int32 position = 0;
  629. anim::value progress;
  630. Ui::Animations::Basic progressAnimation;
  631. };
  632. class HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice, HistoryView::Document> {
  633. // We don't use float64 because components should align to pointer even on 32bit systems.
  634. static constexpr float64 kFloatToIntMultiplier = 65536.;
  635. public:
  636. void ensurePlayback(const HistoryView::Document *interfaces) const;
  637. void checkPlaybackFinished() const;
  638. mutable std::unique_ptr<HistoryDocumentVoicePlayback> playback;
  639. std::shared_ptr<VoiceSeekClickHandler> seekl;
  640. mutable int lastDurationMs = 0;
  641. [[nodiscard]] bool seeking() const;
  642. void startSeeking();
  643. void stopSeeking();
  644. [[nodiscard]] float64 seekingStart() const;
  645. void setSeekingStart(float64 seekingStart) const;
  646. [[nodiscard]] float64 seekingCurrent() const;
  647. void setSeekingCurrent(float64 seekingCurrent);
  648. std::unique_ptr<HistoryView::TranscribeButton> transcribe;
  649. Ui::Text::String transcribeText;
  650. std::unique_ptr<Media::Player::RoundPainter> round;
  651. private:
  652. bool _seeking = false;
  653. mutable int _seekingStart = 0;
  654. mutable int _seekingCurrent = 0;
  655. };