From d41f887766f3f998e7bb5b1bc98d6d5ea2bef870 Mon Sep 17 00:00:00 2001 From: Botzy Date: Tue, 12 May 2026 14:08:11 +0300 Subject: [PATCH 1/3] fix: scroll to top of videos list on season change --- src/routes/MetaDetails/VideosList/VideosList.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/routes/MetaDetails/VideosList/VideosList.js b/src/routes/MetaDetails/VideosList/VideosList.js index b751a625d..d310e7653 100644 --- a/src/routes/MetaDetails/VideosList/VideosList.js +++ b/src/routes/MetaDetails/VideosList/VideosList.js @@ -71,11 +71,19 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, return videosForSeason.every((video) => video.watched); }, [videosForSeason]); + const videosContainerRef = React.useRef(null); + const [search, setSearch] = React.useState(''); const searchInputOnChange = React.useCallback((event) => { setSearch(event.currentTarget.value); }, []); + React.useEffect(() => { + if (videosContainerRef.current) { + videosContainerRef.current.scrollTo({ top: 0, behavior: 'smooth' }); + } + }, [selectedSeason]); + const onMarkVideoAsWatched = (video, watched) => { core.transport.dispatch({ action: 'MetaDetails', @@ -154,7 +162,7 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, value={search} onChange={searchInputOnChange} /> -
+
{ videosForSeason .filter((video) => { From f85991dd8bff4ce4c464989e1c059c9ed1ac87a1 Mon Sep 17 00:00:00 2001 From: Botzy Date: Tue, 12 May 2026 14:09:19 +0300 Subject: [PATCH 2/3] feat: keep scroll position of videos list when clicking on a video --- .../MetaDetails/VideosList/VideosList.js | 70 ++++++++++++------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/routes/MetaDetails/VideosList/VideosList.js b/src/routes/MetaDetails/VideosList/VideosList.js index d310e7653..11e4f8a78 100644 --- a/src/routes/MetaDetails/VideosList/VideosList.js +++ b/src/routes/MetaDetails/VideosList/VideosList.js @@ -11,10 +11,11 @@ const SeasonsBar = require('./SeasonsBar'); const { default: EpisodePicker } = require('../EpisodePicker'); const styles = require('./styles'); +let savedScrollTop = 0; + const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, selectedVideoId, toggleNotifications }) => { const core = useCore(); const profile = useProfile(); - const showNotificationsToggle = React.useMemo(() => { return metaItem?.content?.content?.inLibrary && metaItem?.content?.content?.videos?.length; }, [metaItem]); @@ -72,18 +73,36 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, }, [videosForSeason]); const videosContainerRef = React.useRef(null); + const isMountedRef = React.useRef(false); + + const saveScrollPosition = React.useCallback(() => { + savedScrollTop = videosContainerRef.current?.scrollTop ?? 0; + }, []); + + // Restore scroll on mount (before paint), consume immediately + React.useLayoutEffect(() => { + if (savedScrollTop > 0 && videosContainerRef.current) { + videosContainerRef.current.scrollTop = savedScrollTop; + savedScrollTop = 0; + } + }, []); + + // Scroll to top when the season changes (skip on initial mount to respect restored scroll position) + React.useEffect(() => { + if (!isMountedRef.current) { + isMountedRef.current = true; + return; + } + if (videosContainerRef.current) { + videosContainerRef.current.scrollTo({ top: 0, behavior: 'smooth' }); + } + }, [selectedSeason]); const [search, setSearch] = React.useState(''); const searchInputOnChange = React.useCallback((event) => { setSearch(event.currentTarget.value); }, []); - React.useEffect(() => { - if (videosContainerRef.current) { - videosContainerRef.current.scrollTo({ top: 0, behavior: 'smooth' }); - } - }, [selectedSeason]); - const onMarkVideoAsWatched = (video, watched) => { core.transport.dispatch({ action: 'MetaDetails', @@ -173,24 +192,25 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, ); }) .map((video, index) => ( -
From 4bf254264349809e8a38573160c3611cc45c175d Mon Sep 17 00:00:00 2001 From: Botzy Date: Fri, 15 May 2026 17:54:37 +0300 Subject: [PATCH 3/3] fix: respect selectedVideoId --- src/routes/MetaDetails/VideosList/VideosList.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/MetaDetails/VideosList/VideosList.js b/src/routes/MetaDetails/VideosList/VideosList.js index 11e4f8a78..8c7278cc9 100644 --- a/src/routes/MetaDetails/VideosList/VideosList.js +++ b/src/routes/MetaDetails/VideosList/VideosList.js @@ -93,7 +93,8 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, isMountedRef.current = true; return; } - if (videosContainerRef.current) { + const hasSelectedVideo = videosForSeason.some((v) => v.id === selectedVideoId); + if (!hasSelectedVideo && videosContainerRef.current) { videosContainerRef.current.scrollTo({ top: 0, behavior: 'smooth' }); } }, [selectedSeason]);