diff --git a/web/src/components/player/PreviewThumbnailPlayer.tsx b/web/src/components/player/PreviewThumbnailPlayer.tsx index d2edbff88..598aa234b 100644 --- a/web/src/components/player/PreviewThumbnailPlayer.tsx +++ b/web/src/components/player/PreviewThumbnailPlayer.tsx @@ -1,7 +1,5 @@ -import VideoPlayer from "./VideoPlayer"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useApiHost } from "@/api"; -import Player from "video.js/dist/types/player"; import { formatUnixTimestampToDateTime, isCurrentHour } from "@/utils/dateUtil"; import { ReviewSegment } from "@/types/review"; import { Slider } from "../ui/slider"; @@ -169,6 +167,7 @@ export default function PreviewThumbnailPlayer({ ); } +const PREVIEW_PADDING = 16; type PreviewContentProps = { review: ReviewSegment; relevantPreview: Preview | undefined; @@ -181,15 +180,69 @@ function PreviewContent({ setProgress, setReviewed, }: PreviewContentProps) { - const playerRef = useRef(null); + const playerRef = useRef(null); + + // keep track of playback state + const playerStartTime = useMemo(() => { if (!relevantPreview) { return 0; } // start with a bit of padding - return Math.max(0, review.start_time - relevantPreview.start - 8); + return Math.max(0, review.start_time - relevantPreview.start - PREVIEW_PADDING); }, []); + const [lastPercent, setLastPercent] = useState(0.0); + + // initialize player correctly + + useEffect(() => { + if (!playerRef.current) { + return; + } + + if (isSafari) { + playerRef.current.pause(); + setManualPlayback(true); + } else { + playerRef.current.currentTime = playerStartTime; + playerRef.current.playbackRate = 8; + } + }, [playerRef]); + + // time progress update + + const onProgress = useCallback(() => { + if (!setProgress) { + return; + } + + const playerProgress = + (playerRef.current?.currentTime || 0) - playerStartTime; + + // end with a bit of padding + const playerDuration = review.end_time - review.start_time + PREVIEW_PADDING; + const playerPercent = (playerProgress / playerDuration) * 100; + + if ( + setReviewed && + !review.has_been_reviewed && + lastPercent < 50 && + playerPercent > 50 + ) { + setReviewed(); + } + + setLastPercent(playerPercent); + + if (playerPercent > 100) { + playerRef.current?.pause(); + setManualPlayback(false); + setProgress(100.0); + } else { + setProgress(playerPercent); + } + }, [setProgress, lastPercent]); // manual playback // safari is incapable of playing at a speed > 2x @@ -204,7 +257,7 @@ function PreviewContent({ let counter = 0; const intervalId: NodeJS.Timeout = setInterval(() => { if (playerRef.current) { - playerRef.current.currentTime(playerStartTime + counter); + playerRef.current.currentTime = playerStartTime + counter; counter += 1; } }, 125); @@ -215,77 +268,17 @@ function PreviewContent({ if (relevantPreview) { return ( - { - playerRef.current = player; - - if (!relevantPreview) { - return; - } - - if (isSafari) { - player.pause(); - setManualPlayback(true); - } else { - player.currentTime(playerStartTime); - player.playbackRate(8); - } - - let lastPercent = 0; - player.on("timeupdate", () => { - if (!setProgress) { - return; - } - - const playerProgress = - (player.currentTime() || 0) - playerStartTime; - - // end with a bit of padding - const playerDuration = review.end_time - review.start_time + 8; - const playerPercent = (playerProgress / playerDuration) * 100; - - if ( - setReviewed && - !review.has_been_reviewed && - lastPercent < 50 && - playerPercent > 50 - ) { - setReviewed(); - } - - lastPercent = playerPercent; - - if (playerPercent > 100) { - playerRef.current?.pause(); - setManualPlayback(false); - setProgress(100.0); - } else { - setProgress(playerPercent); - } - }); - }} - onDispose={() => { - playerRef.current = null; - }} - /> + ); } else if (isCurrentHour(review.start_time)) { return ( @@ -373,10 +366,6 @@ function PreviewContextItems({ setReviewed, }: PreviewContextItemsProps) { const exportReview = useCallback(() => { - console.log( - "trying to export to " + - `export/${review.camera}/start/${review.start_time}/end/${review.end_time}` - ); axios.post( `export/${review.camera}/start/${review.start_time}/end/${review.end_time}`, { playback: "realtime" }