From 43bfa1ab939b263f4352865887d62ca36b893de1 Mon Sep 17 00:00:00 2001 From: MerlinScheurer Date: Thu, 30 Jan 2025 18:33:46 +0100 Subject: [PATCH] Refac prepare updating watched state based on progress endpoint --- .../api/actions/updateVideoProgressById.ts | 14 ++++++++++- .../src/components/EmbeddableVideoPlayer.tsx | 5 ++++ frontend/src/components/GoogleCast.tsx | 24 +++++++++---------- frontend/src/components/VideoPlayer.tsx | 15 +++--------- frontend/src/functions/watchedThreshold.ts | 21 ---------------- frontend/src/pages/Video.tsx | 3 +++ 6 files changed, 35 insertions(+), 47 deletions(-) delete mode 100644 frontend/src/functions/watchedThreshold.ts diff --git a/frontend/src/api/actions/updateVideoProgressById.ts b/frontend/src/api/actions/updateVideoProgressById.ts index 8ef6b7ff..e791afeb 100644 --- a/frontend/src/api/actions/updateVideoProgressById.ts +++ b/frontend/src/api/actions/updateVideoProgressById.ts @@ -1,11 +1,23 @@ import APIClient from '../../functions/APIClient'; +type VideoProgressResponseType = { + watched: boolean; + duration: number; + duration_str: string; + watched_date: number; + position: number; + youtube_id: string; +}; + type VideoProgressProp = { youtubeId: string; currentProgress: number; }; -const updateVideoProgressById = async ({ youtubeId, currentProgress }: VideoProgressProp) => { +const updateVideoProgressById = async ({ + youtubeId, + currentProgress, +}: VideoProgressProp): Promise => { return APIClient(`/api/video/${youtubeId}/progress/`, { method: 'POST', body: { position: currentProgress }, diff --git a/frontend/src/components/EmbeddableVideoPlayer.tsx b/frontend/src/components/EmbeddableVideoPlayer.tsx index 13f36443..d68c9a17 100644 --- a/frontend/src/components/EmbeddableVideoPlayer.tsx +++ b/frontend/src/components/EmbeddableVideoPlayer.tsx @@ -115,6 +115,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { setSearchParams({}); }} /> + { @@ -127,12 +128,16 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => { setRefresh(true); }} /> + {cast && ( { setRefresh(true); }} + onWatchStateChanged={() => { + setRefresh(true); + }} /> )} diff --git a/frontend/src/components/GoogleCast.tsx b/frontend/src/components/GoogleCast.tsx index f75175e4..4024c561 100644 --- a/frontend/src/components/GoogleCast.tsx +++ b/frontend/src/components/GoogleCast.tsx @@ -1,8 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; import { VideoType } from '../pages/Home'; -import updateWatchedState from '../api/actions/updateWatchedState'; import updateVideoProgressById from '../api/actions/updateVideoProgressById'; -import watchedThreshold from '../functions/watchedThreshold'; const getURL = () => { return window.location.origin; @@ -29,6 +27,7 @@ async function castVideoProgress( duration: number; }, video: VideoType | undefined, + onWatchStateChanged?: (status: boolean) => void, ) { if (!video) { console.log('castVideoProgress: Video to cast not found...'); @@ -42,19 +41,13 @@ async function castVideoProgress( if (currentTime % 10 <= 1.0 && currentTime !== 0 && duration !== 0) { // Check progress every 10 seconds or else progress is checked a few times a second - await updateVideoProgressById({ + const videoProgressResponse = await updateVideoProgressById({ youtubeId: videoId, currentProgress: currentTime, }); - if (!video.player.watched) { - // Check if video is already marked as watched - if (watchedThreshold(currentTime, duration)) { - await updateWatchedState({ - id: videoId, - is_watched: true, - }); - } + if (videoProgressResponse.watched && video.player.watched !== videoProgressResponse.watched) { + onWatchStateChanged?.(true); } } } @@ -93,9 +86,10 @@ async function castVideoPaused( type GoogleCastProps = { video?: VideoType; setRefresh?: () => void; + onWatchStateChanged?: (status: boolean) => void; }; -const GoogleCast = ({ video, setRefresh }: GoogleCastProps) => { +const GoogleCast = ({ video, setRefresh, onWatchStateChanged }: GoogleCastProps) => { const [isConnected, setIsConnected] = useState(false); const setup = useCallback(() => { @@ -118,12 +112,14 @@ const GoogleCast = ({ video, setRefresh }: GoogleCastProps) => { setIsConnected(player.isConnected); }, ); + playerController.addEventListener( cast.framework.RemotePlayerEventType.CURRENT_TIME_CHANGED, function () { - castVideoProgress(player, video); + castVideoProgress(player, video, onWatchStateChanged); }, ); + playerController.addEventListener( cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED, function () { @@ -131,6 +127,8 @@ const GoogleCast = ({ video, setRefresh }: GoogleCastProps) => { setRefresh?.(); }, ); + + // eslint-disable-next-line react-hooks/exhaustive-deps }, [setRefresh, video]); const startPlayback = useCallback(() => { diff --git a/frontend/src/components/VideoPlayer.tsx b/frontend/src/components/VideoPlayer.tsx index 027c43e8..e8599f9f 100644 --- a/frontend/src/components/VideoPlayer.tsx +++ b/frontend/src/components/VideoPlayer.tsx @@ -1,7 +1,6 @@ import updateVideoProgressById from '../api/actions/updateVideoProgressById'; import updateWatchedState from '../api/actions/updateWatchedState'; import { SponsorBlockSegmentType, SponsorBlockType, VideoResponseType } from '../pages/Video'; -import watchedThreshold from '../functions/watchedThreshold'; import { Dispatch, Fragment, SetStateAction, SyntheticEvent, useState } from 'react'; import formatTime from '../functions/formatTime'; import { useSearchParams } from 'react-router-dom'; @@ -82,21 +81,13 @@ const handleTimeUpdate = if (currentTime < 10) return; if (Number((currentTime % 10).toFixed(1)) <= 0.2) { // Check progress every 10 seconds or else progress is checked a few times a second - await updateVideoProgressById({ + const videoProgressResponse = await updateVideoProgressById({ youtubeId, currentProgress: currentTime, }); - if (!watched) { - // Check if video is already marked as watched - if (watchedThreshold(currentTime, duration)) { - await updateWatchedState({ - id: youtubeId, - is_watched: true, - }); - - onWatchStateChanged?.(true); - } + if (videoProgressResponse.watched && watched !== videoProgressResponse.watched) { + onWatchStateChanged?.(true); } } }; diff --git a/frontend/src/functions/watchedThreshold.ts b/frontend/src/functions/watchedThreshold.ts deleted file mode 100644 index 06b4c0bb..00000000 --- a/frontend/src/functions/watchedThreshold.ts +++ /dev/null @@ -1,21 +0,0 @@ -function watchedThreshold(currentTime: number, duration: number) { - let watched = false; - - if (duration <= 1800) { - // If video is less than 30 min - if (currentTime / duration >= 0.9) { - // Mark as watched at 90% - watched = true; - } - } else { - // If video is more than 30 min - if (currentTime >= duration - 120) { - // Mark as watched if there is two minutes left - watched = true; - } - } - - return watched; -} - -export default watchedThreshold; diff --git a/frontend/src/pages/Video.tsx b/frontend/src/pages/Video.tsx index fce0fb2b..b09544cd 100644 --- a/frontend/src/pages/Video.tsx +++ b/frontend/src/pages/Video.tsx @@ -229,6 +229,9 @@ const Video = () => { setRefresh={() => { setRefreshVideoList(true); }} + onWatchStateChanged={() => { + setRefreshVideoList(true); + }} /> )}

{video.title}