From 0e8350ea7f6023cbb6bdcac3adcc138689f60552 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 13 Mar 2024 08:05:01 -0600 Subject: [PATCH] Fix jumping to segment in recordings view (#10424) * Fix skeletons showing incorrectly * Handle clicking segment from different time range --- .../components/player/DynamicVideoPlayer.tsx | 24 ++++++--- web/src/components/player/PreviewPlayer.tsx | 7 ++- web/src/views/events/RecordingView.tsx | 51 ++++++++++++++++--- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/web/src/components/player/DynamicVideoPlayer.tsx b/web/src/components/player/DynamicVideoPlayer.tsx index 07495da19..045fd7d63 100644 --- a/web/src/components/player/DynamicVideoPlayer.tsx +++ b/web/src/components/player/DynamicVideoPlayer.tsx @@ -345,14 +345,23 @@ export class DynamicVideoController { } } + pause() { + this.playerController.pause(); + } + seekToTimestamp(time: number, play: boolean = false) { if (this.playerMode != "playback") { this.playerMode = "playback"; this.setScrubbing(false); } - if (this.recordings.length == 0) { + if ( + this.recordings.length == 0 || + time < this.recordings[0].start_time || + time > this.recordings[this.recordings.length - 1].end_time + ) { this.timeToStart = time; + return; } let seekSeconds = 0; @@ -371,12 +380,15 @@ export class DynamicVideoController { segment.end_time - segment.start_time - (segment.end_time - time); return true; }); - this.playerController.currentTime(seekSeconds); - if (play) { - this.playerController.play(); - } else { - this.playerController.pause(); + if (seekSeconds != 0) { + this.playerController.currentTime(seekSeconds); + + if (play) { + this.playerController.play(); + } else { + this.playerController.pause(); + } } } diff --git a/web/src/components/player/PreviewPlayer.tsx b/web/src/components/player/PreviewPlayer.tsx index 9c8e9d6a4..9206f7e9b 100644 --- a/web/src/components/player/PreviewPlayer.tsx +++ b/web/src/components/player/PreviewPlayer.tsx @@ -154,8 +154,11 @@ function PreviewVideoPlayer({ Math.round(preview.start) >= timeRange.start && Math.floor(preview.end) <= timeRange.end, ); - setLoaded(false); - setCurrentPreview(preview); + + if (preview != currentPreview) { + setCurrentPreview(preview); + setLoaded(false); + } controller.newPlayback({ preview, diff --git a/web/src/views/events/RecordingView.tsx b/web/src/views/events/RecordingView.tsx index bbc564a46..dc9097e2c 100644 --- a/web/src/views/events/RecordingView.tsx +++ b/web/src/views/events/RecordingView.tsx @@ -92,6 +92,21 @@ export function DesktopRecordingView({ const [scrubbing, setScrubbing] = useState(false); const [currentTime, setCurrentTime] = useState(startTime); + const [playerTime, setPlayerTime] = useState(startTime); + + const updateSelectedSegment = useCallback( + (currentTime: number) => { + const index = timeRange.ranges.findIndex( + (seg) => seg.start <= currentTime && seg.end >= currentTime, + ); + + if (index != -1) { + setSelectedRangeIdx(index); + setPlaybackStart(currentTime); + } + }, + [timeRange], + ); useEffect(() => { if (scrubbing) { @@ -99,13 +114,7 @@ export function DesktopRecordingView({ currentTime > currentTimeRange.end + 60 || currentTime < currentTimeRange.start - 60 ) { - const index = timeRange.ranges.findIndex( - (seg) => seg.start <= currentTime && seg.end >= currentTime, - ); - - if (index != -1) { - setSelectedRangeIdx(index); - } + updateSelectedSegment(currentTime); return; } @@ -115,7 +124,13 @@ export function DesktopRecordingView({ controller.scrubToTimestamp(currentTime); }); } - }, [currentTime, scrubbing, timeRange, currentTimeRange]); + }, [ + currentTime, + scrubbing, + timeRange, + currentTimeRange, + updateSelectedSegment, + ]); useEffect(() => { if (!scrubbing) { @@ -126,6 +141,25 @@ export function DesktopRecordingView({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [scrubbing]); + useEffect(() => { + if (!scrubbing) { + if (Math.abs(currentTime - playerTime) > 10) { + mainControllerRef.current?.pause(); + + if ( + currentTimeRange.start <= currentTime && + currentTimeRange.end >= currentTime + ) { + mainControllerRef.current?.seekToTimestamp(currentTime, true); + } else { + updateSelectedSegment(currentTime); + } + } + } + // we only want to seek when current time doesn't match the player update time + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentTime]); + const onSelectCamera = useCallback( (newCam: string) => { setMainCamera(newCam); @@ -191,6 +225,7 @@ export function DesktopRecordingView({ onControllerReady={(controller) => { mainControllerRef.current = controller; controller.onPlayerTimeUpdate((timestamp: number) => { + setPlayerTime(timestamp); setCurrentTime(timestamp); Object.values(previewRefs.current ?? {}).forEach((prev) => prev.scrubToTimestamp(Math.floor(timestamp)),