Files
OpenCut/apps/web/src/lib/commands/timeline/element/duplicate-elements.ts
T

70 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-01-05 01:35:10 +01:00
import { Command } from "@/lib/commands/base-command";
import type { TimelineTrack } from "@/types/timeline";
import { generateUUID } from "@/lib/utils";
import { EditorCore } from "@/core";
interface DuplicateElementsParams {
elements: { trackId: string; elementId: string }[];
}
export class DuplicateElementsCommand extends Command {
private duplicatedIds: string[] = [];
private savedState: TimelineTrack[] | null = null;
private elements: DuplicateElementsParams["elements"];
constructor({ elements }: DuplicateElementsParams) {
super();
this.elements = elements;
}
execute(): void {
const editor = EditorCore.getInstance();
this.savedState = editor.timeline.getTracks();
this.duplicatedIds = [];
const updatedTracks = this.savedState.map((track) => {
const elementsToDuplicate = this.elements.filter(
(el) => el.trackId === track.id,
);
if (elementsToDuplicate.length === 0) {
return track;
}
const newElements = track.elements.flatMap((element) => {
const shouldDuplicate = elementsToDuplicate.some(
(el) => el.elementId === element.id,
);
if (!shouldDuplicate) {
return [element];
}
const newId = generateUUID();
this.duplicatedIds.push(newId);
return [
element,
{
...element,
id: newId,
name: `${element.name} (copy)`,
2026-01-15 11:05:17 +01:00
startTime: element.startTime + element.duration + 0.1,
2026-01-05 01:35:10 +01:00
},
];
});
return { ...track, elements: newElements } as typeof track;
});
editor.timeline.updateTracks(updatedTracks);
}
undo(): void {
if (this.savedState) {
const editor = EditorCore.getInstance();
editor.timeline.updateTracks(this.savedState);
}
}
}