Handle channelDifferenceTooLong in media and feed.

This commit is contained in:
John Preston 2018-02-05 17:37:22 +03:00
parent 11671e85da
commit e102cb1469
21 changed files with 233 additions and 52 deletions

View file

@ -1729,7 +1729,7 @@ void ApiWrap::clearHistory(not_null<PeerData*> peer) {
Local::addSavedPeer(history->peer, ItemDateTime(last));
}
history->clear();
history->newLoaded = history->oldLoaded = true;
history->markFullyLoaded();
}
if (const auto channel = peer->asChannel()) {
if (const auto migrated = peer->migrateFrom()) {
@ -3827,7 +3827,7 @@ void ApiWrap::readFeeds() {
i = _feedReadsDelayed.erase(i);
}
}
if (!_feedReadRequests.empty()) {
if (!_feedReadsDelayed.empty()) {
_feedReadTimer.callOnce(delay);
}
}

View file

@ -72,14 +72,18 @@ void Feed::registerOne(not_null<ChannelData*> channel) {
if (!base::contains(_channels, history)) {
const auto invisible = (_channels.size() < 2);
_channels.push_back(history);
_parent->session().storage().invalidate(
Storage::FeedMessagesInvalidate(_id));
if (history->lastMessageKnown()) {
recountLastMessage();
if (const auto last = history->lastMessage()) {
if (justUpdateLastMessage(last)) {
updateChatListEntry();
}
}
} else if (lastMessageKnown()) {
_parent->session().api().requestDialogEntry(history);
}
_parent->session().storage().remove(
Storage::FeedMessagesInvalidate(_id));
if (invisible && _channels.size() > 1) {
updateChatListExistence();
for (const auto history : _channels) {
@ -98,14 +102,14 @@ void Feed::unregisterOne(not_null<ChannelData*> channel) {
if (i != end(_channels)) {
const auto visible = (_channels.size() > 1);
_channels.erase(i, end(_channels));
_parent->session().storage().remove(
Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
if (const auto last = lastMessage()) {
if (last->history() == history) {
recountLastMessage();
}
}
_parent->session().storage().remove(
Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
if (visible && _channels.size() < 2) {
updateChatListExistence();
for (const auto history : _channels) {
@ -233,7 +237,6 @@ bool Feed::justUpdateLastMessage(not_null<HistoryItem*> item) {
void Feed::messageRemoved(not_null<HistoryItem*> item) {
if (lastMessage() == item) {
_lastMessage = base::none;
recountLastMessage();
}
}
@ -247,11 +250,17 @@ void Feed::historyCleared(not_null<History*> history) {
}
void Feed::recountLastMessage() {
_lastMessage = base::none;
for (const auto history : _channels) {
if (!history->lastMessageKnown()) {
_parent->session().api().requestDialogEntry(this);
return;
}
}
setLastMessageFromChannels();
}
void Feed::setLastMessageFromChannels() {
_lastMessage = nullptr;
for (const auto history : _channels) {
if (const auto last = history->lastMessage()) {

View file

@ -84,6 +84,7 @@ public:
private:
void indexNameParts();
void recountLastMessage();
void setLastMessageFromChannels();
bool justUpdateLastMessage(not_null<HistoryItem*> item);
void updateChatsListDate();

View file

@ -76,6 +76,14 @@ rpl::producer<MessagesSlice> FeedMessagesViewer(
return builder->invalidated();
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
using InvalidateBottom = Storage::FeedMessagesInvalidateBottom;
Auth().storage().feedMessagesBottomInvalidated(
) | rpl::filter([=](const InvalidateBottom &update) {
return (update.feedId == key.feedId);
}) | rpl::filter([=] {
return builder->bottomInvalidated();
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
using Result = Storage::FeedMessagesResult;
Auth().storage().query(Storage::FeedMessagesQuery(
key,

View file

@ -165,11 +165,25 @@ void MessagesList::removeAll(ChannelId channelId) {
}
}
void MessagesList::invalidated() {
void MessagesList::invalidate() {
_slices.clear();
_count = base::none;
}
void MessagesList::invalidateBottom() {
if (!_slices.empty()) {
const auto &last = _slices.back();
if (last.range.till == MaxMessagePosition) {
_slices.modify(_slices.end() - 1, [](Slice &slice) {
slice.range.till = slice.messages.empty()
? slice.range.from
: slice.messages.back();
});
}
}
_count = base::none;
}
rpl::producer<MessagesResult> MessagesList::query(
MessagesQuery &&query) const {
return [this, query = std::move(query)](auto consumer) {
@ -328,6 +342,12 @@ bool MessagesSliceBuilder::invalidated() {
return false;
}
bool MessagesSliceBuilder::bottomInvalidated() {
_fullCount = _skippedAfter = base::none;
checkInsufficient();
return true;
}
void MessagesSliceBuilder::checkInsufficient() {
sliceToLimits();
}

View file

@ -136,7 +136,8 @@ public:
base::optional<int> count);
void removeOne(MessagePosition messageId);
void removeAll(ChannelId channelId);
void invalidated();
void invalidate();
void invalidateBottom();
rpl::producer<MessagesResult> query(MessagesQuery &&query) const;
rpl::producer<MessagesSliceUpdate> sliceUpdated() const;
@ -202,6 +203,7 @@ public:
bool removeFromChannel(ChannelId channelId);
bool removeAll();
bool invalidated();
bool bottomInvalidated();
void checkInsufficient();
struct AroundData {

View file

@ -118,6 +118,14 @@ rpl::producer<SparseIdsSlice> SharedMediaViewer(
return builder->removeAll();
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
using InvalidateBottom = Storage::SharedMediaInvalidateBottom;
Auth().storage().sharedMediaBottomInvalidated(
) | rpl::filter([=](const InvalidateBottom &update) {
return (update.peerId == key.peerId);
}) | rpl::filter([=] {
return builder->invalidateBottom();
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
using Result = Storage::SharedMediaResult;
Auth().storage().query(Storage::SharedMediaQuery(
key,

View file

@ -249,6 +249,15 @@ bool SparseIdsSliceBuilder::removeAll() {
return true;
}
bool SparseIdsSliceBuilder::invalidateBottom() {
_fullCount = _skippedAfter = base::none;
if (_range.till == ServerMaxMsgId) {
_range.till = _ids.empty() ? _range.from : _ids.back();
}
checkInsufficient();
return true;
}
void SparseIdsSliceBuilder::checkInsufficient() {
sliceToLimits();
}

View file

@ -170,6 +170,7 @@ public:
bool applyUpdate(const Storage::SparseIdsSliceUpdate &update);
bool removeOne(MsgId messageId);
bool removeAll();
bool invalidateBottom();
void checkInsufficient();
struct AroundData {

View file

@ -1302,7 +1302,7 @@ void History::addEdgesToSharedMedia() {
void History::addOlderSlice(const QVector<MTPMessage> &slice) {
if (slice.isEmpty()) {
oldLoaded = true;
_loadedAtTop = true;
checkJoinedMessage();
return;
}
@ -1321,7 +1321,7 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice) {
addToSharedMedia(added);
} else {
// If no items were added it means we've loaded everything old.
oldLoaded = true;
_loadedAtTop = true;
addEdgesToSharedMedia();
}
@ -1333,7 +1333,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice) {
bool wasEmpty = isEmpty(), wasLoadedAtBottom = loadedAtBottom();
if (slice.isEmpty()) {
newLoaded = true;
_loadedAtBottom = true;
if (!lastMessage()) {
setLastMessage(lastAvailableMessage());
}
@ -1348,7 +1348,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice) {
addToSharedMedia(added);
} else {
newLoaded = true;
_loadedAtBottom = true;
setLastMessage(lastAvailableMessage());
addEdgesToSharedMedia();
}
@ -1363,11 +1363,11 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice) {
void History::checkLastMessage() {
if (const auto last = lastMessage()) {
if (!newLoaded && last->mainView()) {
newLoaded = true;
if (!_loadedAtBottom && last->mainView()) {
_loadedAtBottom = true;
checkAddAllToUnreadMentions();
}
} else if (newLoaded) {
} else if (_loadedAtBottom) {
setLastMessage(lastAvailableMessage());
}
}
@ -1974,11 +1974,11 @@ void History::clearNotifications() {
}
bool History::loadedAtBottom() const {
return newLoaded;
return _loadedAtBottom;
}
bool History::loadedAtTop() const {
return oldLoaded;
return _loadedAtTop;
}
bool History::isReadyFor(MsgId msgId) {
@ -2035,20 +2035,38 @@ void History::getReadyFor(MsgId msgId) {
unloadBlocks();
if (msgId == ShowAtTheEndMsgId) {
newLoaded = true;
_loadedAtBottom = true;
}
}
}
void History::setNotLoadedAtBottom() {
newLoaded = false;
_loadedAtBottom = false;
Auth().storage().invalidate(
Storage::SharedMediaInvalidateBottom(peer->id));
if (const auto channel = peer->asChannel()) {
if (const auto feed = channel->feed()) {
Auth().storage().invalidate(
Storage::FeedMessagesInvalidateBottom(
feed->id()));
}
}
}
namespace {
uint32 _dialogsPosToTopShift = 0x80000000UL;
} // namespace
void History::markFullyLoaded() {
_loadedAtTop = _loadedAtBottom = true;
if (isEmpty()) {
Auth().storage().remove(Storage::SharedMediaRemoveAll(peer->id));
if (const auto channel = peer->asChannel()) {
if (const auto feed = channel->feed()) {
Auth().storage().remove(Storage::FeedMessagesRemoveAll(
feed->id(),
channel->bareId()));
}
}
}
}
void History::setLastMessage(HistoryItem *item) {
if (item) {
@ -2479,14 +2497,6 @@ void History::clearBlocks(bool leaveItems) {
} else {
setLastMessage(nullptr);
notifies.clear();
Auth().storage().remove(Storage::SharedMediaRemoveAll(peer->id));
if (const auto channel = peer->asChannel()) {
if (const auto feed = channel->feed()) {
Auth().storage().remove(Storage::FeedMessagesRemoveAll(
feed->id(),
channel->bareId()));
}
}
Auth().data().notifyHistoryCleared(this);
}
blocks.clear();
@ -2505,7 +2515,8 @@ void History::clearBlocks(bool leaveItems) {
}
Auth().data().notifyHistoryChangeDelayed(this);
newLoaded = oldLoaded = false;
_loadedAtTop = false;
_loadedAtBottom = !leaveItems;
forgetScrollState();
if (const auto chat = peer->asChat()) {
chat->lastAuthors.clear();

View file

@ -145,6 +145,7 @@ public:
not_null<UserData*> user) const;
void clear();
void markFullyLoaded();
void unloadBlocks();
void clearUpTill(MsgId availableMinId);
@ -362,8 +363,6 @@ public:
std::deque<std::unique_ptr<HistoryBlock>> blocks;
not_null<PeerData*> peer;
bool oldLoaded = false;
bool newLoaded = true;
HistoryItem *lastSentMsg = nullptr;
typedef QList<HistoryItem*> NotifyQueue;
@ -462,7 +461,7 @@ private:
not_null<HistoryItem*> item,
const MTPDmessageService &data);
// After adding a new history slice check the lastMessage and newLoaded.
// After adding a new history slice check lastMessage / loadedAtBottom.
void checkLastMessage();
void setLastMessage(HistoryItem *item);
@ -491,6 +490,8 @@ private:
Element *_unreadBarView = nullptr;
Element *_firstUnreadView = nullptr;
HistoryService *_joinedMessage = nullptr;
bool _loadedAtTop = false;
bool _loadedAtBottom = true;
base::optional<MsgId> _inboxReadBefore;
base::optional<MsgId> _outboxReadBefore;

View file

@ -196,7 +196,9 @@ void HistoryInner::messagesReceived(
void HistoryInner::messagesReceivedDown(PeerData *peer, const QVector<MTPMessage> &messages) {
if (_history && _history->peer == peer) {
bool oldLoaded = (_migrated && _history->isEmpty() && !_migrated->isEmpty());
const auto oldLoaded = _migrated
&& _history->isEmpty()
&& !_migrated->isEmpty();
_history->addNewerSlice(messages);
if (oldLoaded) {
_history->addOlderSlice(QVector<MTPMessage>());

View file

@ -1057,8 +1057,9 @@ void MainWidget::deleteConversation(
}
}
history->clear();
history->newLoaded = true;
history->oldLoaded = deleteHistory;
if (deleteHistory) {
history->markFullyLoaded();
}
}
if (const auto channel = peer->asChannel()) {
channel->ptsWaitingForShortPoll(-1);

View file

@ -20,10 +20,12 @@ public:
void add(SharedMediaAddSlice &&query);
void remove(SharedMediaRemoveOne &&query);
void remove(SharedMediaRemoveAll &&query);
void invalidate(SharedMediaInvalidateBottom &&query);
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
rpl::producer<SharedMediaSliceUpdate> sharedMediaSliceUpdated() const;
rpl::producer<SharedMediaRemoveOne> sharedMediaOneRemoved() const;
rpl::producer<SharedMediaRemoveAll> sharedMediaAllRemoved() const;
rpl::producer<SharedMediaInvalidateBottom> sharedMediaBottomInvalidated() const;
void add(UserPhotosAddNew &&query);
void add(UserPhotosAddSlice &&query);
@ -36,13 +38,15 @@ public:
void add(FeedMessagesAddSlice &&query);
void remove(FeedMessagesRemoveOne &&query);
void remove(FeedMessagesRemoveAll &&query);
void remove(FeedMessagesInvalidate &&query);
void invalidate(FeedMessagesInvalidate &&query);
void invalidate(FeedMessagesInvalidateBottom &&query);
rpl::producer<FeedMessagesResult> query(
FeedMessagesQuery &&query) const;
rpl::producer<FeedMessagesSliceUpdate> feedMessagesSliceUpdated() const;
rpl::producer<FeedMessagesRemoveOne> feedMessagesOneRemoved() const;
rpl::producer<FeedMessagesRemoveAll> feedMessagesAllRemoved() const;
rpl::producer<FeedMessagesInvalidate> feedMessagesInvalidated() const;
rpl::producer<FeedMessagesInvalidateBottom> feedMessagesBottomInvalidated() const;
private:
SharedMedia _sharedMedia;
@ -71,6 +75,10 @@ void Facade::Impl::remove(SharedMediaRemoveAll &&query) {
_sharedMedia.remove(std::move(query));
}
void Facade::Impl::invalidate(SharedMediaInvalidateBottom &&query) {
_sharedMedia.invalidate(std::move(query));
}
rpl::producer<SharedMediaResult> Facade::Impl::query(SharedMediaQuery &&query) const {
return _sharedMedia.query(std::move(query));
}
@ -87,6 +95,10 @@ rpl::producer<SharedMediaRemoveAll> Facade::Impl::sharedMediaAllRemoved() const
return _sharedMedia.allRemoved();
}
rpl::producer<SharedMediaInvalidateBottom> Facade::Impl::sharedMediaBottomInvalidated() const {
return _sharedMedia.bottomInvalidated();
}
void Facade::Impl::add(UserPhotosAddNew &&query) {
return _userPhotos.add(std::move(query));
}
@ -127,8 +139,12 @@ void Facade::Impl::remove(FeedMessagesRemoveAll &&query) {
return _feedMessages.remove(std::move(query));
}
void Facade::Impl::remove(FeedMessagesInvalidate &&query) {
return _feedMessages.remove(std::move(query));
void Facade::Impl::invalidate(FeedMessagesInvalidate &&query) {
return _feedMessages.invalidate(std::move(query));
}
void Facade::Impl::invalidate(FeedMessagesInvalidateBottom &&query) {
return _feedMessages.invalidate(std::move(query));
}
rpl::producer<FeedMessagesResult> Facade::Impl::query(
@ -152,6 +168,10 @@ rpl::producer<FeedMessagesInvalidate> Facade::Impl::feedMessagesInvalidated() co
return _feedMessages.invalidated();
}
rpl::producer<FeedMessagesInvalidateBottom> Facade::Impl::feedMessagesBottomInvalidated() const {
return _feedMessages.bottomInvalidated();
}
Facade::Facade() : _impl(std::make_unique<Impl>()) {
}
@ -175,6 +195,10 @@ void Facade::remove(SharedMediaRemoveAll &&query) {
_impl->remove(std::move(query));
}
void Facade::invalidate(SharedMediaInvalidateBottom &&query) {
_impl->invalidate(std::move(query));
}
rpl::producer<SharedMediaResult> Facade::query(SharedMediaQuery &&query) const {
return _impl->query(std::move(query));
}
@ -191,6 +215,10 @@ rpl::producer<SharedMediaRemoveAll> Facade::sharedMediaAllRemoved() const {
return _impl->sharedMediaAllRemoved();
}
rpl::producer<SharedMediaInvalidateBottom> Facade::sharedMediaBottomInvalidated() const {
return _impl->sharedMediaBottomInvalidated();
}
void Facade::add(UserPhotosAddNew &&query) {
return _impl->add(std::move(query));
}
@ -231,8 +259,12 @@ void Facade::remove(FeedMessagesRemoveAll &&query) {
return _impl->remove(std::move(query));
}
void Facade::remove(FeedMessagesInvalidate &&query) {
return _impl->remove(std::move(query));
void Facade::invalidate(FeedMessagesInvalidate &&query) {
return _impl->invalidate(std::move(query));
}
void Facade::invalidate(FeedMessagesInvalidateBottom &&query) {
return _impl->invalidate(std::move(query));
}
rpl::producer<FeedMessagesResult> Facade::query(
@ -256,6 +288,10 @@ rpl::producer<FeedMessagesInvalidate> Facade::feedMessagesInvalidated() const {
return _impl->feedMessagesInvalidated();
}
rpl::producer<FeedMessagesInvalidateBottom> Facade::feedMessagesBottomInvalidated() const {
return _impl->feedMessagesBottomInvalidated();
}
Facade::~Facade() = default;
} // namespace Storage

View file

@ -23,6 +23,7 @@ struct SharedMediaAddExisting;
struct SharedMediaAddSlice;
struct SharedMediaRemoveOne;
struct SharedMediaRemoveAll;
struct SharedMediaInvalidateBottom;
struct SharedMediaQuery;
using SharedMediaResult = SparseIdsListResult;
struct SharedMediaSliceUpdate;
@ -40,6 +41,7 @@ struct FeedMessagesAddSlice;
struct FeedMessagesRemoveOne;
struct FeedMessagesRemoveAll;
struct FeedMessagesInvalidate;
struct FeedMessagesInvalidateBottom;
struct FeedMessagesQuery;
using FeedMessagesResult = Data::MessagesResult;
struct FeedMessagesSliceUpdate;
@ -53,11 +55,13 @@ public:
void add(SharedMediaAddSlice &&query);
void remove(SharedMediaRemoveOne &&query);
void remove(SharedMediaRemoveAll &&query);
void invalidate(SharedMediaInvalidateBottom &&query);
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
rpl::producer<SharedMediaSliceUpdate> sharedMediaSliceUpdated() const;
rpl::producer<SharedMediaRemoveOne> sharedMediaOneRemoved() const;
rpl::producer<SharedMediaRemoveAll> sharedMediaAllRemoved() const;
rpl::producer<SharedMediaInvalidateBottom> sharedMediaBottomInvalidated() const;
void add(UserPhotosAddNew &&query);
void add(UserPhotosAddSlice &&query);
@ -71,7 +75,8 @@ public:
void add(FeedMessagesAddSlice &&query);
void remove(FeedMessagesRemoveOne &&query);
void remove(FeedMessagesRemoveAll &&query);
void remove(FeedMessagesInvalidate &&query);
void invalidate(FeedMessagesInvalidate &&query);
void invalidate(FeedMessagesInvalidateBottom &&query);
rpl::producer<FeedMessagesResult> query(
FeedMessagesQuery &&query) const;
@ -79,6 +84,7 @@ public:
rpl::producer<FeedMessagesRemoveOne> feedMessagesOneRemoved() const;
rpl::producer<FeedMessagesRemoveAll> feedMessagesAllRemoved() const;
rpl::producer<FeedMessagesInvalidate> feedMessagesInvalidated() const;
rpl::producer<FeedMessagesInvalidateBottom> feedMessagesBottomInvalidated() const;
~Facade();

View file

@ -55,14 +55,23 @@ void FeedMessages::remove(FeedMessagesRemoveAll &&query) {
}
}
void FeedMessages::remove(FeedMessagesInvalidate &&query) {
void FeedMessages::invalidate(FeedMessagesInvalidate &&query) {
auto feedIt = _lists.find(query.feedId);
if (feedIt != _lists.end()) {
feedIt->second.invalidated();
feedIt->second.invalidateBottom();
feedIt->second.invalidate();
_invalidated.fire(std::move(query));
}
}
void FeedMessages::invalidate(FeedMessagesInvalidateBottom &&query) {
auto feedIt = _lists.find(query.feedId);
if (feedIt != _lists.end()) {
feedIt->second.invalidateBottom();
_bottomInvalidated.fire(std::move(query));
}
}
rpl::producer<FeedMessagesResult> FeedMessages::query(
FeedMessagesQuery &&query) const {
auto feedIt = _lists.find(query.key.feedId);
@ -94,4 +103,8 @@ rpl::producer<FeedMessagesInvalidate> FeedMessages::invalidated() const {
return _invalidated.events();
}
rpl::producer<FeedMessagesInvalidateBottom> FeedMessages::bottomInvalidated() const {
return _bottomInvalidated.events();
}
} // namespace Storage

View file

@ -73,6 +73,16 @@ struct FeedMessagesInvalidate {
};
struct FeedMessagesInvalidateBottom {
explicit FeedMessagesInvalidateBottom(FeedId feedId)
: feedId(feedId) {
}
FeedId feedId = 0;
};
struct FeedMessagesKey {
FeedMessagesKey(
FeedId feedId,
@ -131,7 +141,8 @@ public:
void add(FeedMessagesAddSlice &&query);
void remove(FeedMessagesRemoveOne &&query);
void remove(FeedMessagesRemoveAll &&query);
void remove(FeedMessagesInvalidate &&query);
void invalidate(FeedMessagesInvalidate &&query);
void invalidate(FeedMessagesInvalidateBottom &&query);
rpl::producer<FeedMessagesResult> query(
FeedMessagesQuery &&query) const;
@ -139,6 +150,7 @@ public:
rpl::producer<FeedMessagesRemoveOne> oneRemoved() const;
rpl::producer<FeedMessagesRemoveAll> allRemoved() const;
rpl::producer<FeedMessagesInvalidate> invalidated() const;
rpl::producer<FeedMessagesInvalidateBottom> bottomInvalidated() const;
private:
using List = Data::MessagesList;
@ -151,6 +163,7 @@ private:
rpl::event_stream<FeedMessagesRemoveOne> _oneRemoved;
rpl::event_stream<FeedMessagesRemoveAll> _allRemoved;
rpl::event_stream<FeedMessagesInvalidate> _invalidated;
rpl::event_stream<FeedMessagesInvalidateBottom> _bottomInvalidated;
rpl::lifetime _lifetime;

View file

@ -88,6 +88,16 @@ void SharedMedia::remove(SharedMediaRemoveAll &&query) {
}
}
void SharedMedia::invalidate(SharedMediaInvalidateBottom &&query) {
auto peerIt = _lists.find(query.peerId);
if (peerIt != _lists.end()) {
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
peerIt->second[index].invalidateBottom();
}
_bottomInvalidated.fire(std::move(query));
}
}
rpl::producer<SharedMediaResult> SharedMedia::query(SharedMediaQuery &&query) const {
Expects(IsValidSharedMediaType(query.key.type));
auto peerIt = _lists.find(query.key.peerId);
@ -116,4 +126,8 @@ rpl::producer<SharedMediaRemoveAll> SharedMedia::allRemoved() const {
return _allRemoved.events();
}
rpl::producer<SharedMediaInvalidateBottom> SharedMedia::bottomInvalidated() const {
return _bottomInvalidated.events();
}
} // namespace Storage

View file

@ -113,6 +113,14 @@ struct SharedMediaRemoveAll {
};
struct SharedMediaInvalidateBottom {
SharedMediaInvalidateBottom(PeerId peerId) : peerId(peerId) {
}
PeerId peerId = 0;
};
struct SharedMediaKey {
SharedMediaKey(
PeerId peerId,
@ -180,11 +188,13 @@ public:
void add(SharedMediaAddSlice &&query);
void remove(SharedMediaRemoveOne &&query);
void remove(SharedMediaRemoveAll &&query);
void invalidate(SharedMediaInvalidateBottom &&query);
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
rpl::producer<SharedMediaSliceUpdate> sliceUpdated() const;
rpl::producer<SharedMediaRemoveOne> oneRemoved() const;
rpl::producer<SharedMediaRemoveAll> allRemoved() const;
rpl::producer<SharedMediaInvalidateBottom> bottomInvalidated() const;
private:
using Lists = std::array<SparseIdsList, kSharedMediaTypeCount>;
@ -196,6 +206,7 @@ private:
rpl::event_stream<SharedMediaSliceUpdate> _sliceUpdated;
rpl::event_stream<SharedMediaRemoveOne> _oneRemoved;
rpl::event_stream<SharedMediaRemoveAll> _allRemoved;
rpl::event_stream<SharedMediaInvalidateBottom> _bottomInvalidated;
rpl::lifetime _lifetime;

View file

@ -158,6 +158,20 @@ void SparseIdsList::removeAll() {
_count = 0;
}
void SparseIdsList::invalidateBottom() {
if (!_slices.empty()) {
const auto &last = _slices.back();
if (last.range.till == ServerMaxMsgId) {
_slices.modify(_slices.end() - 1, [](Slice &slice) {
slice.range.till = slice.messages.empty()
? slice.range.from
: slice.messages.back();
});
}
}
_count = base::none;
}
rpl::producer<SparseIdsListResult> SparseIdsList::query(
SparseIdsListQuery &&query) const {
return [this, query = std::move(query)](auto consumer) {

View file

@ -48,6 +48,7 @@ public:
base::optional<int> count);
void removeOne(MsgId messageId);
void removeAll();
void invalidateBottom();
rpl::producer<SparseIdsListResult> query(SparseIdsListQuery &&query) const;
rpl::producer<SparseIdsSliceUpdate> sliceUpdated() const;