diff options
Diffstat (limited to 'apps/web/src/core/managers/renderer-manager.ts')
| -rw-r--r-- | apps/web/src/core/managers/renderer-manager.ts | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/apps/web/src/core/managers/renderer-manager.ts b/apps/web/src/core/managers/renderer-manager.ts index 601a007e..75184c53 100644 --- a/apps/web/src/core/managers/renderer-manager.ts +++ b/apps/web/src/core/managers/renderer-manager.ts @@ -1,6 +1,6 @@ import type { EditorCore } from "@/core"; import type { RootNode } from "@/services/renderer/nodes/root-node"; -import type { ExportOptions, ExportResult } from "@/types/export"; +import type { ExportOptions, ExportResult } from "@/lib/export"; import { CanvasRenderer } from "@/services/renderer/canvas-renderer"; import { SceneExporter } from "@/services/renderer/scene-exporter"; import { buildScene } from "@/services/renderer/scene-builder"; @@ -8,6 +8,10 @@ import { createTimelineAudioBuffer } from "@/lib/media/audio"; import { formatTimeCode, getLastFrameTime } from "@/lib/time"; import { downloadBlob } from "@/utils/browser"; +type SnapshotResult = + | { success: true; blob: Blob; filename: string } + | { success: false; error: string }; + export class RendererManager { private renderTree: RootNode | null = null; private listeners = new Set<() => void>(); @@ -24,6 +28,45 @@ export class RendererManager { } async saveSnapshot(): Promise<{ success: boolean; error?: string }> { + const snapshot = await this.createSnapshot(); + if (!snapshot.success) { + return snapshot; + } + + downloadBlob({ blob: snapshot.blob, filename: snapshot.filename }); + return { success: true }; + } + + async copySnapshot(): Promise<{ success: boolean; error?: string }> { + if (typeof ClipboardItem === "undefined" || !navigator.clipboard?.write) { + return { + success: false, + error: "Clipboard image copy is not supported in this browser", + }; + } + + const snapshot = await this.createSnapshot(); + if (!snapshot.success) { + return snapshot; + } + + try { + await navigator.clipboard.write([ + new ClipboardItem({ + [snapshot.blob.type || "image/png"]: snapshot.blob, + }), + ]); + return { success: true }; + } catch (error) { + console.error("Copy snapshot failed:", error); + return { + success: false, + error: error instanceof Error ? error.message : "Unknown error", + }; + } + } + + private async createSnapshot(): Promise<SnapshotResult> { try { const renderTree = this.getRenderTree(); const activeProject = this.editor.project.getActive(); @@ -70,15 +113,14 @@ export class RendererManager { timeInSeconds: renderTime, fps, }).replace(/:/g, "-"); - const safeName = activeProject.metadata.name - .replace(/[<>:"/\\|?*]/g, "-") - .trim() || "snapshot"; + const safeName = + activeProject.metadata.name.replace(/[<>:"/\\|?*]/g, "-").trim() || + "snapshot"; const filename = `${safeName}-${timecode}.png`; - downloadBlob({ blob, filename }); - return { success: true }; + return { success: true, blob, filename }; } catch (error) { - console.error("Save snapshot failed:", error); + console.error("Snapshot capture failed:", error); return { success: false, error: error instanceof Error ? error.message : "Unknown error", @@ -193,6 +235,8 @@ export class RendererManager { } private notify(): void { - this.listeners.forEach((fn) => fn()); + this.listeners.forEach((fn) => { + fn(); + }); } } |
