import useDraggableHandler from "@/hooks/use-handle-dragging"; import { useEffect, useCallback, useMemo, useRef, useState, RefObject, } from "react"; import MotionSegment from "./MotionSegment"; import { useEventUtils } from "@/hooks/use-event-utils"; import { MotionData, ReviewSegment, ReviewSeverity } from "@/types/review"; import ReviewTimeline from "./ReviewTimeline"; export type MotionReviewTimelineProps = { segmentDuration: number; timestampSpread: number; timelineStart: number; timelineEnd: number; showHandlebar?: boolean; handlebarTime?: number; setHandlebarTime?: React.Dispatch>; showMinimap?: boolean; minimapStartTime?: number; minimapEndTime?: number; events: ReviewSegment[]; motion_events: MotionData[]; severityType: ReviewSeverity; contentRef: RefObject; onHandlebarDraggingChange?: (isDragging: boolean) => void; }; export function MotionReviewTimeline({ segmentDuration, timestampSpread, timelineStart, timelineEnd, showHandlebar = false, handlebarTime, setHandlebarTime, showMinimap = false, minimapStartTime, minimapEndTime, events, motion_events, contentRef, onHandlebarDraggingChange, }: MotionReviewTimelineProps) { const [isDragging, setIsDragging] = useState(false); const handlebarRef = useRef(null); const timelineRef = useRef(null); const handlebarTimeRef = useRef(null); const timelineDuration = useMemo( () => timelineStart - timelineEnd, [timelineEnd, timelineStart], ); const { alignStartDateToTimeline, alignEndDateToTimeline } = useEventUtils( events, segmentDuration, ); const timelineStartAligned = useMemo( () => alignStartDateToTimeline(timelineStart), [timelineStart, alignStartDateToTimeline], ); const { handleMouseDown, handleMouseUp, handleMouseMove } = useDraggableHandler({ contentRef, timelineRef, handlebarRef, alignStartDateToTimeline, alignEndDateToTimeline, segmentDuration, showHandlebar, handlebarTime, setHandlebarTime, timelineDuration, timelineStartAligned, isDragging, setIsDragging, handlebarTimeRef, }); // Generate segments for the timeline const generateSegments = useCallback(() => { const segmentCount = timelineDuration / segmentDuration; return Array.from({ length: segmentCount }, (_, index) => { const segmentTime = timelineStartAligned - index * segmentDuration; return ( ); }); // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps }, [ segmentDuration, timestampSpread, timelineStartAligned, timelineDuration, showMinimap, minimapStartTime, minimapEndTime, events, motion_events, ]); const segments = useMemo( () => generateSegments(), // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps [ segmentDuration, timestampSpread, timelineStartAligned, timelineDuration, showMinimap, minimapStartTime, minimapEndTime, events, motion_events, ], ); useEffect(() => { if (onHandlebarDraggingChange) { onHandlebarDraggingChange(isDragging); } }, [isDragging, onHandlebarDraggingChange]); return ( {segments} ); } export default MotionReviewTimeline;