/* 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 "data/data_message_reaction_id.h" #include "ui/effects/animations.h" namespace Data { class DocumentMedia; struct ReactionId; class Session; class Story; struct SuggestedReaction; struct WeatherArea; } // namespace Data namespace HistoryView::Reactions { class Selector; struct ChosenReaction; enum class AttachSelectorResult; } // namespace HistoryView::Reactions namespace Ui { class RpWidget; struct ReactionFlyAnimationArgs; struct ReactionFlyCenter; class EmojiFlyAnimation; class PopupMenu; } // namespace Ui namespace Media::Stories { class Controller; enum class ReactionsMode { Message, Reaction, }; class StoryAreaView { public: virtual ~StoryAreaView() = default; virtual void setAreaGeometry(QRect geometry, float64 radius) = 0; virtual void updateReactionsCount(int count) = 0; virtual void playEffect() = 0; virtual bool contains(QPoint point) = 0; }; class Reactions final { public: explicit Reactions(not_null controller); ~Reactions(); using Mode = ReactionsMode; template struct ChosenWrap { Reaction reaction; Mode mode; }; using Chosen = ChosenWrap; [[nodiscard]] rpl::producer activeValue() const; [[nodiscard]] rpl::producer chosen() const; [[nodiscard]] Data::ReactionId liked() const; [[nodiscard]] rpl::producer likedValue() const; void showLikeFrom(Data::Story *story); void hide(); void outsidePressed(); void toggleLiked(); void applyLike(Data::ReactionId id); void ready(); [[nodiscard]] auto makeSuggestedReactionWidget( const Data::SuggestedReaction &reaction) -> std::unique_ptr; [[nodiscard]] auto makeWeatherAreaWidget( const Data::WeatherArea &data, rpl::producer weatherInCelsius) -> std::unique_ptr; void setReplyFieldState( rpl::producer focused, rpl::producer hasSendText); void attachToReactionButton(not_null button); void setReactionIconWidget(Ui::RpWidget *widget); void animateAndProcess(Chosen &&chosen); using AttachStripResult = HistoryView::Reactions::AttachSelectorResult; [[nodiscard]] AttachStripResult attachToMenu( not_null menu, QPoint desiredPosition); private: class Panel; void assignLikedId(Data::ReactionId id); [[nodiscard]] Fn setLikedIdIconInit( not_null owner, Data::ReactionId id, bool force = false); void setLikedIdFrom(Data::Story *story); void setLikedId( not_null owner, Data::ReactionId id, bool force = false); void startReactionAnimation( Ui::ReactionFlyAnimationArgs from, not_null target, Fn done = nullptr); void waitForLikeIcon( not_null owner, Data::ReactionId id); void initLikeIcon( not_null owner, Data::ReactionId id, Ui::ReactionFlyCenter center); const not_null _controller; const std::unique_ptr _panel; rpl::event_stream _chosen; bool _replyFocused = false; bool _hasSendText = false; Ui::RpWidget *_likeIconWidget = nullptr; rpl::variable _liked; base::has_weak_ptr _likeIconGuard; std::unique_ptr _likeIcon; std::shared_ptr _likeIconMedia; std::unique_ptr _reactionAnimation; rpl::lifetime _likeIconWaitLifetime; rpl::lifetime _likeFromLifetime; rpl::lifetime _lifetime; }; } // namespace Media::Stories