mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-30 21:09:53 +00:00
232 lines
5.3 KiB
TypeScript
232 lines
5.3 KiB
TypeScript
import { ComfyButton } from "../components/button";
|
|
import { $el } from "../../ui";
|
|
import { api } from "../../api";
|
|
import { ComfyPopup } from "../components/popup";
|
|
import type { ComfyApp } from "@/scripts/app";
|
|
|
|
type ViewListMode = "Queue" | "History";
|
|
|
|
export class ComfyViewListButton {
|
|
popup: ComfyPopup;
|
|
app: ComfyApp;
|
|
button: ComfyButton;
|
|
element: HTMLDivElement;
|
|
list: ComfyViewList;
|
|
|
|
get open() {
|
|
return this.popup.open;
|
|
}
|
|
|
|
set open(open) {
|
|
this.popup.open = open;
|
|
}
|
|
|
|
constructor(
|
|
app: ComfyApp,
|
|
{
|
|
button,
|
|
list,
|
|
mode,
|
|
}: { button: ComfyButton; list: typeof ComfyViewList; mode: ViewListMode }
|
|
) {
|
|
this.app = app;
|
|
this.button = button;
|
|
this.element = $el(
|
|
"div.comfyui-button-wrapper",
|
|
this.button.element
|
|
) as HTMLDivElement;
|
|
this.popup = new ComfyPopup({
|
|
target: this.element,
|
|
container: this.element,
|
|
horizontal: "right",
|
|
});
|
|
this.list = new (list ?? ComfyViewList)(app, mode, this.popup);
|
|
this.popup.children = [this.list.element];
|
|
this.popup.addEventListener("open", () => {
|
|
this.list.update();
|
|
});
|
|
this.popup.addEventListener("close", () => {
|
|
this.list.close();
|
|
});
|
|
this.button.withPopup(this.popup);
|
|
|
|
api.addEventListener("status", () => {
|
|
if (this.popup.open) {
|
|
this.popup.update();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
export class ComfyViewList {
|
|
app: ComfyApp;
|
|
mode: ViewListMode;
|
|
popup: ComfyPopup;
|
|
type: string;
|
|
items: HTMLElement;
|
|
clear: ComfyButton;
|
|
refresh: ComfyButton;
|
|
element: HTMLElement;
|
|
constructor(app: ComfyApp, mode: ViewListMode, popup: ComfyPopup) {
|
|
this.app = app;
|
|
this.mode = mode;
|
|
this.popup = popup;
|
|
this.type = mode.toLowerCase();
|
|
|
|
this.items = $el(`div.comfyui-${this.type}-items.comfyui-view-list-items`);
|
|
this.clear = new ComfyButton({
|
|
icon: "cancel",
|
|
content: "Clear",
|
|
action: async () => {
|
|
this.showSpinner(false);
|
|
await api.clearItems(this.type);
|
|
await this.update();
|
|
},
|
|
});
|
|
|
|
this.refresh = new ComfyButton({
|
|
icon: "refresh",
|
|
content: "Refresh",
|
|
action: async () => {
|
|
await this.update(false);
|
|
},
|
|
});
|
|
|
|
this.element = $el(
|
|
`div.comfyui-${this.type}-popup.comfyui-view-list-popup`,
|
|
[
|
|
$el("h3", mode),
|
|
$el("header", [this.clear.element, this.refresh.element]),
|
|
this.items,
|
|
]
|
|
);
|
|
|
|
api.addEventListener("status", () => {
|
|
if (this.popup.open) {
|
|
this.update();
|
|
}
|
|
});
|
|
}
|
|
|
|
async close() {
|
|
this.items.replaceChildren();
|
|
}
|
|
|
|
async update(resize = true) {
|
|
this.showSpinner(resize);
|
|
const res = await this.loadItems();
|
|
let any = false;
|
|
|
|
const names = Object.keys(res);
|
|
const sections = names
|
|
.map((section) => {
|
|
const items = res[section];
|
|
if (items?.length) {
|
|
any = true;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
const rows = [];
|
|
if (names.length > 1) {
|
|
rows.push($el("h5", section));
|
|
}
|
|
rows.push(...items.flatMap((item) => this.createRow(item, section)));
|
|
return $el("section", rows);
|
|
})
|
|
.filter(Boolean);
|
|
|
|
if (any) {
|
|
this.items.replaceChildren(...sections);
|
|
} else {
|
|
this.items.replaceChildren($el("h5", "None"));
|
|
}
|
|
|
|
this.popup.update();
|
|
this.clear.enabled = this.refresh.enabled = true;
|
|
this.element.style.removeProperty("height");
|
|
}
|
|
|
|
showSpinner(resize = true) {
|
|
// if (!this.spinner) {
|
|
// this.spinner = createSpinner();
|
|
// }
|
|
// if (!resize) {
|
|
// this.element.style.height = this.element.clientHeight + "px";
|
|
// }
|
|
// this.clear.enabled = this.refresh.enabled = false;
|
|
// this.items.replaceChildren(
|
|
// $el(
|
|
// "div",
|
|
// {
|
|
// style: {
|
|
// fontSize: "18px",
|
|
// },
|
|
// },
|
|
// this.spinner
|
|
// )
|
|
// );
|
|
// this.popup.update();
|
|
}
|
|
|
|
async loadItems() {
|
|
return await api.getItems(this.type);
|
|
}
|
|
|
|
getRow(item, section) {
|
|
return {
|
|
text: item.prompt[0] + "",
|
|
actions: [
|
|
{
|
|
text: "Load",
|
|
action: async () => {
|
|
try {
|
|
await this.app.loadGraphData(
|
|
item.prompt[3].extra_pnginfo.workflow
|
|
);
|
|
if (item.outputs) {
|
|
this.app.nodeOutputs = item.outputs;
|
|
}
|
|
} catch (error) {
|
|
alert("Error loading workflow: " + error.message);
|
|
console.error(error);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
text: "Delete",
|
|
action: async () => {
|
|
try {
|
|
await api.deleteItem(this.type, item.prompt[1]);
|
|
this.update();
|
|
} catch (error) {}
|
|
},
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
createRow = (item, section) => {
|
|
const row = this.getRow(item, section);
|
|
return [
|
|
$el("span", row.text),
|
|
...row.actions.map(
|
|
(a) =>
|
|
new ComfyButton({
|
|
content: a.text,
|
|
action: async (e, btn) => {
|
|
btn.enabled = false;
|
|
try {
|
|
await a.action();
|
|
} catch (error) {
|
|
throw error;
|
|
} finally {
|
|
btn.enabled = true;
|
|
}
|
|
},
|
|
}).element
|
|
),
|
|
];
|
|
};
|
|
}
|