diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 7806e1aa63..668ec4c45b 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -78,45 +78,19 @@ using UpdateFlag = StoryUpdate::Flag; } // namespace -int IndexRespectingPinned(const StoriesIds &ids, StoryId id) { - const auto i = ids.list.find(id); - if (ids.pinnedToTop.empty() || i == end(ids.list)) { - return int(i - begin(ids.list)); - } - const auto j = ranges::find(ids.pinnedToTop, id); - if (j != end(ids.pinnedToTop)) { - return int(j - begin(ids.pinnedToTop)); - } - auto result = int(i - begin(ids.list)); - for (const auto &pinnedId : ids.pinnedToTop) { - if (pinnedId < id) { - ++result; - } - } - - Ensures(result < int(ids.list.size())); - return result; -} - -StoryId IdRespectingPinned(const StoriesIds &ids, int index) { - Expects(index >= 0 && index < int(ids.list.size())); - +std::vector RespectingPinned(const StoriesIds &ids) { if (ids.pinnedToTop.empty()) { - return *(begin(ids.list) + index); - } else if (index < int(ids.pinnedToTop.size())) { - return ids.pinnedToTop[index]; + return ids.list | ranges::to_vector; } - auto i = begin(ids.list) + index - int(ids.pinnedToTop.size()); - auto sorted = ids.pinnedToTop; - ranges::sort(sorted, ranges::greater()); - for (const auto &pinnedId : sorted) { - if (pinnedId >= *i) { - ++i; + auto result = std::vector(); + result.reserve(ids.list.size()); + result.insert(end(result), begin(ids.pinnedToTop), end(ids.pinnedToTop)); + for (const auto &id : ids.list) { + if (!ranges::contains(ids.pinnedToTop, id)) { + result.push_back(id); } } - - Ensures(i != end(ids.list)); - return *i; + return result; } StoriesSourceInfo StoriesSource::info() const { diff --git a/Telegram/SourceFiles/data/data_stories.h b/Telegram/SourceFiles/data/data_stories.h index c5f340cc15..2a172e46a3 100644 --- a/Telegram/SourceFiles/data/data_stories.h +++ b/Telegram/SourceFiles/data/data_stories.h @@ -40,9 +40,7 @@ struct StoriesIds { const StoriesIds&) = default; }; -// ids.list.size() if not found. -[[nodiscard]] int IndexRespectingPinned(const StoriesIds &ids, StoryId id); -[[nodiscard]] StoryId IdRespectingPinned(const StoriesIds &ids, int index); +[[nodiscard]] std::vector RespectingPinned(const StoriesIds &ids); struct StoriesSourceInfo { PeerId id = 0; diff --git a/Telegram/SourceFiles/data/data_stories_ids.cpp b/Telegram/SourceFiles/data/data_stories_ids.cpp index fbff87e096..71ccf4275e 100644 --- a/Telegram/SourceFiles/data/data_stories_ids.cpp +++ b/Telegram/SourceFiles/data/data_stories_ids.cpp @@ -39,14 +39,15 @@ rpl::producer SavedStoriesIds( } const auto &saved = stories->saved(peerId); + const auto sorted = RespectingPinned(saved); const auto count = stories->savedCount(peerId); - auto aroundIndex = IndexRespectingPinned(saved, aroundId); - if (aroundIndex == int(saved.list.size())) { - const auto around = saved.list.lower_bound(aroundId); - aroundIndex = int(around - begin(saved.list)); + auto i = ranges::find(sorted, aroundId); + if (i == end(sorted)) { + const auto j = saved.list.lower_bound(aroundId); + i = begin(sorted) + int(j - begin(saved.list)); } - const auto hasBefore = aroundIndex; - const auto hasAfter = int(saved.list.size()) - aroundIndex; + const auto hasBefore = int(i - begin(sorted)); + const auto hasAfter = int(end(sorted) - i); if (hasAfter < limit) { stories->savedLoadMore(peerId); } @@ -54,8 +55,8 @@ rpl::producer SavedStoriesIds( const auto takeAfter = std::min(hasAfter, limit); auto ids = std::vector(); ids.reserve(takeBefore + takeAfter); - for (auto i = aroundIndex - takeBefore; i != aroundIndex + takeAfter; ++i) { - ids.push_back(IdRespectingPinned(saved, i)); + for (auto j = i - takeBefore; j != i + takeAfter; ++j) { + ids.push_back(*j); } const auto added = int(ids.size()); state->slice = StoriesIdsSlice( @@ -118,14 +119,15 @@ rpl::producer ArchiveStoriesIds( } const auto &archive = stories->archive(peerId); - const auto count = stories->archiveCount(peerId); - auto aroundIndex = IndexRespectingPinned(archive, aroundId); - if (aroundIndex == int(archive.list.size())) { - const auto around = archive.list.lower_bound(aroundId); - aroundIndex = int(around - begin(archive.list)); + const auto sorted = RespectingPinned(archive); + const auto count = stories->savedCount(peerId); + auto i = ranges::find(sorted, aroundId); + if (i == end(sorted)) { + const auto j = archive.list.lower_bound(aroundId); + i = begin(sorted) + int(j - begin(archive.list)); } - const auto hasBefore = aroundIndex; - const auto hasAfter = int(archive.list.size()) - aroundIndex; + const auto hasBefore = int(i - begin(sorted)); + const auto hasAfter = int(end(sorted) - i); if (hasAfter < limit) { stories->archiveLoadMore(peerId); } @@ -133,8 +135,8 @@ rpl::producer ArchiveStoriesIds( const auto takeAfter = std::min(hasAfter, limit); auto ids = std::vector(); ids.reserve(takeBefore + takeAfter); - for (auto i = aroundIndex - takeBefore; i != aroundIndex + takeAfter; ++i) { - ids.push_back(IdRespectingPinned(archive, i)); + for (auto j = i - takeBefore; j != i + takeAfter; ++j) { + ids.push_back(*j); } const auto added = int(ids.size()); state->slice = StoriesIdsSlice( diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 2b06956bd0..fa60aa3a74 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -77,8 +77,10 @@ struct SameDayRange { [[nodiscard]] SameDayRange ComputeSameDayRange( not_null story, const Data::StoriesIds &ids, + const std::vector &sorted, int index) { Expects(index >= 0 && index < ids.list.size()); + Expects(index >= 0 && index < sorted.size()); const auto pinned = int(ids.pinnedToTop.size()); if (index < pinned) { @@ -90,7 +92,7 @@ struct SameDayRange { const auto stories = &story->owner().stories(); const auto now = base::unixtime::parse(story->date()); for (auto i = index; i != 0;) { - const auto storyId = IdRespectingPinned(ids, --i); + const auto storyId = sorted[--i]; if (const auto maybeStory = stories->lookup({ peerId, storyId })) { const auto day = base::unixtime::parse((*maybeStory)->date()); if (day.date() != now.date()) { @@ -99,8 +101,8 @@ struct SameDayRange { } --result.from; } - for (auto i = index + 1, c = int(ids.list.size()); i != c; ++i) { - const auto storyId = IdRespectingPinned(ids, i); + for (auto i = index + 1, c = int(sorted.size()); i != c; ++i) { + const auto storyId = sorted[i]; if (const auto maybeStory = stories->lookup({ peerId, storyId })) { const auto day = base::unixtime::parse((*maybeStory)->date()); if (day.date() != now.date()) { @@ -700,16 +702,19 @@ void Controller::rebuildFromContext( }, [&](StoriesContextSaved) { if (stories.savedCountKnown(peerId)) { const auto &saved = stories.saved(peerId); - const auto i = IndexRespectingPinned(saved, id); - if (i < saved.list.size()) { + auto sorted = RespectingPinned(saved); + const auto i = ranges::find(sorted, id); + const auto tillEnd = int(end(sorted) - i); + if (tillEnd > 0) { + _index = int(i - begin(sorted)); list = StoriesList{ .peer = peer, .ids = saved, + .sorted = std::move(sorted), .total = stories.savedCount(peerId), }; - _index = i; if (saved.list.size() < list->total - && (saved.list.size() - i) < kPreloadStoriesCount) { + && tillEnd < kPreloadStoriesCount) { stories.savedLoadMore(peerId); } } @@ -718,16 +723,19 @@ void Controller::rebuildFromContext( }, [&](StoriesContextArchive) { if (stories.archiveCountKnown(peerId)) { const auto &archive = stories.archive(peerId); - const auto i = IndexRespectingPinned(archive, id); - if (i < archive.list.size()) { + auto sorted = RespectingPinned(archive); + const auto i = ranges::find(sorted, id); + const auto tillEnd = int(end(sorted) - i); + if (tillEnd > 0) { + _index = int(i - begin(sorted)); list = StoriesList{ .peer = peer, .ids = archive, + .sorted = std::move(sorted), .total = stories.archiveCount(peerId), }; - _index = i; if (archive.list.size() < list->total - && (archive.list.size() - i) < kPreloadStoriesCount) { + && tillEnd < kPreloadStoriesCount) { stories.archiveLoadMore(peerId); } } @@ -761,7 +769,11 @@ void Controller::rebuildFromContext( } if (const auto maybe = peer->owner().stories().lookup(storyId)) { const auto now = *maybe; - const auto range = ComputeSameDayRange(now, _list->ids, _index); + const auto range = ComputeSameDayRange( + now, + _list->ids, + _list->sorted, + _index); _sliderCount = range.till - range.from + 1; _sliderIndex = _index - range.from; } @@ -779,6 +791,7 @@ void Controller::rebuildFromContext( _list = StoriesList{ .peer = peer, .ids = { { id } }, + .sorted = { id }, .total = 1, }; _index = 0; @@ -1523,8 +1536,8 @@ StoryId Controller::shownId(int index) const { return _source ? (_source->ids.begin() + index)->id - : (index < int(_list->ids.list.size())) - ? IdRespectingPinned(_list->ids, index) + : (index < int(_list->sorted.size())) + ? _list->sorted[index] : StoryId(); } diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index 45590e0a26..b3d7968829 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -194,6 +194,7 @@ private: struct StoriesList { not_null peer; Data::StoriesIds ids; + std::vector sorted; int total = 0; friend inline bool operator==(