stickers_list_widget.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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 "chat_helpers/compose/compose_features.h"
  9. #include "chat_helpers/tabbed_selector.h"
  10. #include "data/stickers/data_stickers.h"
  11. #include "ui/round_rect.h"
  12. #include "base/variant.h"
  13. #include "base/timer.h"
  14. class StickerPremiumMark;
  15. namespace Main {
  16. class Session;
  17. } // namespace Main
  18. namespace Window {
  19. class SessionController;
  20. } // namespace Window
  21. namespace Ui {
  22. class LinkButton;
  23. class PopupMenu;
  24. class RippleAnimation;
  25. class BoxContent;
  26. class PathShiftGradient;
  27. class TabbedSearch;
  28. } // namespace Ui
  29. namespace Lottie {
  30. class Animation;
  31. class MultiPlayer;
  32. class FrameRenderer;
  33. } // namespace Lottie
  34. namespace Data {
  35. class DocumentMedia;
  36. class StickersSet;
  37. } // namespace Data
  38. namespace Media::Clip {
  39. class ReaderPointer;
  40. enum class Notification;
  41. } // namespace Media::Clip
  42. namespace style {
  43. struct EmojiPan;
  44. struct FlatLabel;
  45. } // namespace style
  46. namespace ChatHelpers {
  47. struct StickerIcon;
  48. enum class ValidateIconAnimations;
  49. class StickersListFooter;
  50. class LocalStickersManager;
  51. enum class StickersListMode {
  52. Full,
  53. Masks,
  54. UserpicBuilder,
  55. ChatIntro,
  56. MessageEffects,
  57. };
  58. struct StickerCustomRecentDescriptor {
  59. not_null<DocumentData*> document;
  60. QString cornerEmoji;
  61. };
  62. struct StickersListDescriptor {
  63. std::shared_ptr<Show> show;
  64. StickersListMode mode = StickersListMode::Full;
  65. Fn<bool()> paused;
  66. std::vector<StickerCustomRecentDescriptor> customRecentList;
  67. const style::EmojiPan *st = nullptr;
  68. ComposeFeatures features;
  69. };
  70. class StickersListWidget final : public TabbedSelector::Inner {
  71. public:
  72. using Mode = StickersListMode;
  73. StickersListWidget(
  74. QWidget *parent,
  75. not_null<Window::SessionController*> controller,
  76. PauseReason level,
  77. Mode mode = Mode::Full);
  78. StickersListWidget(
  79. QWidget *parent,
  80. StickersListDescriptor &&descriptor);
  81. rpl::producer<FileChosen> chosen() const;
  82. rpl::producer<> scrollUpdated() const;
  83. rpl::producer<TabbedSelector::Action> choosingUpdated() const;
  84. void refreshRecent() override;
  85. void preloadImages() override;
  86. void clearSelection() override;
  87. object_ptr<TabbedSelector::InnerFooter> createFooter() override;
  88. void showStickerSet(uint64 setId);
  89. void showMegagroupSet(ChannelData *megagroup);
  90. void afterShown() override;
  91. void beforeHiding() override;
  92. void refreshStickers();
  93. std::vector<StickerIcon> fillIcons();
  94. uint64 currentSet(int yOffset) const;
  95. void sendSearchRequest();
  96. void searchForSets(const QString &query, std::vector<EmojiPtr> emoji);
  97. std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
  98. base::unique_qptr<Ui::PopupMenu> fillContextMenu(
  99. const SendMenu::Details &details) override;
  100. bool mySetsEmpty() const;
  101. void applySearchQuery(std::vector<QString> &&query);
  102. [[nodiscard]] rpl::producer<int> recentShownCount() const;
  103. ~StickersListWidget();
  104. protected:
  105. void visibleTopBottomUpdated(
  106. int visibleTop,
  107. int visibleBottom) override;
  108. void mousePressEvent(QMouseEvent *e) override;
  109. void mouseReleaseEvent(QMouseEvent *e) override;
  110. void mouseMoveEvent(QMouseEvent *e) override;
  111. void resizeEvent(QResizeEvent *e) override;
  112. void paintEvent(QPaintEvent *e) override;
  113. void leaveEventHook(QEvent *e) override;
  114. void leaveToChildEvent(QEvent *e, QWidget *child) override;
  115. void enterFromChildEvent(QEvent *e, QWidget *child) override;
  116. TabbedSelector::InnerFooter *getFooter() const override;
  117. void processHideFinished() override;
  118. void processPanelHideFinished() override;
  119. int countDesiredHeight(int newWidth) override;
  120. private:
  121. struct Sticker;
  122. struct Set;
  123. enum class Section {
  124. Featured,
  125. Stickers,
  126. Search,
  127. };
  128. struct OverSticker {
  129. int section = 0;
  130. int index = 0;
  131. bool overDelete = false;
  132. inline bool operator==(OverSticker other) const {
  133. return (section == other.section)
  134. && (index == other.index)
  135. && (overDelete == other.overDelete);
  136. }
  137. inline bool operator!=(OverSticker other) const {
  138. return !(*this == other);
  139. }
  140. };
  141. struct OverSet {
  142. int section = 0;
  143. inline bool operator==(OverSet other) const {
  144. return (section == other.section);
  145. }
  146. inline bool operator!=(OverSet other) const {
  147. return !(*this == other);
  148. }
  149. };
  150. struct OverButton {
  151. int section = 0;
  152. inline bool operator==(OverButton other) const {
  153. return (section == other.section);
  154. }
  155. inline bool operator!=(OverButton other) const {
  156. return !(*this == other);
  157. }
  158. };
  159. struct OverGroupAdd {
  160. inline bool operator==(OverGroupAdd other) const {
  161. return true;
  162. }
  163. inline bool operator!=(OverGroupAdd other) const {
  164. return !(*this == other);
  165. }
  166. };
  167. using OverState = std::variant<
  168. v::null_t,
  169. OverSticker,
  170. OverSet,
  171. OverButton,
  172. OverGroupAdd>;
  173. struct SectionInfo {
  174. int section = 0;
  175. int count = 0;
  176. int top = 0;
  177. int rowsCount = 0;
  178. int rowsTop = 0;
  179. int rowsBottom = 0;
  180. };
  181. struct FeaturedSet {
  182. uint64 id = 0;
  183. Data::StickersSetFlags flags;
  184. std::vector<Sticker> stickers;
  185. };
  186. static std::vector<Sticker> PrepareStickers(
  187. const QVector<DocumentData*> &pack,
  188. bool skipPremium);
  189. void setupSearch();
  190. void preloadMoreOfficial();
  191. QSize boundingBoxSize() const;
  192. template <typename Callback>
  193. bool enumerateSections(Callback callback) const;
  194. SectionInfo sectionInfo(int section) const;
  195. SectionInfo sectionInfoByOffset(int yOffset) const;
  196. void setSection(Section section);
  197. void displaySet(uint64 setId);
  198. void removeMegagroupSet(bool locally);
  199. void removeSet(uint64 setId);
  200. void refreshMySets();
  201. void refreshFeaturedSets();
  202. void refreshSearchSets();
  203. void refreshSearchIndex();
  204. bool setHasTitle(const Set &set) const;
  205. bool stickerHasDeleteButton(const Set &set, int index) const;
  206. [[nodiscard]] std::vector<Sticker> collectRecentStickers();
  207. [[nodiscard]] std::vector<Sticker> collectCustomRecents();
  208. void refreshRecentStickers(bool resize = true);
  209. void refreshEffects();
  210. void refreshFavedStickers();
  211. enum class GroupStickersPlace {
  212. Visible,
  213. Hidden,
  214. };
  215. void refreshMegagroupStickers(GroupStickersPlace place);
  216. void refreshSettingsVisibility();
  217. void updateSelected();
  218. void setSelected(OverState newSelected);
  219. void setPressed(OverState newPressed);
  220. [[nodiscard]] std::unique_ptr<Ui::RippleAnimation> createButtonRipple(
  221. int section);
  222. [[nodiscard]] QPoint buttonRippleTopLeft(int section) const;
  223. [[nodiscard]] std::vector<Set> &shownSets();
  224. [[nodiscard]] const std::vector<Set> &shownSets() const;
  225. [[nodiscard]] int featuredRowHeight() const;
  226. void checkVisibleFeatured(int visibleTop, int visibleBottom);
  227. void readVisibleFeatured(int visibleTop, int visibleBottom);
  228. void paintStickers(Painter &p, QRect clip);
  229. void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected);
  230. void paintSticker(
  231. Painter &p,
  232. Set &set,
  233. int y,
  234. int section,
  235. int index,
  236. crl::time now,
  237. bool paused,
  238. bool selected,
  239. bool deleteSelected);
  240. void paintEmptySearchResults(Painter &p);
  241. void ensureLottiePlayer(Set &set);
  242. void setupLottie(Set &set, int section, int index);
  243. void setupWebm(Set &set, int section, int index);
  244. void clipCallback(
  245. Media::Clip::Notification notification,
  246. uint64 setId,
  247. not_null<DocumentData*> document,
  248. int indexHint);
  249. [[nodiscard]] bool itemVisible(const SectionInfo &info, int index) const;
  250. void markLottieFrameShown(Set &set);
  251. void checkVisibleLottie();
  252. void pauseInvisibleLottieIn(const SectionInfo &info);
  253. void takeHeavyData(std::vector<Set> &to, std::vector<Set> &from);
  254. void takeHeavyData(Set &to, Set &from);
  255. void takeHeavyData(Sticker &to, Sticker &from);
  256. void clearHeavyIn(Set &set, bool clearSavedFrames = true);
  257. void clearHeavyData();
  258. void updateItems();
  259. void updateSets();
  260. void repaintItems(crl::time now = 0);
  261. void updateSet(const SectionInfo &info);
  262. void repaintItems(
  263. const SectionInfo &info,
  264. crl::time now);
  265. [[nodiscard]] int stickersRight() const;
  266. [[nodiscard]] bool featuredHasAddButton(int index) const;
  267. [[nodiscard]] QRect featuredAddRect(int index) const;
  268. [[nodiscard]] QRect featuredAddRect(
  269. const SectionInfo &info,
  270. bool installedSet) const;
  271. [[nodiscard]] bool hasRemoveButton(int index) const;
  272. [[nodiscard]] QRect removeButtonRect(int index) const;
  273. [[nodiscard]] QRect removeButtonRect(const SectionInfo &info) const;
  274. [[nodiscard]] int megagroupSetInfoLeft() const;
  275. void refreshMegagroupSetGeometry();
  276. [[nodiscard]] QRect megagroupSetButtonRectFinal() const;
  277. [[nodiscard]] const Data::StickersSetsOrder &defaultSetsOrder() const;
  278. [[nodiscard]] Data::StickersSetsOrder &defaultSetsOrderRef();
  279. void filterEffectsByEmoji(const std::vector<EmojiPtr> &emoji);
  280. enum class AppendSkip {
  281. None,
  282. Archived,
  283. Installed,
  284. };
  285. bool appendSet(
  286. std::vector<Set> &to,
  287. uint64 setId,
  288. bool externalLayout,
  289. AppendSkip skip = AppendSkip::None);
  290. int stickersLeft() const;
  291. QRect stickerRect(int section, int sel);
  292. void removeRecentSticker(int section, int index);
  293. void removeFavedSticker(int section, int index);
  294. void setColumnCount(int count);
  295. void refreshFooterIcons();
  296. void refreshIcons(ValidateIconAnimations animations);
  297. void showStickerSetBox(
  298. not_null<DocumentData*> document,
  299. uint64 setId);
  300. void cancelSetsSearch();
  301. void showSearchResults();
  302. void searchResultsDone(const MTPmessages_FoundStickerSets &result);
  303. void refreshSearchRows();
  304. void refreshSearchRows(const std::vector<uint64> *cloudSets);
  305. void fillFilteredStickersRow();
  306. void fillLocalSearchRows(const QString &query);
  307. void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
  308. void addSearchRow(not_null<Data::StickersSet*> set);
  309. void toggleSearchLoading(bool loading);
  310. void showPreview();
  311. Ui::MessageSendingAnimationFrom messageSentAnimationInfo(
  312. int section,
  313. int index,
  314. not_null<DocumentData*> document);
  315. const Mode _mode;
  316. const std::shared_ptr<Show> _show;
  317. const ComposeFeatures _features;
  318. Ui::RoundRect _overBg;
  319. std::unique_ptr<Ui::TabbedSearch> _search;
  320. MTP::Sender _api;
  321. std::unique_ptr<LocalStickersManager> _localSetsManager;
  322. ChannelData *_megagroupSet = nullptr;
  323. uint64 _megagroupSetIdRequested = 0;
  324. std::vector<StickerCustomRecentDescriptor> _customRecentIds;
  325. std::vector<Set> _mySets;
  326. std::vector<Set> _officialSets;
  327. std::vector<Set> _searchSets;
  328. int _featuredSetsCount = 0;
  329. std::vector<bool> _custom;
  330. std::vector<EmojiPtr> _cornerEmoji;
  331. base::flat_set<not_null<DocumentData*>> _favedStickersMap;
  332. std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
  333. bool _paintAsPremium = false;
  334. bool _showingSetById = false;
  335. crl::time _lastScrolledAt = 0;
  336. crl::time _lastFullUpdatedAt = 0;
  337. mtpRequestId _officialRequestId = 0;
  338. int _officialOffset = 0;
  339. Section _section = Section::Stickers;
  340. const bool _isMasks;
  341. const bool _isEffects;
  342. base::Timer _updateItemsTimer;
  343. base::Timer _updateSetsTimer;
  344. base::flat_set<uint64> _repaintSetsIds;
  345. StickersListFooter *_footer = nullptr;
  346. int _rowsLeft = 0;
  347. int _columnCount = 1;
  348. QSize _singleSize;
  349. OverState _selected;
  350. OverState _pressed;
  351. QPoint _lastMousePosition;
  352. Ui::RoundRect _trendingAddBgOver, _trendingAddBg, _inactiveButtonBg;
  353. Ui::RoundRect _groupCategoryAddBgOver, _groupCategoryAddBg;
  354. const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
  355. Ui::Text::String _megagroupSetAbout;
  356. QString _megagroupSetButtonText;
  357. int _megagroupSetButtonTextWidth = 0;
  358. QRect _megagroupSetButtonRect;
  359. std::unique_ptr<Ui::RippleAnimation> _megagroupSetButtonRipple;
  360. QString _addText;
  361. int _addWidth;
  362. QString _installedText;
  363. int _installedWidth;
  364. object_ptr<Ui::LinkButton> _settings;
  365. base::Timer _previewTimer;
  366. bool _previewShown = false;
  367. std::unique_ptr<StickerPremiumMark> _premiumMark;
  368. std::vector<not_null<DocumentData*>> _filteredStickers;
  369. std::vector<EmojiPtr> _filterStickersCornerEmoji;
  370. rpl::variable<int> _recentShownCount;
  371. std::map<QString, std::vector<uint64>> _searchCache;
  372. std::vector<std::pair<uint64, QStringList>> _searchIndex;
  373. base::Timer _searchRequestTimer;
  374. QString _searchQuery, _searchNextQuery;
  375. mtpRequestId _searchRequestId = 0;
  376. rpl::event_stream<FileChosen> _chosen;
  377. rpl::event_stream<> _scrollUpdated;
  378. rpl::event_stream<TabbedSelector::Action> _choosingUpdated;
  379. };
  380. [[nodiscard]] object_ptr<Ui::BoxContent> MakeConfirmRemoveSetBox(
  381. not_null<Main::Session*> session,
  382. const style::FlatLabel &st,
  383. uint64 setId);
  384. } // namespace ChatHelpers