From 49e7514dcfda885bb525a1375dadb78c93bec206 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Fri, 27 Feb 2026 23:32:56 +0300 Subject: [PATCH] Fix copy: build fig-kiwi binary synchronously in copy event handler navigator.clipboard.write() inside .then() loses user gesture context and gets blocked by the browser. The schema is prefetched on app init and cached, so encoding is done synchronously in clipboardData.setData within the native copy event. --- src/engine/clipboard.ts | 19 ++++++++++++++----- src/stores/editor.ts | 14 +++----------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/engine/clipboard.ts b/src/engine/clipboard.ts index 1580e5c4a..acb515080 100644 --- a/src/engine/clipboard.ts +++ b/src/engine/clipboard.ts @@ -55,10 +55,17 @@ let cachedSchema: CompiledSchema | null = null let cachedSchemaDeflated: Uint8Array | null = null export function prefetchFigmaSchema(): void { - getFigmaSchema() + getFigmaSchemaAsync() } -async function getFigmaSchema(): Promise<{ compiled: CompiledSchema; deflated: Uint8Array }> { +function getFigmaSchemaSync(): { compiled: CompiledSchema; deflated: Uint8Array } | null { + if (cachedSchema && cachedSchemaDeflated) { + return { compiled: cachedSchema, deflated: cachedSchemaDeflated } + } + return null +} + +async function getFigmaSchemaAsync(): Promise<{ compiled: CompiledSchema; deflated: Uint8Array }> { if (cachedSchema && cachedSchemaDeflated) { return { compiled: cachedSchema, deflated: cachedSchemaDeflated } } @@ -474,11 +481,13 @@ function sceneNodeToKiwi( return result } -export async function buildFigmaClipboardHTML( +export function buildFigmaClipboardHTML( nodes: SceneNode[], graph: SceneGraph -): Promise { - const { compiled, deflated: schemaDeflated } = await getFigmaSchema() +): string | null { + const schema = getFigmaSchemaSync() + if (!schema) return null + const { compiled, deflated: schemaDeflated } = schema const docGuid = { sessionID: 0, localID: 0 } const canvasGuid = { sessionID: 0, localID: 1 } diff --git a/src/stores/editor.ts b/src/stores/editor.ts index 4d8e041a5..4a375ddd0 100644 --- a/src/stores/editor.ts +++ b/src/stores/editor.ts @@ -239,19 +239,11 @@ export function createEditorStore() { const names = nodes.map((n) => n.name).join('\n') const internalHtml = buildOpenPencilClipboardHTML(nodes, graph) + const figmaHtml = buildFigmaClipboardHTML(nodes, graph) + const html = figmaHtml ? figmaHtml + internalHtml : internalHtml + clipboardData.setData('text/html', html) clipboardData.setData('text/plain', names) - clipboardData.setData('text/html', internalHtml) - - buildFigmaClipboardHTML(nodes, graph).then((figmaHtml) => { - const combined = figmaHtml + internalHtml - navigator.clipboard.write([ - new ClipboardItem({ - 'text/html': new Blob([combined], { type: 'text/html' }), - 'text/plain': new Blob([names], { type: 'text/plain' }) - }) - ]) - }) } function pasteFromHTML(html: string) {