data_changes.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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/flags.h"
  9. class History;
  10. class PeerData;
  11. class HistoryItem;
  12. namespace Dialogs {
  13. class Entry;
  14. } // namespace Dialogs
  15. namespace Main {
  16. class Session;
  17. } // namespace Main
  18. namespace Data::details {
  19. template <typename Flag>
  20. inline constexpr int CountBit(Flag Last = Flag::LastUsedBit) {
  21. auto i = 0;
  22. while ((1ULL << i) != static_cast<uint64>(Last)) {
  23. ++i;
  24. Assert(i != 64);
  25. }
  26. return i;
  27. }
  28. } // namespace Data::details
  29. namespace Data {
  30. class ForumTopic;
  31. class Story;
  32. struct NameUpdate {
  33. NameUpdate(
  34. not_null<PeerData*> peer,
  35. base::flat_set<QChar> oldFirstLetters)
  36. : peer(peer)
  37. , oldFirstLetters(std::move(oldFirstLetters)) {
  38. }
  39. not_null<PeerData*> peer;
  40. base::flat_set<QChar> oldFirstLetters;
  41. };
  42. struct PeerUpdate {
  43. enum class Flag : uint64 {
  44. None = 0,
  45. // Common flags
  46. Name = (1ULL << 0),
  47. Username = (1ULL << 1),
  48. Photo = (1ULL << 2),
  49. About = (1ULL << 3),
  50. Notifications = (1ULL << 4),
  51. Migration = (1ULL << 5),
  52. UnavailableReason = (1ULL << 6),
  53. ChatThemeEmoji = (1ULL << 7),
  54. ChatWallPaper = (1ULL << 8),
  55. IsBlocked = (1ULL << 9),
  56. MessagesTTL = (1ULL << 10),
  57. FullInfo = (1ULL << 11),
  58. Usernames = (1ULL << 12),
  59. TranslationDisabled = (1ULL << 13),
  60. Color = (1ULL << 14),
  61. BackgroundEmoji = (1ULL << 15),
  62. StoriesState = (1ULL << 16),
  63. VerifyInfo = (1ULL << 17),
  64. StarsPerMessage = (1ULL << 18),
  65. // For users
  66. CanShareContact = (1ULL << 19),
  67. IsContact = (1ULL << 20),
  68. PhoneNumber = (1ULL << 21),
  69. OnlineStatus = (1ULL << 22),
  70. BotCommands = (1ULL << 23),
  71. BotCanBeInvited = (1ULL << 24),
  72. BotStartToken = (1ULL << 25),
  73. CommonChats = (1ULL << 26),
  74. PeerGifts = (1ULL << 27),
  75. HasCalls = (1ULL << 28),
  76. SupportInfo = (1ULL << 29),
  77. IsBot = (1ULL << 30),
  78. EmojiStatus = (1ULL << 31),
  79. BusinessDetails = (1ULL << 32),
  80. Birthday = (1ULL << 33),
  81. PersonalChannel = (1ULL << 34),
  82. StarRefProgram = (1ULL << 35),
  83. PaysPerMessage = (1ULL << 36),
  84. // For chats and channels
  85. InviteLinks = (1ULL << 37),
  86. Members = (1ULL << 38),
  87. Admins = (1ULL << 39),
  88. BannedUsers = (1ULL << 40),
  89. Rights = (1ULL << 41),
  90. PendingRequests = (1ULL << 42),
  91. Reactions = (1ULL << 43),
  92. // For channels
  93. ChannelAmIn = (1ULL << 44),
  94. StickersSet = (1ULL << 45),
  95. EmojiSet = (1ULL << 46),
  96. ChannelLinkedChat = (1ULL << 47),
  97. ChannelLocation = (1ULL << 48),
  98. Slowmode = (1ULL << 49),
  99. GroupCall = (1ULL << 50),
  100. // For iteration
  101. LastUsedBit = (1ULL << 50),
  102. };
  103. using Flags = base::flags<Flag>;
  104. friend inline constexpr auto is_flag_type(Flag) { return true; }
  105. not_null<PeerData*> peer;
  106. Flags flags = 0;
  107. };
  108. struct HistoryUpdate {
  109. enum class Flag : uint32 {
  110. None = 0,
  111. IsPinned = (1U << 0),
  112. UnreadView = (1U << 1),
  113. TopPromoted = (1U << 2),
  114. Folder = (1U << 3),
  115. UnreadMentions = (1U << 4),
  116. UnreadReactions = (1U << 5),
  117. ClientSideMessages = (1U << 6),
  118. ChatOccupied = (1U << 7),
  119. MessageSent = (1U << 8),
  120. ScheduledSent = (1U << 9),
  121. OutboxRead = (1U << 10),
  122. BotKeyboard = (1U << 11),
  123. CloudDraft = (1U << 12),
  124. TranslateFrom = (1U << 13),
  125. TranslatedTo = (1U << 14),
  126. LastUsedBit = (1U << 14),
  127. };
  128. using Flags = base::flags<Flag>;
  129. friend inline constexpr auto is_flag_type(Flag) { return true; }
  130. not_null<History*> history;
  131. Flags flags = 0;
  132. };
  133. struct TopicUpdate {
  134. enum class Flag : uint32 {
  135. None = 0,
  136. UnreadView = (1U << 1),
  137. UnreadMentions = (1U << 2),
  138. UnreadReactions = (1U << 3),
  139. Notifications = (1U << 4),
  140. Title = (1U << 5),
  141. IconId = (1U << 6),
  142. ColorId = (1U << 7),
  143. CloudDraft = (1U << 8),
  144. Closed = (1U << 9),
  145. Creator = (1U << 10),
  146. Destroyed = (1U << 11),
  147. LastUsedBit = (1U << 11),
  148. };
  149. using Flags = base::flags<Flag>;
  150. friend inline constexpr auto is_flag_type(Flag) { return true; }
  151. not_null<ForumTopic*> topic;
  152. Flags flags = 0;
  153. };
  154. struct MessageUpdate {
  155. enum class Flag : uint32 {
  156. None = 0,
  157. Edited = (1U << 0),
  158. Destroyed = (1U << 1),
  159. DialogRowRepaint = (1U << 2),
  160. DialogRowRefresh = (1U << 3),
  161. NewAdded = (1U << 4),
  162. ReplyMarkup = (1U << 5),
  163. BotCallbackSent = (1U << 6),
  164. NewMaybeAdded = (1U << 7),
  165. ReplyToTopAdded = (1U << 8),
  166. NewUnreadReaction = (1U << 9),
  167. LastUsedBit = (1U << 9),
  168. };
  169. using Flags = base::flags<Flag>;
  170. friend inline constexpr auto is_flag_type(Flag) { return true; }
  171. not_null<HistoryItem*> item;
  172. Flags flags = 0;
  173. };
  174. struct EntryUpdate {
  175. enum class Flag : uint32 {
  176. None = 0,
  177. Repaint = (1U << 0),
  178. HasPinnedMessages = (1U << 1),
  179. ForwardDraft = (1U << 2),
  180. LocalDraftSet = (1U << 3),
  181. Height = (1U << 4),
  182. Destroyed = (1U << 5),
  183. LastUsedBit = (1U << 5),
  184. };
  185. using Flags = base::flags<Flag>;
  186. friend inline constexpr auto is_flag_type(Flag) { return true; }
  187. not_null<Dialogs::Entry*> entry;
  188. Flags flags = 0;
  189. };
  190. struct StoryUpdate {
  191. enum class Flag : uint32 {
  192. None = 0,
  193. Edited = (1U << 0),
  194. Destroyed = (1U << 1),
  195. NewAdded = (1U << 2),
  196. ViewsChanged = (1U << 3),
  197. MarkRead = (1U << 4),
  198. Reaction = (1U << 5),
  199. LastUsedBit = (1U << 5),
  200. };
  201. using Flags = base::flags<Flag>;
  202. friend inline constexpr auto is_flag_type(Flag) { return true; }
  203. not_null<Story*> story;
  204. Flags flags = 0;
  205. };
  206. class Changes final {
  207. public:
  208. explicit Changes(not_null<Main::Session*> session);
  209. [[nodiscard]] Main::Session &session() const;
  210. void nameUpdated(
  211. not_null<PeerData*> peer,
  212. base::flat_set<QChar> oldFirstLetters);
  213. [[nodiscard]] rpl::producer<NameUpdate> realtimeNameUpdates() const;
  214. [[nodiscard]] rpl::producer<NameUpdate> realtimeNameUpdates(
  215. not_null<PeerData*> peer) const;
  216. void peerUpdated(not_null<PeerData*> peer, PeerUpdate::Flags flags);
  217. [[nodiscard]] rpl::producer<PeerUpdate> peerUpdates(
  218. PeerUpdate::Flags flags) const;
  219. [[nodiscard]] rpl::producer<PeerUpdate> peerUpdates(
  220. not_null<PeerData*> peer,
  221. PeerUpdate::Flags flags) const;
  222. [[nodiscard]] rpl::producer<PeerUpdate> peerFlagsValue(
  223. not_null<PeerData*> peer,
  224. PeerUpdate::Flags flags) const;
  225. [[nodiscard]] rpl::producer<PeerUpdate> realtimePeerUpdates(
  226. PeerUpdate::Flag flag) const;
  227. void historyUpdated(
  228. not_null<History*> history,
  229. HistoryUpdate::Flags flags);
  230. [[nodiscard]] rpl::producer<HistoryUpdate> historyUpdates(
  231. HistoryUpdate::Flags flags) const;
  232. [[nodiscard]] rpl::producer<HistoryUpdate> historyUpdates(
  233. not_null<History*> history,
  234. HistoryUpdate::Flags flags) const;
  235. [[nodiscard]] rpl::producer<HistoryUpdate> historyFlagsValue(
  236. not_null<History*> history,
  237. HistoryUpdate::Flags flags) const;
  238. [[nodiscard]] rpl::producer<HistoryUpdate> realtimeHistoryUpdates(
  239. HistoryUpdate::Flag flag) const;
  240. void topicUpdated(
  241. not_null<ForumTopic*> topic,
  242. TopicUpdate::Flags flags);
  243. [[nodiscard]] rpl::producer<TopicUpdate> topicUpdates(
  244. TopicUpdate::Flags flags) const;
  245. [[nodiscard]] rpl::producer<TopicUpdate> topicUpdates(
  246. not_null<ForumTopic*> topic,
  247. TopicUpdate::Flags flags) const;
  248. [[nodiscard]] rpl::producer<TopicUpdate> topicFlagsValue(
  249. not_null<ForumTopic*> topic,
  250. TopicUpdate::Flags flags) const;
  251. [[nodiscard]] rpl::producer<TopicUpdate> realtimeTopicUpdates(
  252. TopicUpdate::Flag flag) const;
  253. void topicRemoved(not_null<ForumTopic*> topic);
  254. void messageUpdated(
  255. not_null<HistoryItem*> item,
  256. MessageUpdate::Flags flags);
  257. [[nodiscard]] rpl::producer<MessageUpdate> messageUpdates(
  258. MessageUpdate::Flags flags) const;
  259. [[nodiscard]] rpl::producer<MessageUpdate> messageUpdates(
  260. not_null<HistoryItem*> item,
  261. MessageUpdate::Flags flags) const;
  262. [[nodiscard]] rpl::producer<MessageUpdate> messageFlagsValue(
  263. not_null<HistoryItem*> item,
  264. MessageUpdate::Flags flags) const;
  265. [[nodiscard]] rpl::producer<MessageUpdate> realtimeMessageUpdates(
  266. MessageUpdate::Flag flag) const;
  267. void entryUpdated(
  268. not_null<Dialogs::Entry*> entry,
  269. EntryUpdate::Flags flags);
  270. [[nodiscard]] rpl::producer<EntryUpdate> entryUpdates(
  271. EntryUpdate::Flags flags) const;
  272. [[nodiscard]] rpl::producer<EntryUpdate> entryUpdates(
  273. not_null<Dialogs::Entry*> entry,
  274. EntryUpdate::Flags flags) const;
  275. [[nodiscard]] rpl::producer<EntryUpdate> entryFlagsValue(
  276. not_null<Dialogs::Entry*> entry,
  277. EntryUpdate::Flags flags) const;
  278. [[nodiscard]] rpl::producer<EntryUpdate> realtimeEntryUpdates(
  279. EntryUpdate::Flag flag) const;
  280. void entryRemoved(not_null<Dialogs::Entry*> entry);
  281. void storyUpdated(
  282. not_null<Story*> story,
  283. StoryUpdate::Flags flags);
  284. [[nodiscard]] rpl::producer<StoryUpdate> storyUpdates(
  285. StoryUpdate::Flags flags) const;
  286. [[nodiscard]] rpl::producer<StoryUpdate> storyUpdates(
  287. not_null<Story*> story,
  288. StoryUpdate::Flags flags) const;
  289. [[nodiscard]] rpl::producer<StoryUpdate> storyFlagsValue(
  290. not_null<Story*> story,
  291. StoryUpdate::Flags flags) const;
  292. [[nodiscard]] rpl::producer<StoryUpdate> realtimeStoryUpdates(
  293. StoryUpdate::Flag flag) const;
  294. void sendNotifications();
  295. private:
  296. template <typename DataType, typename UpdateType>
  297. class Manager final {
  298. public:
  299. using Flag = typename UpdateType::Flag;
  300. using Flags = typename UpdateType::Flags;
  301. void updated(
  302. not_null<DataType*> data,
  303. Flags flags,
  304. bool dropScheduled = false);
  305. [[nodiscard]] rpl::producer<UpdateType> updates(Flags flags) const;
  306. [[nodiscard]] rpl::producer<UpdateType> updates(
  307. not_null<DataType*> data,
  308. Flags flags) const;
  309. [[nodiscard]] rpl::producer<UpdateType> flagsValue(
  310. not_null<DataType*> data,
  311. Flags flags) const;
  312. [[nodiscard]] rpl::producer<UpdateType> realtimeUpdates(
  313. Flag flag) const;
  314. void drop(not_null<DataType*> data);
  315. void sendNotifications();
  316. private:
  317. static constexpr auto kCount = details::CountBit<Flag>() + 1;
  318. void sendRealtimeNotifications(
  319. not_null<DataType*> data,
  320. Flags flags);
  321. std::array<rpl::event_stream<UpdateType>, kCount> _realtimeStreams;
  322. base::flat_map<not_null<DataType*>, Flags> _updates;
  323. rpl::event_stream<UpdateType> _stream;
  324. };
  325. void scheduleNotifications();
  326. const not_null<Main::Session*> _session;
  327. rpl::event_stream<NameUpdate> _nameStream;
  328. Manager<PeerData, PeerUpdate> _peerChanges;
  329. Manager<History, HistoryUpdate> _historyChanges;
  330. Manager<ForumTopic, TopicUpdate> _topicChanges;
  331. Manager<HistoryItem, MessageUpdate> _messageChanges;
  332. Manager<Dialogs::Entry, EntryUpdate> _entryChanges;
  333. Manager<Story, StoryUpdate> _storyChanges;
  334. bool _notify = false;
  335. };
  336. } // namespace Data