media_stories_controller.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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 "base/object_ptr.h"
  9. #include "data/data_stories.h"
  10. #include "ui/effects/animations.h"
  11. namespace style {
  12. struct ReportBox;
  13. } // namespace style
  14. namespace base {
  15. class PowerSaveBlocker;
  16. } // namespace base
  17. namespace ChatHelpers {
  18. class Show;
  19. struct FileChosen;
  20. } // namespace ChatHelpers
  21. namespace Data {
  22. struct FileOrigin;
  23. class DocumentMedia;
  24. } // namespace Data
  25. namespace HistoryView::Reactions {
  26. struct ChosenReaction;
  27. enum class AttachSelectorResult;
  28. } // namespace HistoryView::Reactions
  29. namespace Ui {
  30. class RpWidget;
  31. class BoxContent;
  32. class PopupMenu;
  33. } // namespace Ui
  34. namespace Ui::Toast {
  35. struct Config;
  36. } // namespace Ui::Toast
  37. namespace Main {
  38. class Session;
  39. class SessionShow;
  40. } // namespace Main
  41. namespace Media::Player {
  42. struct TrackState;
  43. } // namespace Media::Player
  44. namespace Media::Stories {
  45. class Header;
  46. class Slider;
  47. class ReplyArea;
  48. class Reactions;
  49. class RecentViews;
  50. class Sibling;
  51. class Delegate;
  52. struct SiblingView;
  53. enum class SiblingType;
  54. struct ContentLayout;
  55. class CaptionFullView;
  56. class RepostView;
  57. enum class ReactionsMode;
  58. class StoryAreaView;
  59. struct RepostClickHandler;
  60. enum class HeaderLayout {
  61. Normal,
  62. Outside,
  63. };
  64. enum class PauseState {
  65. Playing,
  66. Paused,
  67. Inactive,
  68. InactivePaused,
  69. };
  70. struct SiblingLayout {
  71. QRect geometry;
  72. QRect userpic;
  73. QRect nameBoundingRect;
  74. int nameFontSize = 0;
  75. friend inline bool operator==(SiblingLayout, SiblingLayout) = default;
  76. };
  77. struct Layout {
  78. QRect content;
  79. QRect header;
  80. QRect slider;
  81. QRect reactions;
  82. int controlsWidth = 0;
  83. QPoint controlsBottomPosition;
  84. QRect views;
  85. QRect autocompleteRect;
  86. HeaderLayout headerLayout = HeaderLayout::Normal;
  87. SiblingLayout siblingLeft;
  88. SiblingLayout siblingRight;
  89. friend inline bool operator==(Layout, Layout) = default;
  90. };
  91. class Controller final : public base::has_weak_ptr {
  92. public:
  93. explicit Controller(not_null<Delegate*> delegate);
  94. ~Controller();
  95. [[nodiscard]] Data::Story *story() const;
  96. [[nodiscard]] not_null<Ui::RpWidget*> wrap() const;
  97. [[nodiscard]] Layout layout() const;
  98. [[nodiscard]] rpl::producer<Layout> layoutValue() const;
  99. [[nodiscard]] ContentLayout contentLayout() const;
  100. [[nodiscard]] bool closeByClickAt(QPoint position) const;
  101. [[nodiscard]] Data::FileOrigin fileOrigin() const;
  102. [[nodiscard]] TextWithEntities captionText() const;
  103. [[nodiscard]] bool skipCaption() const;
  104. [[nodiscard]] bool repost() const;
  105. void toggleLiked();
  106. void showFullCaption();
  107. void captionClosing();
  108. void captionClosed();
  109. [[nodiscard]] QMargins repostCaptionPadding() const;
  110. void drawRepostInfo(Painter &p, int x, int y, int availableWidth) const;
  111. [[nodiscard]] RepostClickHandler lookupRepostHandler(
  112. QPoint position) const;
  113. [[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
  114. [[nodiscard]] auto stickerOrEmojiChosen() const
  115. -> rpl::producer<ChatHelpers::FileChosen>;
  116. void show(not_null<Data::Story*> story, Data::StoriesContext context);
  117. void jumpTo(not_null<Data::Story*> story, Data::StoriesContext context);
  118. void ready();
  119. void updateVideoPlayback(const Player::TrackState &state);
  120. [[nodiscard]] ClickHandlerPtr lookupAreaHandler(QPoint point) const;
  121. [[nodiscard]] bool subjumpAvailable(int delta) const;
  122. [[nodiscard]] bool subjumpFor(int delta);
  123. [[nodiscard]] bool jumpFor(int delta);
  124. [[nodiscard]] bool paused() const;
  125. void togglePaused(bool paused);
  126. void contentPressed(bool pressed);
  127. void setMenuShown(bool shown);
  128. [[nodiscard]] PauseState pauseState() const;
  129. [[nodiscard]] float64 currentVolume() const;
  130. void toggleVolume();
  131. void changeVolume(float64 volume);
  132. void volumeChangeFinished();
  133. void repaint();
  134. void repaintSibling(not_null<Sibling*> sibling);
  135. [[nodiscard]] SiblingView sibling(SiblingType type) const;
  136. [[nodiscard]] const Data::StoryViews &views(int limit, bool initial);
  137. [[nodiscard]] rpl::producer<> moreViewsLoaded() const;
  138. void unfocusReply();
  139. void shareRequested();
  140. void deleteRequested();
  141. void reportRequested();
  142. void toggleInProfileRequested(bool inProfile);
  143. [[nodiscard]] bool ignoreWindowMove(QPoint position) const;
  144. void tryProcessKeyInput(not_null<QKeyEvent*> e);
  145. [[nodiscard]] bool allowStealthMode() const;
  146. void setupStealthMode();
  147. using AttachStripResult = HistoryView::Reactions::AttachSelectorResult;
  148. [[nodiscard]] AttachStripResult attachReactionsToMenu(
  149. not_null<Ui::PopupMenu*> menu,
  150. QPoint desiredPosition);
  151. [[nodiscard]] rpl::lifetime &lifetime();
  152. private:
  153. class PhotoPlayback;
  154. class Unsupported;
  155. using ChosenReaction = HistoryView::Reactions::ChosenReaction;
  156. struct StoriesList {
  157. not_null<PeerData*> peer;
  158. Data::StoriesIds ids;
  159. std::vector<StoryId> sorted;
  160. int total = 0;
  161. friend inline bool operator==(
  162. const StoriesList &,
  163. const StoriesList &) = default;
  164. };
  165. struct CachedSource {
  166. PeerId peerId = 0;
  167. StoryId shownId = 0;
  168. explicit operator bool() const {
  169. return peerId != 0;
  170. }
  171. };
  172. struct ActiveArea {
  173. QRectF original;
  174. float64 radiusOriginal = 0.;
  175. QRect geometry;
  176. float64 rotation = 0.;
  177. float64 radius = 0.;
  178. ClickHandlerPtr handler;
  179. std::unique_ptr<StoryAreaView> view;
  180. };
  181. void initLayout();
  182. bool changeShown(Data::Story *story);
  183. void subscribeToSession();
  184. void updatePhotoPlayback(const Player::TrackState &state);
  185. void updatePlayback(const Player::TrackState &state);
  186. void updatePowerSaveBlocker(const Player::TrackState &state);
  187. void maybeMarkAsRead(const Player::TrackState &state);
  188. void markAsRead();
  189. void updateContentFaded();
  190. void updatePlayingAllowed();
  191. void setPlayingAllowed(bool allowed);
  192. void rebuildActiveAreas(const Layout &layout) const;
  193. void toggleWeatherMode() const;
  194. void hideSiblings();
  195. void showSiblings(not_null<Main::Session*> session);
  196. void showSibling(
  197. std::unique_ptr<Sibling> &sibling,
  198. not_null<Main::Session*> session,
  199. CachedSource cached);
  200. void subjumpTo(int index);
  201. void checkWaitingFor();
  202. void moveFromShown();
  203. void refreshViewsFromData();
  204. [[nodiscard]] auto viewsGotMoreCallback()
  205. -> Fn<void(Data::StoryViews)>;
  206. [[nodiscard]] bool shown() const;
  207. [[nodiscard]] PeerData *shownPeer() const;
  208. [[nodiscard]] int shownCount() const;
  209. [[nodiscard]] StoryId shownId(int index) const;
  210. [[nodiscard]] std::unique_ptr<RepostView> validateRepostView(
  211. not_null<Data::Story*> story);
  212. void rebuildFromContext(not_null<PeerData*> peer, FullStoryId storyId);
  213. void checkMoveByDelta();
  214. void loadMoreToList();
  215. void preloadNext();
  216. void rebuildCachedSourcesList(
  217. const std::vector<Data::StoriesSourceInfo> &lists,
  218. int index);
  219. [[nodiscard]] int repostSkipTop() const;
  220. void updateAreas(Data::Story *story);
  221. bool reactionChosen(ReactionsMode mode, ChosenReaction chosen);
  222. const not_null<Delegate*> _delegate;
  223. rpl::variable<std::optional<Layout>> _layout;
  224. const not_null<Ui::RpWidget*> _wrap;
  225. const std::unique_ptr<Header> _header;
  226. const std::unique_ptr<Slider> _slider;
  227. const std::unique_ptr<ReplyArea> _replyArea;
  228. const std::unique_ptr<Reactions> _reactions;
  229. const std::unique_ptr<RecentViews> _recentViews;
  230. std::unique_ptr<Unsupported> _unsupported;
  231. std::unique_ptr<PhotoPlayback> _photoPlayback;
  232. std::unique_ptr<CaptionFullView> _captionFullView;
  233. std::unique_ptr<RepostView> _repostView;
  234. Ui::Animations::Simple _contentFadeAnimation;
  235. bool _contentFaded = false;
  236. bool _windowActive = false;
  237. bool _replyActive = false;
  238. bool _layerShown = false;
  239. bool _menuShown = false;
  240. bool _tooltipShown = false;
  241. bool _paused = false;
  242. FullStoryId _shown;
  243. TextWithEntities _captionText;
  244. Data::StoriesContext _context;
  245. std::optional<Data::StoriesSource> _source;
  246. std::optional<StoriesList> _list;
  247. FullStoryId _waitingForId;
  248. int _waitingForDelta = 0;
  249. int _index = 0;
  250. int _sliderIndex = 0;
  251. int _sliderCount = 0;
  252. bool _started = false;
  253. bool _viewed = false;
  254. std::vector<Data::StoryLocation> _locations;
  255. std::vector<Data::SuggestedReaction> _suggestedReactions;
  256. std::vector<Data::ChannelPost> _channelPosts;
  257. std::vector<Data::UrlArea> _urlAreas;
  258. std::vector<Data::WeatherArea> _weatherAreas;
  259. mutable std::vector<ActiveArea> _areas;
  260. mutable rpl::variable<bool> _weatherInCelsius;
  261. std::vector<CachedSource> _cachedSourcesList;
  262. int _cachedSourceIndex = -1;
  263. bool _showingUnreadSources = false;
  264. Data::StoryViews _viewsSlice;
  265. rpl::event_stream<> _moreViewsLoaded;
  266. base::has_weak_ptr _viewsLoadGuard;
  267. std::unique_ptr<Sibling> _siblingLeft;
  268. std::unique_ptr<Sibling> _siblingRight;
  269. std::unique_ptr<base::PowerSaveBlocker> _powerSaveBlocker;
  270. Main::Session *_session = nullptr;
  271. rpl::lifetime _sessionLifetime;
  272. rpl::lifetime _contextLifetime;
  273. rpl::lifetime _lifetime;
  274. };
  275. [[nodiscard]] Ui::Toast::Config PrepareToggleInProfileToast(
  276. bool channel,
  277. int count,
  278. bool inProfile);
  279. [[nodiscard]] Ui::Toast::Config PrepareTogglePinToast(
  280. bool channel,
  281. int count,
  282. bool pin);
  283. void ReportRequested(
  284. std::shared_ptr<Main::SessionShow> show,
  285. FullStoryId id,
  286. const style::ReportBox *stOverride = nullptr);
  287. [[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
  288. not_null<PeerData*> peer);
  289. [[nodiscard]] ClickHandlerPtr MakeChannelPostHandler(
  290. not_null<Main::Session*> session,
  291. FullMsgId item);
  292. [[nodiscard]] ClickHandlerPtr MakeUrlAreaHandler(
  293. base::weak_ptr<Controller> weak,
  294. const QString &url);
  295. } // namespace Media::Stories