notifications_manager_default.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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 "window/notifications_manager.h"
  9. #include "ui/effects/animations.h"
  10. #include "ui/text/text.h"
  11. #include "ui/rp_widget.h"
  12. #include "ui/userpic_view.h"
  13. #include "base/timer.h"
  14. #include "base/binary_guard.h"
  15. #include "base/object_ptr.h"
  16. #include <QtCore/QTimer>
  17. namespace Ui {
  18. class IconButton;
  19. class RoundButton;
  20. class InputField;
  21. } // namespace Ui
  22. namespace Window {
  23. namespace Notifications {
  24. namespace Default {
  25. namespace internal {
  26. class Widget;
  27. class Notification;
  28. class HideAllButton;
  29. } // namespace internal
  30. class Manager;
  31. std::unique_ptr<Manager> Create(System *system);
  32. class Manager final : public Notifications::Manager {
  33. public:
  34. Manager(System *system);
  35. ~Manager();
  36. [[nodiscard]] ManagerType type() const override {
  37. return ManagerType::Default;
  38. }
  39. template <typename Method>
  40. void enumerateNotifications(Method method) {
  41. for (const auto &notification : _notifications) {
  42. method(notification);
  43. }
  44. }
  45. private:
  46. friend class internal::Notification;
  47. friend class internal::HideAllButton;
  48. friend class internal::Widget;
  49. using Notification = internal::Notification;
  50. using HideAllButton = internal::HideAllButton;
  51. struct SessionSubscription {
  52. rpl::lifetime subscription;
  53. rpl::lifetime lifetime;
  54. };
  55. [[nodiscard]] QPixmap hiddenUserpicPlaceholder() const;
  56. void doUpdateAll() override;
  57. void doShowNotification(NotificationFields &&fields) override;
  58. void doClearAll() override;
  59. void doClearAllFast() override;
  60. void doClearFromTopic(not_null<Data::ForumTopic*> topic) override;
  61. void doClearFromHistory(not_null<History*> history) override;
  62. void doClearFromSession(not_null<Main::Session*> session) override;
  63. void doClearFromItem(not_null<HistoryItem*> item) override;
  64. bool doSkipToast() const override;
  65. void doMaybePlaySound(Fn<void()> playSound) override;
  66. void doMaybeFlashBounce(Fn<void()> flashBounce) override;
  67. void showNextFromQueue();
  68. void unlinkFromShown(Notification *remove);
  69. void startAllHiding();
  70. void stopAllHiding();
  71. void checkLastInput();
  72. void removeWidget(internal::Widget *remove);
  73. float64 demoMasterOpacity() const;
  74. void demoMasterOpacityCallback();
  75. void moveWidgets();
  76. void changeNotificationHeight(Notification *widget, int newHeight);
  77. void settingsChanged(ChangeType change);
  78. bool hasReplyingNotification() const;
  79. void subscribeToSession(not_null<Main::Session*> session);
  80. std::vector<std::unique_ptr<Notification>> _notifications;
  81. base::flat_map<
  82. not_null<Main::Session*>,
  83. SessionSubscription> _subscriptions;
  84. std::unique_ptr<HideAllButton> _hideAll;
  85. bool _positionsOutdated = false;
  86. base::Timer _inputCheckTimer;
  87. struct QueuedNotification {
  88. QueuedNotification(NotificationFields &&fields);
  89. not_null<History*> history;
  90. MsgId topicRootId = 0;
  91. not_null<PeerData*> peer;
  92. Data::ReactionId reaction;
  93. QString author;
  94. HistoryItem *item = nullptr;
  95. int forwardedCount = 0;
  96. bool fromScheduled = false;
  97. };
  98. std::deque<QueuedNotification> _queuedNotifications;
  99. Ui::Animations::Simple _demoMasterOpacity;
  100. bool _demoIsShown = false;
  101. mutable QPixmap _hiddenUserpicPlaceholder;
  102. rpl::lifetime _lifetime;
  103. };
  104. namespace internal {
  105. class Widget : public Ui::RpWidget {
  106. public:
  107. enum class Direction {
  108. Up,
  109. Down,
  110. };
  111. Widget(
  112. not_null<Manager*> manager,
  113. QPoint startPosition,
  114. int shift,
  115. Direction shiftDirection);
  116. bool isFadingIn() const {
  117. return _a_opacity.animating() && !_hiding;
  118. }
  119. void updateOpacity();
  120. void changeShift(int top);
  121. int currentShift() const {
  122. return _shift.current();
  123. }
  124. void updatePosition(QPoint startPosition, Direction shiftDirection);
  125. void addToHeight(int add);
  126. void addToShift(int add);
  127. protected:
  128. void hideSlow();
  129. void hideFast();
  130. void hideStop();
  131. QPoint computePosition(int height) const;
  132. virtual void updateGeometry(int x, int y, int width, int height);
  133. protected:
  134. [[nodiscard]] not_null<Manager*> manager() const {
  135. return _manager;
  136. }
  137. private:
  138. void opacityAnimationCallback();
  139. void moveByShift();
  140. void hideAnimated(float64 duration, const anim::transition &func);
  141. bool shiftAnimationCallback(crl::time now);
  142. const not_null<Manager*> _manager;
  143. bool _hiding = false;
  144. base::binary_guard _hidingDelayed;
  145. Ui::Animations::Simple _a_opacity;
  146. QPoint _startPosition;
  147. Direction _direction;
  148. anim::value _shift;
  149. Ui::Animations::Basic _shiftAnimation;
  150. };
  151. class Background : public TWidget {
  152. public:
  153. Background(QWidget *parent);
  154. protected:
  155. void paintEvent(QPaintEvent *e) override;
  156. };
  157. class Notification final : public Widget {
  158. public:
  159. Notification(
  160. not_null<Manager*> manager,
  161. not_null<History*> history,
  162. MsgId topicRootId,
  163. not_null<PeerData*> peer,
  164. const QString &author,
  165. HistoryItem *item,
  166. const Data::ReactionId &reaction,
  167. int forwardedCount,
  168. bool fromScheduled,
  169. QPoint startPosition,
  170. int shift,
  171. Direction shiftDirection);
  172. void startHiding();
  173. void stopHiding();
  174. void updateNotifyDisplay();
  175. void updatePeerPhoto();
  176. bool isUnlinked() const {
  177. return !_history;
  178. }
  179. bool isReplying() const {
  180. return _replyArea && !isUnlinked();
  181. }
  182. [[nodiscard]] History *maybeHistory() const {
  183. return _history;
  184. }
  185. // Called only by Manager.
  186. bool unlinkItem(HistoryItem *del);
  187. bool unlinkHistory(History *history = nullptr, MsgId topicRootId = 0);
  188. bool unlinkSession(not_null<Main::Session*> session);
  189. bool checkLastInput(
  190. bool hasReplyingNotifications,
  191. std::optional<crl::time> lastInputTime);
  192. protected:
  193. void enterEventHook(QEnterEvent *e) override;
  194. void leaveEventHook(QEvent *e) override;
  195. void paintEvent(QPaintEvent *e) override;
  196. void mousePressEvent(QMouseEvent *e) override;
  197. bool eventFilter(QObject *o, QEvent *e) override;
  198. private:
  199. void refreshLang();
  200. void updateReplyGeometry();
  201. bool canReply() const;
  202. void replyResized();
  203. void replyCancel();
  204. void unlinkHistoryInManager();
  205. void toggleActionButtons(bool visible);
  206. void prepareActionsCache();
  207. void showReplyField();
  208. void sendReply();
  209. void changeHeight(int newHeight);
  210. void updateGeometry(int x, int y, int width, int height) override;
  211. void actionsOpacityCallback();
  212. void repaintText();
  213. void paintTitle(Painter &p);
  214. void paintText(Painter &p);
  215. void customEmojiCallback();
  216. [[nodiscard]] Notifications::Manager::NotificationId myId() const;
  217. const not_null<PeerData*> _peer;
  218. QImage _cache;
  219. Ui::Text::String _titleCache;
  220. Ui::Text::String _textCache;
  221. QRect _titleRect;
  222. QRect _textRect;
  223. bool _hideReplyButton = false;
  224. bool _actionsVisible = false;
  225. bool _textsRepaintScheduled = false;
  226. Ui::Animations::Simple a_actionsOpacity;
  227. QPixmap _buttonsCache;
  228. crl::time _started;
  229. History *_history = nullptr;
  230. Data::ForumTopic *_topic = nullptr;
  231. MsgId _topicRootId = 0;
  232. Ui::PeerUserpicView _userpicView;
  233. QString _author;
  234. Data::ReactionId _reaction;
  235. HistoryItem *_item = nullptr;
  236. int _forwardedCount = 0;
  237. bool _fromScheduled = false;
  238. object_ptr<Ui::IconButton> _close;
  239. object_ptr<Ui::RoundButton> _reply;
  240. object_ptr<Background> _background = { nullptr };
  241. object_ptr<Ui::InputField> _replyArea = { nullptr };
  242. object_ptr<Ui::IconButton> _replySend = { nullptr };
  243. bool _waitingForInput = true;
  244. QTimer _hideTimer;
  245. int _replyPadding = 0;
  246. bool _userpicLoaded = false;
  247. };
  248. class HideAllButton : public Widget {
  249. public:
  250. HideAllButton(
  251. not_null<Manager*> manager,
  252. QPoint startPosition,
  253. int shift,
  254. Direction shiftDirection);
  255. void startHiding();
  256. void startHidingFast();
  257. void stopHiding();
  258. protected:
  259. void enterEventHook(QEnterEvent *e) override;
  260. void leaveEventHook(QEvent *e) override;
  261. void mousePressEvent(QMouseEvent *e) override;
  262. void mouseReleaseEvent(QMouseEvent *e) override;
  263. void paintEvent(QPaintEvent *e) override;
  264. private:
  265. bool _mouseOver = false;
  266. bool _mouseDown = false;
  267. };
  268. } // namespace internal
  269. } // namespace Default
  270. } // namespace Notifications
  271. } // namespace Window