|
|
@@ -32,6 +32,12 @@ interface Props {
|
|
|
onPlayingChange?: (playing: boolean) => void;
|
|
|
/** When provided, the parent intercepts timeline seeks in compare mode */
|
|
|
onTimelineSeek?: (time: number) => void;
|
|
|
+ /** Pass-through ref to the underlying <video> element so parent can seek directly */
|
|
|
+ videoRef?: React.RefObject<HTMLVideoElement | null>;
|
|
|
+ /** Called when user clicks the previous-comment button */
|
|
|
+ onPrevComment?: () => void;
|
|
|
+ /** Called when user clicks the next-comment button */
|
|
|
+ onNextComment?: () => void;
|
|
|
// ── Compare mode ───────────────────────────────────────────────────────
|
|
|
/** When provided, this player is slave to the main player in compare mode */
|
|
|
isComparePlayer?: boolean;
|
|
|
@@ -62,8 +68,13 @@ export function VideoPlayer({
|
|
|
isComparePlayer = false,
|
|
|
externalCurrentTime,
|
|
|
externalPlaying,
|
|
|
+ videoRef: externalVideoRef,
|
|
|
+ onPrevComment,
|
|
|
+ onNextComment,
|
|
|
}: Props) {
|
|
|
- const videoRef = useRef<HTMLVideoElement>(null);
|
|
|
+ const internalVideoRef = useRef<HTMLVideoElement>(null);
|
|
|
+ // Use external ref if provided, otherwise internal
|
|
|
+ const videoRef = externalVideoRef ?? internalVideoRef;
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
const displayCanvasRef = useRef<HTMLCanvasElement>(null);
|
|
|
const videoCallbackRef = useRef<number | null>(null);
|
|
|
@@ -499,16 +510,28 @@ export function VideoPlayer({
|
|
|
|
|
|
<div className="flex-1" />
|
|
|
|
|
|
- {/* 3 playback buttons — centered, touch-friendly */}
|
|
|
- <div className="flex items-center gap-2">
|
|
|
+ {/* 5 playback buttons — prev-comment, frame-back, play/pause, frame-forward, next-comment */}
|
|
|
+ <div className="flex items-center gap-1">
|
|
|
+ <button
|
|
|
+ onClick={onPrevComment}
|
|
|
+ className="w-9 h-9 flex items-center justify-center rounded-full transition-all active:scale-90"
|
|
|
+ style={{ background: 'rgba(255,255,255,0.08)' }}
|
|
|
+ title="Previous comment"
|
|
|
+ >
|
|
|
+ <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
|
+ <path strokeLinecap="round" strokeLinejoin="round" d="M11 19l-7-7 7-7M18 19l-7-7 7-7" />
|
|
|
+ </svg>
|
|
|
+ </button>
|
|
|
+
|
|
|
<button
|
|
|
onClick={() => stepFrame(-1)}
|
|
|
- className="w-10 h-10 md:w-9 md:h-9 flex items-center justify-center rounded-full transition-all active:scale-90"
|
|
|
+ className="w-9 h-9 flex items-center justify-center rounded-full transition-all active:scale-90"
|
|
|
style={{ background: 'rgba(255,255,255,0.12)' }}
|
|
|
- title="Previous frame (U)"
|
|
|
+ title="Previous frame (←)"
|
|
|
>
|
|
|
- <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
|
|
|
- <path d="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
|
|
|
+ {/* Frame back — left bracket with vertical bar */}
|
|
|
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5} strokeLinecap="round">
|
|
|
+ <path d="M7 12h1M11 7v10M11 12l-4 5M11 12l-4-5" />
|
|
|
</svg>
|
|
|
</button>
|
|
|
|
|
|
@@ -531,12 +554,24 @@ export function VideoPlayer({
|
|
|
|
|
|
<button
|
|
|
onClick={() => stepFrame(1)}
|
|
|
- className="w-10 h-10 md:w-9 md:h-9 flex items-center justify-center rounded-full transition-all active:scale-90"
|
|
|
+ className="w-9 h-9 flex items-center justify-center rounded-full transition-all active:scale-90"
|
|
|
style={{ background: 'rgba(255,255,255,0.12)' }}
|
|
|
- title="Next frame (I)"
|
|
|
+ title="Next frame (→)"
|
|
|
+ >
|
|
|
+ {/* Frame forward — right bracket with vertical bar */}
|
|
|
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5} strokeLinecap="round">
|
|
|
+ <path d="M17 12h-1M13 7v10M13 12l4 5M13 12l4-5" />
|
|
|
+ </svg>
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <button
|
|
|
+ onClick={onNextComment}
|
|
|
+ className="w-9 h-9 flex items-center justify-center rounded-full transition-all active:scale-90"
|
|
|
+ style={{ background: 'rgba(255,255,255,0.08)' }}
|
|
|
+ title="Next comment"
|
|
|
>
|
|
|
- <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
|
|
|
- <path d="M18 18h-2V6h2zm-3.5 0L6 12z" />
|
|
|
+ <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
|
+ <path strokeLinecap="round" strokeLinejoin="round" d="M13 5l7 7-7 7M6 5l7 7-7 7" />
|
|
|
</svg>
|
|
|
</button>
|
|
|
</div>
|