diff options
Diffstat (limited to 'apps/web/src/timeline/components')
| -rw-r--r-- | apps/web/src/timeline/components/index.tsx | 57 | ||||
| -rw-r--r-- | apps/web/src/timeline/components/timeline-element.tsx | 31 | ||||
| -rw-r--r-- | apps/web/src/timeline/components/timeline-track.tsx | 26 |
3 files changed, 48 insertions, 66 deletions
diff --git a/apps/web/src/timeline/components/index.tsx b/apps/web/src/timeline/components/index.tsx index 5d61a0a9..68f3f37f 100644 --- a/apps/web/src/timeline/components/index.tsx +++ b/apps/web/src/timeline/components/index.tsx @@ -30,7 +30,7 @@ import { type ReactNode, } from "react"; import type { MediaTime } from "@/wasm"; -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"; @@ -288,20 +288,15 @@ export function Timeline() { isReady: tracks.length > 0, }); - const { - dragState, - dragDropTarget, - handleElementMouseDown, - handleElementClick, - lastMouseXRef, - } = useElementInteraction({ + const { dragView, handleElementMouseDown, handleElementClick } = + useElementInteraction({ zoomLevel, - timelineRef, tracksContainerRef, tracksScrollRef, snappingEnabled, onSnapPointChange: handleSnapPointChange, }); + const isElementDragging = dragView.kind === "dragging"; const { dragState: bookmarkDragState, @@ -392,10 +387,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, @@ -458,9 +462,9 @@ export function Timeline() { headerHeight={timelineHeaderHeight} /> <DragLine - dropTarget={dragDropTarget} + dropTarget={isElementDragging ? dragView.dropTarget : null} tracks={tracks} - isVisible={dragState.isDragging} + isVisible={isElementDragging} headerHeight={timelineHeaderHeight} /> @@ -541,9 +545,7 @@ export function Timeline() { <TimelineTrackRows mainTrackId={mainTrackId} zoomLevel={zoomLevel} - dragState={dragState} - tracksScrollRef={tracksScrollRef} - lastMouseXRef={lastMouseXRef} + dragView={dragView} onResizeStart={handleResizeStart} onElementMouseDown={handleElementMouseDown} onElementClick={handleElementClick} @@ -719,9 +721,7 @@ function TrackLabelsPanel({ function TimelineTrackRows({ mainTrackId, zoomLevel, - dragState, - tracksScrollRef, - lastMouseXRef, + dragView, onResizeStart, onElementMouseDown, onElementClick, @@ -733,9 +733,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"]; @@ -777,8 +775,16 @@ function TimelineTrackRows({ [tracks, expandedElementIds], ); + const draggingElementIds = useMemo( + () => + dragView.kind === "dragging" + ? dragView.memberTimeOffsets + : (null as ReadonlyMap<string, MediaTime> | 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) => { @@ -792,7 +798,7 @@ function TimelineTrackRows({ if (bHasDragged) return -1; return 0; }); - }, [tracks, dragState.dragElementIds]); + }, [tracks, draggingElementIds]); return ( <> @@ -812,10 +818,7 @@ function TimelineTrackRows({ <TimelineTrackContent track={track} zoomLevel={zoomLevel} - dragState={dragState} - rulerScrollRef={tracksScrollRef} - tracksScrollRef={tracksScrollRef} - lastMouseXRef={lastMouseXRef} + dragView={dragView} onResizeStart={onResizeStart} onElementMouseDown={onElementMouseDown} onElementClick={onElementClick} diff --git a/apps/web/src/timeline/components/timeline-element.tsx b/apps/web/src/timeline/components/timeline-element.tsx index d85288b1..cb102c71 100644 --- a/apps/web/src/timeline/components/timeline-element.tsx +++ b/apps/web/src/timeline/components/timeline-element.tsx @@ -34,7 +34,7 @@ import { import type { TimelineElement as TimelineElementType, TimelineTrack, - ElementDragState, + ElementDragView, VideoElement, ImageElement, AudioElement, @@ -49,12 +49,7 @@ import { import { buildWaveformGainSamples } from "@/timeline/audio-state"; import { getTimelinePixelsPerSecond } from "@/timeline"; import { buildWaveformSourceKey } from "@/media/waveform-summary"; -import { - addMediaTime, - type MediaTime, - TICKS_PER_SECOND, - ZERO_MEDIA_TIME, -} from "@/wasm"; +import { addMediaTime, type MediaTime, TICKS_PER_SECOND } from "@/wasm"; import { getActionDefinition, type TAction, @@ -219,7 +214,7 @@ interface TimelineElementProps { event: React.MouseEvent, element: TimelineElementType, ) => void; - dragState: ElementDragState; + dragView: ElementDragView; isDropTarget?: boolean; } @@ -231,7 +226,7 @@ export function TimelineElement({ onResizeStart, onElementMouseDown, onElementClick, - dragState, + dragView, isDropTarget = false, }: TimelineElementProps) { const mediaAssets = useEditor((e) => e.media.getAssets()); @@ -257,16 +252,18 @@ export function TimelineElement({ selected.elementId === element.id && selected.trackId === track.id, ); - const isBeingDragged = dragState.dragElementIds.includes(element.id); + const isDragging = dragView.kind === "dragging"; + const dragTimeOffset = isDragging + ? dragView.memberTimeOffsets.get(element.id) + : undefined; + const isBeingDragged = dragTimeOffset !== undefined; const dragOffsetY = - isBeingDragged && dragState.isDragging - ? dragState.currentMouseY - dragState.startMouseY + isDragging && isBeingDragged + ? dragView.currentMouseY - dragView.startMouseY : 0; - const dragTimeOffset = - dragState.dragTimeOffsets[element.id] ?? ZERO_MEDIA_TIME; const elementStartTime = - isBeingDragged && dragState.isDragging - ? addMediaTime({ a: dragState.currentTime, b: dragTimeOffset }) + isDragging && isBeingDragged + ? addMediaTime({ a: dragView.currentTime, b: dragTimeOffset }) : renderElement.startTime; const displayedStartTime = elementStartTime; const displayedDuration = renderElement.duration; @@ -388,7 +385,7 @@ export function TimelineElement({ ? `${baseTrackHeight + expansionHeight}px` : "100%", transform: - isBeingDragged && dragState.isDragging + isDragging && isBeingDragged ? `translate3d(0, ${dragOffsetY}px, 0)` : undefined, }} diff --git a/apps/web/src/timeline/components/timeline-track.tsx b/apps/web/src/timeline/components/timeline-track.tsx index 6c40637e..7608e6df 100644 --- a/apps/web/src/timeline/components/timeline-track.tsx +++ b/apps/web/src/timeline/components/timeline-track.tsx @@ -5,18 +5,12 @@ import { TimelineElement } from "./timeline-element"; import type { TimelineTrack } from "@/timeline"; import type { TimelineElement as TimelineElementType } from "@/timeline"; import { TIMELINE_LAYERS } from "./layers"; -import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/timeline/scale"; -import { useEdgeAutoScroll } from "@/timeline/hooks/use-edge-auto-scroll"; -import type { ElementDragState } from "@/timeline"; -import { useEditor } from "@/editor/use-editor"; +import type { ElementDragView } from "@/timeline"; interface TimelineTrackContentProps { track: TimelineTrack; zoomLevel: number; - dragState: ElementDragState; - rulerScrollRef: React.RefObject<HTMLDivElement | null>; - tracksScrollRef: React.RefObject<HTMLDivElement | null>; - lastMouseXRef: React.RefObject<number>; + dragView: ElementDragView; onResizeStart: (params: { event: React.MouseEvent; element: TimelineElementType; @@ -42,10 +36,7 @@ interface TimelineTrackContentProps { export function TimelineTrackContent({ track, zoomLevel, - dragState, - rulerScrollRef, - tracksScrollRef, - lastMouseXRef, + dragView, onResizeStart, onElementMouseDown, onElementClick, @@ -55,15 +46,6 @@ export function TimelineTrackContent({ targetElementId = null, }: TimelineTrackContentProps) { const { isElementSelected } = useElementSelection(); - const duration = useEditor((e) => e.timeline.getTotalDuration()); - - useEdgeAutoScroll({ - isActive: dragState.isDragging, - getMouseClientX: () => lastMouseXRef.current ?? 0, - rulerScrollRef, - tracksScrollRef, - contentWidth: duration * BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel, - }); return ( <div className="relative size-full"> @@ -120,7 +102,7 @@ export function TimelineTrackContent({ onElementClick={(event, element) => onElementClick({ event, element, track }) } - dragState={dragState} + dragView={dragView} isDropTarget={element.id === targetElementId} /> ); |
