emoji_suggestions_widget.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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 "ui/effects/animations.h"
  9. #include "ui/rp_widget.h"
  10. #include "base/unique_qptr.h"
  11. #include "base/timer.h"
  12. #include <QtWidgets/QTextEdit>
  13. namespace style {
  14. struct EmojiSuggestions;
  15. } // namespace style
  16. namespace Main {
  17. class Session;
  18. } // namespace Main
  19. namespace Ui {
  20. class InnerDropdown;
  21. class InputField;
  22. } // namespace Ui
  23. namespace Ui::Text {
  24. class CustomEmoji;
  25. } // namespace Ui::Text
  26. namespace Ui::Emoji {
  27. class SuggestionsWidget;
  28. using SuggestionsQuery = std::variant<QString, EmojiPtr>;
  29. class SuggestionsController final : public QObject {
  30. public:
  31. struct Options {
  32. bool suggestExactFirstWord = true;
  33. bool suggestCustomEmoji = false;
  34. Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium;
  35. const style::EmojiSuggestions *st = nullptr;
  36. };
  37. SuggestionsController(
  38. not_null<QWidget*> parent,
  39. not_null<QWidget*> outer,
  40. not_null<QTextEdit*> field,
  41. not_null<Main::Session*> session,
  42. const Options &options);
  43. void raise();
  44. void setReplaceCallback(Fn<void(
  45. int from,
  46. int till,
  47. const QString &replacement,
  48. const QString &customEmojiData)> callback);
  49. static not_null<SuggestionsController*> Init(
  50. not_null<QWidget*> outer,
  51. not_null<Ui::InputField*> field,
  52. not_null<Main::Session*> session) {
  53. return Init(outer, field, session, {});
  54. }
  55. static not_null<SuggestionsController*> Init(
  56. not_null<QWidget*> outer,
  57. not_null<Ui::InputField*> field,
  58. not_null<Main::Session*> session,
  59. const Options &options);
  60. private:
  61. void handleCursorPositionChange();
  62. void handleTextChange();
  63. void showWithQuery(SuggestionsQuery query);
  64. [[nodiscard]] SuggestionsQuery getEmojiQuery();
  65. void suggestionsUpdated(bool visible);
  66. void updateGeometry();
  67. void updateForceHidden();
  68. void replaceCurrent(
  69. const QString &replacement,
  70. const QString &customEmojiData);
  71. bool fieldFilter(not_null<QEvent*> event);
  72. bool outerFilter(not_null<QEvent*> event);
  73. const style::EmojiSuggestions &_st;
  74. bool _shown = false;
  75. bool _forceHidden = false;
  76. int _queryStartPosition = 0;
  77. int _emojiQueryLength = 0;
  78. bool _ignoreCursorPositionChange = false;
  79. bool _textChangeAfterKeyPress = false;
  80. QPointer<QTextEdit> _field;
  81. const not_null<Main::Session*> _session;
  82. Fn<void(
  83. int from,
  84. int till,
  85. const QString &replacement,
  86. const QString &customEmojiData)> _replaceCallback;
  87. base::unique_qptr<InnerDropdown> _container;
  88. QPointer<SuggestionsWidget> _suggestions;
  89. base::unique_qptr<QObject> _fieldFilter;
  90. base::unique_qptr<QObject> _outerFilter;
  91. base::Timer _showExactTimer;
  92. bool _keywordsRefreshed = false;
  93. SuggestionsQuery _lastShownQuery;
  94. Options _options;
  95. rpl::lifetime _lifetime;
  96. };
  97. } // namespace Ui::Emoji