diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2026-01-31 00:20:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-31 00:20:04 +0100 |
| commit | 7bf0984698e43b9aa2dd879f65951318ed410390 (patch) | |
| tree | ccf2cd590a47d550152afc07129cb55c71a9ec35 /apps/web/src/lib/commands/timeline/element/move-elements.ts | |
| parent | 0173db99448d1c4c6415dcf15272e17551b48b04 (diff) | |
| download | opencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz | |
codebase overhaul (#697)
Diffstat (limited to 'apps/web/src/lib/commands/timeline/element/move-elements.ts')
| -rw-r--r-- | apps/web/src/lib/commands/timeline/element/move-elements.ts | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/apps/web/src/lib/commands/timeline/element/move-elements.ts b/apps/web/src/lib/commands/timeline/element/move-elements.ts new file mode 100644 index 00000000..2d4f9236 --- /dev/null +++ b/apps/web/src/lib/commands/timeline/element/move-elements.ts @@ -0,0 +1,127 @@ +import { Command } from "@/lib/commands/base-command"; +import { EditorCore } from "@/core"; +import type { + TimelineTrack, + TimelineElement, + TrackType, +} from "@/types/timeline"; +import { + buildEmptyTrack, + isMainTrack, + validateElementTrackCompatibility, +} from "@/lib/timeline/track-utils"; + +export class MoveElementCommand extends Command { + private savedState: TimelineTrack[] | null = null; + + constructor( + private sourceTrackId: string, + private targetTrackId: string, + private elementId: string, + private newStartTime: number, + private createTrack?: { type: TrackType; index: number }, + ) { + super(); + } + + execute(): void { + const editor = EditorCore.getInstance(); + this.savedState = editor.timeline.getTracks(); + + const sourceTrack = this.savedState.find( + (t) => t.id === this.sourceTrackId, + ); + const element = sourceTrack?.elements.find( + (el) => el.id === this.elementId, + ); + + if (!sourceTrack || !element) { + console.error("Source track or element not found"); + return; + } + + let targetTrack = this.savedState.find((t) => t.id === this.targetTrackId); + let tracksToUpdate = this.savedState; + if (!targetTrack && this.createTrack) { + const newTrack = buildEmptyTrack({ + id: this.targetTrackId, + type: this.createTrack.type, + }); + tracksToUpdate = [...this.savedState]; + tracksToUpdate.splice(this.createTrack.index, 0, newTrack); + targetTrack = newTrack; + } + if (!targetTrack) { + console.error("Target track not found"); + return; + } + + const validation = validateElementTrackCompatibility({ + element, + track: targetTrack, + }); + + if (!validation.isValid) { + console.error(validation.errorMessage); + return; + } + + const movedElement: TimelineElement = { + ...element, + startTime: this.newStartTime, + }; + + const isSameTrack = this.sourceTrackId === this.targetTrackId; + + let updatedTracks = tracksToUpdate.map((track) => { + if (isSameTrack && track.id === this.sourceTrackId) { + return { + ...track, + elements: track.elements.map((el) => + el.id === this.elementId ? movedElement : el, + ), + }; + } + + if (track.id === this.sourceTrackId) { + return { + ...track, + elements: track.elements.filter((el) => el.id !== this.elementId), + }; + } + + if (track.id === this.targetTrackId) { + return { + ...track, + elements: [...track.elements, movedElement], + }; + } + + return track; + }) as TimelineTrack[]; + + if (!isSameTrack) { + const sourceTrackAfterMove = updatedTracks.find( + (track) => track.id === this.sourceTrackId, + ); + if ( + sourceTrackAfterMove && + sourceTrackAfterMove.elements.length === 0 && + !isMainTrack(sourceTrackAfterMove) + ) { + updatedTracks = updatedTracks.filter( + (track) => track.id !== this.sourceTrackId, + ); + } + } + + editor.timeline.updateTracks(updatedTracks); + } + + undo(): void { + if (this.savedState) { + const editor = EditorCore.getInstance(); + editor.timeline.updateTracks(this.savedState); + } + } +} |
