import { DraggableElement } from "@/types/draggable-element"; import { ReactNode, RefObject, useCallback, useEffect, useMemo, useRef, useState, } from "react"; import { isIOS, isMobile } from "react-device-detect"; export type ReviewTimelineProps = { timelineRef: RefObject; handlebarRef: RefObject; handlebarTimeRef: RefObject; handlebarMouseMove: ( e: | React.MouseEvent | React.TouchEvent, ) => void; handlebarMouseUp: ( e: | React.MouseEvent | React.TouchEvent, ) => void; handlebarMouseDown: ( e: | React.MouseEvent | React.TouchEvent, ) => void; segmentDuration: number; timelineDuration: number; showHandlebar: boolean; showExportHandles: boolean; exportStartRef: RefObject; exportStartTimeRef: RefObject; exportEndRef: RefObject; exportEndTimeRef: RefObject; exportStartMouseMove: ( e: | React.MouseEvent | React.TouchEvent, ) => void; exportStartMouseUp: ( e: | React.MouseEvent | React.TouchEvent, ) => void; exportStartMouseDown: ( e: | React.MouseEvent | React.TouchEvent, ) => void; exportEndMouseMove: ( e: | React.MouseEvent | React.TouchEvent, ) => void; exportEndMouseUp: ( e: | React.MouseEvent | React.TouchEvent, ) => void; exportEndMouseDown: ( e: | React.MouseEvent | React.TouchEvent, ) => void; isDragging: boolean; exportStartPosition?: number; exportEndPosition?: number; children: ReactNode; }; export function ReviewTimeline({ timelineRef, handlebarRef, handlebarTimeRef, handlebarMouseMove, handlebarMouseUp, handlebarMouseDown, segmentDuration, timelineDuration, showHandlebar = false, showExportHandles = false, exportStartRef, exportStartTimeRef, exportEndRef, exportEndTimeRef, exportStartMouseMove, exportStartMouseUp, exportStartMouseDown, exportEndMouseMove, exportEndMouseUp, exportEndMouseDown, isDragging, exportStartPosition, exportEndPosition, children, }: ReviewTimelineProps) { const exportSectionRef = useRef(null); const segmentHeight = useMemo(() => { if (timelineRef.current) { const { scrollHeight: timelineHeight } = timelineRef.current as HTMLDivElement; return timelineHeight / (timelineDuration / segmentDuration); } // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps }, [segmentDuration, timelineDuration, timelineRef, showExportHandles]); const [draggableElementType, setDraggableElementType] = useState(); const handleHandlebar = useCallback( ( e: | React.MouseEvent | React.TouchEvent, ) => { setDraggableElementType("handlebar"); handlebarMouseDown(e); }, [handlebarMouseDown], ); const handleExportStart = useCallback( ( e: | React.MouseEvent | React.TouchEvent, ) => { setDraggableElementType("export_start"); exportStartMouseDown(e); }, [exportStartMouseDown], ); const handleExportEnd = useCallback( ( e: | React.MouseEvent | React.TouchEvent, ) => { setDraggableElementType("export_end"); exportEndMouseDown(e); }, [exportEndMouseDown], ); const handleMouseMove = useCallback( ( e: | React.MouseEvent | React.TouchEvent, ) => { switch (draggableElementType) { case "export_start": exportStartMouseMove(e); break; case "export_end": exportEndMouseMove(e); break; case "handlebar": handlebarMouseMove(e); break; default: break; } }, [ draggableElementType, exportStartMouseMove, exportEndMouseMove, handlebarMouseMove, ], ); const handleMouseUp = useCallback( ( e: | React.MouseEvent | React.TouchEvent, ) => { switch (draggableElementType) { case "export_start": exportStartMouseUp(e); break; case "export_end": exportEndMouseUp(e); break; case "handlebar": handlebarMouseUp(e); break; default: break; } }, [ draggableElementType, exportStartMouseUp, exportEndMouseUp, handlebarMouseUp, ], ); useEffect(() => { if ( exportSectionRef.current && segmentHeight && exportStartPosition && exportEndPosition ) { exportSectionRef.current.style.top = `${exportEndPosition + segmentHeight}px`; exportSectionRef.current.style.height = `${exportStartPosition - exportEndPosition + segmentHeight / 2}px`; } }, [ showExportHandles, segmentHeight, timelineRef, exportStartPosition, exportEndPosition, ]); return (
{children}
{showHandlebar && (
)} {showExportHandles && ( <>
)}
); } export default ReviewTimeline;