From 8e8a48ff2e845d33b5b9df501459de6f518ccd7a Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 29 Feb 2024 09:27:28 -0700 Subject: [PATCH] Show current time on timeline --- .../player/PreviewThumbnailPlayer.tsx | 39 ++++++++++++++++--- web/src/views/events/EventView.tsx | 7 ++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/web/src/components/player/PreviewThumbnailPlayer.tsx b/web/src/components/player/PreviewThumbnailPlayer.tsx index 29ae46d1ae..2e1a93d040 100644 --- a/web/src/components/player/PreviewThumbnailPlayer.tsx +++ b/web/src/components/player/PreviewThumbnailPlayer.tsx @@ -29,6 +29,7 @@ type PreviewPlayerProps = { autoPlayback?: boolean; setReviewed?: (reviewId: string) => void; onClick?: (reviewId: string) => void; + onTimeUpdate?: (time: number | undefined) => void; }; type Preview = { @@ -44,6 +45,7 @@ export default function PreviewThumbnailPlayer({ relevantPreview, setReviewed, onClick, + onTimeUpdate, }: PreviewPlayerProps) { const apiHost = useApiHost(); const { data: config } = useSWR("config"); @@ -62,7 +64,7 @@ export default function PreviewThumbnailPlayer({ }, [ignoreClick, review, onClick]); const swipeHandlers = useSwipeable({ - onSwipedLeft: () => setPlayback(false), + onSwipedLeft: () => (setReviewed ? setReviewed(review.id) : null), onSwipedRight: () => setPlayback(true), preventScrollOnSwipe: true, }); @@ -92,6 +94,10 @@ export default function PreviewThumbnailPlayer({ } setPlayback(false); + + if (onTimeUpdate) { + onTimeUpdate(undefined); + } } }, @@ -125,6 +131,7 @@ export default function PreviewThumbnailPlayer({ setReviewed={handleSetReviewed} setIgnoreClick={setIgnoreClick} isPlayingBack={setPlayback} + onTimeUpdate={onTimeUpdate} /> )} @@ -190,6 +197,7 @@ type PreviewContentProps = { setReviewed?: () => void; setIgnoreClick: (ignore: boolean) => void; isPlayingBack: (ended: boolean) => void; + onTimeUpdate?: (time: number | undefined) => void; }; function PreviewContent({ review, @@ -197,6 +205,7 @@ function PreviewContent({ setReviewed, setIgnoreClick, isPlayingBack, + onTimeUpdate, }: PreviewContentProps) { // preview @@ -208,6 +217,7 @@ function PreviewContent({ setReviewed={setReviewed} setIgnoreClick={setIgnoreClick} isPlayingBack={isPlayingBack} + onTimeUpdate={onTimeUpdate} /> ); } else if (isCurrentHour(review.start_time)) { @@ -217,6 +227,7 @@ function PreviewContent({ setReviewed={setReviewed} setIgnoreClick={setIgnoreClick} isPlayingBack={isPlayingBack} + onTimeUpdate={onTimeUpdate} /> ); } @@ -229,6 +240,7 @@ type VideoPreviewProps = { setReviewed?: () => void; setIgnoreClick: (ignore: boolean) => void; isPlayingBack: (ended: boolean) => void; + onTimeUpdate?: (time: number | undefined) => void; }; function VideoPreview({ review, @@ -236,6 +248,7 @@ function VideoPreview({ setReviewed, setIgnoreClick, isPlayingBack, + onTimeUpdate, }: VideoPreviewProps) { const playerRef = useRef(null); @@ -286,8 +299,10 @@ function VideoPreview({ // time progress update const onProgress = useCallback(() => { - if (!setProgress) { - return; + if (onTimeUpdate) { + onTimeUpdate( + relevantPreview.start + (playerRef.current?.currentTime || 0), + ); } const playerProgress = @@ -310,6 +325,10 @@ function VideoPreview({ if (playerPercent > 100) { if (isMobile) { isPlayingBack(false); + + if (onTimeUpdate) { + onTimeUpdate(undefined); + } } else { playerRef.current?.pause(); } @@ -424,17 +443,19 @@ type InProgressPreviewProps = { setReviewed?: (reviewId: string) => void; setIgnoreClick: (ignore: boolean) => void; isPlayingBack: (ended: boolean) => void; + onTimeUpdate?: (time: number | undefined) => void; }; function InProgressPreview({ review, setReviewed, setIgnoreClick, isPlayingBack, + onTimeUpdate, }: InProgressPreviewProps) { const apiHost = useApiHost(); const { data: previewFrames } = useSWR( - `preview/${review.camera}/start/${Math.floor(review.start_time) - 4}/end/${ - Math.ceil(review.end_time) + 4 + `preview/${review.camera}/start/${Math.floor(review.start_time) - PREVIEW_PADDING}/end/${ + Math.ceil(review.end_time) + PREVIEW_PADDING }/frames`, ); const [manualFrame, setManualFrame] = useState(false); @@ -445,6 +466,10 @@ function InProgressPreview({ return; } + if (onTimeUpdate) { + onTimeUpdate(review.start_time - PREVIEW_PADDING + key); + } + if (manualFrame) { return; } @@ -452,6 +477,10 @@ function InProgressPreview({ if (key == previewFrames.length - 1) { if (isMobile) { isPlayingBack(false); + + if (onTimeUpdate) { + onTimeUpdate(undefined); + } } return; diff --git a/web/src/views/events/EventView.tsx b/web/src/views/events/EventView.tsx index e5199b4a48..8d7a129660 100644 --- a/web/src/views/events/EventView.tsx +++ b/web/src/views/events/EventView.tsx @@ -187,6 +187,10 @@ export default function EventView({ return data; }, [minimap]); + // preview playback + + const [previewTime, setPreviewTime] = useState(); + if (!config) { return ; } @@ -287,6 +291,7 @@ export default function EventView({ review={value} relevantPreview={relevantPreview} setReviewed={markItemAsReviewed} + onTimeUpdate={setPreviewTime} onClick={onSelectReview} /> @@ -308,6 +313,8 @@ export default function EventView({ showMinimap={showMinimap} minimapStartTime={minimapBounds.start} minimapEndTime={minimapBounds.end} + showHandlebar={previewTime != undefined} + handlebarTime={previewTime} events={reviewItems.all} severityType={severity} contentRef={contentRef}