/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "window/notifications_manager.h" #include "ui/effects/animations.h" #include "base/timer.h" namespace Ui { class IconButton; class RoundButton; class InputField; } // namespace Ui namespace Window { namespace Notifications { namespace Default { namespace internal { class Widget; class Notification; class HideAllButton; } // namespace internal class Manager; std::unique_ptr Create(System *system); class Manager : public Notifications::Manager, private base::Subscriber { public: Manager(System *system); template void enumerateNotifications(Method method) { for_const (auto ¬ification, _notifications) { method(notification); } } ~Manager(); private: friend class internal::Notification; friend class internal::HideAllButton; friend class internal::Widget; using Notification = internal::Notification; using HideAllButton = internal::HideAllButton; QPixmap hiddenUserpicPlaceholder() const; void doUpdateAll() override; void doShowNotification(HistoryItem *item, int forwardedCount) override; void doClearAll() override; void doClearAllFast() override; void doClearFromHistory(History *history) override; void doClearFromItem(HistoryItem *item) override; void showNextFromQueue(); void unlinkFromShown(Notification *remove); void startAllHiding(); void stopAllHiding(); void checkLastInput(); void removeWidget(internal::Widget *remove); float64 demoMasterOpacity() const; void demoMasterOpacityCallback(); void moveWidgets(); void changeNotificationHeight(Notification *widget, int newHeight); void settingsChanged(ChangeType change); bool hasReplyingNotification() const; std::vector> _notifications; std::unique_ptr _hideAll; bool _positionsOutdated = false; base::Timer _inputCheckTimer; struct QueuedNotification { QueuedNotification(not_null item, int forwardedCount); not_null history; not_null peer; PeerData *author; HistoryItem *item; int forwardedCount; }; std::deque _queuedNotifications; Ui::Animations::Simple _demoMasterOpacity; mutable QPixmap _hiddenUserpicPlaceholder; }; namespace internal { class Widget : public TWidget, protected base::Subscriber { public: enum class Direction { Up, Down, }; Widget(Manager *manager, QPoint startPosition, int shift, Direction shiftDirection); bool isShowing() const { return _a_opacity.animating() && !_hiding; } void updateOpacity(); void changeShift(int top); int currentShift() const { return _shift.current(); } void updatePosition(QPoint startPosition, Direction shiftDirection); void addToHeight(int add); void addToShift(int add); protected: void hideSlow(); void hideFast(); void hideStop(); QPoint computePosition(int height) const; virtual void updateGeometry(int x, int y, int width, int height); protected: Manager *manager() const { return _manager; } private: void opacityAnimationCallback(); void destroyDelayed(); void moveByShift(); void hideAnimated(float64 duration, const anim::transition &func); bool shiftAnimationCallback(crl::time now); Manager *_manager = nullptr; bool _hiding = false; bool _deleted = false; base::binary_guard _hidingDelayed; Ui::Animations::Simple _a_opacity; QPoint _startPosition; Direction _direction; anim::value _shift; Ui::Animations::Basic _shiftAnimation; }; class Background : public TWidget { public: Background(QWidget *parent); protected: void paintEvent(QPaintEvent *e) override; }; class Notification : public Widget { public: Notification( Manager *manager, History *history, PeerData *peer, PeerData *author, HistoryItem *item, int forwardedCount, QPoint startPosition, int shift, Direction shiftDirection); void startHiding(); void stopHiding(); void updateNotifyDisplay(); void updatePeerPhoto(); bool isUnlinked() const { return !_history; } bool isReplying() const { return _replyArea && !isUnlinked(); } // Called only by Manager. bool unlinkItem(HistoryItem *del); bool unlinkHistory(History *history = nullptr); bool checkLastInput(bool hasReplyingNotifications); protected: void enterEventHook(QEvent *e) override; void leaveEventHook(QEvent *e) override; void paintEvent(QPaintEvent *e) override; void mousePressEvent(QMouseEvent *e) override; bool eventFilter(QObject *o, QEvent *e) override; private: void refreshLang(); void updateReplyGeometry(); bool canReply() const; void replyResized(); void replyCancel(); void unlinkHistoryInManager(); void toggleActionButtons(bool visible); void prepareActionsCache(); void showReplyField(); void sendReply(); void changeHeight(int newHeight); void updateGeometry(int x, int y, int width, int height) override; void actionsOpacityCallback(); QPixmap _cache; bool _hideReplyButton = false; bool _actionsVisible = false; Ui::Animations::Simple a_actionsOpacity; QPixmap _buttonsCache; crl::time _started; History *_history; PeerData *_peer; PeerData *_author; HistoryItem *_item; int _forwardedCount; object_ptr _close; object_ptr _reply; object_ptr _background = { nullptr }; object_ptr _replyArea = { nullptr }; object_ptr _replySend = { nullptr }; bool _waitingForInput = true; QTimer _hideTimer; int _replyPadding = 0; bool _userpicLoaded = false; }; class HideAllButton : public Widget { public: HideAllButton(Manager *manager, QPoint startPosition, int shift, Direction shiftDirection); void startHiding(); void startHidingFast(); void stopHiding(); protected: void enterEventHook(QEvent *e) override; void leaveEventHook(QEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; void paintEvent(QPaintEvent *e) override; private: bool _mouseOver = false; bool _mouseDown = false; }; } // namespace internal } // namespace Default } // namespace Notifications } // namespace Window