From d9b55765341dcf70c53a2e8afb0eb833da8bc3ae Mon Sep 17 00:00:00 2001 From: MerlinScheurer Date: Tue, 4 Mar 2025 19:01:48 +0100 Subject: [PATCH 1/7] Refac overwrite scrollIntoView default for consistency --- frontend/src/components/EmbeddableVideoPlayer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/EmbeddableVideoPlayer.tsx b/frontend/src/components/EmbeddableVideoPlayer.tsx index 4bab055d..3795cbd5 100644 --- a/frontend/src/components/EmbeddableVideoPlayer.tsx +++ b/frontend/src/components/EmbeddableVideoPlayer.tsx @@ -66,7 +66,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { setVideoResponse(videoResponse); - inlinePlayerRef.current?.scrollIntoView(); + inlinePlayerRef.current?.scrollIntoView({ block: 'start', inline: 'start' }); setRefresh(false); } @@ -75,7 +75,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { }, [videoId, refresh]); useEffect(() => { - inlinePlayerRef.current?.scrollIntoView(); + inlinePlayerRef.current?.scrollIntoView({ block: 'start', inline: 'start' }); }, []); if (videoResponse === undefined) { From 139f1ff937685cca3700df447d1081053b3eef28 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 5 Mar 2025 21:36:10 +0700 Subject: [PATCH 2/7] fix login error message display --- frontend/src/pages/Login.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index e74b6f83..0b556913 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -28,7 +28,7 @@ const Login = () => { navigate(Routes.Home); } else { const data = await loginResponse.json(); - setErrorMessage(data?.message || 'Unknown Error'); + setErrorMessage(data?.error || 'Unknown Error'); navigate(Routes.Login); } }; From 13098b549627eda4c73aadf2f4e1cece1754e76d Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 5 Mar 2025 22:37:38 +0700 Subject: [PATCH 3/7] useLayoutEffect for scrollIntoView --- .../src/components/EmbeddableVideoPlayer.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/EmbeddableVideoPlayer.tsx b/frontend/src/components/EmbeddableVideoPlayer.tsx index 3795cbd5..813953dd 100644 --- a/frontend/src/components/EmbeddableVideoPlayer.tsx +++ b/frontend/src/components/EmbeddableVideoPlayer.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { VideoResponseType } from '../pages/Video'; import VideoPlayer from './VideoPlayer'; import loadVideoById from '../api/loader/loadVideoById'; @@ -26,6 +26,7 @@ type EmbeddableVideoPlayerProps = { const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { const inlinePlayerRef = useRef(null); + const prevVideoId = useRef(null); const { appSettingsConfig } = useAppSettingsStore(); const [, setSearchParams] = useSearchParams(); @@ -65,18 +66,20 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { } setVideoResponse(videoResponse); - - inlinePlayerRef.current?.scrollIntoView({ block: 'start', inline: 'start' }); - setRefresh(false); } })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [videoId, refresh]); - useEffect(() => { - inlinePlayerRef.current?.scrollIntoView({ block: 'start', inline: 'start' }); - }, []); + useLayoutEffect(() => { + if (videoId !== prevVideoId.current) { + setTimeout(() => { + inlinePlayerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, 0); + } + prevVideoId.current = videoId; // Update the previous video ID + }, [videoId]); if (videoResponse === undefined) { return
; From b7e23db750072cef1d2d1ef2e6360d4ac7af99d0 Mon Sep 17 00:00:00 2001 From: MerlinScheurer Date: Wed, 5 Mar 2025 18:34:57 +0100 Subject: [PATCH 4/7] Fix EmbeddableVideoPlayer scrollIntoView v4 --- .../src/components/EmbeddableVideoPlayer.tsx | 22 ++++++++----------- frontend/src/pages/ChannelVideo.tsx | 7 +++--- frontend/src/pages/Home.tsx | 4 +--- frontend/src/pages/Playlist.tsx | 12 ++-------- frontend/src/pages/Search.tsx | 7 +++--- 5 files changed, 20 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/EmbeddableVideoPlayer.tsx b/frontend/src/components/EmbeddableVideoPlayer.tsx index 813953dd..d3be212d 100644 --- a/frontend/src/components/EmbeddableVideoPlayer.tsx +++ b/frontend/src/components/EmbeddableVideoPlayer.tsx @@ -1,4 +1,4 @@ -import { useEffect, useLayoutEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { VideoResponseType } from '../pages/Video'; import VideoPlayer from './VideoPlayer'; import loadVideoById from '../api/loader/loadVideoById'; @@ -21,12 +21,11 @@ type Playlist = { type PlaylistList = Playlist[]; type EmbeddableVideoPlayerProps = { - videoId: string; + videoId: string | null; }; const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { const inlinePlayerRef = useRef(null); - const prevVideoId = useRef(null); const { appSettingsConfig } = useAppSettingsStore(); const [, setSearchParams] = useSearchParams(); @@ -38,6 +37,12 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { useEffect(() => { (async () => { + if (!videoId) { + return; + } + + inlinePlayerRef.current?.scrollIntoView(); + if (refresh || videoId !== videoResponse?.youtube_id) { const videoResponse = await loadVideoById(videoId); @@ -72,16 +77,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [videoId, refresh]); - useLayoutEffect(() => { - if (videoId !== prevVideoId.current) { - setTimeout(() => { - inlinePlayerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); - }, 0); - } - prevVideoId.current = videoId; // Update the previous video ID - }, [videoId]); - - if (videoResponse === undefined) { + if (videoResponse === undefined || videoId === null) { return
; } diff --git a/frontend/src/pages/ChannelVideo.tsx b/frontend/src/pages/ChannelVideo.tsx index 39141e99..3a22aee2 100644 --- a/frontend/src/pages/ChannelVideo.tsx +++ b/frontend/src/pages/ChannelVideo.tsx @@ -47,7 +47,6 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => { const pagination = videoResponse?.paginate; const hasVideos = videoResponse?.data?.length !== 0; - const showEmbeddedVideo = videoId !== null; const view = userConfig.view_style_home; const isGridView = view === ViewStyles.grid; @@ -81,7 +80,6 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => { channelId, pagination?.current_page, videoType, - showEmbeddedVideo, ]); if (!channel) { @@ -152,10 +150,13 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
+
- {showEmbeddedVideo && } + + +
{!hasVideos && ( diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 14e94bca..70a6fb70 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -119,7 +119,6 @@ const Home = () => { const continueVideos = continueVideoResponse?.data; const hasVideos = videoResponse?.data?.length !== 0; - const showEmbeddedVideo = videoId !== null; const isGridView = userConfig.view_style_home === ViewStyles.grid; const gridView = isGridView ? `boxed-${userConfig.grid_items}` : ''; @@ -153,7 +152,6 @@ const Home = () => { userConfig.hide_watched, currentPage, pagination?.current_page, - showEmbeddedVideo, ]); return ( @@ -161,7 +159,7 @@ const Home = () => { TubeArchivist - {showEmbeddedVideo && } +
{continueVideos && continueVideos.length > 0 && ( diff --git a/frontend/src/pages/Playlist.tsx b/frontend/src/pages/Playlist.tsx index b82dfecb..31719d9c 100644 --- a/frontend/src/pages/Playlist.tsx +++ b/frontend/src/pages/Playlist.tsx @@ -56,7 +56,6 @@ const Playlist = () => { const palylistEntries = playlistResponse?.playlist_entries; const videoArchivedCount = Number(palylistEntries?.filter(video => video.downloaded).length); const videoInPlaylistCount = pagination?.total_hits; - const showEmbeddedVideo = videoId !== null; const view = userConfig.view_style_home; const gridItems = userConfig.grid_items; @@ -87,14 +86,7 @@ const Playlist = () => { setRefresh(false); })(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - playlistId, - userConfig.hide_watched, - refresh, - currentPage, - pagination?.current_page, - showEmbeddedVideo, - ]); + }, [playlistId, userConfig.hide_watched, refresh, currentPage, pagination?.current_page]); if (!playlistId || !playlist) { return `Playlist ${playlistId} not found!`; @@ -301,7 +293,7 @@ const Playlist = () => { />
- {showEmbeddedVideo && } +
diff --git a/frontend/src/pages/Search.tsx b/frontend/src/pages/Search.tsx index b391ee18..eb1d13b5 100644 --- a/frontend/src/pages/Search.tsx +++ b/frontend/src/pages/Search.tsx @@ -56,7 +56,6 @@ const Search = () => { const playlistList = searchResults?.results.playlist_results; const fulltextList = searchResults?.results.fulltext_results; const queryType = searchResults?.queryType; - const showEmbeddedVideo = videoId !== null; const hasSearchQuery = searchTerm.length > 0; const hasVideos = Number(videoList?.length) > 0; @@ -90,7 +89,7 @@ const Search = () => { } else { setSearchResults(EmptySearchResponse); } - }, [debouncedSearchTerm, refresh, showEmbeddedVideo]); + }, [debouncedSearchTerm, refresh]); const fetchResults = async (searchQuery: string) => { const searchResults = await loadSearch(searchQuery); @@ -102,7 +101,9 @@ const Search = () => { return ( <> TubeArchivist - {showEmbeddedVideo && } + + +

Search your Archive

From 838c6ae145582296b6f23f65050d7e0fa526bd62 Mon Sep 17 00:00:00 2001 From: MerlinScheurer Date: Thu, 6 Mar 2025 23:53:23 +0100 Subject: [PATCH 5/7] Refac move loading from localStorage to the beginning of the VideoPlayer --- frontend/src/components/VideoPlayer.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/VideoPlayer.tsx b/frontend/src/components/VideoPlayer.tsx index 8c0b609d..a249c1c5 100644 --- a/frontend/src/components/VideoPlayer.tsx +++ b/frontend/src/components/VideoPlayer.tsx @@ -123,6 +123,7 @@ const VideoPlayer = ({ const [searchParams] = useSearchParams(); const searchParamVideoProgress = searchParams.get('t'); + const volumeFromStorage = Number(localStorage.getItem('playerVolume') ?? 1); const playBackSpeedFromStorage = Number(localStorage.getItem('playerSpeed') || 1); const playBackSpeedIndex = VIDEO_PLAYBACK_SPEEDS.indexOf(playBackSpeedFromStorage) !== -1 @@ -334,7 +335,7 @@ const VideoPlayer = ({ localStorage.setItem('playerSpeed', videoTag.currentTarget.playbackRate.toString()); }} onLoadStart={(videoTag: VideoTag) => { - videoTag.currentTarget.volume = Number(localStorage.getItem('playerVolume') ?? 1); + videoTag.currentTarget.volume = volumeFromStorage; videoTag.currentTarget.playbackRate = Number(playBackSpeedFromStorage ?? 1); }} onTimeUpdate={handleTimeUpdate( From 0fc86407be8cf3c7ed5bd7ec56da57bf4a993f31 Mon Sep 17 00:00:00 2001 From: MerlinScheurer Date: Thu, 6 Mar 2025 23:54:12 +0100 Subject: [PATCH 6/7] Refac refresh video list when videoId changing --- frontend/src/pages/ChannelVideo.tsx | 2 ++ frontend/src/pages/Home.tsx | 2 ++ frontend/src/pages/Playlist.tsx | 10 +++++++++- frontend/src/pages/Search.tsx | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/ChannelVideo.tsx b/frontend/src/pages/ChannelVideo.tsx index 3a22aee2..aa8db33f 100644 --- a/frontend/src/pages/ChannelVideo.tsx +++ b/frontend/src/pages/ChannelVideo.tsx @@ -45,6 +45,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => { const channel = channelResponse; const videoList = videoResponse?.data; const pagination = videoResponse?.paginate; + const refreshWhenVideoIdChanges = videoId !== null; const hasVideos = videoResponse?.data?.length !== 0; @@ -80,6 +81,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => { channelId, pagination?.current_page, videoType, + refreshWhenVideoIdChanges, ]); if (!channel) { diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 70a6fb70..0d58f410 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -117,6 +117,7 @@ const Home = () => { const videoList = videoResponse?.data; const pagination = videoResponse?.paginate; const continueVideos = continueVideoResponse?.data; + const refreshWhenVideoIdChanges = videoId !== null; const hasVideos = videoResponse?.data?.length !== 0; @@ -152,6 +153,7 @@ const Home = () => { userConfig.hide_watched, currentPage, pagination?.current_page, + refreshWhenVideoIdChanges, ]); return ( diff --git a/frontend/src/pages/Playlist.tsx b/frontend/src/pages/Playlist.tsx index 31719d9c..bd4ad549 100644 --- a/frontend/src/pages/Playlist.tsx +++ b/frontend/src/pages/Playlist.tsx @@ -56,6 +56,7 @@ const Playlist = () => { const palylistEntries = playlistResponse?.playlist_entries; const videoArchivedCount = Number(palylistEntries?.filter(video => video.downloaded).length); const videoInPlaylistCount = pagination?.total_hits; + const refreshWhenVideoIdChanges = videoId !== null; const view = userConfig.view_style_home; const gridItems = userConfig.grid_items; @@ -86,7 +87,14 @@ const Playlist = () => { setRefresh(false); })(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [playlistId, userConfig.hide_watched, refresh, currentPage, pagination?.current_page]); + }, [ + playlistId, + userConfig.hide_watched, + refresh, + currentPage, + pagination?.current_page, + refreshWhenVideoIdChanges, + ]); if (!playlistId || !playlist) { return `Playlist ${playlistId} not found!`; diff --git a/frontend/src/pages/Search.tsx b/frontend/src/pages/Search.tsx index eb1d13b5..2db6c4f3 100644 --- a/frontend/src/pages/Search.tsx +++ b/frontend/src/pages/Search.tsx @@ -56,6 +56,7 @@ const Search = () => { const playlistList = searchResults?.results.playlist_results; const fulltextList = searchResults?.results.fulltext_results; const queryType = searchResults?.queryType; + const refreshWhenVideoIdChanges = videoId !== null; const hasSearchQuery = searchTerm.length > 0; const hasVideos = Number(videoList?.length) > 0; @@ -89,7 +90,7 @@ const Search = () => { } else { setSearchResults(EmptySearchResponse); } - }, [debouncedSearchTerm, refresh]); + }, [debouncedSearchTerm, refresh, refreshWhenVideoIdChanges]); const fetchResults = async (searchQuery: string) => { const searchResults = await loadSearch(searchQuery); From 9c847f492ab54f2ac9a7df2f42fb8311318edaf5 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 7 Mar 2025 10:39:14 +0700 Subject: [PATCH 7/7] use videoId for refresh dependency --- frontend/src/pages/ChannelVideo.tsx | 3 +-- frontend/src/pages/Home.tsx | 3 +-- frontend/src/pages/Playlist.tsx | 3 +-- frontend/src/pages/Search.tsx | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/frontend/src/pages/ChannelVideo.tsx b/frontend/src/pages/ChannelVideo.tsx index aa8db33f..2533bebe 100644 --- a/frontend/src/pages/ChannelVideo.tsx +++ b/frontend/src/pages/ChannelVideo.tsx @@ -45,7 +45,6 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => { const channel = channelResponse; const videoList = videoResponse?.data; const pagination = videoResponse?.paginate; - const refreshWhenVideoIdChanges = videoId !== null; const hasVideos = videoResponse?.data?.length !== 0; @@ -81,7 +80,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => { channelId, pagination?.current_page, videoType, - refreshWhenVideoIdChanges, + videoId, ]); if (!channel) { diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 0d58f410..446e9ab8 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -117,7 +117,6 @@ const Home = () => { const videoList = videoResponse?.data; const pagination = videoResponse?.paginate; const continueVideos = continueVideoResponse?.data; - const refreshWhenVideoIdChanges = videoId !== null; const hasVideos = videoResponse?.data?.length !== 0; @@ -153,7 +152,7 @@ const Home = () => { userConfig.hide_watched, currentPage, pagination?.current_page, - refreshWhenVideoIdChanges, + videoId, ]); return ( diff --git a/frontend/src/pages/Playlist.tsx b/frontend/src/pages/Playlist.tsx index bd4ad549..38f4079e 100644 --- a/frontend/src/pages/Playlist.tsx +++ b/frontend/src/pages/Playlist.tsx @@ -56,7 +56,6 @@ const Playlist = () => { const palylistEntries = playlistResponse?.playlist_entries; const videoArchivedCount = Number(palylistEntries?.filter(video => video.downloaded).length); const videoInPlaylistCount = pagination?.total_hits; - const refreshWhenVideoIdChanges = videoId !== null; const view = userConfig.view_style_home; const gridItems = userConfig.grid_items; @@ -93,7 +92,7 @@ const Playlist = () => { refresh, currentPage, pagination?.current_page, - refreshWhenVideoIdChanges, + videoId, ]); if (!playlistId || !playlist) { diff --git a/frontend/src/pages/Search.tsx b/frontend/src/pages/Search.tsx index 2db6c4f3..111ca82e 100644 --- a/frontend/src/pages/Search.tsx +++ b/frontend/src/pages/Search.tsx @@ -56,7 +56,6 @@ const Search = () => { const playlistList = searchResults?.results.playlist_results; const fulltextList = searchResults?.results.fulltext_results; const queryType = searchResults?.queryType; - const refreshWhenVideoIdChanges = videoId !== null; const hasSearchQuery = searchTerm.length > 0; const hasVideos = Number(videoList?.length) > 0; @@ -90,7 +89,7 @@ const Search = () => { } else { setSearchResults(EmptySearchResponse); } - }, [debouncedSearchTerm, refresh, refreshWhenVideoIdChanges]); + }, [debouncedSearchTerm, refresh, videoId]); const fetchResults = async (searchQuery: string) => { const searchResults = await loadSearch(searchQuery);