diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index acf15e712..889019261 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1729,7 +1729,7 @@ void ApiWrap::clearHistory(not_null 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); } } diff --git a/Telegram/SourceFiles/data/data_feed.cpp b/Telegram/SourceFiles/data/data_feed.cpp index 65372c23e..1cf5adc62 100644 --- a/Telegram/SourceFiles/data/data_feed.cpp +++ b/Telegram/SourceFiles/data/data_feed.cpp @@ -72,14 +72,18 @@ void Feed::registerOne(not_null 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 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 item) { void Feed::messageRemoved(not_null item) { if (lastMessage() == item) { - _lastMessage = base::none; recountLastMessage(); } } @@ -247,11 +250,17 @@ void Feed::historyCleared(not_null 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()) { diff --git a/Telegram/SourceFiles/data/data_feed.h b/Telegram/SourceFiles/data/data_feed.h index 13e3c8b16..23b2b71bb 100644 --- a/Telegram/SourceFiles/data/data_feed.h +++ b/Telegram/SourceFiles/data/data_feed.h @@ -84,6 +84,7 @@ public: private: void indexNameParts(); void recountLastMessage(); + void setLastMessageFromChannels(); bool justUpdateLastMessage(not_null item); void updateChatsListDate(); diff --git a/Telegram/SourceFiles/data/data_feed_messages.cpp b/Telegram/SourceFiles/data/data_feed_messages.cpp index 8d43b376d..11332e5fa 100644 --- a/Telegram/SourceFiles/data/data_feed_messages.cpp +++ b/Telegram/SourceFiles/data/data_feed_messages.cpp @@ -76,6 +76,14 @@ rpl::producer 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, diff --git a/Telegram/SourceFiles/data/data_messages.cpp b/Telegram/SourceFiles/data/data_messages.cpp index 4204c3001..f3ab4a6fd 100644 --- a/Telegram/SourceFiles/data/data_messages.cpp +++ b/Telegram/SourceFiles/data/data_messages.cpp @@ -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 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(); } diff --git a/Telegram/SourceFiles/data/data_messages.h b/Telegram/SourceFiles/data/data_messages.h index 7f79f619d..10c8ed935 100644 --- a/Telegram/SourceFiles/data/data_messages.h +++ b/Telegram/SourceFiles/data/data_messages.h @@ -136,7 +136,8 @@ public: base::optional count); void removeOne(MessagePosition messageId); void removeAll(ChannelId channelId); - void invalidated(); + void invalidate(); + void invalidateBottom(); rpl::producer query(MessagesQuery &&query) const; rpl::producer sliceUpdated() const; @@ -202,6 +203,7 @@ public: bool removeFromChannel(ChannelId channelId); bool removeAll(); bool invalidated(); + bool bottomInvalidated(); void checkInsufficient(); struct AroundData { diff --git a/Telegram/SourceFiles/data/data_shared_media.cpp b/Telegram/SourceFiles/data/data_shared_media.cpp index 9c727772b..66dd5be51 100644 --- a/Telegram/SourceFiles/data/data_shared_media.cpp +++ b/Telegram/SourceFiles/data/data_shared_media.cpp @@ -118,6 +118,14 @@ rpl::producer 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, diff --git a/Telegram/SourceFiles/data/data_sparse_ids.cpp b/Telegram/SourceFiles/data/data_sparse_ids.cpp index 592136b95..774f9d28d 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.cpp +++ b/Telegram/SourceFiles/data/data_sparse_ids.cpp @@ -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(); } diff --git a/Telegram/SourceFiles/data/data_sparse_ids.h b/Telegram/SourceFiles/data/data_sparse_ids.h index 7a49a425d..487fb6fca 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.h +++ b/Telegram/SourceFiles/data/data_sparse_ids.h @@ -170,6 +170,7 @@ public: bool applyUpdate(const Storage::SparseIdsSliceUpdate &update); bool removeOne(MsgId messageId); bool removeAll(); + bool invalidateBottom(); void checkInsufficient(); struct AroundData { diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index fe44e92e4..c55ea9977 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -1302,7 +1302,7 @@ void History::addEdgesToSharedMedia() { void History::addOlderSlice(const QVector &slice) { if (slice.isEmpty()) { - oldLoaded = true; + _loadedAtTop = true; checkJoinedMessage(); return; } @@ -1321,7 +1321,7 @@ void History::addOlderSlice(const QVector &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 &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 &slice) { addToSharedMedia(added); } else { - newLoaded = true; + _loadedAtBottom = true; setLastMessage(lastAvailableMessage()); addEdgesToSharedMedia(); } @@ -1363,11 +1363,11 @@ void History::addNewerSlice(const QVector &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(); diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 74fed55e1..628cc69b8 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -145,6 +145,7 @@ public: not_null user) const; void clear(); + void markFullyLoaded(); void unloadBlocks(); void clearUpTill(MsgId availableMinId); @@ -362,8 +363,6 @@ public: std::deque> blocks; not_null peer; - bool oldLoaded = false; - bool newLoaded = true; HistoryItem *lastSentMsg = nullptr; typedef QList NotifyQueue; @@ -462,7 +461,7 @@ private: not_null 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 _inboxReadBefore; base::optional _outboxReadBefore; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index bb5fc6c9a..2e74a7f3b 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -196,7 +196,9 @@ void HistoryInner::messagesReceived( void HistoryInner::messagesReceivedDown(PeerData *peer, const QVector &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()); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 0a5af556f..5242fc0c7 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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); diff --git a/Telegram/SourceFiles/storage/storage_facade.cpp b/Telegram/SourceFiles/storage/storage_facade.cpp index de670c0e3..99d8fecfc 100644 --- a/Telegram/SourceFiles/storage/storage_facade.cpp +++ b/Telegram/SourceFiles/storage/storage_facade.cpp @@ -20,10 +20,12 @@ public: void add(SharedMediaAddSlice &&query); void remove(SharedMediaRemoveOne &&query); void remove(SharedMediaRemoveAll &&query); + void invalidate(SharedMediaInvalidateBottom &&query); rpl::producer query(SharedMediaQuery &&query) const; rpl::producer sharedMediaSliceUpdated() const; rpl::producer sharedMediaOneRemoved() const; rpl::producer sharedMediaAllRemoved() const; + rpl::producer 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 query( FeedMessagesQuery &&query) const; rpl::producer feedMessagesSliceUpdated() const; rpl::producer feedMessagesOneRemoved() const; rpl::producer feedMessagesAllRemoved() const; rpl::producer feedMessagesInvalidated() const; + rpl::producer 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 Facade::Impl::query(SharedMediaQuery &&query) const { return _sharedMedia.query(std::move(query)); } @@ -87,6 +95,10 @@ rpl::producer Facade::Impl::sharedMediaAllRemoved() const return _sharedMedia.allRemoved(); } +rpl::producer 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 Facade::Impl::query( @@ -152,6 +168,10 @@ rpl::producer Facade::Impl::feedMessagesInvalidated() co return _feedMessages.invalidated(); } +rpl::producer Facade::Impl::feedMessagesBottomInvalidated() const { + return _feedMessages.bottomInvalidated(); +} + Facade::Facade() : _impl(std::make_unique()) { } @@ -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 Facade::query(SharedMediaQuery &&query) const { return _impl->query(std::move(query)); } @@ -191,6 +215,10 @@ rpl::producer Facade::sharedMediaAllRemoved() const { return _impl->sharedMediaAllRemoved(); } +rpl::producer 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 Facade::query( @@ -256,6 +288,10 @@ rpl::producer Facade::feedMessagesInvalidated() const { return _impl->feedMessagesInvalidated(); } +rpl::producer Facade::feedMessagesBottomInvalidated() const { + return _impl->feedMessagesBottomInvalidated(); +} + Facade::~Facade() = default; } // namespace Storage diff --git a/Telegram/SourceFiles/storage/storage_facade.h b/Telegram/SourceFiles/storage/storage_facade.h index 4d9f8eefc..2df5d0816 100644 --- a/Telegram/SourceFiles/storage/storage_facade.h +++ b/Telegram/SourceFiles/storage/storage_facade.h @@ -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 query(SharedMediaQuery &&query) const; rpl::producer sharedMediaSliceUpdated() const; rpl::producer sharedMediaOneRemoved() const; rpl::producer sharedMediaAllRemoved() const; + rpl::producer 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 query( FeedMessagesQuery &&query) const; @@ -79,6 +84,7 @@ public: rpl::producer feedMessagesOneRemoved() const; rpl::producer feedMessagesAllRemoved() const; rpl::producer feedMessagesInvalidated() const; + rpl::producer feedMessagesBottomInvalidated() const; ~Facade(); diff --git a/Telegram/SourceFiles/storage/storage_feed_messages.cpp b/Telegram/SourceFiles/storage/storage_feed_messages.cpp index 9bbe9e3c5..7d797f053 100644 --- a/Telegram/SourceFiles/storage/storage_feed_messages.cpp +++ b/Telegram/SourceFiles/storage/storage_feed_messages.cpp @@ -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 FeedMessages::query( FeedMessagesQuery &&query) const { auto feedIt = _lists.find(query.key.feedId); @@ -94,4 +103,8 @@ rpl::producer FeedMessages::invalidated() const { return _invalidated.events(); } +rpl::producer FeedMessages::bottomInvalidated() const { + return _bottomInvalidated.events(); +} + } // namespace Storage diff --git a/Telegram/SourceFiles/storage/storage_feed_messages.h b/Telegram/SourceFiles/storage/storage_feed_messages.h index efb60b56f..1f9768b4b 100644 --- a/Telegram/SourceFiles/storage/storage_feed_messages.h +++ b/Telegram/SourceFiles/storage/storage_feed_messages.h @@ -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 query( FeedMessagesQuery &&query) const; @@ -139,6 +150,7 @@ public: rpl::producer oneRemoved() const; rpl::producer allRemoved() const; rpl::producer invalidated() const; + rpl::producer bottomInvalidated() const; private: using List = Data::MessagesList; @@ -151,6 +163,7 @@ private: rpl::event_stream _oneRemoved; rpl::event_stream _allRemoved; rpl::event_stream _invalidated; + rpl::event_stream _bottomInvalidated; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/storage/storage_shared_media.cpp b/Telegram/SourceFiles/storage/storage_shared_media.cpp index f5a88773f..14d9d5c19 100644 --- a/Telegram/SourceFiles/storage/storage_shared_media.cpp +++ b/Telegram/SourceFiles/storage/storage_shared_media.cpp @@ -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 SharedMedia::query(SharedMediaQuery &&query) const { Expects(IsValidSharedMediaType(query.key.type)); auto peerIt = _lists.find(query.key.peerId); @@ -116,4 +126,8 @@ rpl::producer SharedMedia::allRemoved() const { return _allRemoved.events(); } +rpl::producer SharedMedia::bottomInvalidated() const { + return _bottomInvalidated.events(); +} + } // namespace Storage diff --git a/Telegram/SourceFiles/storage/storage_shared_media.h b/Telegram/SourceFiles/storage/storage_shared_media.h index 19d2c59f6..0bd27860d 100644 --- a/Telegram/SourceFiles/storage/storage_shared_media.h +++ b/Telegram/SourceFiles/storage/storage_shared_media.h @@ -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 query(SharedMediaQuery &&query) const; rpl::producer sliceUpdated() const; rpl::producer oneRemoved() const; rpl::producer allRemoved() const; + rpl::producer bottomInvalidated() const; private: using Lists = std::array; @@ -196,6 +206,7 @@ private: rpl::event_stream _sliceUpdated; rpl::event_stream _oneRemoved; rpl::event_stream _allRemoved; + rpl::event_stream _bottomInvalidated; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp b/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp index 5ea43dd38..23679c9cd 100644 --- a/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp +++ b/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp @@ -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 SparseIdsList::query( SparseIdsListQuery &&query) const { return [this, query = std::move(query)](auto consumer) { diff --git a/Telegram/SourceFiles/storage/storage_sparse_ids_list.h b/Telegram/SourceFiles/storage/storage_sparse_ids_list.h index 05e45250a..46f58d1d2 100644 --- a/Telegram/SourceFiles/storage/storage_sparse_ids_list.h +++ b/Telegram/SourceFiles/storage/storage_sparse_ids_list.h @@ -48,6 +48,7 @@ public: base::optional count); void removeOne(MsgId messageId); void removeAll(); + void invalidateBottom(); rpl::producer query(SparseIdsListQuery &&query) const; rpl::producer sliceUpdated() const;