field_autocomplete.h 5.4 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 "api/api_common.h"
  9. #include "ui/effects/animations.h"
  10. #include "ui/effects/message_sending_animation_common.h"
  11. #include "ui/rp_widget.h"
  12. #include "base/timer.h"
  13. #include "base/object_ptr.h"
  14. namespace style {
  15. struct EmojiPan;
  16. } // namespace style
  17. namespace Ui {
  18. class PopupMenu;
  19. class ScrollArea;
  20. class InputField;
  21. } // namespace Ui
  22. namespace Lottie {
  23. class SinglePlayer;
  24. class FrameRenderer;
  25. } // namespace Lottie;
  26. namespace Main {
  27. class Session;
  28. } // namespace Main
  29. namespace Window {
  30. class SessionController;
  31. } // namespace Window
  32. namespace Data {
  33. class DocumentMedia;
  34. } // namespace Data
  35. namespace SendMenu {
  36. struct Details;
  37. } // namespace SendMenu
  38. namespace ChatHelpers {
  39. struct ComposeFeatures;
  40. struct FileChosen;
  41. class Show;
  42. enum class FieldAutocompleteChooseMethod {
  43. ByEnter,
  44. ByTab,
  45. ByClick,
  46. };
  47. class FieldAutocomplete final : public Ui::RpWidget {
  48. public:
  49. FieldAutocomplete(
  50. QWidget *parent,
  51. std::shared_ptr<Show> show,
  52. const style::EmojiPan *stOverride = nullptr);
  53. ~FieldAutocomplete();
  54. [[nodiscard]] std::shared_ptr<Show> uiShow() const;
  55. bool clearFilteredBotCommands();
  56. void showFiltered(
  57. not_null<PeerData*> peer,
  58. QString query,
  59. bool addInlineBots);
  60. void showStickers(EmojiPtr emoji);
  61. [[nodiscard]] EmojiPtr stickersEmoji() const;
  62. void setBoundings(QRect boundings);
  63. [[nodiscard]] const QString &filter() const;
  64. [[nodiscard]] ChatData *chat() const;
  65. [[nodiscard]] ChannelData *channel() const;
  66. [[nodiscard]] UserData *user() const;
  67. [[nodiscard]] int32 innerTop();
  68. [[nodiscard]] int32 innerBottom();
  69. bool eventFilter(QObject *obj, QEvent *e) override;
  70. using ChooseMethod = FieldAutocompleteChooseMethod;
  71. struct MentionChosen {
  72. not_null<UserData*> user;
  73. QString mention;
  74. ChooseMethod method = ChooseMethod::ByEnter;
  75. };
  76. struct HashtagChosen {
  77. QString hashtag;
  78. ChooseMethod method = ChooseMethod::ByEnter;
  79. };
  80. struct BotCommandChosen {
  81. not_null<UserData*> user;
  82. QString command;
  83. ChooseMethod method = ChooseMethod::ByEnter;
  84. };
  85. using StickerChosen = FileChosen;
  86. enum class Type {
  87. Mentions,
  88. Hashtags,
  89. BotCommands,
  90. Stickers,
  91. };
  92. bool chooseSelected(ChooseMethod method) const;
  93. [[nodiscard]] bool stickersShown() const {
  94. return !_srows.empty();
  95. }
  96. [[nodiscard]] bool overlaps(const QRect &globalRect) {
  97. if (isHidden() || !testAttribute(Qt::WA_OpaquePaintEvent)) {
  98. return false;
  99. }
  100. return rect().contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
  101. }
  102. void setModerateKeyActivateCallback(Fn<bool(int)> callback) {
  103. _moderateKeyActivateCallback = std::move(callback);
  104. }
  105. void setSendMenuDetails(Fn<SendMenu::Details()> &&callback);
  106. void hideFast();
  107. void showAnimated();
  108. void hideAnimated();
  109. void requestRefresh();
  110. [[nodiscard]] rpl::producer<> refreshRequests() const;
  111. void requestStickersUpdate();
  112. [[nodiscard]] rpl::producer<> stickersUpdateRequests() const;
  113. [[nodiscard]] rpl::producer<MentionChosen> mentionChosen() const;
  114. [[nodiscard]] rpl::producer<HashtagChosen> hashtagChosen() const;
  115. [[nodiscard]] rpl::producer<BotCommandChosen> botCommandChosen() const;
  116. [[nodiscard]] rpl::producer<StickerChosen> stickerChosen() const;
  117. [[nodiscard]] rpl::producer<Type> choosingProcesses() const;
  118. protected:
  119. void paintEvent(QPaintEvent *e) override;
  120. private:
  121. class Inner;
  122. friend class Inner;
  123. struct StickerSuggestion;
  124. struct MentionRow;
  125. struct BotCommandRow;
  126. using HashtagRows = std::vector<QString>;
  127. using BotCommandRows = std::vector<BotCommandRow>;
  128. using StickerRows = std::vector<StickerSuggestion>;
  129. using MentionRows = std::vector<MentionRow>;
  130. void animationCallback();
  131. void hideFinish();
  132. void updateFiltered(bool resetScroll = false);
  133. void recount(bool resetScroll = false);
  134. StickerRows getStickerSuggestions();
  135. const std::shared_ptr<Show> _show;
  136. const not_null<Main::Session*> _session;
  137. const style::EmojiPan &_st;
  138. QPixmap _cache;
  139. MentionRows _mrows;
  140. HashtagRows _hrows;
  141. BotCommandRows _brows;
  142. StickerRows _srows;
  143. void rowsUpdated(
  144. MentionRows &&mrows,
  145. HashtagRows &&hrows,
  146. BotCommandRows &&brows,
  147. StickerRows &&srows,
  148. bool resetScroll);
  149. object_ptr<Ui::ScrollArea> _scroll;
  150. QPointer<Inner> _inner;
  151. ChatData *_chat = nullptr;
  152. UserData *_user = nullptr;
  153. ChannelData *_channel = nullptr;
  154. EmojiPtr _emoji;
  155. uint64 _stickersSeed = 0;
  156. Type _type = Type::Mentions;
  157. QString _filter;
  158. QRect _boundings;
  159. bool _addInlineBots;
  160. bool _hiding = false;
  161. Ui::Animations::Simple _a_opacity;
  162. rpl::event_stream<> _refreshRequests;
  163. rpl::event_stream<> _stickersUpdateRequests;
  164. Fn<bool(int)> _moderateKeyActivateCallback;
  165. };
  166. struct FieldAutocompleteDescriptor {
  167. not_null<QWidget*> parent;
  168. std::shared_ptr<Show> show;
  169. not_null<Ui::InputField*> field;
  170. const style::EmojiPan *stOverride = nullptr;
  171. not_null<PeerData*> peer;
  172. Fn<ComposeFeatures()> features;
  173. Fn<SendMenu::Details()> sendMenuDetails;
  174. Fn<void()> stickerChoosing;
  175. Fn<void(FileChosen&&)> stickerChosen;
  176. Fn<void(TextWithTags)> setText;
  177. Fn<void(QString)> sendBotCommand;
  178. Fn<void(QString)> processShortcut;
  179. Fn<bool(int)> moderateKeyActivateCallback;
  180. };
  181. void InitFieldAutocomplete(
  182. std::unique_ptr<FieldAutocomplete> &autocomplete,
  183. FieldAutocompleteDescriptor &&descriptor);
  184. } // namespace ChatHelpers