import useDraggableElement from "@/hooks/use-draggable-element"; import { useEffect, useCallback, useMemo, useRef, useState, RefObject, } from "react"; import EventSegment from "./EventSegment"; import { useTimelineUtils } from "@/hooks/use-timeline-utils"; import { ReviewSegment, ReviewSeverity } from "@/types/review"; import ReviewTimeline from "./ReviewTimeline"; export type EventReviewTimelineProps = { segmentDuration: number; timestampSpread: number; timelineStart: number; timelineEnd: number; showHandlebar?: boolean; handlebarTime?: number; setHandlebarTime?: React.Dispatch>; showMinimap?: boolean; minimapStartTime?: number; minimapEndTime?: number; showExportHandles?: boolean; exportStartTime?: number; exportEndTime?: number; setExportStartTime?: React.Dispatch>; setExportEndTime?: React.Dispatch>; events: ReviewSegment[]; severityType: ReviewSeverity; contentRef: RefObject; onHandlebarDraggingChange?: (isDragging: boolean) => void; }; export function EventReviewTimeline({ segmentDuration, timestampSpread, timelineStart, timelineEnd, showHandlebar = false, handlebarTime, setHandlebarTime, showMinimap = false, minimapStartTime, minimapEndTime, showExportHandles = false, exportStartTime, exportEndTime, setExportStartTime, setExportEndTime, events, severityType, contentRef, onHandlebarDraggingChange, }: EventReviewTimelineProps) { const [isDragging, setIsDragging] = useState(false); const [exportStartPosition, setExportStartPosition] = useState(0); const [exportEndPosition, setExportEndPosition] = useState(0); const timelineRef = useRef(null); const handlebarRef = useRef(null); const handlebarTimeRef = useRef(null); const exportStartRef = useRef(null); const exportStartTimeRef = useRef(null); const exportEndRef = useRef(null); const exportEndTimeRef = useRef(null); const timelineDuration = useMemo( () => timelineStart - timelineEnd, [timelineEnd, timelineStart], ); const { alignStartDateToTimeline, alignEndDateToTimeline } = useTimelineUtils(segmentDuration); const timelineStartAligned = useMemo( () => alignStartDateToTimeline(timelineStart), [timelineStart, alignStartDateToTimeline], ); const paddedExportStartTime = useMemo(() => { if (exportStartTime) { return alignStartDateToTimeline(exportStartTime) + segmentDuration; } }, [exportStartTime, segmentDuration, alignStartDateToTimeline]); const paddedExportEndTime = useMemo(() => { if (exportEndTime) { return alignEndDateToTimeline(exportEndTime) - segmentDuration * 2; } }, [exportEndTime, segmentDuration, alignEndDateToTimeline]); const { handleMouseDown: handlebarMouseDown, handleMouseUp: handlebarMouseUp, handleMouseMove: handlebarMouseMove, } = useDraggableElement({ contentRef, timelineRef, draggableElementRef: handlebarRef, segmentDuration, showDraggableElement: showHandlebar, draggableElementTime: handlebarTime, setDraggableElementTime: setHandlebarTime, timelineDuration, timelineStartAligned, isDragging, setIsDragging, draggableElementTimeRef: handlebarTimeRef, }); const { handleMouseDown: exportStartMouseDown, handleMouseUp: exportStartMouseUp, handleMouseMove: exportStartMouseMove, } = useDraggableElement({ contentRef, timelineRef, draggableElementRef: exportStartRef, segmentDuration, showDraggableElement: showExportHandles, draggableElementTime: exportStartTime, draggableElementLatestTime: paddedExportEndTime, setDraggableElementTime: setExportStartTime, timelineDuration, timelineStartAligned, isDragging, setIsDragging, draggableElementTimeRef: exportStartTimeRef, setDraggableElementPosition: setExportStartPosition, }); const { handleMouseDown: exportEndMouseDown, handleMouseUp: exportEndMouseUp, handleMouseMove: exportEndMouseMove, } = useDraggableElement({ contentRef, timelineRef, draggableElementRef: exportEndRef, segmentDuration, showDraggableElement: showExportHandles, draggableElementTime: exportEndTime, draggableElementEarliestTime: paddedExportStartTime, setDraggableElementTime: setExportEndTime, timelineDuration, timelineStartAligned, isDragging, setIsDragging, draggableElementTimeRef: exportEndTimeRef, setDraggableElementPosition: setExportEndPosition, }); // 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, timelineStart, timelineDuration, showMinimap, minimapStartTime, minimapEndTime, events, ]); const segments = useMemo( () => generateSegments(), // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps [ segmentDuration, timestampSpread, timelineStart, timelineDuration, showMinimap, minimapStartTime, minimapEndTime, events, ], ); useEffect(() => { if (onHandlebarDraggingChange) { onHandlebarDraggingChange(isDragging); } }, [isDragging, onHandlebarDraggingChange]); return ( {segments} ); } export default EventReviewTimeline;