Skip to content

[bugfix] canvas: register copied media in the target canvas on paste - #80

Merged
princepride merged 1 commit into
mainfrom
fix/cross-canvas-paste
Nov 4, 2026
Merged

princepride merged 1 commit into
mainfrom
fix/cross-canvas-paste

Conversation

@princepride

Copy link
Copy Markdown
Collaborator

Summary

Fixes #69. 跨画布复制图片节点后,粘贴结果图片损坏,自动保存提示 保存失败:TypeError: Failed to fetch。

原因。 复制的节点保存的是来源画布的 blob: 预览地址。切换画布时 CreationClient.close() 会释放这些地址,保存时 importResource() 再读取就失败了。

修复。

  • 复制和剪切时,趁地址仍然有效,读取片段中所有内联媒体字段(src、sourceImageUri、output,与画布导出使用同一组字段)。
  • 粘贴到其他画布时,先把这些素材登记到目标工程,并换成目标工程自己的预览地址和素材 ID,全部成功后才插入节点。任一素材读取或登记失败时,一个节点都不插入,并提示"跨画布粘贴失败,未粘贴任何节点"。
  • 登记结果按目标工程缓存:同一次复制粘贴多次只登记一次;失败后重试时,复用已成功的素材,不重复创建对象。
  • 主体卡片、分组、堆叠中的素材一并迁移,并去掉来源工程的 backendAssetId / copiedSourceId。
  • 同画布内的复制、剪切和 duplicate 路径不变。

生成图片的来源关系。 契约要求图片的 materialOverride 必须来自已记录的生成或编辑(Image overrides require recorded generation or edit provenance),而生成任务属于来源工程。因此,跨画布粘贴的生成图片会变成普通素材图片(upload 来源),不带提示词和生成参数,也不伪造生成记录。指向它的引用连线会一起去掉,因为素材节点没有生成配置来接收引用;它指向其他节点的连线保留。生成视频和音频沿用同画布复制时的做法,保留生成配置,以导入的媒体作为结果。

Test Plan / Result

本地工作树:Node.js 24.22.1;浏览器使用隔离 API/Vite、Chromium 和模拟图片生成服务,启动方式见 docs/development/validation.md,未调用付费服务。

检查 命令 结果
跨画布粘贴 node tests/browser/cross_canvas_paste.mjs(新增,已加入 CI) 通过:A 中生成一张图、上传一张图,复制后经项目切换器切到 B 粘贴,图片正常显示,自动保存成功;B 中两个 material 节点、两个 upload 素材、无 Job;再粘贴一次,素材数不变;重新加载 B 后,4 张图片仍可读取;A 未改变
修复前对照 同上,撤销 CanvasWorkspace.tsx 改动 失败:粘贴后图片无法加载
迁移逻辑 node --test tests/clipboardMedia.test.ts(新增) 4 passed:来源地址被释放后仍可粘贴、生成图片转为素材、重复粘贴与失败重试、读取失败不插入
前端 npm test 523 passed
构建 npm run build 通过

Known issues / Validation limits

  • 在同一画布复制,切到别的画布再切回来后粘贴:来源地址同样已被释放,但这走的是同画布路径,本 PR 未改。
  • 视频以及包含视频的主体,只有单元测试覆盖;浏览器端到端测试只覆盖了图片。
  • 大视频在复制时会读入内存,直到下一次复制或页面关闭才释放。

🤖 Generated with Claude Code

Copied nodes kept the source canvas's blob: preview URLs. Switching
canvases closes the source client, which revokes them, so a paste in
another canvas showed broken images and autosave failed with
"Failed to fetch".

Copy and cut now read every inline media field while the URLs are still
alive. A paste into another canvas registers that media in the target
project first and inserts the nodes only when all of it succeeded; a
failure inserts nothing and says so. Registrations are cached per target
project, so repeated pastes and retries reuse them.

A generated image's task stays in its source project, and image
overrides require recorded generation provenance, so its copy becomes a
material image without the generation settings instead of claiming that
provenance. Generated video and audio keep their settings.

Fixes #69

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: princepride <wangzhipeng628@gmail.com>
@princepride
princepride merged commit 5581f19 into main Nov 4, 2026
@hsliuustc0106
hsliuustc0106 deleted the fix/cross-canvas-paste branch November 6, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] 跨画布粘贴图片后素材无法显示且保存失败

1 participant