summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/timeline/controllers')
-rw-r--r--apps/web/src/timeline/controllers/drag-drop-controller.ts5
-rw-r--r--apps/web/src/timeline/controllers/element-interaction-controller.ts85
-rw-r--r--apps/web/src/timeline/controllers/resize-controller.ts13
-rw-r--r--apps/web/src/timeline/controllers/zoom-controller.ts25
4 files changed, 89 insertions, 39 deletions
diff --git a/apps/web/src/timeline/controllers/drag-drop-controller.ts b/apps/web/src/timeline/controllers/drag-drop-controller.ts
index 7fca2676..e0624a74 100644
--- a/apps/web/src/timeline/controllers/drag-drop-controller.ts
+++ b/apps/web/src/timeline/controllers/drag-drop-controller.ts
@@ -326,7 +326,10 @@ export class DragDropController {
trackType: TrackType;
}): void {
if (target.isNewTrack) {
- const addTrackCmd = new AddTrackCommand(trackType, target.trackIndex);
+ const addTrackCmd = new AddTrackCommand({
+ type: trackType,
+ index: target.trackIndex,
+ });
this.config.executeCommand(
new BatchCommand([
addTrackCmd,
diff --git a/apps/web/src/timeline/controllers/element-interaction-controller.ts b/apps/web/src/timeline/controllers/element-interaction-controller.ts
index d0d6426a..5afc3a93 100644
--- a/apps/web/src/timeline/controllers/element-interaction-controller.ts
+++ b/apps/web/src/timeline/controllers/element-interaction-controller.ts
@@ -124,20 +124,27 @@ const IDLE_VIEW: ElementDragView = { kind: "idle" };
// --- Pure helpers ---
-function pixelToClickOffsetTime(
- clientX: number,
- elementRect: DOMRect,
- zoomLevel: number,
-): MediaTime {
+function pixelToClickOffsetTime({
+ clientX,
+ elementRect,
+ zoomLevel,
+}: {
+ clientX: number;
+ elementRect: DOMRect;
+ zoomLevel: number;
+}): MediaTime {
const clickOffsetX = clientX - elementRect.left;
const seconds = clickOffsetX / (BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel);
return mediaTime({ ticks: Math.round(seconds * TICKS_PER_SECOND) });
}
-function verticalDirection(
- startMouseY: number,
- currentMouseY: number,
-): "up" | "down" | null {
+function verticalDirection({
+ startMouseY,
+ currentMouseY,
+}: {
+ startMouseY: number;
+ currentMouseY: number;
+}): "up" | "down" | null {
if (currentMouseY < startMouseY) return "up";
if (currentMouseY > startMouseY) return "down";
return null;
@@ -147,7 +154,13 @@ function orderedTracks(sceneTracks: SceneTracks): TimelineTrack[] {
return [...sceneTracks.overlay, sceneTracks.main, ...sceneTracks.audio];
}
-function movedPastDragThreshold(current: Point, origin: Point): boolean {
+function movedPastDragThreshold({
+ current,
+ origin,
+}: {
+ current: Point;
+ origin: Point;
+}): boolean {
return (
Math.abs(current.x - origin.x) > TIMELINE_DRAG_THRESHOLD_PX ||
Math.abs(current.y - origin.y) > TIMELINE_DRAG_THRESHOLD_PX
@@ -374,11 +387,11 @@ export class ElementInteractionController {
elementId: element.id,
trackId: track.id,
startElementTime: element.startTime,
- clickOffsetTime: pixelToClickOffsetTime(
- event.clientX,
- event.currentTarget.getBoundingClientRect(),
- this.deps.viewport.getZoomLevel(),
- ),
+ clickOffsetTime: pixelToClickOffsetTime({
+ clientX: event.clientX,
+ elementRect: event.currentTarget.getBoundingClientRect(),
+ zoomLevel: this.deps.viewport.getZoomLevel(),
+ }),
selectedElements,
},
};
@@ -437,10 +450,13 @@ export class ElementInteractionController {
this.notify();
}
- private snapResult(
- frameSnappedTime: MediaTime,
- group: MoveGroup,
- ): { snappedTime: MediaTime; snapPoint: SnapPoint | null } {
+ private snapResult({
+ frameSnappedTime,
+ group,
+ }: {
+ frameSnappedTime: MediaTime;
+ group: MoveGroup;
+ }): { snappedTime: MediaTime; snapPoint: SnapPoint | null } {
const { snap, input, scene, viewport, playback } = this.deps;
if (!snap.isEnabled() || input.isShiftHeld()) {
@@ -487,7 +503,10 @@ export class ElementInteractionController {
viewport,
zoomLevel,
snappedTime,
- verticalDragDirection: verticalDirection(mousedown.origin.y, clientY),
+ verticalDragDirection: verticalDirection({
+ startMouseY: mousedown.origin.y,
+ currentMouseY: clientY,
+ }),
});
const nextGroupMoveResult = anchorDropTarget
@@ -543,7 +562,12 @@ export class ElementInteractionController {
clientY: number;
scrollContainer: HTMLDivElement;
}): void {
- if (!movedPastDragThreshold({ x: clientX, y: clientY }, mousedown.origin)) {
+ if (
+ !movedPastDragThreshold({
+ current: { x: clientX, y: clientY },
+ origin: mousedown.origin,
+ })
+ ) {
return;
}
@@ -568,10 +592,10 @@ export class ElementInteractionController {
clickOffsetTime: mousedown.clickOffsetTime,
fps,
});
- const { snappedTime, snapPoint } = this.snapResult(
+ const { snappedTime, snapPoint } = this.snapResult({
frameSnappedTime,
- moveGroup,
- );
+ group: moveGroup,
+ });
// Ensure the anchor is selected before we render the drag — covers the
// case where the selection store hasn't committed the mousedown-time
@@ -632,10 +656,10 @@ export class ElementInteractionController {
clickOffsetTime: mousedown.clickOffsetTime,
fps,
});
- const { snappedTime, snapPoint } = this.snapResult(
+ const { snappedTime, snapPoint } = this.snapResult({
frameSnappedTime,
- drag.moveGroup,
- );
+ group: drag.moveGroup,
+ });
drag.currentTime = snappedTime;
drag.currentMouseX = clientX;
@@ -666,7 +690,12 @@ export class ElementInteractionController {
// If the drag returned within the click threshold of its origin, treat
// this as a cancel rather than a commit — the user dragged then put the
// element back.
- if (!movedPastDragThreshold({ x: clientX, y: clientY }, mousedown.origin)) {
+ if (
+ !movedPastDragThreshold({
+ current: { x: clientX, y: clientY },
+ origin: mousedown.origin,
+ })
+ ) {
this.lastGestureWasDrag = false;
this.finishSession();
return;
diff --git a/apps/web/src/timeline/controllers/resize-controller.ts b/apps/web/src/timeline/controllers/resize-controller.ts
index e8cbaa80..a1098915 100644
--- a/apps/web/src/timeline/controllers/resize-controller.ts
+++ b/apps/web/src/timeline/controllers/resize-controller.ts
@@ -263,10 +263,13 @@ export class ResizeController {
this.notify();
}
- private snappedDelta(
- session: ResizeSession,
- rawDeltaTime: MediaTime,
- ): MediaTime {
+ private snappedDelta({
+ session,
+ rawDeltaTime,
+ }: {
+ session: ResizeSession;
+ rawDeltaTime: MediaTime;
+ }): MediaTime {
const { snappingEnabled, isShiftHeld, zoomLevel } = this.config;
if (!snappingEnabled || isShiftHeld()) {
@@ -330,7 +333,7 @@ export class ResizeController {
TICKS_PER_SECOND,
),
});
- const deltaTime = this.snappedDelta(session, rawDeltaTime);
+ const deltaTime = this.snappedDelta({ session, rawDeltaTime });
const result = computeGroupResize({
members: session.members,
side: session.side,
diff --git a/apps/web/src/timeline/controllers/zoom-controller.ts b/apps/web/src/timeline/controllers/zoom-controller.ts
index c5090e16..91147354 100644
--- a/apps/web/src/timeline/controllers/zoom-controller.ts
+++ b/apps/web/src/timeline/controllers/zoom-controller.ts
@@ -25,7 +25,13 @@ export interface ZoomConfigRef {
readonly current: ZoomConfig;
}
-function clampZoom(zoomLevel: number, minZoom: number): number {
+function clampZoom({
+ zoomLevel,
+ minZoom,
+}: {
+ zoomLevel: number;
+ minZoom: number;
+}): number {
return Math.max(minZoom, Math.min(TIMELINE_ZOOM_MAX, zoomLevel));
}
@@ -49,7 +55,7 @@ export class ZoomController {
const minZoom = this.config.minZoom;
this.zoomLevelValue =
deps.initialZoom !== undefined
- ? clampZoom(deps.initialZoom, minZoom)
+ ? clampZoom({ zoomLevel: deps.initialZoom, minZoom })
: minZoom;
this.previousZoom = this.zoomLevelValue;
this.hasInitialized = deps.initialZoom !== undefined;
@@ -89,7 +95,10 @@ export class ZoomController {
typeof zoomLevelOrUpdater === "function"
? zoomLevelOrUpdater(this.zoomLevelValue)
: zoomLevelOrUpdater;
- const nextZoom = clampZoom(nextZoomRaw, this.config.minZoom);
+ const nextZoom = clampZoom({
+ zoomLevel: nextZoomRaw,
+ minZoom: this.config.minZoom,
+ });
if (nextZoom === this.zoomLevelValue) return;
this.zoomLevelValue = nextZoom;
@@ -115,10 +124,16 @@ export class ZoomController {
}
}
- reconcileInitialAndMinZoom(minZoom: number, initialZoom?: number): void {
+ reconcileInitialAndMinZoom({
+ minZoom,
+ initialZoom,
+ }: {
+ minZoom: number;
+ initialZoom?: number;
+ }): void {
if (initialZoom !== undefined && !this.hasInitialized) {
this.hasInitialized = true;
- this.setZoomLevel(clampZoom(initialZoom, minZoom));
+ this.setZoomLevel(clampZoom({ zoomLevel: initialZoom, minZoom }));
return;
}