From 7bf0984698e43b9aa2dd879f65951318ed410390 Mon Sep 17 00:00:00 2001 From: Maze <167211895+mazeincoding@users.noreply.github.com> Date: Sat, 31 Jan 2026 00:20:04 +0100 Subject: codebase overhaul (#697) --- .../lib/commands/timeline/element/move-elements.ts | 127 +++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 apps/web/src/lib/commands/timeline/element/move-elements.ts (limited to 'apps/web/src/lib/commands/timeline/element/move-elements.ts') 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); + } + } +} -- cgit v1.3.1