From 4f3507b08e9ed20e9becfe85bd09819f1e7f08a8 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:10:35 -0500 Subject: [PATCH] pause on lifecycle item click and point click --- .../components/overlay/ObjectTrackOverlay.tsx | 4 +-- web/src/components/player/HlsVideoPlayer.tsx | 7 +++-- .../player/dynamic/DynamicVideoController.ts | 1 + .../player/dynamic/DynamicVideoPlayer.tsx | 9 ++++-- web/src/components/timeline/DetailStream.tsx | 30 +++++++++++-------- web/src/views/recording/RecordingView.tsx | 6 ++-- 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/web/src/components/overlay/ObjectTrackOverlay.tsx b/web/src/components/overlay/ObjectTrackOverlay.tsx index 17526bb09..211df7e86 100644 --- a/web/src/components/overlay/ObjectTrackOverlay.tsx +++ b/web/src/components/overlay/ObjectTrackOverlay.tsx @@ -19,7 +19,7 @@ type ObjectTrackOverlayProps = { videoWidth: number; videoHeight: number; className?: string; - onSeekToTime?: (timestamp: number) => void; + onSeekToTime?: (timestamp: number, play?: boolean) => void; objectTimeline?: ObjectLifecycleSequence[]; }; @@ -227,7 +227,7 @@ export default function ObjectTrackOverlay({ const handlePointClick = useCallback( (timestamp: number) => { - onSeekToTime?.(timestamp); + onSeekToTime?.(timestamp, false); }, [onSeekToTime], ); diff --git a/web/src/components/player/HlsVideoPlayer.tsx b/web/src/components/player/HlsVideoPlayer.tsx index 881e702ff..fd850255a 100644 --- a/web/src/components/player/HlsVideoPlayer.tsx +++ b/web/src/components/player/HlsVideoPlayer.tsx @@ -49,7 +49,7 @@ type HlsVideoPlayerProps = { onPlayerLoaded?: () => void; onTimeUpdate?: (time: number) => void; onPlaying?: () => void; - onSeekToTime?: (timestamp: number) => void; + onSeekToTime?: (timestamp: number, play?: boolean) => void; setFullResolution?: React.Dispatch>; onUploadFrame?: (playTime: number) => Promise | undefined; toggleFullscreen?: () => void; @@ -328,9 +328,10 @@ export default function HlsVideoPlayer({ videoWidth={videoDimensions.width} videoHeight={videoDimensions.height} className="absolute inset-0 z-10" - onSeekToTime={(timestamp) => { + onSeekToTime={(timestamp, play) => { if (onSeekToTime) { - onSeekToTime(timestamp); + console.log("object track overlay seek", timestamp, play); + onSeekToTime(timestamp, play); } }} objectTimeline={selectedObjectTimeline} diff --git a/web/src/components/player/dynamic/DynamicVideoController.ts b/web/src/components/player/dynamic/DynamicVideoController.ts index d4d7d4a2b..c55b6b7b0 100644 --- a/web/src/components/player/dynamic/DynamicVideoController.ts +++ b/web/src/components/player/dynamic/DynamicVideoController.ts @@ -111,6 +111,7 @@ export class DynamicVideoController { if (play) { this.waitAndPlay(); } else { + console.log("called pause", Date.now()); this.playerController.pause(); } } else { diff --git a/web/src/components/player/dynamic/DynamicVideoPlayer.tsx b/web/src/components/player/dynamic/DynamicVideoPlayer.tsx index 2faa50042..472a99bbe 100644 --- a/web/src/components/player/dynamic/DynamicVideoPlayer.tsx +++ b/web/src/components/player/dynamic/DynamicVideoPlayer.tsx @@ -32,7 +32,7 @@ type DynamicVideoPlayerProps = { onControllerReady: (controller: DynamicVideoController) => void; onTimestampUpdate?: (timestamp: number) => void; onClipEnded?: () => void; - onSeekToTime?: (timestamp: number) => void; + onSeekToTime?: (timestamp: number, play?: boolean) => void; setFullResolution: React.Dispatch>; toggleFullscreen: () => void; containerRef?: React.MutableRefObject; @@ -267,7 +267,12 @@ export default function DynamicVideoPlayer({ onTimeUpdate={onTimeUpdate} onPlayerLoaded={onPlayerLoaded} onClipEnded={onValidateClipEnd} - onSeekToTime={onSeekToTime} + onSeekToTime={(timestamp, play) => { + if (onSeekToTime) { + console.log("hls player seek", timestamp, play); + onSeekToTime(timestamp, play); + } + }} onPlaying={() => { if (isScrubbing) { playerRef.current?.pause(); diff --git a/web/src/components/timeline/DetailStream.tsx b/web/src/components/timeline/DetailStream.tsx index 396523c0c..dad01c651 100644 --- a/web/src/components/timeline/DetailStream.tsx +++ b/web/src/components/timeline/DetailStream.tsx @@ -28,7 +28,8 @@ import { cn } from "@/lib/utils"; type DetailStreamProps = { reviewItems?: ReviewSegment[]; currentTime: number; - onSeek: (timestamp: number) => void; + // `play` follows DynamicVideoController convention; pass `false` to pause + onSeek: (timestamp: number, play?: boolean) => void; }; export default function DetailStream({ @@ -398,7 +399,7 @@ function EventCollapsible({ event.id != selectedObjectId && (effectiveTime ?? 0) >= (event.start_time ?? 0) && (effectiveTime ?? 0) <= (event.end_time ?? event.start_time ?? 0) && - "bg-secondary-highlight/80 outline-[1px] -outline-offset-[0.8px] outline-primary/40", + "bg-secondary outline-[1px] -outline-offset-[0.8px] outline-primary/40", )} >
@@ -464,11 +465,12 @@ function EventCollapsible({ type LifecycleItemProps = { event: ObjectLifecycleSequence; - onSeek: (timestamp: number) => void; isActive?: boolean; + onSeek?: (timestamp: number, play?: boolean) => void; + play?: boolean; }; -function LifecycleItem({ event, isActive }: LifecycleItemProps) { +function LifecycleItem({ event, isActive, onSeek }: LifecycleItemProps) { const { t } = useTranslation("views/events"); const { data: config } = useSWR("config"); @@ -490,9 +492,13 @@ function LifecycleItem({ event, isActive }: LifecycleItemProps) { return (
onSeek?.(event.timestamp ?? 0, false)} className={cn( - "flex items-center gap-2 text-sm text-primary-variant", - isActive ? "text-white" : "duration-500", + "flex cursor-pointer items-center gap-2 text-sm text-primary-variant", + isActive + ? "font-semibold text-primary dark:font-normal" + : "duration-500", )} >
@@ -542,14 +548,12 @@ function ObjectTimeline({ const isActive = Math.abs((effectiveTime ?? 0) - (event.timestamp ?? 0)) <= 0.5; return ( -
{ - onSeek(event.timestamp); - }} - > - -
+ event={event} + onSeek={onSeek} + isActive={isActive} + /> ); })}
diff --git a/web/src/views/recording/RecordingView.tsx b/web/src/views/recording/RecordingView.tsx index aa15d693f..d6a071259 100644 --- a/web/src/views/recording/RecordingView.tsx +++ b/web/src/views/recording/RecordingView.tsx @@ -283,15 +283,15 @@ export function RecordingView({ ]); const manuallySetCurrentTime = useCallback( - (time: number) => { + (time: number, play: boolean = false) => { if (!currentTimeRange) { return; } - + console.log("manually set time", time, play); setCurrentTime(time); if (currentTimeRange.after <= time && currentTimeRange.before >= time) { - mainControllerRef.current?.seekToTimestamp(time, true); + mainControllerRef.current?.seekToTimestamp(time, !play); } else { updateSelectedSegment(time, true); }