From 2272598d420cf078aaa3928246bfa3a414f6eddb Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 13 Apr 2026 04:40:56 +0200 Subject: feat: clipboard with keyframe paste Made-with: Cursor --- apps/web/src/core/managers/clipboard-manager.ts | 81 +++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 apps/web/src/core/managers/clipboard-manager.ts (limited to 'apps/web/src/core/managers') diff --git a/apps/web/src/core/managers/clipboard-manager.ts b/apps/web/src/core/managers/clipboard-manager.ts new file mode 100644 index 00000000..b19343df --- /dev/null +++ b/apps/web/src/core/managers/clipboard-manager.ts @@ -0,0 +1,81 @@ +import type { EditorCore } from "@/core"; +import { + buildPasteClipboardCommand, + copyClipboardEntry, + type ClipboardEntry, + type CopyContext, + type PasteContext, +} from "@/lib/clipboard"; + +export class ClipboardManager { + private entry: ClipboardEntry | null = null; + private listeners = new Set<() => void>(); + + constructor(private editor: EditorCore) {} + + getEntry(): ClipboardEntry | null { + return this.entry; + } + + hasEntry(): boolean { + return this.entry !== null; + } + + copy(): boolean { + const entry = copyClipboardEntry({ + context: this.getCopyContext(), + }); + if (!entry) { + return false; + } + + this.entry = entry; + this.notify(); + return true; + } + + paste({ time }: { time?: number } = {}): boolean { + if (!this.entry) { + return false; + } + + const command = buildPasteClipboardCommand({ + entry: this.entry, + context: this.getPasteContext({ time }), + }); + if (!command) { + return false; + } + + this.editor.command.execute({ command }); + return true; + } + + subscribe(listener: () => void): () => void { + this.listeners.add(listener); + return () => this.listeners.delete(listener); + } + + private getCopyContext(): CopyContext { + return { + editor: this.editor, + selectedElements: this.editor.selection.getSelectedElements(), + selectedKeyframes: this.editor.selection.getSelectedKeyframes(), + }; + } + + private getPasteContext({ time }: { time?: number }): PasteContext { + return { + editor: this.editor, + selectedElements: this.editor.selection.getSelectedElements(), + selectedKeyframes: this.editor.selection.getSelectedKeyframes(), + time: time ?? this.editor.playback.getCurrentTime(), + }; + } + + private notify(): void { + this.listeners.forEach((listener) => { + listener(); + }); + } +} -- cgit v1.3.1