From 4d127a038bf768eded68aae3cfa5c1b12241bdac Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Fri, 27 Mar 2026 00:55:15 +0100 Subject: chore: normalize line endings --- apps/web/src/hooks/timeline/use-timeline-seek.ts | 394 +++++++++++------------ 1 file changed, 197 insertions(+), 197 deletions(-) (limited to 'apps/web/src/hooks/timeline/use-timeline-seek.ts') diff --git a/apps/web/src/hooks/timeline/use-timeline-seek.ts b/apps/web/src/hooks/timeline/use-timeline-seek.ts index 127ebcbb..4abbf023 100644 --- a/apps/web/src/hooks/timeline/use-timeline-seek.ts +++ b/apps/web/src/hooks/timeline/use-timeline-seek.ts @@ -1,197 +1,197 @@ -import { useCallback, useRef } from "react"; -import type { MutableRefObject, RefObject } from "react"; -import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; -import { getSnappedSeekTime } from "@/lib/time"; -import { useEditor } from "../use-editor"; - -interface UseTimelineSeekProps { - playheadRef: RefObject; - trackLabelsRef: RefObject; - rulerScrollRef: RefObject; - tracksScrollRef: RefObject; - zoomLevel: number; - duration: number; - isSelecting: boolean; - clearSelectedElements: () => void; - seek: (time: number) => void; -} - -function resetMouseTracking({ - mouseTrackingRef, -}: { - mouseTrackingRef: MutableRefObject<{ - isMouseDown: boolean; - downX: number; - downY: number; - downTime: number; - }>; -}) { - mouseTrackingRef.current = { - isMouseDown: false, - downX: 0, - downY: 0, - downTime: 0, - }; -} - -function setMouseTracking({ - mouseTrackingRef, - event, -}: { - mouseTrackingRef: MutableRefObject<{ - isMouseDown: boolean; - downX: number; - downY: number; - downTime: number; - }>; - event: React.MouseEvent; -}) { - mouseTrackingRef.current = { - isMouseDown: true, - downX: event.clientX, - downY: event.clientY, - downTime: event.timeStamp, - }; -} - -export function useTimelineSeek({ - playheadRef, - trackLabelsRef, - rulerScrollRef, - tracksScrollRef, - zoomLevel, - duration, - isSelecting, - clearSelectedElements, - seek, -}: UseTimelineSeekProps) { - const editor = useEditor(); - const activeProject = editor.project.getActive(); - - const mouseTrackingRef = useRef({ - isMouseDown: false, - downX: 0, - downY: 0, - downTime: 0, - }); - - const handleTracksMouseDown = useCallback((event: React.MouseEvent) => { - if (event.button !== 0) return; - setMouseTracking({ mouseTrackingRef, event }); - }, []); - - const handleRulerMouseDown = useCallback((event: React.MouseEvent) => { - if (event.button !== 0) return; - setMouseTracking({ mouseTrackingRef, event }); - }, []); - - const shouldProcessTimelineClick = useCallback( - ({ event }: { event: React.MouseEvent }) => { - const target = event.target as HTMLElement; - const { isMouseDown, downX, downY, downTime } = mouseTrackingRef.current; - const deltaX = Math.abs(event.clientX - downX); - const deltaY = Math.abs(event.clientY - downY); - const deltaTime = event.timeStamp - downTime; - const isPlayhead = !!playheadRef.current?.contains(target); - const isTrackLabels = !!trackLabelsRef.current?.contains(target); - const shouldBlockForDrag = deltaX > 5 || deltaY > 5 || deltaTime > 500; - - if (!isMouseDown) return false; - if (shouldBlockForDrag) return false; - if (isSelecting) return false; - if (isPlayhead) return false; - if (isTrackLabels) { - clearSelectedElements(); - return false; - } - - return true; - }, - [isSelecting, clearSelectedElements, playheadRef, trackLabelsRef], - ); - - const handleTimelineSeek = useCallback( - ({ - event, - source, - }: { - event: React.MouseEvent; - source: "ruler" | "tracks"; - }) => { - const scrollContainer = - source === "ruler" ? rulerScrollRef.current : tracksScrollRef.current; - - if (!scrollContainer) return; - - const rect = scrollContainer.getBoundingClientRect(); - const mouseX = event.clientX - rect.left; - const scrollLeft = scrollContainer.scrollLeft; - - const rawTime = Math.max( - 0, - Math.min( - duration, - (mouseX + scrollLeft) / - (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel), - ), - ); - - const projectFps = activeProject?.settings.fps || 30; - const time = getSnappedSeekTime({ - rawTime, - duration, - fps: projectFps, - }); - seek(time); - editor.project.setTimelineViewState({ - viewState: { - zoomLevel, - scrollLeft: scrollContainer.scrollLeft, - playheadTime: time, - }, - }); - }, - [ - duration, - zoomLevel, - rulerScrollRef, - tracksScrollRef, - seek, - editor, - activeProject?.settings.fps, - ], - ); - - const handleTracksClick = useCallback( - (event: React.MouseEvent) => { - const shouldProcess = shouldProcessTimelineClick({ event }); - resetMouseTracking({ mouseTrackingRef }); - - if (shouldProcess) { - clearSelectedElements(); - handleTimelineSeek({ event, source: "tracks" }); - } - }, - [shouldProcessTimelineClick, handleTimelineSeek, clearSelectedElements], - ); - - const handleRulerClick = useCallback( - (event: React.MouseEvent) => { - const shouldProcess = shouldProcessTimelineClick({ event }); - resetMouseTracking({ mouseTrackingRef }); - - if (shouldProcess) { - clearSelectedElements(); - handleTimelineSeek({ event, source: "ruler" }); - } - }, - [shouldProcessTimelineClick, handleTimelineSeek, clearSelectedElements], - ); - - return { - handleTracksMouseDown, - handleTracksClick, - handleRulerMouseDown, - handleRulerClick, - }; -} +import { useCallback, useRef } from "react"; +import type { MutableRefObject, RefObject } from "react"; +import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; +import { getSnappedSeekTime } from "@/lib/time"; +import { useEditor } from "../use-editor"; + +interface UseTimelineSeekProps { + playheadRef: RefObject; + trackLabelsRef: RefObject; + rulerScrollRef: RefObject; + tracksScrollRef: RefObject; + zoomLevel: number; + duration: number; + isSelecting: boolean; + clearSelectedElements: () => void; + seek: (time: number) => void; +} + +function resetMouseTracking({ + mouseTrackingRef, +}: { + mouseTrackingRef: MutableRefObject<{ + isMouseDown: boolean; + downX: number; + downY: number; + downTime: number; + }>; +}) { + mouseTrackingRef.current = { + isMouseDown: false, + downX: 0, + downY: 0, + downTime: 0, + }; +} + +function setMouseTracking({ + mouseTrackingRef, + event, +}: { + mouseTrackingRef: MutableRefObject<{ + isMouseDown: boolean; + downX: number; + downY: number; + downTime: number; + }>; + event: React.MouseEvent; +}) { + mouseTrackingRef.current = { + isMouseDown: true, + downX: event.clientX, + downY: event.clientY, + downTime: event.timeStamp, + }; +} + +export function useTimelineSeek({ + playheadRef, + trackLabelsRef, + rulerScrollRef, + tracksScrollRef, + zoomLevel, + duration, + isSelecting, + clearSelectedElements, + seek, +}: UseTimelineSeekProps) { + const editor = useEditor(); + const activeProject = editor.project.getActive(); + + const mouseTrackingRef = useRef({ + isMouseDown: false, + downX: 0, + downY: 0, + downTime: 0, + }); + + const handleTracksMouseDown = useCallback((event: React.MouseEvent) => { + if (event.button !== 0) return; + setMouseTracking({ mouseTrackingRef, event }); + }, []); + + const handleRulerMouseDown = useCallback((event: React.MouseEvent) => { + if (event.button !== 0) return; + setMouseTracking({ mouseTrackingRef, event }); + }, []); + + const shouldProcessTimelineClick = useCallback( + ({ event }: { event: React.MouseEvent }) => { + const target = event.target as HTMLElement; + const { isMouseDown, downX, downY, downTime } = mouseTrackingRef.current; + const deltaX = Math.abs(event.clientX - downX); + const deltaY = Math.abs(event.clientY - downY); + const deltaTime = event.timeStamp - downTime; + const isPlayhead = !!playheadRef.current?.contains(target); + const isTrackLabels = !!trackLabelsRef.current?.contains(target); + const shouldBlockForDrag = deltaX > 5 || deltaY > 5 || deltaTime > 500; + + if (!isMouseDown) return false; + if (shouldBlockForDrag) return false; + if (isSelecting) return false; + if (isPlayhead) return false; + if (isTrackLabels) { + clearSelectedElements(); + return false; + } + + return true; + }, + [isSelecting, clearSelectedElements, playheadRef, trackLabelsRef], + ); + + const handleTimelineSeek = useCallback( + ({ + event, + source, + }: { + event: React.MouseEvent; + source: "ruler" | "tracks"; + }) => { + const scrollContainer = + source === "ruler" ? rulerScrollRef.current : tracksScrollRef.current; + + if (!scrollContainer) return; + + const rect = scrollContainer.getBoundingClientRect(); + const mouseX = event.clientX - rect.left; + const scrollLeft = scrollContainer.scrollLeft; + + const rawTime = Math.max( + 0, + Math.min( + duration, + (mouseX + scrollLeft) / + (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel), + ), + ); + + const projectFps = activeProject?.settings.fps || 30; + const time = getSnappedSeekTime({ + rawTime, + duration, + fps: projectFps, + }); + seek(time); + editor.project.setTimelineViewState({ + viewState: { + zoomLevel, + scrollLeft: scrollContainer.scrollLeft, + playheadTime: time, + }, + }); + }, + [ + duration, + zoomLevel, + rulerScrollRef, + tracksScrollRef, + seek, + editor, + activeProject?.settings.fps, + ], + ); + + const handleTracksClick = useCallback( + (event: React.MouseEvent) => { + const shouldProcess = shouldProcessTimelineClick({ event }); + resetMouseTracking({ mouseTrackingRef }); + + if (shouldProcess) { + clearSelectedElements(); + handleTimelineSeek({ event, source: "tracks" }); + } + }, + [shouldProcessTimelineClick, handleTimelineSeek, clearSelectedElements], + ); + + const handleRulerClick = useCallback( + (event: React.MouseEvent) => { + const shouldProcess = shouldProcessTimelineClick({ event }); + resetMouseTracking({ mouseTrackingRef }); + + if (shouldProcess) { + clearSelectedElements(); + handleTimelineSeek({ event, source: "ruler" }); + } + }, + [shouldProcessTimelineClick, handleTimelineSeek, clearSelectedElements], + ); + + return { + handleTracksMouseDown, + handleTracksClick, + handleRulerMouseDown, + handleRulerClick, + }; +} -- cgit v1.3.1