mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-19 06:20:10 +00:00
fix: handle Unicode characters in clipboard copy/paste and add Paste menu option (#7103)
## Summary Use TextEncoder/TextDecoder for UTF-8 safe base64 encoding/decoding When copying nodes containing non-Latin1 characters (e.g., Chinese characters in localized_name field), btoa() throws an error: InvalidCharacterError: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range. The copy operation saved data to localStorage successfully, but failed to write to the browser clipboard. On paste, the browser clipboard still contained old data, causing the wrong node to be pasted. <!-- Fixes #ISSUE_NUMBER --> https://github.com/Comfy-Org/ComfyUI_frontend/issues/6993 https://github.com/Comfy-Org/ComfyUI_frontend/issues/5449 https://github.com/comfyanonymous/ComfyUI/issues/8481 ## Screenshots (if applicable) before https://github.com/user-attachments/assets/8abd9049-91bb-4200-8853-e26753376007 after https://github.com/user-attachments/assets/7d969f32-bb0f-4c7a-baa2-65d576a4eba2 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7103-fix-handle-Unicode-characters-in-clipboard-copy-paste-and-add-Paste-menu-option-2bd6d73d365081f39c40e7e7f832b97c) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
@@ -23,10 +23,16 @@ export const useCopy = () => {
|
||||
const canvas = canvasStore.canvas
|
||||
if (canvas?.selectedItems) {
|
||||
const serializedData = canvas.copyToClipboard()
|
||||
// Use TextEncoder to handle Unicode characters properly
|
||||
const base64Data = btoa(
|
||||
String.fromCharCode(
|
||||
...Array.from(new TextEncoder().encode(serializedData))
|
||||
)
|
||||
)
|
||||
// clearData doesn't remove images from clipboard
|
||||
e.clipboardData?.setData(
|
||||
'text/html',
|
||||
clipboardHTMLWrapper.join(btoa(serializedData))
|
||||
clipboardHTMLWrapper.join(base64Data)
|
||||
)
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
|
||||
@@ -14,9 +14,11 @@ function pasteClipboardItems(data: DataTransfer): boolean {
|
||||
const match = rawData.match(/data-metadata="([A-Za-z0-9+/=]+)"/)?.[1]
|
||||
if (!match) return false
|
||||
try {
|
||||
useCanvasStore()
|
||||
.getCanvas()
|
||||
._deserializeItems(JSON.parse(atob(match)), {})
|
||||
// Decode UTF-8 safe base64
|
||||
const binaryString = atob(match)
|
||||
const bytes = Uint8Array.from(binaryString, (c) => c.charCodeAt(0))
|
||||
const decodedData = new TextDecoder().decode(bytes)
|
||||
useCanvasStore().getCanvas()._deserializeItems(JSON.parse(decodedData), {})
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
|
||||
@@ -8031,7 +8031,13 @@ export class LGraphCanvas
|
||||
has_submenu: true,
|
||||
callback: LGraphCanvas.onMenuAdd
|
||||
},
|
||||
{ content: 'Add Group', callback: LGraphCanvas.onGroupAdd }
|
||||
{ content: 'Add Group', callback: LGraphCanvas.onGroupAdd },
|
||||
{
|
||||
content: 'Paste',
|
||||
callback: () => {
|
||||
this.pasteFromClipboard()
|
||||
}
|
||||
}
|
||||
// { content: "Arrange", callback: that.graph.arrange },
|
||||
// {content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll }
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user