(`input[type="checkbox"][id="${item.key}"]`, {
parent: container,
checked: initialValue,
});
} else {
input = $el(`input[id="${item.key}"]`, {
parent: container,
value: initialValue,
});
}
$el("div.fieldrow-value", { children: [input], parent: container });
return container;
}
/**
* A dialog to edit rgthree-comfy settings and config.
*/
export class RgthreeConfigDialog extends RgthreeDialog {
constructor() {
const content = $el("div");
content.appendChild(RgthreeConfigDialog.buildFieldset(CONFIGURABLE["features"]!, "Features"));
content.appendChild(RgthreeConfigDialog.buildFieldset(CONFIGURABLE["menus"]!, "Menus"));
content.appendChild(RgthreeConfigDialog.buildFieldset(CONFIGURABLE["groups"]!, "Groups"));
content.appendChild(RgthreeConfigDialog.buildFieldset(CONFIGURABLE["advanced"]!, "Advanced"));
content.addEventListener("input", (e) => {
const changed = this.getChangedFormData();
($$(".save-button", this.element)[0] as HTMLButtonElement).disabled =
!Object.keys(changed).length;
});
content.addEventListener("change", (e) => {
const changed = this.getChangedFormData();
($$(".save-button", this.element)[0] as HTMLButtonElement).disabled =
!Object.keys(changed).length;
});
const dialogOptions: RgthreeDialogOptions = {
class: "-iconed -settings",
title: logoRgthree + `Settings - rgthree-comfy
`,
content,
onBeforeClose: () => {
const changed = this.getChangedFormData();
if (Object.keys(changed).length) {
return confirm("Looks like there are unsaved changes. Are you sure you want close?");
}
return true;
},
buttons: [
{
label: "Save",
disabled: true,
className: "rgthree-button save-button -blue",
callback: async (e) => {
const changed = this.getChangedFormData();
if (!Object.keys(changed).length) {
this.close();
return;
}
const success = await CONFIG_SERVICE.setConfigValues(changed);
if (success) {
for (const key of Object.keys(changed)) {
Object.values(CONFIGURABLE)
.flat()
.find((f) => f.key === key)
?.onSave?.(changed[key]);
}
this.close();
rgthree.showMessage({
id: "config-success",
message: `${checkmark} Successfully saved rgthree-comfy settings!`,
timeout: 4000,
});
($$(".save-button", this.element)[0] as HTMLButtonElement).disabled = true;
} else {
alert("There was an error saving rgthree-comfy configuration.");
}
},
},
],
};
super(dialogOptions);
}
private static buildFieldset(datas: ConfigurationSchema[], label: string) {
const fieldset = $el(`fieldset`, { children: [$el(`legend[text="${label}"]`)] });
for (const data of datas) {
if (data.isDevOnly && !rgthree.isDevMode()) {
continue;
}
const container = $el("div.formrow");
container.appendChild(fieldrow(data));
if (data.subconfig) {
for (const subfeature of data.subconfig) {
container.appendChild(fieldrow(subfeature));
}
}
fieldset.appendChild(container);
}
return fieldset;
}
getChangedFormData() {
return $$("[data-name]", this.contentElement).reduce((acc: { [key: string]: any }, el) => {
const name = el.dataset["name"]!;
const type = el.dataset["type"]!;
const initialValue = CONFIG_SERVICE.getConfigValue(name);
let currentValueEl = $$("input, textarea, select", el)[0] as HTMLInputElement;
let currentValue: any = null;
if (type === String(ConfigType.BOOLEAN)) {
currentValue = currentValueEl.checked;
// Not sure I like this side effect in here, but it's easy to just do it now.
el.classList.toggle("-checked", currentValue);
} else {
currentValue = currentValueEl?.value;
if (currentValueEl.nodeName === "SELECT") {
currentValue = JSON.parse(currentValue).value;
} else if (type === String(ConfigType.NUMBER)) {
currentValue = Number(currentValue) || initialValue;
}
}
if (JSON.stringify(currentValue) !== JSON.stringify(initialValue)) {
acc[name] = currentValue;
}
return acc;
}, {});
}
}
app.ui.settings.addSetting({
id: "rgthree.config",
name: "Open rgthree-comfy config",
type: () => {
// Adds a row to open the dialog from the ComfyUI settings.
return $el("tr.rgthree-comfyui-settings-row", {
children: [
$el("td", {
child: `${logoRgthree} [rgthree-comfy] configuration / settings
`,
}),
$el("td", {
child: $el('button.rgthree-button.-blue[text="rgthree-comfy settings"]', {
events: {
click: (e: PointerEvent) => {
new RgthreeConfigDialog().show();
},
},
}),
}),
],
});
},
});