diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 5bf2db6d4..2883bf42c 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1051,6 +1051,40 @@ FullMsgId ResolveTopPinnedId( } } +FullMsgId ResolveMinPinnedId( + not_null peer, + PeerData *migrated) { + const auto slice = peer->session().storage().snapshot( + Storage::SharedMediaQuery( + Storage::SharedMediaKey( + peer->id, + Storage::SharedMediaType::Pinned, + 1), + 1, + 1)); + const auto old = migrated + ? migrated->session().storage().snapshot( + Storage::SharedMediaQuery( + Storage::SharedMediaKey( + migrated->id, + Storage::SharedMediaType::Pinned, + 1), + 1, + 1)) + : Storage::SharedMediaResult{ + .count = 0, + .skippedBefore = 0, + .skippedAfter = 0, + }; + if (!old.messageIds.empty()) { + return FullMsgId(0, old.messageIds.front()); + } else if (old.count == 0 && !slice.messageIds.empty()) { + return FullMsgId(peerToChannel(peer->id), slice.messageIds.front()); + } else { + return FullMsgId(); + } +} + std::optional ResolvePinnedCount( not_null peer, PeerData *migrated) { diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 3a01b6e98..07a76fd77 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -446,6 +446,9 @@ void SetTopPinnedMessageId(not_null peer, MsgId messageId); [[nodiscard]] FullMsgId ResolveTopPinnedId( not_null peer, PeerData *migrated); +[[nodiscard]] FullMsgId ResolveMinPinnedId( + not_null peer, + PeerData *migrated); [[nodiscard]] std::optional ResolvePinnedCount( not_null peer, PeerData *migrated); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 8dbe75450..f816bf062 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1609,6 +1609,7 @@ void HistoryWidget::showHistory( MsgId showAtMsgId, bool reload) { _pinnedClickedId = FullMsgId(); + _minPinnedId = std::nullopt; MsgId wasMsgId = _showAtMsgId; History *wasHistory = _history; @@ -5195,7 +5196,17 @@ void HistoryWidget::updatePinnedViewer() { if (_pinnedClickedId && lessThanId <= lastClickedId) { _pinnedClickedId = FullMsgId(); } - _pinnedTracker->trackAround(std::min(lessThanId, lastClickedId)); + if (_pinnedClickedId && !_minPinnedId) { + _minPinnedId = Data::ResolveMinPinnedId( + _peer, + _migrated ? _migrated->peer.get() : nullptr); + } + if (_pinnedClickedId && _minPinnedId == _pinnedClickedId) { + // After click on the last pinned message we should the top one. + _pinnedTracker->trackAround(ServerMaxMsgId - 1); + } else { + _pinnedTracker->trackAround(std::min(lessThanId, lastClickedId)); + } } void HistoryWidget::checkLastPinnedClickedIdReset( @@ -5211,6 +5222,7 @@ void HistoryWidget::checkLastPinnedClickedIdReset( if (wasScrollTop < nowScrollTop && _pinnedClickedId) { // User scrolled down. _pinnedClickedId = FullMsgId(); + _minPinnedId = std::nullopt; updatePinnedViewer(); } } @@ -5269,7 +5281,13 @@ void HistoryWidget::checkPinnedBarState() { _peer, nullptr, Storage::SharedMediaType::Pinned + ) | rpl::distinct_until_changed( ) | rpl::map([=](int count) { + if (_pinnedClickedId) { + _pinnedClickedId = FullMsgId(); + _minPinnedId = std::nullopt; + updatePinnedViewer(); + } return (count > 1); }) | rpl::distinct_until_changed( ) | rpl::start_with_next([=](bool many) { @@ -5297,6 +5315,7 @@ void HistoryWidget::checkPinnedBarState() { if (const auto item = session().data().message(id.message)) { Ui::showPeerHistory(item->history()->peer, item->id); _pinnedClickedId = id.message; + _minPinnedId = std::nullopt; updatePinnedViewer(); } }, _pinnedBar->lifetime()); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 8520cda6b..7242417fc 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -600,6 +600,7 @@ private: std::unique_ptr _pinnedBar; int _pinnedBarHeight = 0; FullMsgId _pinnedClickedId; + std::optional _minPinnedId; mtpRequestId _saveEditMsgRequestId = 0; diff --git a/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp b/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp index 9cc01c70c..c3845ddca 100644 --- a/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp +++ b/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp @@ -54,8 +54,7 @@ SparseIdsList::AddResult SparseIdsList::uniteAndAdd( } update.messages = &uniteFrom->messages; update.range = uniteFrom->range; - const auto count = int(uniteFrom->messages.size()); - return { count, count - was }; + return { int(uniteFrom->messages.size()) - was }; } template @@ -65,6 +64,10 @@ SparseIdsList::AddResult SparseIdsList::addRangeItemsAndCountNew( MsgRange noSkipRange) { Expects(noSkipRange.from <= noSkipRange.till); + if (noSkipRange.from == noSkipRange.till + && std::begin(messages) == std::end(messages)) { + return { 0 }; + } auto uniteFrom = ranges::lower_bound( _slices, noSkipRange.from, @@ -88,8 +91,7 @@ SparseIdsList::AddResult SparseIdsList::addRangeItemsAndCountNew( ).first; update.messages = &slice->messages; update.range = slice->range; - const auto count = int(slice->messages.size()); - return { count, count }; + return { int(slice->messages.size()) }; } template @@ -111,12 +113,17 @@ void SparseIdsList::addRange( *_count += result.added; } if (_slices.size() == 1) { - if (_slices.front().range == MsgRange { 0, ServerMaxMsgId }) { + if (_count && _slices.front().messages.size() >= *_count) { + _slices.modify(_slices.begin(), [&](Slice &slice) { + slice.range = { 0, ServerMaxMsgId }; + }); + } + if (_slices.front().range == MsgRange{ 0, ServerMaxMsgId }) { _count = _slices.front().messages.size(); } } - if (_count) { - accumulate_max(*_count, result.inslice); + if (_count && update.messages) { + accumulate_max(*_count, int(update.messages->size())); } update.count = _count; _sliceUpdated.fire(std::move(update)); diff --git a/Telegram/SourceFiles/storage/storage_sparse_ids_list.h b/Telegram/SourceFiles/storage/storage_sparse_ids_list.h index 88635f71a..5977e7dc2 100644 --- a/Telegram/SourceFiles/storage/storage_sparse_ids_list.h +++ b/Telegram/SourceFiles/storage/storage_sparse_ids_list.h @@ -71,7 +71,6 @@ private: }; struct AddResult { - int inslice = 0; int added = 0; }; template