/* 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 "base/object_ptr.h" #include "data/data_stories.h" #include "ui/effects/animations.h" namespace style { struct ReportBox; } // namespace style namespace base { class PowerSaveBlocker; } // namespace base namespace ChatHelpers { class Show; struct FileChosen; } // namespace ChatHelpers namespace Data { struct FileOrigin; class DocumentMedia; } // namespace Data namespace HistoryView::Reactions { struct ChosenReaction; enum class AttachSelectorResult; } // namespace HistoryView::Reactions namespace Ui { class RpWidget; class BoxContent; class PopupMenu; } // namespace Ui namespace Ui::Toast { struct Config; } // namespace Ui::Toast namespace Main { class Session; class SessionShow; } // namespace Main namespace Media::Player { struct TrackState; } // namespace Media::Player namespace Media::Stories { class Header; class Slider; class ReplyArea; class Reactions; class RecentViews; class Sibling; class Delegate; struct SiblingView; enum class SiblingType; struct ContentLayout; class CaptionFullView; class RepostView; enum class ReactionsMode; class StoryAreaView; struct RepostClickHandler; enum class HeaderLayout { Normal, Outside, }; enum class PauseState { Playing, Paused, Inactive, InactivePaused, }; struct SiblingLayout { QRect geometry; QRect userpic; QRect nameBoundingRect; int nameFontSize = 0; friend inline bool operator==(SiblingLayout, SiblingLayout) = default; }; struct Layout { QRect content; QRect header; QRect slider; QRect reactions; int controlsWidth = 0; QPoint controlsBottomPosition; QRect views; QRect autocompleteRect; HeaderLayout headerLayout = HeaderLayout::Normal; SiblingLayout siblingLeft; SiblingLayout siblingRight; friend inline bool operator==(Layout, Layout) = default; }; class Controller final : public base::has_weak_ptr { public: explicit Controller(not_null delegate); ~Controller(); [[nodiscard]] Data::Story *story() const; [[nodiscard]] not_null wrap() const; [[nodiscard]] Layout layout() const; [[nodiscard]] rpl::producer layoutValue() const; [[nodiscard]] ContentLayout contentLayout() const; [[nodiscard]] bool closeByClickAt(QPoint position) const; [[nodiscard]] Data::FileOrigin fileOrigin() const; [[nodiscard]] TextWithEntities captionText() const; [[nodiscard]] bool skipCaption() const; [[nodiscard]] bool repost() const; void toggleLiked(); void showFullCaption(); void captionClosing(); void captionClosed(); [[nodiscard]] QMargins repostCaptionPadding() const; void drawRepostInfo(Painter &p, int x, int y, int availableWidth) const; [[nodiscard]] RepostClickHandler lookupRepostHandler( QPoint position) const; [[nodiscard]] std::shared_ptr uiShow() const; [[nodiscard]] auto stickerOrEmojiChosen() const -> rpl::producer; void show(not_null story, Data::StoriesContext context); void jumpTo(not_null story, Data::StoriesContext context); void ready(); void updateVideoPlayback(const Player::TrackState &state); [[nodiscard]] ClickHandlerPtr lookupAreaHandler(QPoint point) const; [[nodiscard]] bool subjumpAvailable(int delta) const; [[nodiscard]] bool subjumpFor(int delta); [[nodiscard]] bool jumpFor(int delta); [[nodiscard]] bool paused() const; void togglePaused(bool paused); void contentPressed(bool pressed); void setMenuShown(bool shown); [[nodiscard]] PauseState pauseState() const; [[nodiscard]] float64 currentVolume() const; void toggleVolume(); void changeVolume(float64 volume); void volumeChangeFinished(); void repaint(); void repaintSibling(not_null sibling); [[nodiscard]] SiblingView sibling(SiblingType type) const; [[nodiscard]] const Data::StoryViews &views(int limit, bool initial); [[nodiscard]] rpl::producer<> moreViewsLoaded() const; void unfocusReply(); void shareRequested(); void deleteRequested(); void reportRequested(); void toggleInProfileRequested(bool inProfile); [[nodiscard]] bool ignoreWindowMove(QPoint position) const; void tryProcessKeyInput(not_null e); [[nodiscard]] bool allowStealthMode() const; void setupStealthMode(); using AttachStripResult = HistoryView::Reactions::AttachSelectorResult; [[nodiscard]] AttachStripResult attachReactionsToMenu( not_null menu, QPoint desiredPosition); [[nodiscard]] rpl::lifetime &lifetime(); private: class PhotoPlayback; class Unsupported; using ChosenReaction = HistoryView::Reactions::ChosenReaction; struct StoriesList { not_null peer; Data::StoriesIds ids; std::vector sorted; int total = 0; friend inline bool operator==( const StoriesList &, const StoriesList &) = default; }; struct CachedSource { PeerId peerId = 0; StoryId shownId = 0; explicit operator bool() const { return peerId != 0; } }; struct ActiveArea { QRectF original; float64 radiusOriginal = 0.; QRect geometry; float64 rotation = 0.; float64 radius = 0.; ClickHandlerPtr handler; std::unique_ptr view; }; void initLayout(); bool changeShown(Data::Story *story); void subscribeToSession(); void updatePhotoPlayback(const Player::TrackState &state); void updatePlayback(const Player::TrackState &state); void updatePowerSaveBlocker(const Player::TrackState &state); void maybeMarkAsRead(const Player::TrackState &state); void markAsRead(); void updateContentFaded(); void updatePlayingAllowed(); void setPlayingAllowed(bool allowed); void rebuildActiveAreas(const Layout &layout) const; void toggleWeatherMode() const; void hideSiblings(); void showSiblings(not_null session); void showSibling( std::unique_ptr &sibling, not_null session, CachedSource cached); void subjumpTo(int index); void checkWaitingFor(); void moveFromShown(); void refreshViewsFromData(); [[nodiscard]] auto viewsGotMoreCallback() -> Fn; [[nodiscard]] bool shown() const; [[nodiscard]] PeerData *shownPeer() const; [[nodiscard]] int shownCount() const; [[nodiscard]] StoryId shownId(int index) const; [[nodiscard]] std::unique_ptr validateRepostView( not_null story); void rebuildFromContext(not_null peer, FullStoryId storyId); void checkMoveByDelta(); void loadMoreToList(); void preloadNext(); void rebuildCachedSourcesList( const std::vector &lists, int index); [[nodiscard]] int repostSkipTop() const; void updateAreas(Data::Story *story); bool reactionChosen(ReactionsMode mode, ChosenReaction chosen); const not_null _delegate; rpl::variable> _layout; const not_null _wrap; const std::unique_ptr
_header; const std::unique_ptr _slider; const std::unique_ptr _replyArea; const std::unique_ptr _reactions; const std::unique_ptr _recentViews; std::unique_ptr _unsupported; std::unique_ptr _photoPlayback; std::unique_ptr _captionFullView; std::unique_ptr _repostView; Ui::Animations::Simple _contentFadeAnimation; bool _contentFaded = false; bool _windowActive = false; bool _replyActive = false; bool _layerShown = false; bool _menuShown = false; bool _tooltipShown = false; bool _paused = false; FullStoryId _shown; TextWithEntities _captionText; Data::StoriesContext _context; std::optional _source; std::optional _list; FullStoryId _waitingForId; int _waitingForDelta = 0; int _index = 0; int _sliderIndex = 0; int _sliderCount = 0; bool _started = false; bool _viewed = false; std::vector _locations; std::vector _suggestedReactions; std::vector _channelPosts; std::vector _urlAreas; std::vector _weatherAreas; mutable std::vector _areas; mutable rpl::variable _weatherInCelsius; std::vector _cachedSourcesList; int _cachedSourceIndex = -1; bool _showingUnreadSources = false; Data::StoryViews _viewsSlice; rpl::event_stream<> _moreViewsLoaded; base::has_weak_ptr _viewsLoadGuard; std::unique_ptr _siblingLeft; std::unique_ptr _siblingRight; std::unique_ptr _powerSaveBlocker; Main::Session *_session = nullptr; rpl::lifetime _sessionLifetime; rpl::lifetime _contextLifetime; rpl::lifetime _lifetime; }; [[nodiscard]] Ui::Toast::Config PrepareToggleInProfileToast( bool channel, int count, bool inProfile); [[nodiscard]] Ui::Toast::Config PrepareTogglePinToast( bool channel, int count, bool pin); void ReportRequested( std::shared_ptr show, FullStoryId id, const style::ReportBox *stOverride = nullptr); [[nodiscard]] object_ptr PrepareShortInfoBox( not_null peer); [[nodiscard]] ClickHandlerPtr MakeChannelPostHandler( not_null session, FullMsgId item); [[nodiscard]] ClickHandlerPtr MakeUrlAreaHandler( base::weak_ptr weak, const QString &url); } // namespace Media::Stories