mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-08 00:50:05 +00:00
Rename to ts (#92)
Rename Remove ts-nocheck, fix errors Update state when graph cleared via UI (#88) Convert to ts, fix imports Co-authored-by: pythongosssss <125205205+pythongosssss@users.noreply.github.com>
This commit is contained in:
@@ -20,9 +20,9 @@ import {
|
||||
parseComfyWorkflow,
|
||||
} from "../types/comfyWorkflow";
|
||||
import { ComfyNodeDef } from "/types/apiTypes";
|
||||
import { ComfyAppMenu } from "./ui/menu/index.js";
|
||||
import { getStorageValue, setStorageValue } from "./utils.js";
|
||||
import { ComfyWorkflowManager } from "./workflows.js";
|
||||
import { ComfyAppMenu } from "./ui/menu/index";
|
||||
import { getStorageValue } from "./utils";
|
||||
import { ComfyWorkflowManager, ComfyWorkflow } from "./workflows";
|
||||
import {
|
||||
LGraphCanvas,
|
||||
LGraph,
|
||||
@@ -2179,16 +2179,11 @@ export class ComfyApp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the graph with the specified workflow data
|
||||
* @param {*} graphData A serialized graph object
|
||||
* @param { boolean } clean If the graph state, e.g. images, should be cleared
|
||||
*/
|
||||
async loadGraphData(
|
||||
graphData?: ComfyWorkflowJSON,
|
||||
clean: boolean = true,
|
||||
restore_view: boolean = true,
|
||||
workflow: string | null = null
|
||||
workflow: string | null | ComfyWorkflow = null
|
||||
) {
|
||||
if (clean !== false) {
|
||||
this.clean();
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import type { ComfyApp } from "./app";
|
||||
import { api } from "./api";
|
||||
import { clone } from "./utils";
|
||||
import { LGraphCanvas, LiteGraph } from "@comfyorg/litegraph";
|
||||
import { ComfyWorkflow } from "./workflows";
|
||||
|
||||
export class ChangeTracker {
|
||||
static MAX_HISTORY = 50;
|
||||
#app;
|
||||
#app: ComfyApp;
|
||||
undo = [];
|
||||
redo = [];
|
||||
activeState = null;
|
||||
isOurLoad = false;
|
||||
/** @type { import("./workflows").ComfyWorkflow | null } */
|
||||
workflow;
|
||||
workflow: ComfyWorkflow | null;
|
||||
|
||||
ds;
|
||||
nodeOutputs;
|
||||
ds: { scale: number; offset: [number, number]; };
|
||||
nodeOutputs: any;
|
||||
|
||||
get app() {
|
||||
return this.#app ?? this.workflow.manager.app;
|
||||
}
|
||||
|
||||
constructor(workflow) {
|
||||
constructor(workflow: ComfyWorkflow) {
|
||||
this.workflow = workflow;
|
||||
}
|
||||
|
||||
@@ -90,8 +89,7 @@ export class ChangeTracker {
|
||||
}
|
||||
}
|
||||
|
||||
/** @param { import("./app").ComfyApp } app */
|
||||
static init(app) {
|
||||
static init(app: ComfyApp) {
|
||||
const changeTracker = () =>
|
||||
app.workflowManager.activeWorkflow?.changeTracker ?? globalTracker;
|
||||
globalTracker.#setApp(app);
|
||||
@@ -137,7 +135,7 @@ export class ChangeTracker {
|
||||
if (await changeTracker().undoRedo(e)) return;
|
||||
|
||||
// If our active element is some type of input then handle changes after they're done
|
||||
if (ChangeTracker.bindInput(activeEl)) return;
|
||||
if (ChangeTracker.bindInput(app, activeEl)) return;
|
||||
changeTracker().checkState();
|
||||
});
|
||||
},
|
||||
@@ -277,4 +275,4 @@ export class ChangeTracker {
|
||||
}
|
||||
}
|
||||
|
||||
const globalTracker = new ChangeTracker({});
|
||||
const globalTracker = new ChangeTracker({} as ComfyWorkflow);
|
||||
@@ -24,11 +24,15 @@ type Props = {
|
||||
|
||||
type Children = Element[] | Element | string | string[];
|
||||
|
||||
export function $el(
|
||||
tag: string,
|
||||
type ElementType<K extends string> = K extends keyof HTMLElementTagNameMap
|
||||
? HTMLElementTagNameMap[K]
|
||||
: HTMLElement;
|
||||
|
||||
export function $el<TTag extends string>(
|
||||
tag: TTag,
|
||||
propsOrChildren?: Children | Props,
|
||||
children?: Children
|
||||
): HTMLElement {
|
||||
): ElementType<TTag> {
|
||||
const split = tag.split(".");
|
||||
const element = document.createElement(split.shift() as string);
|
||||
if (split.length > 0) {
|
||||
@@ -78,10 +82,10 @@ export function $el(
|
||||
}
|
||||
}
|
||||
}
|
||||
return element;
|
||||
return element as ElementType<TTag>;
|
||||
}
|
||||
|
||||
function dragElement(dragEl, settings) {
|
||||
function dragElement(dragEl, settings): () => void {
|
||||
var posDiffX = 0,
|
||||
posDiffY = 0,
|
||||
posStartX = 0,
|
||||
@@ -340,6 +344,8 @@ export class ComfyUI {
|
||||
menuHamburger: HTMLDivElement;
|
||||
menuContainer: HTMLDivElement;
|
||||
queueSize: Element;
|
||||
restoreMenuPosition: () => void;
|
||||
loadFile: () => void;
|
||||
|
||||
constructor(app) {
|
||||
this.app = app;
|
||||
@@ -425,7 +431,6 @@ export class ComfyUI {
|
||||
},
|
||||
}) as HTMLInputElement;
|
||||
|
||||
// @ts-ignore
|
||||
this.loadFile = () => fileInput.click();
|
||||
|
||||
const autoQueueModeEl = toggleSwitch(
|
||||
@@ -740,7 +745,6 @@ export class ComfyUI {
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
this.restoreMenuPosition = dragElement(this.menuContainer, this.settings);
|
||||
|
||||
this.setStatus({ exec_info: { queue_remaining: "X" } });
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ComfyDialog } from "../dialog";
|
||||
import { $el } from "../../ui";
|
||||
|
||||
export class ComfyAsyncDialog extends ComfyDialog {
|
||||
#resolve;
|
||||
export class ComfyAsyncDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
#resolve: (value: any) => void;
|
||||
|
||||
constructor(actions) {
|
||||
constructor(actions?: Array<string | { value?: any; text: string }>) {
|
||||
super(
|
||||
"dialog.comfy-dialog.comfyui-dialog",
|
||||
actions?.map((opt) => {
|
||||
@@ -20,7 +20,7 @@ export class ComfyAsyncDialog extends ComfyDialog {
|
||||
);
|
||||
}
|
||||
|
||||
show(html) {
|
||||
show(html: string | HTMLElement | HTMLElement[]) {
|
||||
this.element.addEventListener("close", () => {
|
||||
this.close();
|
||||
});
|
||||
@@ -32,7 +32,7 @@ export class ComfyAsyncDialog extends ComfyDialog {
|
||||
});
|
||||
}
|
||||
|
||||
showModal(html) {
|
||||
showModal(html: string | HTMLElement | HTMLElement[]) {
|
||||
this.element.addEventListener("close", () => {
|
||||
this.close();
|
||||
});
|
||||
@@ -1,37 +1,41 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { $el } from "../../ui";
|
||||
import { applyClasses, toggleElement } from "../utils";
|
||||
import { applyClasses, ClassList, toggleElement } from "../utils";
|
||||
import { prop } from "../../utils";
|
||||
import type { ComfyPopup } from "./popup";
|
||||
import type { ComfyComponent } from ".";
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* icon?: string;
|
||||
* overIcon?: string;
|
||||
* iconSize?: number;
|
||||
* content?: string | HTMLElement;
|
||||
* tooltip?: string;
|
||||
* enabled?: boolean;
|
||||
* action?: (e: Event, btn: ComfyButton) => void,
|
||||
* classList?: import("../utils").ClassList,
|
||||
* visibilitySetting?: { id: string, showValue: any },
|
||||
* app?: import("../../app").ComfyApp
|
||||
* }} ComfyButtonProps
|
||||
*/
|
||||
export class ComfyButton {
|
||||
type ComfyButtonProps = {
|
||||
icon?: string;
|
||||
overIcon?: string;
|
||||
iconSize?: number;
|
||||
content?: string | HTMLElement;
|
||||
tooltip?: string;
|
||||
enabled?: boolean;
|
||||
action?: (e: Event, btn: ComfyButton) => void;
|
||||
classList?: ClassList;
|
||||
visibilitySetting?: { id: string; showValue: any };
|
||||
app?: ComfyApp;
|
||||
};
|
||||
|
||||
export class ComfyButton implements ComfyComponent<HTMLElement> {
|
||||
#over = 0;
|
||||
#popupOpen = false;
|
||||
isOver = false;
|
||||
iconElement = $el("i.mdi");
|
||||
contentElement = $el("span");
|
||||
/**
|
||||
* @type {import("./popup").ComfyPopup}
|
||||
*/
|
||||
popup;
|
||||
popup: ComfyPopup;
|
||||
element: HTMLElement;
|
||||
overIcon: string;
|
||||
iconSize: number;
|
||||
content: string | HTMLElement;
|
||||
icon: string;
|
||||
tooltip: string;
|
||||
classList: ClassList;
|
||||
hidden: boolean;
|
||||
enabled: boolean;
|
||||
action: (e: Event, btn: ComfyButton) => void;
|
||||
|
||||
/**
|
||||
* @param {ComfyButtonProps} opts
|
||||
*/
|
||||
constructor({
|
||||
icon,
|
||||
overIcon,
|
||||
@@ -43,7 +47,7 @@ export class ComfyButton {
|
||||
visibilitySetting,
|
||||
app,
|
||||
enabled = true,
|
||||
}) {
|
||||
}: ComfyButtonProps) {
|
||||
this.element = $el(
|
||||
"button",
|
||||
{
|
||||
@@ -101,7 +105,7 @@ export class ComfyButton {
|
||||
this.hidden = prop(this, "hidden", false, this.updateClasses);
|
||||
this.enabled = prop(this, "enabled", enabled, () => {
|
||||
this.updateClasses();
|
||||
this.element.disabled = !this.enabled;
|
||||
(this.element as HTMLButtonElement).disabled = !this.enabled;
|
||||
});
|
||||
this.action = prop(this, "action", action);
|
||||
this.element.addEventListener("click", (e) => {
|
||||
@@ -148,12 +152,7 @@ export class ComfyButton {
|
||||
applyClasses(this.element, this.classList, ...internalClasses);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param { import("./popup").ComfyPopup } popup
|
||||
* @param { "click" | "hover" } mode
|
||||
*/
|
||||
withPopup(popup, mode = "click") {
|
||||
withPopup(popup: ComfyPopup, mode: "click" | "hover" = "click") {
|
||||
this.popup = popup;
|
||||
|
||||
if (mode === "hover") {
|
||||
@@ -1,34 +1,26 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { $el } from "../../ui";
|
||||
import { ComfyButton } from "./button";
|
||||
import { prop } from "../../utils";
|
||||
|
||||
export class ComfyButtonGroup {
|
||||
element = $el("div.comfyui-button-group");
|
||||
buttons: (HTMLElement | ComfyButton)[];
|
||||
|
||||
/** @param {Array<ComfyButton | HTMLElement>} buttons */
|
||||
constructor(...buttons) {
|
||||
constructor(...buttons: (HTMLElement | ComfyButton)[]) {
|
||||
this.buttons = prop(this, "buttons", buttons, () => this.update());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ComfyButton} button
|
||||
* @param {number} index
|
||||
*/
|
||||
insert(button, index) {
|
||||
insert(button: ComfyButton, index: number) {
|
||||
this.buttons.splice(index, 0, button);
|
||||
this.update();
|
||||
}
|
||||
|
||||
/** @param {ComfyButton} button */
|
||||
append(button) {
|
||||
append(button: ComfyButton) {
|
||||
this.buttons.push(button);
|
||||
this.update();
|
||||
}
|
||||
|
||||
/** @param {ComfyButton|number} indexOrButton */
|
||||
remove(indexOrButton) {
|
||||
remove(indexOrButton: ComfyButton | number) {
|
||||
if (typeof indexOrButton !== "number") {
|
||||
indexOrButton = this.buttons.indexOf(indexOrButton);
|
||||
}
|
||||
3
src/scripts/ui/components/index.ts
Normal file
3
src/scripts/ui/components/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface ComfyComponent<T extends HTMLElement = HTMLElement> {
|
||||
element: T;
|
||||
}
|
||||
@@ -1,24 +1,19 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { prop } from "../../utils";
|
||||
import { $el } from "../../ui";
|
||||
import { applyClasses } from "../utils";
|
||||
import { applyClasses, ClassList } from "../utils";
|
||||
|
||||
export class ComfyPopup extends EventTarget {
|
||||
element = $el("div.comfyui-popup");
|
||||
open: boolean;
|
||||
children: HTMLElement[];
|
||||
target: HTMLElement;
|
||||
ignoreTarget: boolean;
|
||||
container: HTMLElement;
|
||||
position: string;
|
||||
closeOnEscape: boolean;
|
||||
horizontal: string;
|
||||
classList: ClassList;
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* target: HTMLElement,
|
||||
* container?: HTMLElement,
|
||||
* classList?: import("../utils").ClassList,
|
||||
* ignoreTarget?: boolean,
|
||||
* closeOnEscape?: boolean,
|
||||
* position?: "absolute" | "relative",
|
||||
* horizontal?: "left" | "right"
|
||||
* }} param0
|
||||
* @param {...HTMLElement} children
|
||||
*/
|
||||
constructor(
|
||||
{
|
||||
target,
|
||||
@@ -28,8 +23,16 @@ export class ComfyPopup extends EventTarget {
|
||||
closeOnEscape = true,
|
||||
position = "absolute",
|
||||
horizontal = "left",
|
||||
}: {
|
||||
target: HTMLElement;
|
||||
container?: HTMLElement;
|
||||
classList?: ClassList;
|
||||
ignoreTarget?: boolean;
|
||||
closeOnEscape?: boolean;
|
||||
position?: "absolute" | "relative";
|
||||
horizontal?: "left" | "right";
|
||||
},
|
||||
...children
|
||||
...children: HTMLElement[]
|
||||
) {
|
||||
super();
|
||||
this.target = target;
|
||||
@@ -1,23 +1,27 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { $el } from "../../ui";
|
||||
import { ComfyButton } from "./button";
|
||||
import { prop } from "../../utils";
|
||||
import { ComfyPopup } from "./popup";
|
||||
|
||||
export class ComfySplitButton {
|
||||
/**
|
||||
* @param {{
|
||||
* primary: ComfyButton,
|
||||
* mode?: "hover" | "click",
|
||||
* horizontal?: "left" | "right",
|
||||
* position?: "relative" | "absolute"
|
||||
* }} param0
|
||||
* @param {Array<ComfyButton> | Array<HTMLElement>} items
|
||||
*/
|
||||
arrow: ComfyButton;
|
||||
element: HTMLElement;
|
||||
popup: ComfyPopup;
|
||||
items: Array<HTMLElement | ComfyButton>;
|
||||
|
||||
constructor(
|
||||
{ primary, mode, horizontal = "left", position = "relative" },
|
||||
...items
|
||||
{
|
||||
primary,
|
||||
mode,
|
||||
horizontal = "left",
|
||||
position = "relative",
|
||||
}: {
|
||||
primary: ComfyButton;
|
||||
mode?: "hover" | "click";
|
||||
horizontal?: "left" | "right";
|
||||
position?: "relative" | "absolute";
|
||||
},
|
||||
...items: Array<HTMLElement | ComfyButton>
|
||||
) {
|
||||
this.arrow = new ComfyButton({
|
||||
icon: "chevron-down",
|
||||
@@ -46,7 +50,7 @@ export class ComfySplitButton {
|
||||
|
||||
update() {
|
||||
this.popup.element.replaceChildren(
|
||||
...this.items.map((b) => b.element ?? b)
|
||||
...this.items.map((b) => ("element" in b ? b.element : b))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
import { api } from "../../api";
|
||||
import { $el } from "../../ui";
|
||||
import { downloadBlob } from "../../utils";
|
||||
@@ -12,6 +11,9 @@ import { ComfyWorkflowsMenu } from "./workflows";
|
||||
import { ComfyViewQueueButton } from "./viewQueue";
|
||||
import { getInteruptButton } from "./interruptButton";
|
||||
import "./menu.css";
|
||||
import type { ComfySettingsDialog } from "../settings";
|
||||
|
||||
type MenuPosition = "Disabled" | "Top" | "Bottom";
|
||||
|
||||
const collapseOnMobile = (t) => {
|
||||
(t.element ?? t).classList.add("comfyui-menu-mobile-collapse");
|
||||
@@ -33,15 +35,23 @@ export class ComfyAppMenu {
|
||||
#sizeBreaks = Object.keys(this.#lastSizeBreaks);
|
||||
#cachedInnerSize = null;
|
||||
#cacheTimeout = null;
|
||||
app: ComfyApp;
|
||||
workflows: ComfyWorkflowsMenu;
|
||||
logo: HTMLElement;
|
||||
saveButton: ComfySplitButton;
|
||||
actionsGroup: ComfyButtonGroup;
|
||||
settingsGroup: ComfyButtonGroup;
|
||||
viewGroup: ComfyButtonGroup;
|
||||
mobileMenuButton: ComfyButton;
|
||||
element: HTMLElement;
|
||||
menuPositionSetting: ReturnType<ComfySettingsDialog["addSetting"]>;
|
||||
position: MenuPosition;
|
||||
|
||||
/**
|
||||
* @param { import("../../app").ComfyApp } app
|
||||
*/
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
this.app = app;
|
||||
|
||||
this.workflows = new ComfyWorkflowsMenu(app);
|
||||
const getSaveButton = (t) =>
|
||||
const getSaveButton = (t?: string) =>
|
||||
new ComfyButton({
|
||||
icon: "content-save",
|
||||
tooltip: "Save the current workflow",
|
||||
@@ -158,14 +168,14 @@ export class ComfyAppMenu {
|
||||
showOnMobile(this.mobileMenuButton).element,
|
||||
]);
|
||||
|
||||
let resizeHandler;
|
||||
let resizeHandler: () => void;
|
||||
this.menuPositionSetting = app.ui.settings.addSetting({
|
||||
id: "Comfy.UseNewMenu",
|
||||
defaultValue: "Disabled",
|
||||
name: "[Beta] Use new menu and workflow management. Note: On small screens the menu will always be at the top.",
|
||||
type: "combo",
|
||||
options: ["Disabled", "Top", "Bottom"],
|
||||
onChange: async (v) => {
|
||||
onChange: async (v: MenuPosition) => {
|
||||
if (v && v !== "Disabled") {
|
||||
if (!resizeHandler) {
|
||||
resizeHandler = () => {
|
||||
@@ -189,7 +199,7 @@ export class ComfyAppMenu {
|
||||
});
|
||||
}
|
||||
|
||||
updatePosition(v) {
|
||||
updatePosition(v: MenuPosition) {
|
||||
document.body.style.display = "grid";
|
||||
this.app.ui.menuContainer.style.display = "none";
|
||||
this.element.style.removeProperty("display");
|
||||
@@ -202,7 +212,7 @@ export class ComfyAppMenu {
|
||||
this.calculateSizeBreak();
|
||||
}
|
||||
|
||||
updateSizeBreak(idx, prevIdx, direction) {
|
||||
updateSizeBreak(idx: number, prevIdx: number, direction: number) {
|
||||
const newSize = this.#sizeBreaks[idx];
|
||||
if (newSize === this.#sizeBreak) return;
|
||||
this.#cachedInnerSize = null;
|
||||
@@ -264,7 +274,7 @@ export class ComfyAppMenu {
|
||||
this.updateSizeBreak(idx, currIdx, direction);
|
||||
}
|
||||
|
||||
calculateInnerSize(idx) {
|
||||
calculateInnerSize(idx: number) {
|
||||
// Cache the inner size to prevent too much calculation when resizing the window
|
||||
clearTimeout(this.#cacheTimeout);
|
||||
if (this.#cachedInnerSize) {
|
||||
@@ -293,10 +303,7 @@ export class ComfyAppMenu {
|
||||
return this.#cachedInnerSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} defaultName
|
||||
*/
|
||||
getFilename(defaultName) {
|
||||
getFilename(defaultName: string) {
|
||||
if (this.app.ui.settings.getSettingValue("Comfy.PromptFilename", true)) {
|
||||
defaultName = prompt("Save workflow as:", defaultName);
|
||||
if (!defaultName) return;
|
||||
@@ -307,11 +314,10 @@ export class ComfyAppMenu {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [filename]
|
||||
* @param { "workflow" | "output" } [promptProperty]
|
||||
*/
|
||||
async exportWorkflow(filename, promptProperty) {
|
||||
async exportWorkflow(
|
||||
filename: string,
|
||||
promptProperty: "workflow" | "output"
|
||||
) {
|
||||
if (this.app.workflowManager.activeWorkflow?.path) {
|
||||
filename = this.app.workflowManager.activeWorkflow.name;
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { api } from "../../api";
|
||||
import { ComfyButton } from "../components/button";
|
||||
|
||||
export function getInteruptButton(visibility) {
|
||||
export function getInteruptButton(visibility: string) {
|
||||
const btn = new ComfyButton({
|
||||
icon: "close",
|
||||
tooltip: "Cancel current generation",
|
||||
@@ -1,17 +1,16 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ComfyButton } from "../components/button";
|
||||
import { $el } from "../../ui";
|
||||
import { api } from "../../api";
|
||||
import { ComfySplitButton } from "../components/splitButton";
|
||||
import { ComfyQueueOptions } from "./queueOptions";
|
||||
import { prop } from "../../utils";
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
|
||||
export class ComfyQueueButton {
|
||||
element = $el("div.comfyui-queue-button");
|
||||
#internalQueueSize = 0;
|
||||
|
||||
queuePrompt = async (e) => {
|
||||
queuePrompt = async (e?: MouseEvent) => {
|
||||
this.#internalQueueSize += this.queueOptions.batchCount;
|
||||
// Hold shift to queue front, event is undefined when auto-queue is enabled
|
||||
await this.app.queuePrompt(
|
||||
@@ -19,8 +18,13 @@ export class ComfyQueueButton {
|
||||
this.queueOptions.batchCount
|
||||
);
|
||||
};
|
||||
queueOptions: ComfyQueueOptions;
|
||||
app: ComfyApp;
|
||||
queueSizeElement: HTMLElement;
|
||||
autoQueueMode: string;
|
||||
graphHasChanged: boolean;
|
||||
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
this.app = app;
|
||||
this.queueSizeElement = $el("span.comfyui-queue-count", {
|
||||
textContent: "?",
|
||||
@@ -1,12 +1,17 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
import { $el } from "../../ui";
|
||||
import { prop } from "../../utils";
|
||||
|
||||
export class ComfyQueueOptions extends EventTarget {
|
||||
element = $el("div.comfyui-queue-options");
|
||||
app: ComfyApp;
|
||||
batchCountInput: HTMLInputElement;
|
||||
batchCount: number;
|
||||
batchCountRange: HTMLInputElement;
|
||||
autoQueueMode: string;
|
||||
autoQueueEl: HTMLElement;
|
||||
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
super();
|
||||
this.app = app;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
import { ComfyButton } from "../components/button";
|
||||
import { ComfyViewList, ComfyViewListButton } from "./viewList";
|
||||
|
||||
export class ComfyViewHistoryButton extends ComfyViewListButton {
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
super(app, {
|
||||
button: new ComfyButton({
|
||||
content: "View History",
|
||||
@@ -1,11 +1,18 @@
|
||||
// @ts-nocheck
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -14,10 +21,20 @@ export class ComfyViewListButton {
|
||||
this.popup.open = open;
|
||||
}
|
||||
|
||||
constructor(app, { button, list, mode }) {
|
||||
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);
|
||||
this.element = $el(
|
||||
"div.comfyui-button-wrapper",
|
||||
this.button.element
|
||||
) as HTMLDivElement;
|
||||
this.popup = new ComfyPopup({
|
||||
target: this.element,
|
||||
container: this.element,
|
||||
@@ -42,9 +59,15 @@ export class ComfyViewListButton {
|
||||
}
|
||||
|
||||
export class ComfyViewList {
|
||||
popup;
|
||||
|
||||
constructor(app, mode, popup) {
|
||||
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;
|
||||
@@ -1,11 +1,10 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ComfyButton } from "../components/button";
|
||||
import { ComfyViewList, ComfyViewListButton } from "./viewList";
|
||||
import { api } from "../../api";
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
|
||||
export class ComfyViewQueueButton extends ComfyViewListButton {
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
super(app, {
|
||||
button: new ComfyButton({
|
||||
content: "View Queue",
|
||||
@@ -1,5 +1,3 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { ComfyButton } from "../components/button";
|
||||
import { prop, getStorageValue, setStorageValue } from "../../utils";
|
||||
import { $el } from "../../ui";
|
||||
@@ -8,10 +6,19 @@ import { ComfyPopup } from "../components/popup";
|
||||
import { createSpinner } from "../spinner";
|
||||
import { ComfyWorkflow, trimJsonExt } from "../../workflows";
|
||||
import { ComfyAsyncDialog } from "../components/asyncDialog";
|
||||
import type { ComfyApp } from "scripts/app";
|
||||
import type { ComfyComponent } from "../components";
|
||||
|
||||
export class ComfyWorkflowsMenu {
|
||||
#first = true;
|
||||
element = $el("div.comfyui-workflows");
|
||||
popup: ComfyPopup;
|
||||
app: ComfyApp;
|
||||
buttonProgress: HTMLElement;
|
||||
workflowLabel: HTMLElement;
|
||||
button: ComfyButton;
|
||||
content: ComfyWorkflowsContent;
|
||||
unsaved: boolean;
|
||||
|
||||
get open() {
|
||||
return this.popup.open;
|
||||
@@ -21,10 +28,7 @@ export class ComfyWorkflowsMenu {
|
||||
this.popup.open = open;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../../app").ComfyApp} app
|
||||
*/
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
this.app = app;
|
||||
this.#bindEvents();
|
||||
|
||||
@@ -158,10 +162,7 @@ export class ComfyWorkflowsMenu {
|
||||
return menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../../app").ComfyApp} app
|
||||
*/
|
||||
registerExtension(app) {
|
||||
registerExtension(app: ComfyApp) {
|
||||
const self = this;
|
||||
app.registerExtension({
|
||||
name: "Comfy.Workflows",
|
||||
@@ -192,11 +193,10 @@ export class ComfyWorkflowsMenu {
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLImageElement} img
|
||||
* @param {ComfyWorkflow} workflow
|
||||
*/
|
||||
async function sendToWorkflow(img, workflow) {
|
||||
async function sendToWorkflow(
|
||||
img: HTMLImageElement,
|
||||
workflow: ComfyWorkflow
|
||||
) {
|
||||
await workflow.load();
|
||||
let options = [];
|
||||
const nodes = app.graph.computeExecutionOrder(false);
|
||||
@@ -226,22 +226,23 @@ export class ComfyWorkflowsMenu {
|
||||
}
|
||||
|
||||
const getExtraMenuOptions = nodeType.prototype["getExtraMenuOptions"];
|
||||
nodeType.prototype["getExtraMenuOptions"] = function (_, options) {
|
||||
nodeType.prototype["getExtraMenuOptions"] = function (
|
||||
this: { imageIndex?: number; overIndex?: number; imgs: string[] },
|
||||
_,
|
||||
options
|
||||
) {
|
||||
const r = getExtraMenuOptions?.apply?.(this, arguments);
|
||||
if (
|
||||
app.ui.settings.getSettingValue("Comfy.UseNewMenu", false) === true
|
||||
) {
|
||||
const t =
|
||||
/** @type { {imageIndex?: number, overIndex?: number, imgs: string[]} } */ /** @type {any} */ (
|
||||
this
|
||||
);
|
||||
const t = this;
|
||||
let img;
|
||||
if (t.imageIndex != null) {
|
||||
// An image is selected so select that
|
||||
img = t.imgs?.[t.imageIndex];
|
||||
} else if (t.overIndex != null) {
|
||||
// No image is selected but one is hovered
|
||||
img = t.img?.s[t.overIndex];
|
||||
img = t.imgs?.[t.overIndex];
|
||||
}
|
||||
|
||||
if (img) {
|
||||
@@ -283,17 +284,20 @@ export class ComfyWorkflowsMenu {
|
||||
export class ComfyWorkflowsContent {
|
||||
element = $el("div.comfyui-workflows-panel");
|
||||
treeState = {};
|
||||
treeFiles = {};
|
||||
/** @type { Map<ComfyWorkflow, WorkflowElement> } */
|
||||
openFiles = new Map();
|
||||
/** @type {WorkflowElement} */
|
||||
activeElement = null;
|
||||
treeFiles: Record<string, WorkflowElement> = {};
|
||||
openFiles: Map<ComfyWorkflow, WorkflowElement<ComfyComponent>> = new Map();
|
||||
activeElement: WorkflowElement<ComfyComponent> = null;
|
||||
spinner: Element;
|
||||
openElement: HTMLElement;
|
||||
favoritesElement: HTMLElement;
|
||||
treeElement: HTMLElement;
|
||||
app: ComfyApp;
|
||||
popup: ComfyPopup;
|
||||
actions: HTMLElement;
|
||||
filterText: string | undefined;
|
||||
treeRoot: HTMLElement;
|
||||
|
||||
/**
|
||||
* @param {import("../../app").ComfyApp} app
|
||||
* @param {ComfyPopup} popup
|
||||
*/
|
||||
constructor(app, popup) {
|
||||
constructor(app: ComfyApp, popup: ComfyPopup) {
|
||||
this.app = app;
|
||||
this.popup = popup;
|
||||
this.actions = $el("div.comfyui-workflows-actions", [
|
||||
@@ -511,7 +515,7 @@ export class ComfyWorkflowsContent {
|
||||
$el("input", {
|
||||
placeholder: "Search",
|
||||
value: this.filterText ?? "",
|
||||
oninput: (e) => {
|
||||
oninput: (e: InputEvent) => {
|
||||
this.filterText = e.target["value"]?.trim();
|
||||
clearTimeout(typingTimeout);
|
||||
typingTimeout = setTimeout(() => this.filterTree(), 250);
|
||||
@@ -589,25 +593,21 @@ export class ComfyWorkflowsContent {
|
||||
this.activeElement.primary.element.classList.remove("mdi-play");
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getFavoriteIcon(workflow) {
|
||||
#getFavoriteIcon(workflow: ComfyWorkflow) {
|
||||
return workflow.isFavorite ? "star" : "file-outline";
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getFavoriteOverIcon(workflow) {
|
||||
#getFavoriteOverIcon(workflow: ComfyWorkflow) {
|
||||
return workflow.isFavorite ? "star-off" : "star-outline";
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getFavoriteTooltip(workflow) {
|
||||
#getFavoriteTooltip(workflow: ComfyWorkflow) {
|
||||
return workflow.isFavorite
|
||||
? "Remove this workflow from your favorites"
|
||||
: "Add this workflow to your favorites";
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getFavoriteButton(workflow, primary) {
|
||||
#getFavoriteButton(workflow: ComfyWorkflow, primary: boolean) {
|
||||
return new ComfyButton({
|
||||
icon: this.#getFavoriteIcon(workflow),
|
||||
overIcon: this.#getFavoriteOverIcon(workflow),
|
||||
@@ -623,8 +623,7 @@ export class ComfyWorkflowsContent {
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getDeleteButton(workflow) {
|
||||
#getDeleteButton(workflow: ComfyWorkflow) {
|
||||
const deleteButton = new ComfyButton({
|
||||
icon: "delete",
|
||||
tooltip: "Delete this workflow",
|
||||
@@ -650,8 +649,7 @@ export class ComfyWorkflowsContent {
|
||||
return deleteButton;
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getInsertButton(workflow) {
|
||||
#getInsertButton(workflow: ComfyWorkflow) {
|
||||
return new ComfyButton({
|
||||
icon: "file-move-outline",
|
||||
iconSize: 18,
|
||||
@@ -671,7 +669,7 @@ export class ComfyWorkflowsContent {
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getRenameButton(workflow) {
|
||||
#getRenameButton(workflow: ComfyWorkflow) {
|
||||
return new ComfyButton({
|
||||
icon: "pencil",
|
||||
tooltip: workflow.path
|
||||
@@ -690,8 +688,7 @@ export class ComfyWorkflowsContent {
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#getWorkflowElement(workflow) {
|
||||
#getWorkflowElement(workflow: ComfyWorkflow) {
|
||||
return new WorkflowElement(this, workflow, {
|
||||
primary: this.#getFavoriteButton(workflow, true),
|
||||
buttons: [
|
||||
@@ -702,8 +699,7 @@ export class ComfyWorkflowsContent {
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {ComfyWorkflow} workflow */
|
||||
#createLeafNode(workflow) {
|
||||
#createLeafNode(workflow: ComfyWorkflow) {
|
||||
const fileNode = this.#getWorkflowElement(workflow);
|
||||
this.treeFiles[workflow.path] = fileNode;
|
||||
return fileNode;
|
||||
@@ -741,12 +737,21 @@ export class ComfyWorkflowsContent {
|
||||
}
|
||||
}
|
||||
|
||||
class WorkflowElement {
|
||||
/**
|
||||
* @param { ComfyWorkflowsContent } parent
|
||||
* @param { ComfyWorkflow } workflow
|
||||
*/
|
||||
constructor(parent, workflow, { tagName = "li", primary, buttons }) {
|
||||
class WorkflowElement<TPrimary extends ComfyComponent = ComfyButton> {
|
||||
parent: ComfyWorkflowsContent;
|
||||
workflow: ComfyWorkflow;
|
||||
primary: TPrimary;
|
||||
buttons: ComfyButton[];
|
||||
element: HTMLElement;
|
||||
constructor(
|
||||
parent: ComfyWorkflowsContent,
|
||||
workflow: ComfyWorkflow,
|
||||
{
|
||||
tagName = "li",
|
||||
primary,
|
||||
buttons,
|
||||
}: { tagName?: string; primary: TPrimary; buttons: ComfyButton[] }
|
||||
) {
|
||||
this.parent = parent;
|
||||
this.workflow = workflow;
|
||||
this.primary = primary;
|
||||
@@ -770,13 +775,15 @@ class WorkflowElement {
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetSelectionDialog extends ComfyAsyncDialog {
|
||||
#options;
|
||||
type WidgetSelectionDialogOptions = Array<{
|
||||
widget: { name: string };
|
||||
node: { pos: [number, number]; title: string; id: string; type: string };
|
||||
}>;
|
||||
|
||||
/**
|
||||
* @param {Array<{widget: {name: string}, node: {pos: [number, number], title: string, id: string, type: string}}>} options
|
||||
*/
|
||||
constructor(options) {
|
||||
class WidgetSelectionDialog extends ComfyAsyncDialog {
|
||||
#options: WidgetSelectionDialogOptions;
|
||||
|
||||
constructor(options: WidgetSelectionDialogOptions) {
|
||||
super();
|
||||
this.#options = options;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ interface SettingParams {
|
||||
onChange?: (newValue: any, oldValue?: any) => void;
|
||||
attrs?: any;
|
||||
tooltip?: string;
|
||||
options?: SettingOption[] | ((value: any) => SettingOption[]);
|
||||
options?: Array<string | SettingOption> | ((value: any) => SettingOption[]);
|
||||
}
|
||||
|
||||
export class ComfySettingsDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
/**
|
||||
* @typedef { string | string[] | Record<string, boolean> } ClassList
|
||||
*/
|
||||
export type ClassList = string | string[] | Record<string, boolean>;
|
||||
|
||||
/**
|
||||
* @param { HTMLElement } element
|
||||
* @param { ClassList } classList
|
||||
* @param { string[] } requiredClasses
|
||||
*/
|
||||
export function applyClasses(element, classList, ...requiredClasses) {
|
||||
export function applyClasses(
|
||||
element: HTMLElement,
|
||||
classList: ClassList,
|
||||
...requiredClasses: string[]
|
||||
) {
|
||||
classList ??= "";
|
||||
|
||||
let str;
|
||||
let str: string;
|
||||
if (typeof classList === "string") {
|
||||
str = classList;
|
||||
} else if (classList instanceof Array) {
|
||||
@@ -29,14 +26,18 @@ export function applyClasses(element, classList, ...requiredClasses) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { HTMLElement } element
|
||||
* @param { { onHide?: (el: HTMLElement) => void, onShow?: (el: HTMLElement, value) => void } } [param1]
|
||||
* @returns
|
||||
*/
|
||||
export function toggleElement(element, { onHide, onShow } = {}) {
|
||||
let placeholder;
|
||||
let hidden;
|
||||
export function toggleElement(
|
||||
element: HTMLElement,
|
||||
{
|
||||
onHide,
|
||||
onShow,
|
||||
}: {
|
||||
onHide?: (el: HTMLElement) => void;
|
||||
onShow?: (el: HTMLElement, value) => void;
|
||||
} = {}
|
||||
) {
|
||||
let placeholder: HTMLElement | Comment;
|
||||
let hidden: boolean;
|
||||
return (value) => {
|
||||
if (value) {
|
||||
if (hidden) {
|
||||
@@ -136,14 +136,17 @@ export function downloadBlob(filename, blob) {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} name
|
||||
* @param {T} [defaultValue]
|
||||
* @param {(currentValue: any, previousValue: any)=>void} [onChanged]
|
||||
* @returns {T}
|
||||
*/
|
||||
export function prop(target, name, defaultValue, onChanged) {
|
||||
export function prop<T>(
|
||||
target: object,
|
||||
name: string,
|
||||
defaultValue: T,
|
||||
onChanged?: (
|
||||
currentValue: T,
|
||||
previousValue: T,
|
||||
target: object,
|
||||
name: string
|
||||
) => void
|
||||
): T {
|
||||
let currentValue;
|
||||
Object.defineProperty(target, name, {
|
||||
get() {
|
||||
|
||||
@@ -1,36 +1,31 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import type { ComfyApp } from "./app";
|
||||
import { api } from "./api";
|
||||
import { ChangeTracker } from "./changeTracker";
|
||||
import { ComfyAsyncDialog } from "./ui/components/asyncDialog";
|
||||
import { getStorageValue, setStorageValue } from "./utils";
|
||||
import { LGraphCanvas } from "@comfyorg/litegraph";
|
||||
import { LGraphCanvas, LGraph } from "@comfyorg/litegraph";
|
||||
|
||||
function appendJsonExt(path) {
|
||||
function appendJsonExt(path: string) {
|
||||
if (!path.toLowerCase().endsWith(".json")) {
|
||||
path += ".json";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
export function trimJsonExt(path) {
|
||||
export function trimJsonExt(path: string) {
|
||||
return path?.replace(/\.json$/, "");
|
||||
}
|
||||
|
||||
export class ComfyWorkflowManager extends EventTarget {
|
||||
/** @type {string | null} */
|
||||
#activePromptId = null;
|
||||
#activePromptId: string | null = null;
|
||||
#unsavedCount = 0;
|
||||
#activeWorkflow;
|
||||
#activeWorkflow: ComfyWorkflow;
|
||||
|
||||
/** @type {Record<string, ComfyWorkflow>} */
|
||||
workflowLookup = {};
|
||||
/** @type {Array<ComfyWorkflow>} */
|
||||
workflows = [];
|
||||
/** @type {Array<ComfyWorkflow>} */
|
||||
openWorkflows = [];
|
||||
/** @type {Record<string, {workflow?: ComfyWorkflow, nodes?: Record<string, boolean>}>} */
|
||||
queuedPrompts = {};
|
||||
workflowLookup: Record<string, ComfyWorkflow> = {};
|
||||
workflows: Array<ComfyWorkflow> = [];
|
||||
openWorkflows: Array<ComfyWorkflow> = [];
|
||||
queuedPrompts: Record<string, { workflow?: ComfyWorkflow; nodes?: Record<string, boolean>; }> = {};
|
||||
app: ComfyApp;
|
||||
|
||||
get activeWorkflow() {
|
||||
return this.#activeWorkflow ?? this.openWorkflows[0];
|
||||
@@ -44,10 +39,7 @@ export class ComfyWorkflowManager extends EventTarget {
|
||||
return this.queuedPrompts[this.#activePromptId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./app").ComfyApp} app
|
||||
*/
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
super();
|
||||
this.app = app;
|
||||
ChangeTracker.init(app);
|
||||
@@ -238,9 +230,9 @@ export class ComfyWorkflow {
|
||||
#path;
|
||||
#pathParts;
|
||||
#isFavorite = false;
|
||||
/** @type {ChangeTracker | null} */
|
||||
changeTracker = null;
|
||||
changeTracker: ChangeTracker | null = null;
|
||||
unsaved = false;
|
||||
manager: ComfyWorkflowManager;
|
||||
|
||||
get name() {
|
||||
return this.#name;
|
||||
@@ -262,25 +254,7 @@ export class ComfyWorkflow {
|
||||
return !!this.changeTracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overload
|
||||
* @param {ComfyWorkflowManager} manager
|
||||
* @param {string} path
|
||||
*/
|
||||
/**
|
||||
* @overload
|
||||
* @param {ComfyWorkflowManager} manager
|
||||
* @param {string} path
|
||||
* @param {string[]} pathParts
|
||||
* @param {boolean} isFavorite
|
||||
*/
|
||||
/**
|
||||
* @param {ComfyWorkflowManager} manager
|
||||
* @param {string} path
|
||||
* @param {string[]} [pathParts]
|
||||
* @param {boolean} [isFavorite]
|
||||
*/
|
||||
constructor(manager, path, pathParts, isFavorite) {
|
||||
constructor(manager: ComfyWorkflowManager, path: string, pathParts?: string[], isFavorite?: boolean) {
|
||||
this.manager = manager;
|
||||
if (pathParts) {
|
||||
this.#updatePath(path, pathParts);
|
||||
@@ -291,11 +265,7 @@ export class ComfyWorkflow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {string[]} [pathParts]
|
||||
*/
|
||||
#updatePath(path, pathParts) {
|
||||
#updatePath(path: string, pathParts: string[]) {
|
||||
this.#path = path;
|
||||
|
||||
if (!pathParts) {
|
||||
@@ -344,10 +314,7 @@ export class ComfyWorkflow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} value
|
||||
*/
|
||||
async favorite(value) {
|
||||
async favorite(value: boolean) {
|
||||
try {
|
||||
if (this.#isFavorite === value) return;
|
||||
this.#isFavorite = value;
|
||||
@@ -363,10 +330,7 @@ export class ComfyWorkflow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
*/
|
||||
async rename(path) {
|
||||
async rename(path: string) {
|
||||
path = appendJsonExt(path);
|
||||
let resp = await api.moveUserData(
|
||||
"workflows/" + this.path,
|
||||
@@ -412,8 +376,10 @@ export class ComfyWorkflow {
|
||||
if (!data) return;
|
||||
|
||||
const old = localStorage.getItem("litegrapheditor_clipboard");
|
||||
// @ts-ignore
|
||||
const graph = new LGraph(data);
|
||||
const canvas = new LGraphCanvas(null, graph, {
|
||||
// @ts-ignore
|
||||
skip_events: true,
|
||||
skip_render: true,
|
||||
});
|
||||
@@ -449,11 +415,7 @@ export class ComfyWorkflow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|null} path
|
||||
* @param {boolean} overwrite
|
||||
*/
|
||||
async #save(path, overwrite) {
|
||||
async #save(path: string | null, overwrite: boolean) {
|
||||
if (!path) {
|
||||
path = prompt(
|
||||
"Save workflow as:",
|
||||
Reference in New Issue
Block a user