|
|
@ -3,7 +3,10 @@ import { api } from "./api.js";
|
|
|
|
export function $el(tag, propsOrChildren, children) {
|
|
|
|
export function $el(tag, propsOrChildren, children) {
|
|
|
|
const split = tag.split(".");
|
|
|
|
const split = tag.split(".");
|
|
|
|
const element = document.createElement(split.shift());
|
|
|
|
const element = document.createElement(split.shift());
|
|
|
|
|
|
|
|
if (split.length > 0) {
|
|
|
|
element.classList.add(...split);
|
|
|
|
element.classList.add(...split);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (propsOrChildren) {
|
|
|
|
if (propsOrChildren) {
|
|
|
|
if (Array.isArray(propsOrChildren)) {
|
|
|
|
if (Array.isArray(propsOrChildren)) {
|
|
|
|
element.append(...propsOrChildren);
|
|
|
|
element.append(...propsOrChildren);
|
|
|
@ -14,6 +17,10 @@ export function $el(tag, propsOrChildren, children) {
|
|
|
|
delete propsOrChildren.dataset;
|
|
|
|
delete propsOrChildren.dataset;
|
|
|
|
delete propsOrChildren.style;
|
|
|
|
delete propsOrChildren.style;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Object.hasOwn(propsOrChildren, "for")) {
|
|
|
|
|
|
|
|
element.setAttribute("for", propsOrChildren.for)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (style) {
|
|
|
|
if (style) {
|
|
|
|
Object.assign(element.style, style);
|
|
|
|
Object.assign(element.style, style);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -119,6 +126,7 @@ function dragElement(dragEl, settings) {
|
|
|
|
savePos = value;
|
|
|
|
savePos = value;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function dragMouseDown(e) {
|
|
|
|
function dragMouseDown(e) {
|
|
|
|
e = e || window.event;
|
|
|
|
e = e || window.event;
|
|
|
|
e.preventDefault();
|
|
|
|
e.preventDefault();
|
|
|
@ -193,7 +201,22 @@ export class ComfyDialog {
|
|
|
|
class ComfySettingsDialog extends ComfyDialog {
|
|
|
|
class ComfySettingsDialog extends ComfyDialog {
|
|
|
|
constructor() {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
super();
|
|
|
|
this.element.classList.add("comfy-settings");
|
|
|
|
this.element = $el("dialog", {
|
|
|
|
|
|
|
|
id: "comfy-settings-dialog",
|
|
|
|
|
|
|
|
parent: document.body,
|
|
|
|
|
|
|
|
}, [
|
|
|
|
|
|
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
|
|
|
|
|
|
$el("caption", {textContent: "Settings"}),
|
|
|
|
|
|
|
|
$el("tbody", {$: (tbody) => (this.textElement = tbody)}),
|
|
|
|
|
|
|
|
$el("button", {
|
|
|
|
|
|
|
|
type: "button",
|
|
|
|
|
|
|
|
textContent: "Close",
|
|
|
|
|
|
|
|
onclick: () => {
|
|
|
|
|
|
|
|
this.element.close();
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
]),
|
|
|
|
|
|
|
|
]);
|
|
|
|
this.settings = [];
|
|
|
|
this.settings = [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -212,11 +235,12 @@ class ComfySettingsDialog extends ComfyDialog {
|
|
|
|
if (!id) {
|
|
|
|
if (!id) {
|
|
|
|
throw new Error("Settings must have an ID");
|
|
|
|
throw new Error("Settings must have an ID");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.settings.find((s) => s.id === id)) {
|
|
|
|
if (this.settings.find((s) => s.id === id)) {
|
|
|
|
throw new Error("Setting IDs must be unique");
|
|
|
|
throw new Error(`Setting ${id} of type ${type} must have a unique ID.`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const settingId = "Comfy.Settings." + id;
|
|
|
|
const settingId = `Comfy.Settings.${id}`;
|
|
|
|
const v = localStorage[settingId];
|
|
|
|
const v = localStorage[settingId];
|
|
|
|
let value = v == null ? defaultValue : JSON.parse(v);
|
|
|
|
let value = v == null ? defaultValue : JSON.parse(v);
|
|
|
|
|
|
|
|
|
|
|
@ -234,34 +258,50 @@ class ComfySettingsDialog extends ComfyDialog {
|
|
|
|
localStorage[settingId] = JSON.stringify(v);
|
|
|
|
localStorage[settingId] = JSON.stringify(v);
|
|
|
|
value = v;
|
|
|
|
value = v;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
value = this.getSettingValue(id, defaultValue);
|
|
|
|
|
|
|
|
|
|
|
|
let element;
|
|
|
|
let element;
|
|
|
|
value = this.getSettingValue(id, defaultValue);
|
|
|
|
const htmlID = id.replaceAll(".", "-");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const labelCell = $el("td", [
|
|
|
|
|
|
|
|
$el("label", {
|
|
|
|
|
|
|
|
for: htmlID,
|
|
|
|
|
|
|
|
classList: [tooltip !== "" ? "comfy-tooltip-indicator" : ""],
|
|
|
|
|
|
|
|
textContent: name.endsWith(":") ? name : `${name}:`,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof type === "function") {
|
|
|
|
if (typeof type === "function") {
|
|
|
|
element = type(name, setter, value, attrs);
|
|
|
|
element = type(name, setter, value, attrs);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
switch (type) {
|
|
|
|
switch (type) {
|
|
|
|
case "boolean":
|
|
|
|
case "boolean":
|
|
|
|
element = $el("div", [
|
|
|
|
element = $el("tr", [
|
|
|
|
$el("label", { textContent: name || id }, [
|
|
|
|
labelCell,
|
|
|
|
|
|
|
|
$el("td", [
|
|
|
|
$el("input", {
|
|
|
|
$el("input", {
|
|
|
|
|
|
|
|
id: htmlID,
|
|
|
|
type: "checkbox",
|
|
|
|
type: "checkbox",
|
|
|
|
checked: !!value,
|
|
|
|
checked: value,
|
|
|
|
oninput: (e) => {
|
|
|
|
onchange: (event) => {
|
|
|
|
setter(e.target.checked);
|
|
|
|
const isChecked = event.target.checked;
|
|
|
|
|
|
|
|
if (onChange !== undefined) {
|
|
|
|
|
|
|
|
onChange(isChecked)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.setSettingValue(id, isChecked);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
...attrs
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
]);
|
|
|
|
])
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case "number":
|
|
|
|
case "number":
|
|
|
|
element = $el("div", [
|
|
|
|
element = $el("tr", [
|
|
|
|
$el("label", { textContent: name || id }, [
|
|
|
|
labelCell,
|
|
|
|
|
|
|
|
$el("td", [
|
|
|
|
$el("input", {
|
|
|
|
$el("input", {
|
|
|
|
type,
|
|
|
|
type,
|
|
|
|
value,
|
|
|
|
value,
|
|
|
|
|
|
|
|
id: htmlID,
|
|
|
|
oninput: (e) => {
|
|
|
|
oninput: (e) => {
|
|
|
|
setter(e.target.value);
|
|
|
|
setter(e.target.value);
|
|
|
|
},
|
|
|
|
},
|
|
|
@ -271,39 +311,55 @@ class ComfySettingsDialog extends ComfyDialog {
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case "slider":
|
|
|
|
case "slider":
|
|
|
|
element = $el("div", [
|
|
|
|
element = $el("tr", [
|
|
|
|
$el("label", { textContent: name }, [
|
|
|
|
labelCell,
|
|
|
|
|
|
|
|
$el("td", [
|
|
|
|
|
|
|
|
$el("div", {
|
|
|
|
|
|
|
|
style: {
|
|
|
|
|
|
|
|
display: "grid",
|
|
|
|
|
|
|
|
gridAutoFlow: "column",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}, [
|
|
|
|
$el("input", {
|
|
|
|
$el("input", {
|
|
|
|
type: "range",
|
|
|
|
...attrs,
|
|
|
|
value,
|
|
|
|
value,
|
|
|
|
|
|
|
|
type: "range",
|
|
|
|
oninput: (e) => {
|
|
|
|
oninput: (e) => {
|
|
|
|
setter(e.target.value);
|
|
|
|
setter(e.target.value);
|
|
|
|
e.target.nextElementSibling.value = e.target.value;
|
|
|
|
e.target.nextElementSibling.value = e.target.value;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
...attrs
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
$el("input", {
|
|
|
|
$el("input", {
|
|
|
|
type: "number",
|
|
|
|
...attrs,
|
|
|
|
value,
|
|
|
|
value,
|
|
|
|
|
|
|
|
id: htmlID,
|
|
|
|
|
|
|
|
type: "number",
|
|
|
|
|
|
|
|
style: {maxWidth: "4rem"},
|
|
|
|
oninput: (e) => {
|
|
|
|
oninput: (e) => {
|
|
|
|
setter(e.target.value);
|
|
|
|
setter(e.target.value);
|
|
|
|
e.target.previousElementSibling.value = e.target.value;
|
|
|
|
e.target.previousElementSibling.value = e.target.value;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
...attrs
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
|
|
|
|
]),
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "text":
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
console.warn("Unsupported setting type, defaulting to text");
|
|
|
|
if (type !== "text") {
|
|
|
|
element = $el("div", [
|
|
|
|
console.warn(`Unsupported setting type '${type}, defaulting to text`);
|
|
|
|
$el("label", { textContent: name || id }, [
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element = $el("tr", [
|
|
|
|
|
|
|
|
labelCell,
|
|
|
|
|
|
|
|
$el("td", [
|
|
|
|
$el("input", {
|
|
|
|
$el("input", {
|
|
|
|
value,
|
|
|
|
value,
|
|
|
|
|
|
|
|
id: htmlID,
|
|
|
|
oninput: (e) => {
|
|
|
|
oninput: (e) => {
|
|
|
|
setter(e.target.value);
|
|
|
|
setter(e.target.value);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
...attrs
|
|
|
|
...attrs,
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
]);
|
|
|
|
]);
|
|
|
@ -330,13 +386,16 @@ class ComfySettingsDialog extends ComfyDialog {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
show() {
|
|
|
|
show() {
|
|
|
|
super.show();
|
|
|
|
this.textElement.replaceChildren(
|
|
|
|
Object.assign(this.textElement.style, {
|
|
|
|
$el("tr", {
|
|
|
|
display: "flex",
|
|
|
|
style: {display: "none"},
|
|
|
|
flexDirection: "column",
|
|
|
|
}, [
|
|
|
|
gap: "10px"
|
|
|
|
$el("th"),
|
|
|
|
});
|
|
|
|
$el("th", {style: {width: "33%"}})
|
|
|
|
this.textElement.replaceChildren(...this.settings.map((s) => s.render()));
|
|
|
|
]),
|
|
|
|
|
|
|
|
...this.settings.map((s) => s.render()),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
this.element.showModal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -475,8 +534,8 @@ export class ComfyUI {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
const previewImage = this.settings.addSetting({
|
|
|
|
const previewImage = this.settings.addSetting({
|
|
|
|
id: "Comfy.PreviewFormat",
|
|
|
|
id: "Comfy.PreviewFormat",
|
|
|
|
name: "When displaying a preview in the image widget, convert it to a lightweight image. (webp, jpeg, webp;50, ...)",
|
|
|
|
name: "When displaying a preview in the image widget, convert it to a lightweight image, e.g. webp, jpeg, webp;50, etc.",
|
|
|
|
type: "string",
|
|
|
|
type: "text",
|
|
|
|
defaultValue: "",
|
|
|
|
defaultValue: "",
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
@ -492,7 +551,14 @@ export class ComfyUI {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.menuContainer = $el("div.comfy-menu", {parent: document.body}, [
|
|
|
|
this.menuContainer = $el("div.comfy-menu", {parent: document.body}, [
|
|
|
|
$el("div.drag-handle", { style: { overflow: "hidden", position: "relative", width: "100%", cursor: "default" } }, [
|
|
|
|
$el("div.drag-handle", {
|
|
|
|
|
|
|
|
style: {
|
|
|
|
|
|
|
|
overflow: "hidden",
|
|
|
|
|
|
|
|
position: "relative",
|
|
|
|
|
|
|
|
width: "100%",
|
|
|
|
|
|
|
|
cursor: "default"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}, [
|
|
|
|
$el("span.drag-handle"),
|
|
|
|
$el("span.drag-handle"),
|
|
|
|
$el("span", {$: (q) => (this.queueSize = q)}),
|
|
|
|
$el("span", {$: (q) => (this.queueSize = q)}),
|
|
|
|
$el("button.comfy-settings-btn", {textContent: "⚙️", onclick: () => this.settings.show()}),
|
|
|
|
$el("button.comfy-settings-btn", {textContent: "⚙️", onclick: () => this.settings.show()}),
|
|
|
@ -547,7 +613,11 @@ export class ComfyUI {
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
$el("div.comfy-menu-btns", [
|
|
|
|
$el("div.comfy-menu-btns", [
|
|
|
|
$el("button", { id: "queue-front-button", textContent: "Queue Front", onclick: () => app.queuePrompt(-1, this.batchCount) }),
|
|
|
|
$el("button", {
|
|
|
|
|
|
|
|
id: "queue-front-button",
|
|
|
|
|
|
|
|
textContent: "Queue Front",
|
|
|
|
|
|
|
|
onclick: () => app.queuePrompt(-1, this.batchCount)
|
|
|
|
|
|
|
|
}),
|
|
|
|
$el("button", {
|
|
|
|
$el("button", {
|
|
|
|
$: (b) => (this.queue.button = b),
|
|
|
|
$: (b) => (this.queue.button = b),
|
|
|
|
id: "comfy-view-queue-button",
|
|
|
|
id: "comfy-view-queue-button",
|
|
|
@ -598,19 +668,27 @@ export class ComfyUI {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
$el("button", {id: "comfy-load-button", textContent: "Load", onclick: () => fileInput.click()}),
|
|
|
|
$el("button", {id: "comfy-load-button", textContent: "Load", onclick: () => fileInput.click()}),
|
|
|
|
$el("button", { id: "comfy-refresh-button", textContent: "Refresh", onclick: () => app.refreshComboInNodes() }),
|
|
|
|
$el("button", {
|
|
|
|
|
|
|
|
id: "comfy-refresh-button",
|
|
|
|
|
|
|
|
textContent: "Refresh",
|
|
|
|
|
|
|
|
onclick: () => app.refreshComboInNodes()
|
|
|
|
|
|
|
|
}),
|
|
|
|
$el("button", {id: "comfy-clipspace-button", textContent: "Clipspace", onclick: () => app.openClipspace()}),
|
|
|
|
$el("button", {id: "comfy-clipspace-button", textContent: "Clipspace", onclick: () => app.openClipspace()}),
|
|
|
|
$el("button", { id: "comfy-clear-button", textContent: "Clear", onclick: () => {
|
|
|
|
$el("button", {
|
|
|
|
|
|
|
|
id: "comfy-clear-button", textContent: "Clear", onclick: () => {
|
|
|
|
if (!confirmClear.value || confirm("Clear workflow?")) {
|
|
|
|
if (!confirmClear.value || confirm("Clear workflow?")) {
|
|
|
|
app.clean();
|
|
|
|
app.clean();
|
|
|
|
app.graph.clear();
|
|
|
|
app.graph.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}),
|
|
|
|
}
|
|
|
|
$el("button", { id: "comfy-load-default-button", textContent: "Load Default", onclick: () => {
|
|
|
|
}),
|
|
|
|
|
|
|
|
$el("button", {
|
|
|
|
|
|
|
|
id: "comfy-load-default-button", textContent: "Load Default", onclick: () => {
|
|
|
|
if (!confirmClear.value || confirm("Load default workflow?")) {
|
|
|
|
if (!confirmClear.value || confirm("Load default workflow?")) {
|
|
|
|
app.loadGraphData()
|
|
|
|
app.loadGraphData()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}),
|
|
|
|
}
|
|
|
|
|
|
|
|
}),
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
dragElement(this.menuContainer, this.settings);
|
|
|
|
dragElement(this.menuContainer, this.settings);
|
|
|
|