Compare commits

..
1 Commits
Author SHA1 Message Date
Adachi 880dfb518d Retry comparison previews and add reload control 2026-11-05 21:40:27 +08:00
7 changed files with 31 additions and 5 deletions
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## 1.0.1
- Retry comparison image loading after network errors or timeouts and add a manual reload button. Expired preview references still require a new generation.
## 1.0.0
- First stable release of the inline inpainting workspace, comparison, crop blending and workflow switching tools.
+2
View File
@@ -91,6 +91,8 @@ The panel includes mask inside/outside, original/fill/noise/zero-latent content,
Move the pointer over **Image Compare**: **result on the left, original on the right**. Leave the picture to see the full result. The divider stays thin, the image stays fitted, and scrolling navigates the workflow background.
Loading errors and timeouts are retried automatically; **↻** reloads the comparison manually. If the temporary memory preview has expired after server restart or cache eviction, run the workflow again.
Results accumulate within an editing round, with the newest selected automatically. Each result retains its matching original; replayed preview notifications are not counted twice.
Use the **↓** button to download the latest generated result at its original resolution, even when an older result is selected in the list. For a batch, it downloads the last image in that batch.
+2
View File
@@ -91,6 +91,8 @@
鼠标移入**图像对比**:**左边是重绘结果,右边是原图**;移开后显示完整结果。分隔线保持细线,图片持续适应编辑区,滚轮作用于工作流背景。
网络错误或加载超时时会自动重试,也可点击 **↻** 手动重新加载;如果临时预览已因服务器重启或缓存淘汰而失效,请重新运行工作流。
同一轮编辑中的结果会累计保存并默认选中最新一张,每张结果对应当时的原图;重复的预览通知不会重复计数。
点击 **↓** 可以按原始分辨率下载最新生成的结果,即使列表中正在查看旧图也会下载最新一张;批量生成时下载该批最后一张。
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "adachi-inpaint-workbench"
version = "1.0.0"
version = "1.0.1"
description = "Inline mask painting and WebUI-style inpainting nodes for ComfyUI"
requires-python = ">=3.10"
license = { file = "LICENSE" }
+20 -3
View File
@@ -8,8 +8,9 @@ const element = (tag, className, text) => {
};
const imageFrom = url => new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => resolve(image);
image.onerror = () => reject(new Error(T("Preview unavailable; run the workflow again")));
const timer = setTimeout(() => { image.src = ""; reject(new Error(T("Preview unavailable; run the workflow again"))); }, 15000);
image.onload = () => { clearTimeout(timer); resolve(image); };
image.onerror = () => { clearTimeout(timer); reject(new Error(T("Preview unavailable; run the workflow again"))); };
image.src = url;
});
@@ -27,6 +28,10 @@ export class ImageCompareView {
this.resultSelect.onchange = () => { this.index = Number(this.resultSelect.value); this.options.onSelect?.(this.index); this.loadSelected(); };
toolbar.append(this.resultSelect, this.dimensionsLabel);
const spacer = element("span", "dd-spacer"); toolbar.append(spacer);
this.reloadButton = element("button", "", "↻"); this.reloadButton.type = "button";
this.reloadButton.title = T("Reload comparison images"); this.reloadButton.setAttribute("aria-label", this.reloadButton.title);
this.reloadButton.onclick = event => { event.preventDefault(); event.stopPropagation(); this.loadSelected(); };
toolbar.append(this.reloadButton);
this.downloadButton = element("button", "", "↓"); this.downloadButton.type = "button";
this.downloadButton.title = T("Download the latest generated image");
this.downloadButton.setAttribute("aria-label", this.downloadButton.title);
@@ -128,12 +133,24 @@ export class ImageCompareView {
async loadSelected() {
const version = ++this.version;
this.reloadButton.disabled = !this.originals.length || !this.results.length;
this.ready = false; this.updateButton();
if (!this.originals.length || !this.results.length) return;
const repetitions = this.results.length / this.originals.length;
const original = this.originals[Math.min(this.originals.length - 1, Math.floor(this.index / repetitions))];
try {
const images = await Promise.all([imageFrom(this.options.resolveUrl(original)), imageFrom(this.options.resolveUrl(this.results[this.index]))]);
let images;
for (let attempt = 0; attempt < 3; attempt++) {
try {
images = await Promise.all([imageFrom(this.options.resolveUrl(original)), imageFrom(this.options.resolveUrl(this.results[this.index]))]);
break;
} catch (error) {
if (version !== this.version || this.destroyed) return;
if (attempt === 2) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));
if (version !== this.version || this.destroyed) return;
}
}
if (version !== this.version || this.destroyed) return;
this.before = images[0]; this.after = images[1];
this.ready = true; this.empty.hidden = true;
+1 -1
View File
@@ -1,6 +1,6 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { ImageCompareView } from "./compare.js?v=0.8.1";
import { ImageCompareView } from "./compare.js?v=1.0.1";
import { appendComparison } from "./compare_history.js?v=0.5.8";
import { routeWheelOutsideImage } from "./wheel_routing.js";
import { T } from "./i18n.js";
+1
View File
@@ -6,6 +6,7 @@
// buttons are drawn by this plugin, so they translate here by reading Comfy.Locale.
const ZH = {
"Reload comparison images": "重新加载对比图片",
"Image upload progress": "图片上传进度",
"Uploading image": "正在上传图片",
"Uploading image…": "正在上传图片…",