data_custom_emoji.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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/stickers/data_stickers_set.h"
  9. #include "ui/text/custom_emoji_instance.h"
  10. #include "base/timer.h"
  11. #include "base/weak_ptr.h"
  12. namespace Main {
  13. class Session;
  14. } // namespace Main
  15. namespace Data {
  16. class Session;
  17. class CustomEmojiLoader;
  18. enum class CustomEmojiSizeTag : uchar {
  19. Normal,
  20. Large,
  21. Isolated,
  22. SetIcon,
  23. kCount,
  24. };
  25. class CustomEmojiManager final : public base::has_weak_ptr {
  26. public:
  27. using SizeTag = CustomEmojiSizeTag;
  28. CustomEmojiManager(not_null<Session*> owner);
  29. ~CustomEmojiManager();
  30. [[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
  31. QStringView data,
  32. Fn<void()> update,
  33. SizeTag tag = SizeTag::Normal,
  34. int sizeOverride = 0);
  35. [[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
  36. DocumentId documentId,
  37. Fn<void()> update,
  38. SizeTag tag = SizeTag::Normal,
  39. int sizeOverride = 0);
  40. [[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
  41. not_null<DocumentData*> document,
  42. Fn<void()> update,
  43. SizeTag tag = SizeTag::Normal,
  44. int sizeOverride = 0);
  45. [[nodiscard]] Ui::Text::CustomEmojiFactory factory(
  46. SizeTag tag = SizeTag::Normal,
  47. int sizeOverride = 0);
  48. class Listener {
  49. public:
  50. virtual void customEmojiResolveDone(
  51. not_null<DocumentData*> document) = 0;
  52. };
  53. void resolve(QStringView data, not_null<Listener*> listener);
  54. void resolve(DocumentId documentId, not_null<Listener*> listener);
  55. void unregisterListener(not_null<Listener*> listener);
  56. [[nodiscard]] auto resolve(DocumentId documentId)
  57. -> rpl::producer<not_null<DocumentData*>, rpl::empty_error>;
  58. [[nodiscard]] std::unique_ptr<Ui::CustomEmoji::Loader> createLoader(
  59. not_null<DocumentData*> document,
  60. SizeTag tag,
  61. int sizeOverride = 0);
  62. [[nodiscard]] std::unique_ptr<Ui::CustomEmoji::Loader> createLoader(
  63. DocumentId documentId,
  64. SizeTag tag,
  65. int sizeOverride = 0);
  66. [[nodiscard]] QString lookupSetName(uint64 setId);
  67. [[nodiscard]] Main::Session &session() const;
  68. [[nodiscard]] Session &owner() const;
  69. [[nodiscard]] QString registerInternalEmoji(
  70. QImage emoji,
  71. QMargins padding = {},
  72. bool textColor = true);
  73. [[nodiscard]] QString registerInternalEmoji(
  74. const style::icon &icon,
  75. QMargins padding = {},
  76. bool textColor = true);
  77. [[nodiscard]] QString peerUserpicEmojiData(
  78. not_null<PeerData*> peer,
  79. QMargins padding = {},
  80. bool respectSavedRepliesEtc = false);
  81. [[nodiscard]] uint64 coloredSetId() const;
  82. [[nodiscard]] TextWithEntities creditsEmoji(QMargins padding = {});
  83. [[nodiscard]] TextWithEntities ministarEmoji(QMargins padding = {});
  84. private:
  85. static constexpr auto kSizeCount = int(SizeTag::kCount);
  86. struct InternalEmojiData {
  87. QImage image;
  88. bool textColor = true;
  89. };
  90. struct RepaintBunch {
  91. crl::time when = 0;
  92. std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances;
  93. };
  94. struct LoaderWithSetId {
  95. std::unique_ptr<Ui::CustomEmoji::Loader> loader;
  96. uint64 setId = 0;
  97. bool colored = false;
  98. };
  99. [[nodiscard]] LoaderWithSetId createLoaderWithSetId(
  100. not_null<DocumentData*> document,
  101. SizeTag tag,
  102. int sizeOverride = 0);
  103. [[nodiscard]] LoaderWithSetId createLoaderWithSetId(
  104. DocumentId documentId,
  105. SizeTag tag,
  106. int sizeOverride = 0);
  107. void request();
  108. void requestFinished();
  109. void repaintLater(
  110. not_null<Ui::CustomEmoji::Instance*> instance,
  111. Ui::CustomEmoji::RepaintRequest request);
  112. void scheduleRepaintTimer();
  113. bool checkEmptyRepaints();
  114. void invokeRepaints();
  115. void fillColoredFlags(not_null<DocumentData*> document);
  116. void processLoaders(not_null<DocumentData*> document);
  117. void processListeners(not_null<DocumentData*> document);
  118. void requestSetFor(not_null<DocumentData*> document);
  119. [[nodiscard]] Ui::CustomEmoji::Preview prepareNonExactPreview(
  120. DocumentId documentId,
  121. SizeTag tag,
  122. int sizeOverride) const;
  123. template <typename LoaderFactory>
  124. [[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
  125. DocumentId documentId,
  126. Fn<void()> update,
  127. SizeTag tag,
  128. int sizeOverride,
  129. LoaderFactory factory);
  130. [[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> internal(
  131. QStringView data);
  132. [[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> userpic(
  133. QStringView data,
  134. Fn<void()> update,
  135. int size);
  136. [[nodiscard]] static int SizeIndex(SizeTag tag);
  137. const not_null<Session*> _owner;
  138. std::array<
  139. base::flat_map<
  140. DocumentId,
  141. std::unique_ptr<Ui::CustomEmoji::Instance>>,
  142. kSizeCount> _instances;
  143. std::array<
  144. base::flat_map<
  145. DocumentId,
  146. std::vector<base::weak_ptr<CustomEmojiLoader>>>,
  147. kSizeCount> _loaders;
  148. base::flat_map<
  149. DocumentId,
  150. base::flat_set<not_null<Listener*>>> _resolvers;
  151. base::flat_map<
  152. not_null<Listener*>,
  153. base::flat_set<DocumentId>> _listeners;
  154. base::flat_set<DocumentId> _pendingForRequest;
  155. mtpRequestId _requestId = 0;
  156. uint64 _coloredSetId = 0;
  157. base::flat_map<crl::time, RepaintBunch> _repaints;
  158. crl::time _repaintNext = 0;
  159. base::Timer _repaintTimer;
  160. bool _repaintTimerScheduled = false;
  161. bool _requestSetsScheduled = false;
  162. std::vector<InternalEmojiData> _internalEmoji;
  163. base::flat_map<not_null<const style::icon*>, QString> _iconEmoji;
  164. #if 0 // inject-to-on_main
  165. crl::time _repaintsLastAdded = 0;
  166. rpl::lifetime _repaintsLifetime;
  167. #endif
  168. rpl::lifetime _lifetime;
  169. };
  170. [[nodiscard]] int FrameSizeFromTag(CustomEmojiManager::SizeTag tag);
  171. [[nodiscard]] QString SerializeCustomEmojiId(DocumentId id);
  172. [[nodiscard]] QString SerializeCustomEmojiId(
  173. not_null<DocumentData*> document);
  174. [[nodiscard]] DocumentId ParseCustomEmojiData(QStringView data);
  175. [[nodiscard]] TextWithEntities SingleCustomEmoji(DocumentId id);
  176. [[nodiscard]] TextWithEntities SingleCustomEmoji(
  177. not_null<DocumentData*> document);
  178. [[nodiscard]] bool AllowEmojiWithoutPremium(
  179. not_null<PeerData*> peer,
  180. DocumentData *exactEmoji = nullptr);
  181. void InsertCustomEmoji(
  182. not_null<Ui::InputField*> field,
  183. not_null<DocumentData*> document);
  184. [[nodiscard]] Ui::Text::CustomEmojiFactory ReactedMenuFactory(
  185. not_null<Main::Session*> session);
  186. [[nodiscard]] QString CollectibleCustomEmojiId(
  187. Data::EmojiStatusCollectible &data);
  188. [[nodiscard]] QString EmojiStatusCustomId(const EmojiStatusId &id);
  189. } // namespace Data