gifs_list_widget.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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/tabbed_selector.h"
  9. #include "base/timer.h"
  10. #include "inline_bots/inline_bot_layout_item.h"
  11. #include "layout/layout_mosaic.h"
  12. #include <QtCore/QTimer>
  13. namespace style {
  14. struct ComposeIcons;
  15. } // namespace style
  16. namespace Api {
  17. struct SendOptions;
  18. } // namespace Api
  19. namespace InlineBots {
  20. namespace Layout {
  21. class ItemBase;
  22. } // namespace Layout
  23. class Result;
  24. } // namespace InlineBots
  25. namespace Ui {
  26. class PopupMenu;
  27. class RoundButton;
  28. class TabbedSearch;
  29. } // namespace Ui
  30. namespace Window {
  31. class SessionController;
  32. } // namespace Window
  33. namespace SendMenu {
  34. struct Details;
  35. } // namespace SendMenu
  36. namespace Data {
  37. class StickersSet;
  38. } // namespace Data
  39. namespace ChatHelpers {
  40. void AddGifAction(
  41. Fn<void(QString, Fn<void()> &&, const style::icon*)> callback,
  42. std::shared_ptr<Show> show,
  43. not_null<DocumentData*> document,
  44. const style::ComposeIcons *iconsOverride = nullptr);
  45. class StickersListFooter;
  46. struct StickerIcon;
  47. struct GifSection;
  48. struct GifsListDescriptor {
  49. std::shared_ptr<Show> show;
  50. Fn<bool()> paused;
  51. const style::EmojiPan *st = nullptr;
  52. };
  53. class GifsListWidget final
  54. : public TabbedSelector::Inner
  55. , public InlineBots::Layout::Context {
  56. public:
  57. GifsListWidget(
  58. QWidget *parent,
  59. not_null<Window::SessionController*> controller,
  60. PauseReason level);
  61. GifsListWidget(QWidget *parent, GifsListDescriptor &&descriptor);
  62. rpl::producer<FileChosen> fileChosen() const;
  63. rpl::producer<PhotoChosen> photoChosen() const;
  64. rpl::producer<InlineChosen> inlineResultChosen() const;
  65. void refreshRecent() override;
  66. void preloadImages() override;
  67. void clearSelection() override;
  68. object_ptr<TabbedSelector::InnerFooter> createFooter() override;
  69. void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) override;
  70. void inlineItemRepaint(const InlineBots::Layout::ItemBase *layout) override;
  71. bool inlineItemVisible(const InlineBots::Layout::ItemBase *layout) override;
  72. Data::FileOrigin inlineItemFileOrigin() override;
  73. void afterShown() override;
  74. void beforeHiding() override;
  75. void setInlineQueryPeer(PeerData *peer) {
  76. _inlineQueryPeer = peer;
  77. }
  78. void searchForGifs(const QString &query);
  79. void sendInlineRequest();
  80. void cancelled();
  81. rpl::producer<> cancelRequests() const;
  82. base::unique_qptr<Ui::PopupMenu> fillContextMenu(
  83. const SendMenu::Details &details) override;
  84. ~GifsListWidget();
  85. protected:
  86. void visibleTopBottomUpdated(
  87. int visibleTop,
  88. int visibleBottom) override;
  89. void mousePressEvent(QMouseEvent *e) override;
  90. void mouseReleaseEvent(QMouseEvent *e) override;
  91. void mouseMoveEvent(QMouseEvent *e) override;
  92. void paintEvent(QPaintEvent *e) override;
  93. void leaveEventHook(QEvent *e) override;
  94. void leaveToChildEvent(QEvent *e, QWidget *child) override;
  95. void enterFromChildEvent(QEvent *e, QWidget *child) override;
  96. TabbedSelector::InnerFooter *getFooter() const override;
  97. void processHideFinished() override;
  98. void processPanelHideFinished() override;
  99. int countDesiredHeight(int newWidth) override;
  100. private:
  101. enum class Section {
  102. Inlines,
  103. Gifs,
  104. };
  105. using InlineResult = InlineBots::Result;
  106. using InlineResults = std::vector<std::shared_ptr<InlineResult>>;
  107. using LayoutItem = InlineBots::Layout::ItemBase;
  108. struct InlineCacheEntry {
  109. QString nextOffset;
  110. InlineResults results;
  111. };
  112. void setupSearch();
  113. void clearHeavyData();
  114. void cancelGifsSearch();
  115. void switchToSavedGifs();
  116. void refreshSavedGifs();
  117. int refreshInlineRows(const InlineCacheEntry *results, bool resultsDeleted);
  118. void checkLoadMore();
  119. int32 showInlineRows(bool newResults);
  120. bool refreshInlineRows(int32 *added = 0);
  121. void inlineResultsDone(const MTPmessages_BotResults &result);
  122. void updateSelected();
  123. void paintInlineItems(Painter &p, QRect clip);
  124. void refreshIcons();
  125. [[nodiscard]] std::vector<StickerIcon> fillIcons();
  126. void updateInlineItems();
  127. void repaintItems(crl::time now = 0);
  128. void showPreview();
  129. void clearInlineRows(bool resultsDeleted);
  130. LayoutItem *layoutPrepareSavedGif(not_null<DocumentData*> document);
  131. LayoutItem *layoutPrepareInlineResult(
  132. std::shared_ptr<InlineResult> result);
  133. void deleteUnusedGifLayouts();
  134. void deleteUnusedInlineLayouts();
  135. int validateExistingInlineRows(const InlineResults &results);
  136. void selectInlineResult(
  137. int index,
  138. Api::SendOptions options,
  139. bool forceSend = false,
  140. TextWithTags caption = {});
  141. const std::shared_ptr<Show> _show;
  142. std::unique_ptr<Ui::TabbedSearch> _search;
  143. MTP::Sender _api;
  144. Section _section = Section::Gifs;
  145. crl::time _lastScrolledAt = 0;
  146. crl::time _lastUpdatedAt = 0;
  147. base::Timer _updateInlineItems;
  148. bool _inlineWithThumb = false;
  149. std::map<
  150. not_null<DocumentData*>,
  151. std::unique_ptr<LayoutItem>> _gifLayouts;
  152. std::map<
  153. not_null<InlineResult*>,
  154. std::unique_ptr<LayoutItem>> _inlineLayouts;
  155. StickersListFooter *_footer = nullptr;
  156. std::vector<GifSection> _sections;
  157. base::flat_map<uint64, std::unique_ptr<Data::StickersSet>> _fakeSets;
  158. uint64 _chosenSetId = 0;
  159. Mosaic::Layout::MosaicLayout<LayoutItem> _mosaic;
  160. int _selected = -1;
  161. int _pressed = -1;
  162. QPoint _lastMousePos;
  163. base::Timer _previewTimer;
  164. bool _previewShown = false;
  165. std::map<QString, std::unique_ptr<InlineCacheEntry>> _inlineCache;
  166. QTimer _inlineRequestTimer;
  167. UserData *_searchBot = nullptr;
  168. mtpRequestId _searchBotRequestId = 0;
  169. PeerData *_inlineQueryPeer = nullptr;
  170. QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
  171. mtpRequestId _inlineRequestId = 0;
  172. rpl::event_stream<FileChosen> _fileChosen;
  173. rpl::event_stream<PhotoChosen> _photoChosen;
  174. rpl::event_stream<InlineChosen> _inlineResultChosen;
  175. rpl::event_stream<> _cancelled;
  176. };
  177. } // namespace ChatHelpers