data_stories.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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/qt/qt_compare.h"
  9. #include "base/expected.h"
  10. #include "base/timer.h"
  11. #include "base/weak_ptr.h"
  12. #include "data/data_story.h"
  13. namespace Main {
  14. class Session;
  15. } // namespace Main
  16. namespace Ui {
  17. class Show;
  18. } // namespace Ui
  19. namespace Data {
  20. class Folder;
  21. class Session;
  22. struct StoryView;
  23. struct StoryIdDates;
  24. class Story;
  25. class StoryPreload;
  26. struct StoriesIds {
  27. base::flat_set<StoryId, std::greater<>> list;
  28. std::vector<StoryId> pinnedToTop;
  29. friend inline bool operator==(
  30. const StoriesIds&,
  31. const StoriesIds&) = default;
  32. };
  33. [[nodiscard]] std::vector<StoryId> RespectingPinned(const StoriesIds &ids);
  34. struct StoriesSourceInfo {
  35. PeerId id = 0;
  36. TimeId last = 0;
  37. uint32 count : 15 = 0;
  38. uint32 unreadCount : 15 = 0;
  39. uint32 premium : 1 = 0;
  40. friend inline bool operator==(
  41. StoriesSourceInfo,
  42. StoriesSourceInfo) = default;
  43. };
  44. struct StoriesSource {
  45. not_null<PeerData*> peer;
  46. base::flat_set<StoryIdDates> ids;
  47. StoryId readTill = 0;
  48. bool hidden = false;
  49. [[nodiscard]] StoriesSourceInfo info() const;
  50. [[nodiscard]] int unreadCount() const;
  51. [[nodiscard]] StoryIdDates toOpen() const;
  52. friend inline bool operator==(StoriesSource, StoriesSource) = default;
  53. };
  54. enum class NoStory : uchar {
  55. Unknown,
  56. Deleted,
  57. };
  58. enum class StorySourcesList : uchar {
  59. NotHidden,
  60. Hidden,
  61. };
  62. struct StoriesContextSingle {
  63. friend inline auto operator<=>(
  64. StoriesContextSingle,
  65. StoriesContextSingle) = default;
  66. friend inline bool operator==(StoriesContextSingle, StoriesContextSingle) = default;
  67. };
  68. struct StoriesContextPeer {
  69. friend inline auto operator<=>(
  70. StoriesContextPeer,
  71. StoriesContextPeer) = default;
  72. friend inline bool operator==(StoriesContextPeer, StoriesContextPeer) = default;
  73. };
  74. struct StoriesContextSaved {
  75. friend inline auto operator<=>(
  76. StoriesContextSaved,
  77. StoriesContextSaved) = default;
  78. friend inline bool operator==(StoriesContextSaved, StoriesContextSaved) = default;
  79. };
  80. struct StoriesContextArchive {
  81. friend inline auto operator<=>(
  82. StoriesContextArchive,
  83. StoriesContextArchive) = default;
  84. friend inline bool operator==(StoriesContextArchive, StoriesContextArchive) = default;
  85. };
  86. struct StoriesContext {
  87. std::variant<
  88. StoriesContextSingle,
  89. StoriesContextPeer,
  90. StoriesContextSaved,
  91. StoriesContextArchive,
  92. StorySourcesList> data;
  93. friend inline auto operator<=>(
  94. StoriesContext,
  95. StoriesContext) = default;
  96. friend inline bool operator==(StoriesContext, StoriesContext) = default;
  97. };
  98. struct StealthMode {
  99. TimeId enabledTill = 0;
  100. TimeId cooldownTill = 0;
  101. friend inline auto operator<=>(StealthMode, StealthMode) = default;
  102. friend inline bool operator==(StealthMode, StealthMode) = default;
  103. };
  104. inline constexpr auto kStorySourcesListCount = 2;
  105. class Stories final : public base::has_weak_ptr {
  106. public:
  107. explicit Stories(not_null<Session*> owner);
  108. ~Stories();
  109. static constexpr auto kInProfileToastDuration = 4 * crl::time(1000);
  110. [[nodiscard]] Session &owner() const;
  111. [[nodiscard]] Main::Session &session() const;
  112. void updateDependentMessages(not_null<Data::Story*> story);
  113. void registerDependentMessage(
  114. not_null<HistoryItem*> dependent,
  115. not_null<Data::Story*> dependency);
  116. void unregisterDependentMessage(
  117. not_null<HistoryItem*> dependent,
  118. not_null<Data::Story*> dependency);
  119. void loadMore(StorySourcesList list);
  120. void apply(const MTPDupdateStory &data);
  121. void apply(const MTPDupdateReadStories &data);
  122. void apply(const MTPStoriesStealthMode &stealthMode);
  123. void apply(not_null<PeerData*> peer, const MTPPeerStories *data);
  124. Story *applySingle(PeerId peerId, const MTPstoryItem &story);
  125. void loadAround(FullStoryId id, StoriesContext context);
  126. const StoriesSource *source(PeerId id) const;
  127. [[nodiscard]] const std::vector<StoriesSourceInfo> &sources(
  128. StorySourcesList list) const;
  129. [[nodiscard]] bool sourcesLoaded(StorySourcesList list) const;
  130. [[nodiscard]] rpl::producer<> sourcesChanged(
  131. StorySourcesList list) const;
  132. [[nodiscard]] rpl::producer<PeerId> sourceChanged() const;
  133. [[nodiscard]] rpl::producer<PeerId> itemsChanged() const;
  134. [[nodiscard]] base::expected<not_null<Story*>, NoStory> lookup(
  135. FullStoryId id) const;
  136. void resolve(FullStoryId id, Fn<void()> done, bool force = false);
  137. [[nodiscard]] std::shared_ptr<HistoryItem> resolveItem(FullStoryId id);
  138. [[nodiscard]] std::shared_ptr<HistoryItem> resolveItem(
  139. not_null<Story*> story);
  140. [[nodiscard]] bool isQuitPrevent();
  141. void markAsRead(FullStoryId id, bool viewed);
  142. void toggleHidden(
  143. PeerId peerId,
  144. bool hidden,
  145. std::shared_ptr<Ui::Show> show);
  146. static constexpr auto kViewsPerPage = 50;
  147. void loadViewsSlice(
  148. not_null<PeerData*> peer,
  149. StoryId id,
  150. QString offset,
  151. Fn<void(StoryViews)> done);
  152. void loadReactionsSlice(
  153. not_null<PeerData*> peer,
  154. StoryId id,
  155. QString offset,
  156. Fn<void(StoryViews)> done);
  157. [[nodiscard]] bool hasArchive(not_null<PeerData*> peer) const;
  158. [[nodiscard]] const StoriesIds &archive(PeerId peerId) const;
  159. [[nodiscard]] rpl::producer<PeerId> archiveChanged() const;
  160. [[nodiscard]] int archiveCount(PeerId peerId) const;
  161. [[nodiscard]] bool archiveCountKnown(PeerId peerId) const;
  162. [[nodiscard]] bool archiveLoaded(PeerId peerId) const;
  163. void archiveLoadMore(PeerId peerId);
  164. [[nodiscard]] const StoriesIds &saved(PeerId peerId) const;
  165. [[nodiscard]] rpl::producer<PeerId> savedChanged() const;
  166. [[nodiscard]] int savedCount(PeerId peerId) const;
  167. [[nodiscard]] bool savedCountKnown(PeerId peerId) const;
  168. [[nodiscard]] bool savedLoaded(PeerId peerId) const;
  169. void savedLoadMore(PeerId peerId);
  170. void deleteList(const std::vector<FullStoryId> &ids);
  171. void toggleInProfileList(
  172. const std::vector<FullStoryId> &ids,
  173. bool inProfile);
  174. [[nodiscard]] bool canTogglePinnedList(
  175. const std::vector<FullStoryId> &ids,
  176. bool pin) const;
  177. [[nodiscard]] int maxPinnedCount() const;
  178. void togglePinnedList(const std::vector<FullStoryId> &ids, bool pin);
  179. void incrementPreloadingMainSources();
  180. void decrementPreloadingMainSources();
  181. void incrementPreloadingHiddenSources();
  182. void decrementPreloadingHiddenSources();
  183. void setPreloadingInViewer(std::vector<FullStoryId> ids);
  184. struct PeerSourceState {
  185. StoryId maxId = 0;
  186. StoryId readTill = 0;
  187. };
  188. [[nodiscard]] std::optional<PeerSourceState> peerSourceState(
  189. not_null<PeerData*> peer,
  190. StoryId storyMaxId);
  191. [[nodiscard]] bool isUnread(not_null<Story*> story);
  192. enum class Polling {
  193. Chat,
  194. Viewer,
  195. };
  196. void registerPolling(not_null<Story*> story, Polling polling);
  197. void unregisterPolling(not_null<Story*> story, Polling polling);
  198. [[nodiscard]] bool registerPolling(FullStoryId id, Polling polling);
  199. void unregisterPolling(FullStoryId id, Polling polling);
  200. void requestPeerStories(
  201. not_null<PeerData*> peer,
  202. Fn<void()> done = nullptr);
  203. void savedStateChanged(not_null<Story*> story);
  204. [[nodiscard]] std::shared_ptr<HistoryItem> lookupItem(
  205. not_null<Story*> story);
  206. [[nodiscard]] StealthMode stealthMode() const;
  207. [[nodiscard]] rpl::producer<StealthMode> stealthModeValue() const;
  208. void activateStealthMode(Fn<void()> done = nullptr);
  209. void sendReaction(FullStoryId id, Data::ReactionId reaction);
  210. private:
  211. struct Set {
  212. StoriesIds ids;
  213. int total = -1;
  214. StoryId lastId = 0;
  215. bool loaded = false;
  216. mtpRequestId requestId = 0;
  217. };
  218. struct PollingSettings {
  219. int chat = 0;
  220. int viewer = 0;
  221. };
  222. void parseAndApply(const MTPPeerStories &stories);
  223. [[nodiscard]] Story *parseAndApply(
  224. not_null<PeerData*> peer,
  225. const MTPDstoryItem &data,
  226. TimeId now);
  227. StoryIdDates parseAndApply(
  228. not_null<PeerData*> peer,
  229. const MTPstoryItem &story,
  230. TimeId now);
  231. void processResolvedStories(
  232. not_null<PeerData*> peer,
  233. const QVector<MTPStoryItem> &list);
  234. void sendResolveRequests();
  235. void finalizeResolve(FullStoryId id);
  236. void updatePeerStoriesState(not_null<PeerData*> peer);
  237. [[nodiscard]] Set *lookupArchive(not_null<PeerData*> peer);
  238. void clearArchive(not_null<PeerData*> peer);
  239. void applyDeleted(not_null<PeerData*> peer, StoryId id);
  240. void applyExpired(FullStoryId id);
  241. void applyRemovedFromActive(FullStoryId id);
  242. void applyDeletedFromSources(PeerId id, StorySourcesList list);
  243. void removeDependencyStory(not_null<Story*> story);
  244. void sort(StorySourcesList list);
  245. bool bumpReadTill(PeerId peerId, StoryId maxReadTill);
  246. void requestReadTills();
  247. void sendMarkAsReadRequests();
  248. void sendMarkAsReadRequest(not_null<PeerData*> peer, StoryId tillId);
  249. void sendIncrementViewsRequests();
  250. void checkQuitPreventFinished();
  251. void registerExpiring(TimeId expires, FullStoryId id);
  252. void scheduleExpireTimer();
  253. void processExpired();
  254. void preloadSourcesChanged(StorySourcesList list);
  255. bool rebuildPreloadSources(StorySourcesList list);
  256. void continuePreloading();
  257. [[nodiscard]] bool shouldContinuePreload(FullStoryId id) const;
  258. [[nodiscard]] FullStoryId nextPreloadId() const;
  259. void startPreloading(not_null<Story*> story);
  260. void preloadFinished(FullStoryId id, bool markAsPreloaded = false);
  261. void preloadListsMore();
  262. void notifySourcesChanged(StorySourcesList list);
  263. void pushHiddenCountsToFolder();
  264. void setPinnedToTop(
  265. PeerId peerId,
  266. std::vector<StoryId> &&pinnedToTop);
  267. [[nodiscard]] int pollingInterval(
  268. const PollingSettings &settings) const;
  269. void maybeSchedulePolling(
  270. not_null<Story*> story,
  271. const PollingSettings &settings,
  272. TimeId now);
  273. void sendPollingRequests();
  274. void sendPollingViewsRequests();
  275. void sendViewsSliceRequest();
  276. void sendViewsCountsRequest();
  277. const not_null<Session*> _owner;
  278. std::unordered_map<
  279. PeerId,
  280. base::flat_map<StoryId, std::unique_ptr<Story>>> _stories;
  281. base::flat_map<FullStoryId, std::unique_ptr<Story>> _deletingStories;
  282. std::unordered_map<
  283. PeerId,
  284. base::flat_map<StoryId, std::weak_ptr<HistoryItem>>> _items;
  285. base::flat_multi_map<TimeId, FullStoryId> _expiring;
  286. base::flat_set<PeerId> _peersWithDeletedStories;
  287. base::flat_set<FullStoryId> _deleted;
  288. base::Timer _expireTimer;
  289. bool _expireSchedulePosted = false;
  290. base::flat_map<
  291. PeerId,
  292. base::flat_map<StoryId, std::vector<Fn<void()>>>> _resolvePending;
  293. base::flat_map<
  294. PeerId,
  295. base::flat_map<StoryId, std::vector<Fn<void()>>>> _resolveSent;
  296. std::unordered_map<
  297. not_null<Data::Story*>,
  298. base::flat_set<not_null<HistoryItem*>>> _dependentMessages;
  299. std::unordered_map<PeerId, StoriesSource> _all;
  300. std::vector<StoriesSourceInfo> _sources[kStorySourcesListCount];
  301. rpl::event_stream<> _sourcesChanged[kStorySourcesListCount];
  302. bool _sourcesLoaded[kStorySourcesListCount] = { false };
  303. QString _sourcesStates[kStorySourcesListCount];
  304. Folder *_folderForHidden = nullptr;
  305. mtpRequestId _loadMoreRequestId[kStorySourcesListCount] = { 0 };
  306. rpl::event_stream<PeerId> _sourceChanged;
  307. rpl::event_stream<PeerId> _itemsChanged;
  308. std::unordered_map<PeerId, Set> _archive;
  309. rpl::event_stream<PeerId> _archiveChanged;
  310. std::unordered_map<PeerId, Set> _saved;
  311. rpl::event_stream<PeerId> _savedChanged;
  312. base::flat_set<PeerId> _markReadPending;
  313. base::Timer _markReadTimer;
  314. base::flat_set<PeerId> _markReadRequests;
  315. base::flat_map<
  316. not_null<PeerData*>,
  317. std::vector<Fn<void()>>> _requestingPeerStories;
  318. base::flat_map<PeerId, base::flat_set<StoryId>> _incrementViewsPending;
  319. base::Timer _incrementViewsTimer;
  320. base::flat_set<PeerId> _incrementViewsRequests;
  321. PeerData *_viewsStoryPeer = nullptr;
  322. StoryId _viewsStoryId = 0;
  323. QString _viewsOffset;
  324. Fn<void(StoryViews)> _viewsDone;
  325. mtpRequestId _viewsRequestId = 0;
  326. PeerData *_reactionsStoryPeer = nullptr;
  327. StoryId _reactionsStoryId = 0;
  328. QString _reactionsOffset;
  329. Fn<void(StoryViews)> _reactionsDone;
  330. mtpRequestId _reactionsRequestId = 0;
  331. base::flat_set<FullStoryId> _preloaded;
  332. std::vector<FullStoryId> _toPreloadSources[kStorySourcesListCount];
  333. std::vector<FullStoryId> _toPreloadViewer;
  334. std::unique_ptr<StoryPreload> _preloading;
  335. int _preloadingHiddenSourcesCounter = 0;
  336. int _preloadingMainSourcesCounter = 0;
  337. base::flat_map<PeerId, StoryId> _readTill;
  338. base::flat_set<FullStoryId> _pendingReadTillItems;
  339. base::flat_map<not_null<PeerData*>, StoryId> _pendingPeerStateMaxId;
  340. mtpRequestId _readTillsRequestId = 0;
  341. bool _readTillReceived = false;
  342. base::flat_map<not_null<Story*>, PollingSettings> _pollingSettings;
  343. base::flat_set<not_null<Story*>> _pollingViews;
  344. base::Timer _pollingTimer;
  345. base::Timer _pollingViewsTimer;
  346. rpl::variable<StealthMode> _stealthMode;
  347. rpl::lifetime _lifetime;
  348. };
  349. } // namespace Data