diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-03-02 13:26:40 +0100 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-03-02 13:26:40 +0100 |
| commit | db50b5214de28b9ffc02d0d80623cde13794c5ef (patch) | |
| tree | 127fcdaf3b22e010f70f4724bf7494a87c298e80 /apps/web/src/lib | |
| parent | e7dcb586c0408255a0bf788e355fdb6d50d9b923 (diff) | |
| download | opencut-db50b5214de28b9ffc02d0d80623cde13794c5ef.tar.gz | |
feat: ripple support for element resize
Diffstat (limited to 'apps/web/src/lib')
| -rw-r--r-- | apps/web/src/lib/commands/timeline/element/update-element-trim.ts | 66 |
1 files changed, 49 insertions, 17 deletions
diff --git a/apps/web/src/lib/commands/timeline/element/update-element-trim.ts b/apps/web/src/lib/commands/timeline/element/update-element-trim.ts index 6afcb9d0..7548638a 100644 --- a/apps/web/src/lib/commands/timeline/element/update-element-trim.ts +++ b/apps/web/src/lib/commands/timeline/element/update-element-trim.ts @@ -2,6 +2,7 @@ import { Command } from "@/lib/commands/base-command"; import type { TimelineTrack } from "@/types/timeline"; import { EditorCore } from "@/core"; import { clampAnimationsToDuration } from "@/lib/animation"; +import { rippleShiftElements } from "@/lib/timeline"; export class UpdateElementTrimCommand extends Command { private savedState: TimelineTrack[] | null = null; @@ -10,6 +11,7 @@ export class UpdateElementTrimCommand extends Command { private readonly trimEnd: number; private readonly startTime: number | undefined; private readonly duration: number | undefined; + private readonly rippleEnabled: boolean; constructor({ elementId, @@ -17,12 +19,14 @@ export class UpdateElementTrimCommand extends Command { trimEnd, startTime, duration, + rippleEnabled = false, }: { elementId: string; trimStart: number; trimEnd: number; startTime?: number; duration?: number; + rippleEnabled?: boolean; }) { super(); this.elementId = elementId; @@ -30,6 +34,7 @@ export class UpdateElementTrimCommand extends Command { this.trimEnd = trimEnd; this.startTime = startTime; this.duration = duration; + this.rippleEnabled = rippleEnabled; } execute(): void { @@ -37,25 +42,52 @@ export class UpdateElementTrimCommand extends Command { this.savedState = editor.timeline.getTracks(); const updatedTracks = this.savedState.map((track) => { - const newElements = track.elements.map((element) => { - if (element.id !== this.elementId) { - return element; - } + const targetElement = track.elements.find( + (element) => element.id === this.elementId, + ); + if (!targetElement) return track; - const nextDuration = this.duration ?? element.duration; - return { - ...element, - trimStart: this.trimStart, - trimEnd: this.trimEnd, - startTime: this.startTime ?? element.startTime, + const nextDuration = this.duration ?? targetElement.duration; + const nextStartTime = this.startTime ?? targetElement.startTime; + + const oldEndTime = targetElement.startTime + targetElement.duration; + const newEndTime = nextStartTime + nextDuration; + const shiftAmount = oldEndTime - newEndTime; + + const updatedElement = { + ...targetElement, + trimStart: this.trimStart, + trimEnd: this.trimEnd, + startTime: nextStartTime, + duration: nextDuration, + animations: clampAnimationsToDuration({ + animations: targetElement.animations, duration: nextDuration, - animations: clampAnimationsToDuration({ - animations: element.animations, - duration: nextDuration, - }), - }; - }); - return { ...track, elements: newElements } as typeof track; + }), + }; + + if (this.rippleEnabled && Math.abs(shiftAmount) > 0) { + const shiftedOthers = rippleShiftElements({ + elements: track.elements.filter((element) => element.id !== this.elementId), + afterTime: oldEndTime, + shiftAmount, + }); + return { + ...track, + elements: track.elements.map((element) => + element.id === this.elementId + ? updatedElement + : (shiftedOthers.find((shifted) => shifted.id === element.id) ?? element) + ), + } as typeof track; + } + + return { + ...track, + elements: track.elements.map((element) => + element.id === this.elementId ? updatedElement : element + ), + } as typeof track; }); editor.timeline.updateTracks(updatedTracks); |
