Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
880dfb518d |
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
|
||||
鼠标移入**图像对比**:**左边是重绘结果,右边是原图**;移开后显示完整结果。分隔线保持细线,图片持续适应编辑区,滚轮作用于工作流背景。
|
||||
|
||||
网络错误或加载超时时会自动重试,也可点击 **↻** 手动重新加载;如果临时预览已因服务器重启或缓存淘汰而失效,请重新运行工作流。
|
||||
|
||||
同一轮编辑中的结果会累计保存并默认选中最新一张,每张结果对应当时的原图;重复的预览通知不会重复计数。
|
||||
|
||||
点击 **↓** 可以按原始分辨率下载最新生成的结果,即使列表中正在查看旧图也会下载最新一张;批量生成时下载该批最后一张。
|
||||
|
||||
+1
-1
@@ -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
@@ -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
@@ -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";
|
||||
|
||||
@@ -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…": "正在上传图片…",
|
||||
|
||||
Reference in New Issue
Block a user