summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/components
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/timeline/components')
-rw-r--r--apps/web/src/timeline/components/index.tsx57
-rw-r--r--apps/web/src/timeline/components/timeline-element.tsx31
-rw-r--r--apps/web/src/timeline/components/timeline-track.tsx26
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}
/>
);