diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-04-25 03:56:22 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-04-25 03:56:22 +0200 |
| commit | 6a22a3ecbdff2d0e6a4c24c8db40bb86bc01b692 (patch) | |
| tree | 976d60dbe1ac8e44d6a9259f9d6e20fe6530c698 /apps/web/src/timeline/components/index.tsx | |
| parent | 0dffefdd59d8c70fece63436e8556f8ec1e43a49 (diff) | |
| download | opencut-6a22a3ecbdff2d0e6a4c24c8db40bb86bc01b692.tar.gz | |
refactor: centralize editor interaction state
Move timeline and preview gestures into dedicated controllers so hooks stay thin around editor state and DOM events.
This also routes drag and playback synchronization through manager APIs and reuses persistent wasm surfaces so scrubbing, seeking, and preview rendering stay in sync.
Made-with: Cursor
Diffstat (limited to 'apps/web/src/timeline/components/index.tsx')
| -rw-r--r-- | apps/web/src/timeline/components/index.tsx | 69 |
1 files changed, 36 insertions, 33 deletions
diff --git a/apps/web/src/timeline/components/index.tsx b/apps/web/src/timeline/components/index.tsx index e6a9df49..88fb93b7 100644 --- a/apps/web/src/timeline/components/index.tsx +++ b/apps/web/src/timeline/components/index.tsx @@ -29,7 +29,7 @@ import { useState, type ReactNode, } from "react"; -import type { ElementDragState, DropTarget } from "@/timeline"; +import type { ElementDragView, DropTarget } from "@/timeline"; import { TimelineTrackContent } from "./timeline-track"; import { TimelinePlayhead } from "./timeline-playhead"; import { SelectionBox } from "@/selection/selection-box"; @@ -287,20 +287,15 @@ export function Timeline() { isReady: tracks.length > 0, }); - const { - dragState, - dragDropTarget, - handleElementMouseDown, - handleElementClick, - lastMouseXRef, - } = useElementInteraction({ - zoomLevel, - timelineRef, - tracksContainerRef, - tracksScrollRef, - snappingEnabled, - onSnapPointChange: handleSnapPointChange, - }); + const { dragView, handleElementMouseDown, handleElementClick } = + useElementInteraction({ + zoomLevel, + tracksContainerRef, + tracksScrollRef, + snappingEnabled, + onSnapPointChange: handleSnapPointChange, + }); + const isElementDragging = dragView.kind === "dragging"; const { dragState: bookmarkDragState, @@ -391,10 +386,19 @@ export function Timeline() { contentWidth: dynamicTimelineWidth, }); + useEdgeAutoScroll({ + isActive: isElementDragging, + getMouseClientX: () => + dragView.kind === "dragging" ? dragView.currentMouseX : 0, + rulerScrollRef, + tracksScrollRef, + contentWidth: dynamicTimelineWidth, + }); + const showSnapIndicator = snappingEnabled && currentSnapPoint !== null && - (dragState.isDragging || bookmarkDragState.isDragging || isResizing); + (isElementDragging || bookmarkDragState.isDragging || isResizing); const { handleTracksMouseDown, @@ -457,9 +461,9 @@ export function Timeline() { headerHeight={timelineHeaderHeight} /> <DragLine - dropTarget={dragDropTarget} + dropTarget={isElementDragging ? dragView.dropTarget : null} tracks={tracks} - isVisible={dragState.isDragging} + isVisible={isElementDragging} headerHeight={timelineHeaderHeight} /> @@ -540,9 +544,7 @@ export function Timeline() { <TimelineTrackRows mainTrackId={mainTrackId} zoomLevel={zoomLevel} - dragState={dragState} - tracksScrollRef={tracksScrollRef} - lastMouseXRef={lastMouseXRef} + dragView={dragView} onResizeStart={handleResizeStart} onElementMouseDown={handleElementMouseDown} onElementClick={handleElementClick} @@ -718,9 +720,7 @@ function TrackLabelsPanel({ function TimelineTrackRows({ mainTrackId, zoomLevel, - dragState, - tracksScrollRef, - lastMouseXRef, + dragView, onResizeStart, onElementMouseDown, onElementClick, @@ -732,9 +732,7 @@ function TimelineTrackRows({ }: { mainTrackId: string | null; zoomLevel: number; - dragState: ElementDragState; - tracksScrollRef: React.RefObject<HTMLDivElement | null>; - lastMouseXRef: React.RefObject<number>; + dragView: ElementDragView; onResizeStart: React.ComponentProps< typeof TimelineTrackContent >["onResizeStart"]; @@ -776,8 +774,16 @@ function TimelineTrackRows({ [tracks, expandedElementIds], ); + const draggingElementIds = useMemo( + () => + dragView.kind === "dragging" + ? dragView.memberTimeOffsets + : (null as ReadonlyMap<string, number> | null), + [dragView], + ); const sortedTracks = useMemo(() => { - const draggingElementIds = new Set(dragState.dragElementIds); + if (!draggingElementIds) + return tracks.map((track, index) => ({ track, index })); return [...tracks] .map((track, index) => ({ track, index })) .sort((a, b) => { @@ -791,7 +797,7 @@ function TimelineTrackRows({ if (bHasDragged) return -1; return 0; }); - }, [tracks, dragState.dragElementIds]); + }, [tracks, draggingElementIds]); return ( <> @@ -811,10 +817,7 @@ function TimelineTrackRows({ <TimelineTrackContent track={track} zoomLevel={zoomLevel} - dragState={dragState} - rulerScrollRef={tracksScrollRef} - tracksScrollRef={tracksScrollRef} - lastMouseXRef={lastMouseXRef} + dragView={dragView} onResizeStart={onResizeStart} onElementMouseDown={onElementMouseDown} onElementClick={onElementClick} |
