data_story.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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/weak_ptr.h"
  9. #include "data/data_location.h"
  10. #include "data/data_message_reaction_id.h"
  11. class Image;
  12. class PhotoData;
  13. class DocumentData;
  14. namespace Main {
  15. class Session;
  16. } // namespace Main
  17. namespace Data {
  18. class Session;
  19. class Thread;
  20. class MediaPreload;
  21. struct SendError;
  22. enum class StoryPrivacy : uchar {
  23. Public,
  24. CloseFriends,
  25. Contacts,
  26. SelectedContacts,
  27. Other,
  28. };
  29. struct StoryIdDates {
  30. StoryId id = 0;
  31. TimeId date = 0;
  32. TimeId expires = 0;
  33. [[nodiscard]] bool valid() const {
  34. return id != 0;
  35. }
  36. explicit operator bool() const {
  37. return valid();
  38. }
  39. friend inline auto operator<=>(StoryIdDates, StoryIdDates) = default;
  40. friend inline bool operator==(StoryIdDates, StoryIdDates) = default;
  41. };
  42. struct StoryMedia {
  43. std::variant<
  44. v::null_t,
  45. not_null<PhotoData*>,
  46. not_null<DocumentData*>> data;
  47. friend inline bool operator==(StoryMedia, StoryMedia) = default;
  48. };
  49. struct StoryView {
  50. not_null<PeerData*> peer;
  51. Data::ReactionId reaction;
  52. StoryId repostId = 0;
  53. MsgId forwardId = 0;
  54. TimeId date = 0;
  55. friend inline bool operator==(StoryView, StoryView) = default;
  56. };
  57. struct StoryViews {
  58. std::vector<StoryView> list;
  59. QString nextOffset;
  60. int reactions = 0;
  61. int forwards = 0;
  62. int views = 0;
  63. int total = 0;
  64. bool known = false;
  65. };
  66. struct StoryArea {
  67. QRectF geometry;
  68. float64 rotation = 0;
  69. float64 radius = 0;
  70. friend inline bool operator==(
  71. const StoryArea &,
  72. const StoryArea &) = default;
  73. };
  74. struct StoryLocation {
  75. StoryArea area;
  76. Data::LocationPoint point;
  77. QString title;
  78. QString address;
  79. QString provider;
  80. QString venueId;
  81. QString venueType;
  82. friend inline bool operator==(
  83. const StoryLocation &,
  84. const StoryLocation &) = default;
  85. };
  86. struct SuggestedReaction {
  87. StoryArea area;
  88. Data::ReactionId reaction;
  89. int count = 0;
  90. bool flipped = false;
  91. bool dark = false;
  92. friend inline bool operator==(
  93. const SuggestedReaction &,
  94. const SuggestedReaction &) = default;
  95. };
  96. struct ChannelPost {
  97. StoryArea area;
  98. FullMsgId itemId;
  99. friend inline bool operator==(
  100. const ChannelPost &,
  101. const ChannelPost &) = default;
  102. };
  103. struct UrlArea {
  104. StoryArea area;
  105. QString url;
  106. friend inline bool operator==(
  107. const UrlArea &,
  108. const UrlArea &) = default;
  109. };
  110. struct WeatherArea {
  111. StoryArea area;
  112. QString emoji;
  113. QColor color;
  114. int millicelsius = 0;
  115. friend inline bool operator==(
  116. const WeatherArea &,
  117. const WeatherArea &) = default;
  118. };
  119. class Story final {
  120. public:
  121. Story(
  122. StoryId id,
  123. not_null<PeerData*> peer,
  124. StoryMedia media,
  125. const MTPDstoryItem &data,
  126. TimeId now);
  127. static constexpr int kRecentViewersMax = 3;
  128. [[nodiscard]] Session &owner() const;
  129. [[nodiscard]] Main::Session &session() const;
  130. [[nodiscard]] not_null<PeerData*> peer() const;
  131. [[nodiscard]] StoryId id() const;
  132. [[nodiscard]] bool mine() const;
  133. [[nodiscard]] StoryIdDates idDates() const;
  134. [[nodiscard]] FullStoryId fullId() const;
  135. [[nodiscard]] TimeId date() const;
  136. [[nodiscard]] TimeId expires() const;
  137. [[nodiscard]] bool unsupported() const;
  138. [[nodiscard]] bool expired(TimeId now = 0) const;
  139. [[nodiscard]] const StoryMedia &media() const;
  140. [[nodiscard]] PhotoData *photo() const;
  141. [[nodiscard]] DocumentData *document() const;
  142. [[nodiscard]] bool hasReplyPreview() const;
  143. [[nodiscard]] Image *replyPreview() const;
  144. [[nodiscard]] TextWithEntities inReplyText() const;
  145. void setPinnedToTop(bool pinned);
  146. bool pinnedToTop() const;
  147. void setInProfile(bool value);
  148. [[nodiscard]] bool inProfile() const;
  149. [[nodiscard]] StoryPrivacy privacy() const;
  150. [[nodiscard]] bool forbidsForward() const;
  151. [[nodiscard]] bool edited() const;
  152. [[nodiscard]] bool out() const;
  153. [[nodiscard]] bool canDownloadIfPremium() const;
  154. [[nodiscard]] bool canDownloadChecked() const;
  155. [[nodiscard]] bool canShare() const;
  156. [[nodiscard]] bool canDelete() const;
  157. [[nodiscard]] bool canReport() const;
  158. [[nodiscard]] bool hasDirectLink() const;
  159. [[nodiscard]] Data::SendError errorTextForForward(
  160. not_null<Thread*> to) const;
  161. void setCaption(TextWithEntities &&caption);
  162. [[nodiscard]] const TextWithEntities &caption() const;
  163. [[nodiscard]] Data::ReactionId sentReactionId() const;
  164. void setReactionId(Data::ReactionId id);
  165. [[nodiscard]] auto recentViewers() const
  166. -> const std::vector<not_null<PeerData*>> &;
  167. [[nodiscard]] const StoryViews &viewsList() const;
  168. [[nodiscard]] const StoryViews &channelReactionsList() const;
  169. [[nodiscard]] int interactions() const;
  170. [[nodiscard]] int views() const;
  171. [[nodiscard]] int forwards() const;
  172. [[nodiscard]] int reactions() const;
  173. void applyViewsSlice(const QString &offset, const StoryViews &slice);
  174. void applyChannelReactionsSlice(
  175. const QString &offset,
  176. const StoryViews &slice);
  177. [[nodiscard]] const std::vector<StoryLocation> &locations() const;
  178. [[nodiscard]] auto suggestedReactions() const
  179. -> const std::vector<SuggestedReaction> &;
  180. [[nodiscard]] auto channelPosts() const
  181. -> const std::vector<ChannelPost> &;
  182. [[nodiscard]] auto urlAreas() const
  183. -> const std::vector<UrlArea> &;
  184. [[nodiscard]] auto weatherAreas() const
  185. -> const std::vector<WeatherArea> &;
  186. void applyChanges(
  187. StoryMedia media,
  188. const MTPDstoryItem &data,
  189. TimeId now);
  190. void applyViewsCounts(const MTPDstoryViews &data);
  191. [[nodiscard]] TimeId lastUpdateTime() const;
  192. [[nodiscard]] bool repost() const;
  193. [[nodiscard]] bool repostModified() const;
  194. [[nodiscard]] PeerData *repostSourcePeer() const;
  195. [[nodiscard]] QString repostSourceName() const;
  196. [[nodiscard]] StoryId repostSourceId() const;
  197. [[nodiscard]] PeerData *fromPeer() const;
  198. private:
  199. struct ViewsCounts {
  200. int views = 0;
  201. int forwards = 0;
  202. int reactions = 0;
  203. base::flat_map<Data::ReactionId, int> reactionsCounts;
  204. std::vector<not_null<PeerData*>> viewers;
  205. };
  206. void changeSuggestedReactionCount(Data::ReactionId id, int delta);
  207. void applyFields(
  208. StoryMedia media,
  209. const MTPDstoryItem &data,
  210. TimeId now,
  211. bool initial);
  212. void updateViewsCounts(ViewsCounts &&counts, bool known, bool initial);
  213. [[nodiscard]] ViewsCounts parseViewsCounts(
  214. const MTPDstoryViews &data,
  215. const Data::ReactionId &mine);
  216. const StoryId _id = 0;
  217. const not_null<PeerData*> _peer;
  218. PeerData * const _repostSourcePeer = nullptr;
  219. const QString _repostSourceName;
  220. const StoryId _repostSourceId = 0;
  221. PeerData * const _fromPeer = nullptr;
  222. Data::ReactionId _sentReactionId;
  223. StoryMedia _media;
  224. TextWithEntities _caption;
  225. std::vector<not_null<PeerData*>> _recentViewers;
  226. std::vector<StoryLocation> _locations;
  227. std::vector<SuggestedReaction> _suggestedReactions;
  228. std::vector<ChannelPost> _channelPosts;
  229. std::vector<UrlArea> _urlAreas;
  230. std::vector<WeatherArea> _weatherAreas;
  231. StoryViews _views;
  232. StoryViews _channelReactions;
  233. const TimeId _date = 0;
  234. const TimeId _expires = 0;
  235. TimeId _lastUpdateTime = 0;
  236. bool _out : 1 = false;
  237. bool _inProfile : 1 = false;
  238. bool _pinnedToTop : 1 = false;
  239. bool _privacyPublic : 1 = false;
  240. bool _privacyCloseFriends : 1 = false;
  241. bool _privacyContacts : 1 = false;
  242. bool _privacySelectedContacts : 1 = false;
  243. const bool _repostModified : 1 = false;
  244. bool _noForwards : 1 = false;
  245. bool _edited : 1 = false;
  246. };
  247. class StoryPreload final : public base::has_weak_ptr {
  248. public:
  249. StoryPreload(not_null<Story*> story, Fn<void()> done);
  250. ~StoryPreload();
  251. [[nodiscard]] FullStoryId id() const;
  252. [[nodiscard]] not_null<Story*> story() const;
  253. private:
  254. const not_null<Story*> _story;
  255. std::unique_ptr<MediaPreload> _task;
  256. };
  257. } // namespace Data