1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include "storage/storage_shared_media.h" 11 #include "base/weak_ptr.h" 12 #include "data/data_sparse_ids.h" 13 14 class History; 15 16 namespace Main { 17 class Session; 18 } // namespace Main 19 20 std::optional<Storage::SharedMediaType> SharedMediaOverviewType( 21 Storage::SharedMediaType type); 22 void SharedMediaShowOverview( 23 Storage::SharedMediaType type, 24 not_null<History*> history); 25 bool SharedMediaAllowSearch(Storage::SharedMediaType type); 26 27 rpl::producer<SparseIdsSlice> SharedMediaViewer( 28 not_null<Main::Session*> session, 29 Storage::SharedMediaKey key, 30 int limitBefore, 31 int limitAfter); 32 33 struct SharedMediaMergedKey { 34 using Type = Storage::SharedMediaType; 35 SharedMediaMergedKeySharedMediaMergedKey36 SharedMediaMergedKey( 37 SparseIdsMergedSlice::Key mergedKey, 38 Type type) 39 : mergedKey(mergedKey) 40 , type(type) { 41 } 42 43 bool operator==(const SharedMediaMergedKey &other) const { 44 return (mergedKey == other.mergedKey) 45 && (type == other.type); 46 } 47 48 SparseIdsMergedSlice::Key mergedKey; 49 Type type = Type::kCount; 50 51 }; 52 53 rpl::producer<SparseIdsMergedSlice> SharedScheduledMediaViewer( 54 not_null<Main::Session*> session, 55 SharedMediaMergedKey key, 56 int limitBefore, 57 int limitAfter); 58 59 rpl::producer<SparseIdsMergedSlice> SharedMediaMergedViewer( 60 not_null<Main::Session*> session, 61 SharedMediaMergedKey key, 62 int limitBefore, 63 int limitAfter); 64 65 class SharedMediaWithLastSlice { 66 public: 67 using Type = Storage::SharedMediaType; 68 69 using Value = std::variant<FullMsgId, not_null<PhotoData*>>; 70 using MessageId = SparseIdsMergedSlice::UniversalMsgId; 71 using UniversalMsgId = std::variant< 72 MessageId, 73 not_null<PhotoData*>>; 74 75 struct Key { 76 Key( 77 PeerId peerId, 78 PeerId migratedPeerId, 79 Type type, 80 UniversalMsgId universalId, 81 bool scheduled = false) peerIdKey82 : peerId(peerId) 83 , migratedPeerId(migratedPeerId) 84 , type(type) 85 , universalId(universalId) 86 , scheduled(scheduled) { 87 Expects(v::is<MessageId>(universalId) || type == Type::ChatPhoto); 88 } 89 90 bool operator==(const Key &other) const { 91 return (peerId == other.peerId) 92 && (migratedPeerId == other.migratedPeerId) 93 && (type == other.type) 94 && (universalId == other.universalId); 95 } 96 bool operator!=(const Key &other) const { 97 return !(*this == other); 98 } 99 100 PeerId peerId = 0; 101 PeerId migratedPeerId = 0; 102 Type type = Type::kCount; 103 UniversalMsgId universalId; 104 bool scheduled = false; 105 106 }; 107 108 SharedMediaWithLastSlice( 109 not_null<Main::Session*> session, 110 Key key); 111 SharedMediaWithLastSlice( 112 not_null<Main::Session*> session, 113 Key key, 114 SparseIdsMergedSlice slice, 115 std::optional<SparseIdsMergedSlice> ending); 116 117 std::optional<int> fullCount() const; 118 std::optional<int> skippedBefore() const; 119 std::optional<int> skippedAfter() const; 120 std::optional<int> indexOf(Value fullId) const; 121 int size() const; 122 Value operator[](int index) const; 123 std::optional<int> distance(const Key &a, const Key &b) const; 124 125 void reverse(); 126 ViewerKey(const Key & key)127 static SparseIdsMergedSlice::Key ViewerKey(const Key &key) { 128 return { 129 key.peerId, 130 key.migratedPeerId, 131 v::is<MessageId>(key.universalId) 132 ? v::get<MessageId>(key.universalId) 133 : ServerMaxMsgId - 1 134 }; 135 } EndingKey(const Key & key)136 static SparseIdsMergedSlice::Key EndingKey(const Key &key) { 137 return { 138 key.peerId, 139 key.migratedPeerId, 140 ServerMaxMsgId - 1 141 }; 142 } 143 144 private: EndingSlice(const Key & key)145 static std::optional<SparseIdsMergedSlice> EndingSlice(const Key &key) { 146 return v::is<MessageId>(key.universalId) 147 ? base::make_optional(SparseIdsMergedSlice(EndingKey(key))) 148 : std::nullopt; 149 } 150 151 static std::optional<PhotoId> LastPeerPhotoId( 152 not_null<Main::Session*> session, 153 PeerId peerId); 154 static std::optional<bool> IsLastIsolated( 155 not_null<Main::Session*> session, 156 const SparseIdsMergedSlice &slice, 157 const std::optional<SparseIdsMergedSlice> &ending, 158 std::optional<PhotoId> lastPeerPhotoId); 159 static std::optional<FullMsgId> LastFullMsgId( 160 const SparseIdsMergedSlice &slice); Add(const std::optional<int> & a,const std::optional<int> & b)161 static std::optional<int> Add( 162 const std::optional<int> &a, 163 const std::optional<int> &b) { 164 return (a && b) ? base::make_optional(*a + *b) : std::nullopt; 165 } ComputeId(PeerId peerId,MsgId msgId)166 static Value ComputeId(PeerId peerId, MsgId msgId) { 167 return FullMsgId(peerToChannel(peerId), msgId); 168 } ComputeId(const Key & key)169 static Value ComputeId(const Key &key) { 170 if (const auto messageId = std::get_if<MessageId>(&key.universalId)) { 171 return (*messageId >= 0) 172 ? ComputeId(key.peerId, *messageId) 173 : ComputeId(key.migratedPeerId, ServerMaxMsgId + *messageId); 174 } 175 return v::get<not_null<PhotoData*>>(key.universalId); 176 } 177 isolatedInSlice()178 bool isolatedInSlice() const { 179 return (_slice.skippedAfter() != 0); 180 } lastPhotoSkip()181 std::optional<int> lastPhotoSkip() const { 182 return _isolatedLastPhoto 183 | [](bool isolated) { return isolated ? 1 : 0; }; 184 } 185 186 std::optional<int> skippedBeforeImpl() const; 187 std::optional<int> skippedAfterImpl() const; 188 std::optional<int> indexOfImpl(Value fullId) const; 189 190 not_null<Main::Session*> _session; 191 Key _key; 192 SparseIdsMergedSlice _slice; 193 std::optional<SparseIdsMergedSlice> _ending; 194 std::optional<PhotoId> _lastPhotoId; 195 std::optional<bool> _isolatedLastPhoto; 196 bool _reversed = false; 197 198 }; 199 200 rpl::producer<SharedMediaWithLastSlice> SharedMediaWithLastViewer( 201 not_null<Main::Session*> session, 202 SharedMediaWithLastSlice::Key key, 203 int limitBefore, 204 int limitAfter); 205 206 rpl::producer<SharedMediaWithLastSlice> SharedMediaWithLastReversedViewer( 207 not_null<Main::Session*> session, 208 SharedMediaWithLastSlice::Key key, 209 int limitBefore, 210 int limitAfter); 211