diff --git a/Telegram/SourceFiles/data/data_shared_media.cpp b/Telegram/SourceFiles/data/data_shared_media.cpp index 1db3ab294..d27224a2a 100644 --- a/Telegram/SourceFiles/data/data_shared_media.cpp +++ b/Telegram/SourceFiles/data/data_shared_media.cpp @@ -16,8 +16,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_shared_media.h" #include "history/history.h" #include "history/history_item.h" +#include "data/data_document.h" #include "data/data_media_types.h" #include "data/data_photo.h" +#include "data/data_scheduled_messages.h" #include "data/data_sparse_ids.h" #include "data/data_session.h" #include "info/info_memento.h" @@ -30,6 +32,42 @@ namespace { using Type = Storage::SharedMediaType; +bool IsItemGoodForType(const not_null item, Type type) { + const auto media = item->media(); + if (!media) { + return false; + } + const auto photo = media->photo(); + const auto photoType = (type == Type::Photo); + if (photoType && photo) { + return true; + } + + const auto document = media->document(); + if (!document) { + return false; + } + const auto voiceType = (type == Type::VoiceFile) + || (type == Type::RoundVoiceFile); + const auto voiceDoc = (document->isVoiceMessage() + || document->isVideoMessage()); + + const auto audioType = (type == Type::MusicFile); + const auto audioDoc = document->isAudioFile(); + + const auto gifType = (type == Type::GIF); + const auto gifDoc = document->isGifv(); + + const auto videoType = (type == Type::Video); + const auto videoDoc = document->isVideoFile(); + + return (audioType && audioDoc) + || (voiceType && voiceDoc) + || (gifType && gifDoc) + || (videoType && videoDoc) + || (photoType && document->isImage()); +} + } // namespace std::optional SharedMediaOverviewType( @@ -153,6 +191,55 @@ rpl::producer SharedMediaViewer( }; } +rpl::producer SharedScheduledMediaViewer( + not_null session, + SharedMediaMergedKey key, + int limitBefore, + int limitAfter) { + Expects(!IsServerMsgId(key.mergedKey.universalId)); + Expects((key.mergedKey.universalId != 0) + || (limitBefore == 0 && limitAfter == 0)); + + const auto history = session->data().history(key.mergedKey.peerId); + + return rpl::single( + rpl::empty_value() + ) | rpl::then( + session->data().scheduledMessages().updates(history) + ) | rpl::map([=] { + const auto list = session->data().scheduledMessages().list(history); + + auto items = ranges::views::all( + list.ids + ) | ranges::views::transform([=](const FullMsgId &fullId) { + return session->data().message(fullId); + }) | ranges::views::filter([=](HistoryItem *item) { + return item + ? IsItemGoodForType(item, key.type) + : false; + }) | ranges::to_vector; + + ranges::sort(items, ranges::less(), &HistoryItem::position); + + auto finishMsgIds = ranges::views::all( + items + ) | ranges::views::transform([=](not_null item) { + return item->fullId().msg; + }) | ranges::to_vector; + + const auto fullCount = finishMsgIds.size(); + + auto unsorted = SparseUnsortedIdsSlice( + std::move(finishMsgIds), + fullCount, + list.skippedBefore, + list.skippedAfter); + return SparseIdsMergedSlice( + key.mergedKey, + std::move(unsorted)); + }); +} + rpl::producer SharedMediaMergedViewer( not_null session, SharedMediaMergedKey key, diff --git a/Telegram/SourceFiles/data/data_shared_media.h b/Telegram/SourceFiles/data/data_shared_media.h index 937a1a882..673186152 100644 --- a/Telegram/SourceFiles/data/data_shared_media.h +++ b/Telegram/SourceFiles/data/data_shared_media.h @@ -50,6 +50,12 @@ struct SharedMediaMergedKey { }; +rpl::producer SharedScheduledMediaViewer( + not_null session, + SharedMediaMergedKey key, + int limitBefore, + int limitAfter); + rpl::producer SharedMediaMergedViewer( not_null session, SharedMediaMergedKey key, diff --git a/Telegram/SourceFiles/data/data_sparse_ids.cpp b/Telegram/SourceFiles/data/data_sparse_ids.cpp index 69b669e91..84fe3a831 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.cpp +++ b/Telegram/SourceFiles/data/data_sparse_ids.cpp @@ -26,33 +26,48 @@ SparseIdsMergedSlice::SparseIdsMergedSlice( , _migrated(std::move(migrated)) { } +SparseIdsMergedSlice::SparseIdsMergedSlice( + Key key, + SparseUnsortedIdsSlice scheduled) +: _key(key) +, _scheduled(std::move(scheduled)) { +} + std::optional SparseIdsMergedSlice::fullCount() const { - return Add( - _part.fullCount(), - _migrated ? _migrated->fullCount() : 0); + return _scheduled + ? _scheduled->fullCount() + : Add( + _part.fullCount(), + _migrated ? _migrated->fullCount() : 0); } std::optional SparseIdsMergedSlice::skippedBefore() const { - return Add( - isolatedInMigrated() ? 0 : _part.skippedBefore(), - _migrated - ? (isolatedInPart() - ? _migrated->fullCount() - : _migrated->skippedBefore()) - : 0 - ); + return _scheduled + ? _scheduled->skippedBefore() + : Add( + isolatedInMigrated() ? 0 : _part.skippedBefore(), + _migrated + ? (isolatedInPart() + ? _migrated->fullCount() + : _migrated->skippedBefore()) + : 0 + ); } std::optional SparseIdsMergedSlice::skippedAfter() const { - return Add( - isolatedInMigrated() ? _part.fullCount() : _part.skippedAfter(), - isolatedInPart() ? 0 : _migrated->skippedAfter() - ); + return _scheduled + ? _scheduled->skippedAfter() + : Add( + isolatedInMigrated() ? _part.fullCount() : _part.skippedAfter(), + isolatedInPart() ? 0 : _migrated->skippedAfter() + ); } std::optional SparseIdsMergedSlice::indexOf( FullMsgId fullId) const { - return isFromPart(fullId) + return _scheduled + ? _scheduled->indexOf(fullId.msg) + : isFromPart(fullId) ? (_part.indexOf(fullId.msg) | func::add(migratedSize())) : isolatedInPart() ? std::nullopt @@ -62,14 +77,20 @@ std::optional SparseIdsMergedSlice::indexOf( } int SparseIdsMergedSlice::size() const { - return (isolatedInPart() ? 0 : migratedSize()) - + (isolatedInMigrated() ? 0 : _part.size()); + return _scheduled + ? _scheduled->size() + : (isolatedInPart() ? 0 : migratedSize()) + + (isolatedInMigrated() ? 0 : _part.size()); } FullMsgId SparseIdsMergedSlice::operator[](int index) const { Expects(index >= 0 && index < size()); - if (auto size = migratedSize()) { + if (_scheduled) { + return ComputeId(_key.peerId, (*_scheduled)[index]); + } + + if (const auto size = migratedSize()) { if (index < size) { return ComputeId(_key.migratedPeerId, (*_migrated)[index]); } @@ -81,8 +102,8 @@ FullMsgId SparseIdsMergedSlice::operator[](int index) const { std::optional SparseIdsMergedSlice::distance( const Key &a, const Key &b) const { - if (auto i = indexOf(ComputeId(a))) { - if (auto j = indexOf(ComputeId(b))) { + if (const auto i = indexOf(ComputeId(a))) { + if (const auto j = indexOf(ComputeId(b))) { return *j - *i; } } @@ -91,10 +112,15 @@ std::optional SparseIdsMergedSlice::distance( auto SparseIdsMergedSlice::nearest( UniversalMsgId id) const -> std::optional { - auto convertFromPartNearest = [&](MsgId result) { + if (_scheduled) { + if (const auto nearestId = _scheduled->nearest(id)) { + return ComputeId(_key.peerId, *nearestId); + } + } + const auto convertFromPartNearest = [&](MsgId result) { return ComputeId(_key.peerId, result); }; - auto convertFromMigratedNearest = [&](MsgId result) { + const auto convertFromMigratedNearest = [&](MsgId result) { return ComputeId(_key.migratedPeerId, result); }; if (IsServerMsgId(id)) { @@ -388,4 +414,4 @@ rpl::producer SparseIdsMergedSlice::CreateViewer( std::move(migrated))); }); }; -} \ No newline at end of file +} diff --git a/Telegram/SourceFiles/data/data_sparse_ids.h b/Telegram/SourceFiles/data/data_sparse_ids.h index e1801d24c..1fb2b5fad 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.h +++ b/Telegram/SourceFiles/data/data_sparse_ids.h @@ -22,6 +22,8 @@ public: }; +using SparseUnsortedIdsSlice = AbstractSparseIds>; + class SparseIdsMergedSlice { public: using UniversalMsgId = MsgId; @@ -29,9 +31,11 @@ public: Key( PeerId peerId, PeerId migratedPeerId, - UniversalMsgId universalId) + UniversalMsgId universalId, + bool scheduled = false) : peerId(peerId) - , migratedPeerId(migratedPeerId) + , scheduled(scheduled) + , migratedPeerId(scheduled ? 0 : migratedPeerId) , universalId(universalId) { } @@ -45,6 +49,7 @@ public: } PeerId peerId = 0; + bool scheduled = false; PeerId migratedPeerId = 0; UniversalMsgId universalId = 0; @@ -55,6 +60,9 @@ public: Key key, SparseIdsSlice part, std::optional migrated); + SparseIdsMergedSlice( + Key key, + SparseUnsortedIdsSlice scheduled); std::optional fullCount() const; std::optional skippedBefore() const; @@ -133,6 +141,7 @@ private: Key _key; SparseIdsSlice _part; std::optional _migrated; + std::optional _scheduled; };