From e7312697bf242f5674461514b4efc39e6708182d Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 21 Jul 2023 18:49:54 +0400 Subject: [PATCH] In the viewer remember which story was opened. --- .../stories/media_stories_controller.cpp | 56 +++++++++++++------ .../media/stories/media_stories_controller.h | 12 +++- .../media/stories/media_stories_sibling.cpp | 28 ++++++++-- .../media/stories/media_stories_sibling.h | 7 ++- 4 files changed, 75 insertions(+), 28 deletions(-) diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 489ed9ad4..2c2efc7d6 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -673,6 +673,7 @@ void Controller::rebuildFromContext( _showingUnreadSources = source && (source->readTill < id); } rebuildCachedSourcesList(sources, (i - begin(sources))); + _cachedSourcesList[_cachedSourceIndex].shownId = storyId.story; showSiblings(&user->session()); if (int(sources.end() - i) < kPreloadUsersCount) { stories.loadMore(list); @@ -980,13 +981,13 @@ void Controller::showSiblings(not_null session) { session, (_cachedSourceIndex > 0 ? _cachedSourcesList[_cachedSourceIndex - 1] - : PeerId())); + : CachedSource())); showSibling( _siblingRight, session, (_cachedSourceIndex + 1 < _cachedSourcesList.size() ? _cachedSourcesList[_cachedSourceIndex + 1] - : PeerId())); + : CachedSource())); } void Controller::hideSiblings() { @@ -997,16 +998,16 @@ void Controller::hideSiblings() { void Controller::showSibling( std::unique_ptr &sibling, not_null session, - PeerId peerId) { - if (!peerId) { + CachedSource cached) { + if (!cached) { sibling = nullptr; return; } - const auto source = session->data().stories().source(peerId); + const auto source = session->data().stories().source(cached.peerId); if (!source) { sibling = nullptr; - } else if (!sibling || !sibling->shows(*source)) { - sibling = std::make_unique(this, *source); + } else if (!sibling || !sibling->shows(*source, cached.shownId)) { + sibling = std::make_unique(this, *source, cached.shownId); } } @@ -1301,12 +1302,18 @@ void Controller::rebuildCachedSourcesList( // Remove removed. _cachedSourcesList.erase(ranges::remove_if(_cachedSourcesList, [&]( - PeerId id) { - return !ranges::contains(lists, id, &Data::StoriesSourceInfo::id); + CachedSource source) { + return !ranges::contains( + lists, + source.peerId, + &Data::StoriesSourceInfo::id); }), end(_cachedSourcesList)); // Find current, full rebuild if can't find. - const auto i = ranges::find(_cachedSourcesList, currentPeerId); + const auto i = ranges::find( + _cachedSourcesList, + currentPeerId, + &CachedSource::peerId); if (i == end(_cachedSourcesList)) { _cachedSourcesList.clear(); } else { @@ -1320,17 +1327,24 @@ void Controller::rebuildCachedSourcesList( || (info.unreadCount > 0) || (info.id == currentPeerId); }; + const auto mapper = [](const Data::StoriesSourceInfo &info) { + return CachedSource{ info.id }; + }; _cachedSourcesList = lists | ranges::views::filter(predicate) - | ranges::views::transform(&Data::StoriesSourceInfo::id) + | ranges::views::transform(mapper) | ranges::to_vector; - _cachedSourceIndex = ranges::find(_cachedSourcesList, currentPeerId) - - begin(_cachedSourcesList); + _cachedSourceIndex = ranges::find( + _cachedSourcesList, + currentPeerId, + &CachedSource::peerId + ) - begin(_cachedSourcesList); } else if (ranges::equal( lists, _cachedSourcesList, ranges::equal_to(), - &Data::StoriesSourceInfo::id)) { + &Data::StoriesSourceInfo::id, + &CachedSource::peerId)) { // No rebuild needed. } else { // All that go before the current push to front. @@ -1338,10 +1352,13 @@ void Controller::rebuildCachedSourcesList( const auto &info = lists[--before]; if (_showingUnreadSources && !info.unreadCount) { continue; - } else if (!ranges::contains(_cachedSourcesList, info.id)) { + } else if (!ranges::contains( + _cachedSourcesList, + info.id, + &CachedSource::peerId)) { _cachedSourcesList.insert( begin(_cachedSourcesList), - info.id); + { info.id }); ++_cachedSourceIndex; } } @@ -1352,8 +1369,11 @@ void Controller::rebuildCachedSourcesList( const auto &info = lists[after]; if (_showingUnreadSources && !info.unreadCount) { continue; - } else if (!ranges::contains(_cachedSourcesList, info.id)) { - _cachedSourcesList.push_back(info.id); + } else if (!ranges::contains( + _cachedSourcesList, + info.id, + &CachedSource::peerId)) { + _cachedSourcesList.push_back({ info.id }); } } } diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index 1d83d24e5..760835a81 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -177,6 +177,14 @@ private: const StoriesList &, const StoriesList &) = default; }; + struct CachedSource { + PeerId peerId = 0; + StoryId shownId = 0; + + explicit operator bool() const { + return peerId != 0; + } + }; class PhotoPlayback; class Unsupported; @@ -198,7 +206,7 @@ private: void showSibling( std::unique_ptr &sibling, not_null session, - PeerId peerId); + CachedSource cached); void subjumpTo(int index); void checkWaitingFor(); @@ -264,7 +272,7 @@ private: bool _started = false; bool _viewed = false; - std::vector _cachedSourcesList; + std::vector _cachedSourcesList; int _cachedSourceIndex = -1; bool _showingUnreadSources = false; diff --git a/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp b/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp index 0da004993..1024edadb 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp @@ -33,6 +33,17 @@ constexpr auto kSiblingFadeOver = 0.4; constexpr auto kSiblingNameOpacity = 0.8; constexpr auto kSiblingNameOpacityOver = 1.; +[[nodiscard]] StoryId LookupShownId( + const Data::StoriesSource &source, + StoryId suggestedId) { + const auto i = suggestedId + ? source.ids.lower_bound(Data::StoryIdDates{ suggestedId }) + : end(source.ids); + return (i != end(source.ids) && i->id == suggestedId) + ? suggestedId + : source.toOpen().id; +} + } // namespace class Sibling::Loader { @@ -229,9 +240,10 @@ bool Sibling::LoaderVideo::updateAfterGoodCheck() { Sibling::Sibling( not_null controller, - const Data::StoriesSource &source) + const Data::StoriesSource &source, + StoryId suggestedId) : _controller(controller) -, _id{ source.user->id, source.ids.front().id } +, _id{ source.user->id, LookupShownId(source, suggestedId) } , _peer(source.user) { checkStory(); _goodShown.stop(); @@ -288,10 +300,14 @@ not_null Sibling::peer() const { return _peer; } -bool Sibling::shows(const Data::StoriesSource &source) const { - Expects(!source.ids.empty()); - - return _id == FullStoryId{ source.user->id, source.ids.front().id }; +bool Sibling::shows( + const Data::StoriesSource &source, + StoryId suggestedId) const { + const auto fullId = FullStoryId{ + source.user->id, + LookupShownId(source, suggestedId), + }; + return (_id == fullId); } SiblingView Sibling::view(const SiblingLayout &layout, float64 over) { diff --git a/Telegram/SourceFiles/media/stories/media_stories_sibling.h b/Telegram/SourceFiles/media/stories/media_stories_sibling.h index 28cfc9cbc..24f334cae 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_sibling.h +++ b/Telegram/SourceFiles/media/stories/media_stories_sibling.h @@ -26,12 +26,15 @@ class Sibling final : public base::has_weak_ptr { public: Sibling( not_null controller, - const Data::StoriesSource &source); + const Data::StoriesSource &source, + StoryId suggestedId); ~Sibling(); [[nodiscard]] FullStoryId shownId() const; [[nodiscard]] not_null peer() const; - [[nodiscard]] bool shows(const Data::StoriesSource &source) const; + [[nodiscard]] bool shows( + const Data::StoriesSource &source, + StoryId suggestedId) const; [[nodiscard]] SiblingView view( const SiblingLayout &layout,