/* 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; namespace Main { class Session; } // namespace Main std::optional SharedMediaOverviewType( Storage::SharedMediaType type); void SharedMediaShowOverview( Storage::SharedMediaType type, not_null history); bool SharedMediaAllowSearch(Storage::SharedMediaType type); rpl::producer SharedMediaViewer( not_null session, 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 SharedScheduledMediaViewer( not_null session, SharedMediaMergedKey key, int limitBefore, int limitAfter); rpl::producer SharedMediaMergedViewer( not_null session, SharedMediaMergedKey key, int limitBefore, int limitAfter); class SharedMediaWithLastSlice { public: using Type = Storage::SharedMediaType; using Value = std::variant>; using MessageId = SparseIdsMergedSlice::UniversalMsgId; using UniversalMsgId = std::variant< MessageId, not_null>; struct Key { Key( PeerId peerId, PeerId migratedPeerId, Type type, UniversalMsgId universalId, bool scheduled = false) : peerId(peerId) , migratedPeerId(migratedPeerId) , type(type) , universalId(universalId) , scheduled(scheduled) { Expects(v::is(universalId) || 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; bool scheduled = false; }; SharedMediaWithLastSlice( not_null session, Key key); SharedMediaWithLastSlice( not_null session, 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, v::is(key.universalId) ? v::get(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 v::is(key.universalId) ? base::make_optional(SparseIdsMergedSlice(EndingKey(key))) : std::nullopt; } static std::optional LastPeerPhotoId( not_null session, PeerId peerId); static std::optional IsLastIsolated( not_null session, 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(peerToChannel(peerId), msgId); } static Value ComputeId(const Key &key) { if (const auto messageId = std::get_if(&key.universalId)) { return (*messageId >= 0) ? ComputeId(key.peerId, *messageId) : ComputeId(key.migratedPeerId, ServerMaxMsgId + *messageId); } return v::get>(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; not_null _session; Key _key; SparseIdsMergedSlice _slice; std::optional _ending; std::optional _lastPhotoId; std::optional _isolatedLastPhoto; bool _reversed = false; }; rpl::producer SharedMediaWithLastViewer( not_null session, SharedMediaWithLastSlice::Key key, int limitBefore, int limitAfter); rpl::producer SharedMediaWithLastReversedViewer( not_null session, SharedMediaWithLastSlice::Key key, int limitBefore, int limitAfter);