storage_shared_media.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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 <rpl/event_stream.h>
  9. #include "storage/storage_facade.h"
  10. #include "storage/storage_sparse_ids_list.h"
  11. namespace Storage {
  12. // Allow forward declarations.
  13. enum class SharedMediaType : signed char {
  14. Photo,
  15. Video,
  16. PhotoVideo,
  17. MusicFile,
  18. File,
  19. VoiceFile,
  20. Link,
  21. ChatPhoto,
  22. RoundVoiceFile,
  23. GIF,
  24. RoundFile,
  25. Pinned,
  26. kCount,
  27. };
  28. constexpr auto kSharedMediaTypeCount = static_cast<int>(SharedMediaType::kCount);
  29. constexpr bool IsValidSharedMediaType(SharedMediaType type) {
  30. return (static_cast<int>(type) >= 0)
  31. && (static_cast<int>(type) < kSharedMediaTypeCount);
  32. }
  33. using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
  34. struct SharedMediaAddNew {
  35. SharedMediaAddNew(
  36. PeerId peerId,
  37. MsgId topicRootId,
  38. SharedMediaTypesMask types,
  39. MsgId messageId)
  40. : peerId(peerId)
  41. , topicRootId(topicRootId)
  42. , messageId(messageId)
  43. , types(types) {
  44. }
  45. PeerId peerId = 0;
  46. MsgId topicRootId = 0;
  47. MsgId messageId = 0;
  48. SharedMediaTypesMask types;
  49. };
  50. struct SharedMediaAddExisting {
  51. SharedMediaAddExisting(
  52. PeerId peerId,
  53. MsgId topicRootId,
  54. SharedMediaTypesMask types,
  55. MsgId messageId,
  56. MsgRange noSkipRange)
  57. : peerId(peerId)
  58. , topicRootId(topicRootId)
  59. , messageId(messageId)
  60. , noSkipRange(noSkipRange)
  61. , types(types) {
  62. }
  63. PeerId peerId = 0;
  64. MsgId topicRootId = 0;
  65. MsgId messageId = 0;
  66. MsgRange noSkipRange;
  67. SharedMediaTypesMask types;
  68. };
  69. struct SharedMediaAddSlice {
  70. SharedMediaAddSlice(
  71. PeerId peerId,
  72. MsgId topicRootId,
  73. SharedMediaType type,
  74. std::vector<MsgId> &&messageIds,
  75. MsgRange noSkipRange,
  76. std::optional<int> count = std::nullopt)
  77. : peerId(peerId)
  78. , topicRootId(topicRootId)
  79. , messageIds(std::move(messageIds))
  80. , noSkipRange(noSkipRange)
  81. , type(type)
  82. , count(count) {
  83. }
  84. PeerId peerId = 0;
  85. MsgId topicRootId = 0;
  86. std::vector<MsgId> messageIds;
  87. MsgRange noSkipRange;
  88. SharedMediaType type = SharedMediaType::kCount;
  89. std::optional<int> count;
  90. };
  91. struct SharedMediaRemoveOne {
  92. SharedMediaRemoveOne(
  93. PeerId peerId,
  94. SharedMediaTypesMask types,
  95. MsgId messageId)
  96. : peerId(peerId)
  97. , messageId(messageId)
  98. , types(types) {
  99. }
  100. PeerId peerId = 0;
  101. MsgId messageId = 0;
  102. SharedMediaTypesMask types;
  103. };
  104. struct SharedMediaRemoveAll {
  105. SharedMediaRemoveAll(
  106. PeerId peerId,
  107. SharedMediaTypesMask types = SharedMediaTypesMask::All())
  108. : peerId(peerId)
  109. , types(types) {
  110. }
  111. SharedMediaRemoveAll(
  112. PeerId peerId,
  113. MsgId topicRootId,
  114. SharedMediaTypesMask types = SharedMediaTypesMask::All())
  115. : peerId(peerId)
  116. , topicRootId(topicRootId)
  117. , types(types) {
  118. }
  119. PeerId peerId = 0;
  120. MsgId topicRootId = 0;
  121. SharedMediaTypesMask types;
  122. };
  123. struct SharedMediaInvalidateBottom {
  124. SharedMediaInvalidateBottom(PeerId peerId) : peerId(peerId) {
  125. }
  126. PeerId peerId = 0;
  127. };
  128. struct SharedMediaKey {
  129. SharedMediaKey(
  130. PeerId peerId,
  131. MsgId topicRootId,
  132. SharedMediaType type,
  133. MsgId messageId)
  134. : peerId(peerId)
  135. , topicRootId(topicRootId)
  136. , type(type)
  137. , messageId(messageId) {
  138. }
  139. friend inline constexpr auto operator<=>(
  140. const SharedMediaKey &,
  141. const SharedMediaKey &) = default;
  142. PeerId peerId = 0;
  143. MsgId topicRootId = 0;
  144. SharedMediaType type = SharedMediaType::kCount;
  145. MsgId messageId = 0;
  146. };
  147. struct SharedMediaQuery {
  148. SharedMediaQuery(
  149. SharedMediaKey key,
  150. int limitBefore,
  151. int limitAfter)
  152. : key(key)
  153. , limitBefore(limitBefore)
  154. , limitAfter(limitAfter) {
  155. }
  156. SharedMediaKey key;
  157. int limitBefore = 0;
  158. int limitAfter = 0;
  159. };
  160. using SharedMediaResult = SparseIdsListResult;
  161. struct SharedMediaSliceUpdate {
  162. SharedMediaSliceUpdate(
  163. PeerId peerId,
  164. MsgId topicRootId,
  165. SharedMediaType type,
  166. const SparseIdsSliceUpdate &data)
  167. : peerId(peerId)
  168. , topicRootId(topicRootId)
  169. , type(type)
  170. , data(data) {
  171. }
  172. PeerId peerId = 0;
  173. MsgId topicRootId = 0;
  174. SharedMediaType type = SharedMediaType::kCount;
  175. SparseIdsSliceUpdate data;
  176. };
  177. struct SharedMediaUnloadThread {
  178. SharedMediaUnloadThread(
  179. PeerId peerId,
  180. MsgId topicRootId)
  181. : peerId(peerId)
  182. , topicRootId(topicRootId) {
  183. }
  184. PeerId peerId = 0;
  185. MsgId topicRootId = 0;
  186. };
  187. class SharedMedia {
  188. public:
  189. using Type = SharedMediaType;
  190. void add(SharedMediaAddNew &&query);
  191. void add(SharedMediaAddExisting &&query);
  192. void add(SharedMediaAddSlice &&query);
  193. void remove(SharedMediaRemoveOne &&query);
  194. void remove(SharedMediaRemoveAll &&query);
  195. void invalidate(SharedMediaInvalidateBottom &&query);
  196. void unload(SharedMediaUnloadThread &&query);
  197. rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
  198. SharedMediaResult snapshot(const SharedMediaQuery &query) const;
  199. bool empty(const SharedMediaKey &key) const;
  200. rpl::producer<SharedMediaSliceUpdate> sliceUpdated() const;
  201. rpl::producer<SharedMediaRemoveOne> oneRemoved() const;
  202. rpl::producer<SharedMediaRemoveAll> allRemoved() const;
  203. rpl::producer<SharedMediaInvalidateBottom> bottomInvalidated() const;
  204. private:
  205. struct Key {
  206. PeerId peerId = 0;
  207. MsgId topicRootId = 0;
  208. friend inline constexpr auto operator<=>(Key, Key) = default;
  209. };
  210. using Lists = std::array<SparseIdsList, kSharedMediaTypeCount>;
  211. std::map<Key, Lists>::iterator enforceLists(Key key);
  212. std::map<Key, Lists> _lists;
  213. rpl::event_stream<SharedMediaSliceUpdate> _sliceUpdated;
  214. rpl::event_stream<SharedMediaRemoveOne> _oneRemoved;
  215. rpl::event_stream<SharedMediaRemoveAll> _allRemoved;
  216. rpl::event_stream<SharedMediaInvalidateBottom> _bottomInvalidated;
  217. rpl::lifetime _lifetime;
  218. };
  219. } // namespace Storage