/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "storage/storage_shared_media.h" #include "base/weak_ptr.h" #include "data/data_sparse_ids.h" class History; std::optional SharedMediaOverviewType( Storage::SharedMediaType type); void SharedMediaShowOverview( Storage::SharedMediaType type, not_null history); bool SharedMediaAllowSearch(Storage::SharedMediaType type); rpl::producer SharedMediaViewer( Storage::SharedMediaKey key, int limitBefore, int limitAfter); struct SharedMediaMergedKey { using Type = Storage::SharedMediaType; SharedMediaMergedKey( SparseIdsMergedSlice::Key mergedKey, Type type) : mergedKey(mergedKey) , type(type) { } bool operator==(const SharedMediaMergedKey &other) const { return (mergedKey == other.mergedKey) && (type == other.type); } SparseIdsMergedSlice::Key mergedKey; Type type = Type::kCount; }; rpl::producer SharedMediaMergedViewer( SharedMediaMergedKey key, int limitBefore, int limitAfter); class SharedMediaWithLastSlice { public: using Type = Storage::SharedMediaType; using Value = base::variant>; using MessageId = SparseIdsMergedSlice::UniversalMsgId; using UniversalMsgId = base::variant< MessageId, not_null>; struct Key { Key( PeerId peerId, PeerId migratedPeerId, Type type, UniversalMsgId universalId) : peerId(peerId) , migratedPeerId(migratedPeerId) , type(type) , universalId(universalId) { Expects(base::get_if(&universalId) != nullptr || type == Type::ChatPhoto); } bool operator==(const Key &other) const { return (peerId == other.peerId) && (migratedPeerId == other.migratedPeerId) && (type == other.type) && (universalId == other.universalId); } bool operator!=(const Key &other) const { return !(*this == other); } PeerId peerId = 0; PeerId migratedPeerId = 0; Type type = Type::kCount; UniversalMsgId universalId; }; SharedMediaWithLastSlice(Key key); SharedMediaWithLastSlice( Key key, SparseIdsMergedSlice slice, std::optional ending); std::optional fullCount() const; std::optional skippedBefore() const; std::optional skippedAfter() const; std::optional indexOf(Value fullId) const; int size() const; Value operator[](int index) const; std::optional distance(const Key &a, const Key &b) const; void reverse(); static SparseIdsMergedSlice::Key ViewerKey(const Key &key) { return { key.peerId, key.migratedPeerId, base::get_if(&key.universalId) ? (*base::get_if(&key.universalId)) : ServerMaxMsgId - 1 }; } static SparseIdsMergedSlice::Key EndingKey(const Key &key) { return { key.peerId, key.migratedPeerId, ServerMaxMsgId - 1 }; } private: static std::optional EndingSlice(const Key &key) { return base::get_if(&key.universalId) ? base::make_optional(SparseIdsMergedSlice(EndingKey(key))) : std::nullopt; } static std::optional LastPeerPhotoId(PeerId peerId); static std::optional IsLastIsolated( const SparseIdsMergedSlice &slice, const std::optional &ending, std::optional lastPeerPhotoId); static std::optional LastFullMsgId( const SparseIdsMergedSlice &slice); static std::optional Add( const std::optional &a, const std::optional &b) { return (a && b) ? base::make_optional(*a + *b) : std::nullopt; } static Value ComputeId(PeerId peerId, MsgId msgId) { return FullMsgId( peerIsChannel(peerId) ? peerToBareInt(peerId) : 0, msgId); } static Value ComputeId(const Key &key) { if (auto messageId = base::get_if(&key.universalId)) { return (*messageId >= 0) ? ComputeId(key.peerId, *messageId) : ComputeId(key.migratedPeerId, ServerMaxMsgId + *messageId); } return *base::get_if>(&key.universalId); } bool isolatedInSlice() const { return (_slice.skippedAfter() != 0); } std::optional lastPhotoSkip() const { return _isolatedLastPhoto | [](bool isolated) { return isolated ? 1 : 0; }; } std::optional skippedBeforeImpl() const; std::optional skippedAfterImpl() const; std::optional indexOfImpl(Value fullId) const; Key _key; SparseIdsMergedSlice _slice; std::optional _ending; std::optional _lastPhotoId; std::optional _isolatedLastPhoto; bool _reversed = false; }; rpl::producer SharedMediaWithLastViewer( SharedMediaWithLastSlice::Key key, int limitBefore, int limitAfter); rpl::producer SharedMediaWithLastReversedViewer( SharedMediaWithLastSlice::Key key, int limitBefore, int limitAfter);