Restore the canvas even when a PNG export fails

export() resized the canvas, changed its scale and offset, and only
restored them after the blob came back. Anything that threw in between —
most plausibly toBlob on a workflow large enough to exceed the browser's
canvas limit, which is exactly the workflow someone wants a PNG of — left
the user's view stuck at export dimensions until they reloaded.

restoreState() now runs in a finally, followed by a redraw.

The GuLuLu yes/no callbacks also swallowed the rejection, so the failure
looked like the button simply doing nothing. They now go through a wrapper
that logs and shows a toast naming the canvas limit as the likely cause.
This commit is contained in:
kk8bit
2026-09-20 21:43:59 +08:00
parent c3af5a43ac
commit 75b1dde389
3 changed files with 33 additions and 7 deletions
+2
View File
@@ -1,6 +1,8 @@
# Changelog
## [未发布 Unreleased]
- 修复 Workflow PNG 导出失败时画布视图被留在导出状态、只能刷新页面才能恢复的问题;导出失败现在也会明确提示(大工作流可能超出浏览器画布上限),不再静默无反应
- Fixed a failed Workflow PNG export leaving the canvas stuck in its export state until the page was reloaded; failures are now reported instead of silently doing nothing (a very large workflow can exceed the browser's canvas limit)
- 给三个翻译节点的网络请求加上超时(连接 10 秒、读取 30 秒)。此前 requests 默认永不超时,对端连上却不回包会把整个工作流队列无限期堵死且无任何提示;百度翻译节点的网络异常也统一转成可读报错
- Added timeouts to the three translator nodes (10s connect, 30s read). requests never times out by default, so a server that accepted the connection but never replied would block the whole workflow queue indefinitely with nothing reported; network failures in the Baidu node are now reported as readable errors too
- 修复自定义图像保存节点把图片写到进程工作目录、并且无视 ComfyUI `--output-directory` 设置的问题;现在始终保存到 ComfyUI 的输出目录下的 `Custom_Save_Image` 子目录
+2
View File
@@ -9,6 +9,8 @@ This is a custom node utility package developed for ComfyUI. Initially created f
## 最新更新 / Last Update
### [未发布 Unreleased]
- 修复 Workflow PNG 导出失败时画布视图被留在导出状态、只能刷新页面才能恢复的问题;导出失败现在也会明确提示(大工作流可能超出浏览器画布上限),不再静默无反应
- Fixed a failed Workflow PNG export leaving the canvas stuck in its export state until the page was reloaded; failures are now reported instead of silently doing nothing (a very large workflow can exceed the browser's canvas limit)
- 给三个翻译节点的网络请求加上超时(连接 10 秒、读取 30 秒)。此前 requests 默认永不超时,对端连上却不回包会把整个工作流队列无限期堵死且无任何提示;百度翻译节点的网络异常也统一转成可读报错
- Added timeouts to the three translator nodes (10s connect, 30s read). requests never times out by default, so a server that accepted the connection but never replied would block the whole workflow queue indefinitely with nothing reported; network failures in the Baidu node are now reported as readable errors too
- 修复自定义图像保存节点把图片写到进程工作目录、并且无视 ComfyUI `--output-directory` 设置的问题;现在始终保存到 ComfyUI 的输出目录下的 `Custom_Save_Image` 子目录
+29 -7
View File
@@ -69,11 +69,17 @@ class KayWorkflowImage {
async export(includeWorkflow) {
this.saveState();
this.updateView(this.getBounds());
const getDrawTextConfig = this.getDrawTextConfig;
app.canvas.draw(true, true);
const blob = await this.getBlob(includeWorkflow ? JSON.stringify(app.graph.serialize()) : undefined);
this.restoreState();
let blob;
try {
this.updateView(this.getBounds());
app.canvas.draw(true, true);
blob = await this.getBlob(includeWorkflow ? JSON.stringify(app.graph.serialize()) : undefined);
} finally {
// 必须无条件还原:updateView 会改掉画布的尺寸、缩放和偏移,
// 中途失败而不还原的话,用户的视图就一直停在导出用的状态,只能刷新页面。
this.restoreState();
app.canvas.draw(true, true);
}
if (blob) this.download(blob);
}
@@ -161,13 +167,29 @@ class KayWorkflowImage {
}
}
async function runExport(includeWorkflow) {
try {
await new KayWorkflowImage().export(includeWorkflow);
} catch (e) {
console.error("[KayTool] Workflow PNG export failed:", e);
// 画布太大时 toBlob 会失败,这是最常见的原因,直接说清楚
app.extensionManager?.toast?.add?.({
severity: "error",
summary: "Workflow PNG",
detail: `Export failed: ${e?.message || e}. A very large workflow can exceed the browser's canvas limit.`,
life: 8000,
});
}
}
function exportWorkflowPNG() {
showNotification({
message: `GuLuLu: 你需要把工作流信息嵌入到PNG中吗?啊?Do you need to embed Workflow information into PNG? *GuLuLu~Gulu*`,
bgColor: "#fff3cd",
size: "medium",
onYes: () => new KayWorkflowImage().export(true),
onNo: () => new KayWorkflowImage().export(false)
// 回调里的异常没人接,会被静默吞掉,用户只看到「没反应」。
onYes: () => runExport(true),
onNo: () => runExport(false)
});
}