diff --git a/web/scripts/app.js b/web/scripts/app.js index f0bb8640c..d0198f093 100644 --- a/web/scripts/app.js +++ b/web/scripts/app.js @@ -61,7 +61,7 @@ export class ComfyApp { getPreviewFormatParam() { let preview_format = this.ui.settings.getSettingValue("Comfy.PreviewFormat"); - if(preview_format) + if (preview_format) return `&preview=${preview_format}`; else return ""; @@ -72,7 +72,7 @@ export class ComfyApp { } static onClipspaceEditorSave() { - if(ComfyApp.clipspace_return_node) { + if (ComfyApp.clipspace_return_node) { ComfyApp.pasteFromClipspace(ComfyApp.clipspace_return_node); } } @@ -83,13 +83,13 @@ export class ComfyApp { static copyToClipspace(node) { var widgets = null; - if(node.widgets) { + if (node.widgets) { widgets = node.widgets.map(({ type, name, value }) => ({ type, name, value })); } var imgs = undefined; var orig_imgs = undefined; - if(node.imgs != undefined) { + if (node.imgs != undefined) { imgs = []; orig_imgs = []; @@ -101,7 +101,7 @@ export class ComfyApp { } var selectedIndex = 0; - if(node.imageIndex) { + if (node.imageIndex) { selectedIndex = node.imageIndex; } @@ -116,30 +116,30 @@ export class ComfyApp { ComfyApp.clipspace_return_node = null; - if(ComfyApp.clipspace_invalidate_handler) { + if (ComfyApp.clipspace_invalidate_handler) { ComfyApp.clipspace_invalidate_handler(); } } static pasteFromClipspace(node) { - if(ComfyApp.clipspace) { + if (ComfyApp.clipspace) { // image paste - if(ComfyApp.clipspace.imgs && node.imgs) { - if(node.images && ComfyApp.clipspace.images) { - if(ComfyApp.clipspace['img_paste_mode'] == 'selected') { + if (ComfyApp.clipspace.imgs && node.imgs) { + if (node.images && ComfyApp.clipspace.images) { + if (ComfyApp.clipspace['img_paste_mode'] == 'selected') { node.images = [ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']]]; } else { node.images = ComfyApp.clipspace.images; } - if(app.nodeOutputs[node.id + ""]) + if (app.nodeOutputs[node.id + ""]) app.nodeOutputs[node.id + ""].images = node.images; } - if(ComfyApp.clipspace.imgs) { + if (ComfyApp.clipspace.imgs) { // deep-copy to cut link with clipspace - if(ComfyApp.clipspace['img_paste_mode'] == 'selected') { + if (ComfyApp.clipspace['img_paste_mode'] == 'selected') { const img = new Image(); img.src = ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src; node.imgs = [img]; @@ -147,7 +147,7 @@ export class ComfyApp { } else { const imgs = []; - for(let i=0; i obj.name === 'image'); - if(index >= 0) { - if(node.widgets[index].type != 'image' && typeof node.widgets[index].value == "string" && clip_image.filename) { - node.widgets[index].value = (clip_image.subfolder?clip_image.subfolder+'/':'') + clip_image.filename + (clip_image.type?` [${clip_image.type}]`:''); + if (index >= 0) { + if (node.widgets[index].type != 'image' && typeof node.widgets[index].value == "string" && clip_image.filename) { + node.widgets[index].value = (clip_image.subfolder ? clip_image.subfolder + '/' : '') + clip_image.filename + (clip_image.type ? ` [${clip_image.type}]` : ''); } else { node.widgets[index].value = clip_image; } } } - if(ComfyApp.clipspace.widgets) { + if (ComfyApp.clipspace.widgets) { ComfyApp.clipspace.widgets.forEach(({ type, name, value }) => { const prop = Object.values(node.widgets).find(obj => obj.type === type && obj.name === name); if (prop && prop.type != 'button') { - if(prop.type != 'image' && typeof prop.value == "string" && value.filename) { - prop.value = (value.subfolder?value.subfolder+'/':'') + value.filename + (value.type?` [${value.type}]`:''); + if (prop.type != 'image' && typeof prop.value == "string" && value.filename) { + prop.value = (value.subfolder ? value.subfolder + '/' : '') + value.filename + (value.type ? ` [${value.type}]` : ''); } else { prop.value = value; @@ -285,33 +285,33 @@ export class ComfyApp { } options.push({ - content: "Bypass", - callback: (obj) => { if (this.mode === 4) this.mode = 0; else this.mode = 4; this.graph.change(); } - }); + content: "Bypass", + callback: (obj) => { if (this.mode === 4) this.mode = 0; else this.mode = 4; this.graph.change(); } + }); // prevent conflict of clipspace content - if(!ComfyApp.clipspace_return_node) { + if (!ComfyApp.clipspace_return_node) { options.push({ - content: "Copy (Clipspace)", - callback: (obj) => { ComfyApp.copyToClipspace(this); } - }); + content: "Copy (Clipspace)", + callback: (obj) => { ComfyApp.copyToClipspace(this); } + }); - if(ComfyApp.clipspace != null) { + if (ComfyApp.clipspace != null) { options.push({ - content: "Paste (Clipspace)", - callback: () => { ComfyApp.pasteFromClipspace(this); } - }); + content: "Paste (Clipspace)", + callback: () => { ComfyApp.pasteFromClipspace(this); } + }); } - if(ComfyApp.isImageNode(this)) { + if (ComfyApp.isImageNode(this)) { options.push({ - content: "Open in MaskEditor", - callback: (obj) => { - ComfyApp.copyToClipspace(this); - ComfyApp.clipspace_return_node = this; - ComfyApp.open_maskeditor(); - } - }); + content: "Open in MaskEditor", + callback: (obj) => { + ComfyApp.copyToClipspace(this); + ComfyApp.clipspace_return_node = this; + ComfyApp.open_maskeditor(); + } + }); } } }; @@ -321,7 +321,7 @@ export class ComfyApp { const app = this; const origNodeOnKeyDown = node.prototype.onKeyDown; - node.prototype.onKeyDown = function(e) { + node.prototype.onKeyDown = function (e) { if (origNodeOnKeyDown && origNodeOnKeyDown.apply(this, e) === false) { return false; } @@ -376,7 +376,7 @@ export class ComfyApp { if (w.computeSize) { shiftY += w.computeSize()[1] + 4; } - else if(w.computedHeight) { + else if (w.computedHeight) { shiftY += w.computedHeight; } else { @@ -533,14 +533,14 @@ export class ComfyApp { } this.imageRects.push([x, y, cellWidth, cellHeight]); - let wratio = cellWidth/img.width; - let hratio = cellHeight/img.height; + let wratio = cellWidth / img.width; + let hratio = cellHeight / img.height; var ratio = Math.min(wratio, hratio); let imgHeight = ratio * img.height; - let imgY = row * cellHeight + shiftY + (cellHeight - imgHeight)/2; + let imgY = row * cellHeight + shiftY + (cellHeight - imgHeight) / 2; let imgWidth = ratio * img.width; - let imgX = col * cellWidth + shiftX + (cellWidth - imgWidth)/2; + let imgX = col * cellWidth + shiftX + (cellWidth - imgWidth) / 2; ctx.drawImage(img, imgX, imgY, imgWidth, imgHeight); ctx.filter = "none"; @@ -631,7 +631,7 @@ export class ComfyApp { } // Dragging from Chrome->Firefox there is a file but its a bmp, so ignore that if (event.dataTransfer.files.length && event.dataTransfer.files[0].type !== "image/bmp") { - await this.handleFile(event.dataTransfer.files[0]); + await this.handleFile(event.dataTransfer.files[0]); } else { // Try loading the first URI in the transfer list const validTypes = ["text/uri-list", "text/x-moz-url"]; @@ -683,7 +683,7 @@ export class ComfyApp { document.addEventListener("paste", (e) => { // ctrl+shift+v is used to paste nodes with connections // this is handled by litegraph - if(this.shiftDown) return; + if (this.shiftDown) return; let data = (e.clipboardData || window.clipboardData); const items = data.items; @@ -724,7 +724,7 @@ export class ComfyApp { data = data.slice(data.indexOf("workflow\n")); data = data.slice(data.indexOf("{")); workflow = JSON.parse(data); - } catch (error) {} + } catch (error) { } } if (workflow && workflow.version && workflow.nodes && workflow.extra) { @@ -774,7 +774,7 @@ export class ComfyApp { const self = this; const origProcessMouseDown = LGraphCanvas.prototype.processMouseDown; - LGraphCanvas.prototype.processMouseDown = function(e) { + LGraphCanvas.prototype.processMouseDown = function (e) { const res = origProcessMouseDown.apply(this, arguments); this.selected_group_moving = false; @@ -794,7 +794,7 @@ export class ComfyApp { } const origProcessMouseMove = LGraphCanvas.prototype.processMouseMove; - LGraphCanvas.prototype.processMouseMove = function(e) { + LGraphCanvas.prototype.processMouseMove = function (e) { const orig_selected_group = this.selected_group; if (this.selected_group && !this.selected_group_resizing && !this.selected_group_moving) { @@ -819,7 +819,7 @@ export class ComfyApp { #addProcessKeyHandler() { const self = this; const origProcessKey = LGraphCanvas.prototype.processKey; - LGraphCanvas.prototype.processKey = function(e) { + LGraphCanvas.prototype.processKey = function (e) { if (!this.graph) { return; } @@ -893,7 +893,7 @@ export class ComfyApp { const self = this; const origDrawGroups = LGraphCanvas.prototype.drawGroups; - LGraphCanvas.prototype.drawGroups = function(canvas, ctx) { + LGraphCanvas.prototype.drawGroups = function (canvas, ctx) { if (!this.graph) { return; } @@ -980,7 +980,7 @@ export class ComfyApp { 12 + size[0] + 1, 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT, [this.round_radius * 2, this.round_radius * 2, 2, 2] - ); + ); else if (shape == LiteGraph.CIRCLE_SHAPE) ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5 + 6, 0, Math.PI * 2); ctx.strokeStyle = color; @@ -1117,18 +1117,18 @@ export class ComfyApp { * Loads all extensions from the API into the window in parallel */ async #loadExtensions() { - const extensions = await api.getExtensions(); - this.logging.addEntry("Comfy.App", "debug", { Extensions: extensions }); - - const extensionPromises = extensions.map(async ext => { - try { - await import(api.apiURL(ext)); - } catch (error) { - console.error("Error loading extension", ext, error); - } - }); - - await Promise.all(extensionPromises); + const extensions = await api.getExtensions(); + this.logging.addEntry("Comfy.App", "debug", { Extensions: extensions }); + + const extensionPromises = extensions.map(async ext => { + try { + await import(api.apiURL(ext)); + } catch (error) { + console.error("Error loading extension", ext, error); + } + }); + + await Promise.all(extensionPromises); } /** @@ -1216,7 +1216,7 @@ export class ComfyApp { await this.#invokeExtensionsAsync("registerCustomNodes"); } - async registerNodesFromDefs(defs) { + async registerNodesFromDefs(defs) { await this.#invokeExtensionsAsync("addCustomNodeDefs", defs); // Generate list of known widgets @@ -1232,8 +1232,8 @@ export class ComfyApp { const node = Object.assign( function ComfyNode() { var inputs = nodeData["input"]["required"]; - if (nodeData["input"]["optional"] != undefined){ - inputs = Object.assign({}, nodeData["input"]["required"], nodeData["input"]["optional"]) + if (nodeData["input"]["optional"] != undefined) { + inputs = Object.assign({}, nodeData["input"]["required"], nodeData["input"]["optional"]) } const config = { minWidth: 1, minHeight: 1 }; for (const inputName in inputs) { @@ -1256,11 +1256,11 @@ export class ComfyApp { widgetCreated = false; } - if(widgetCreated && inputData[1]?.forceInput && config?.widget) { + if (widgetCreated && inputData[1]?.forceInput && config?.widget) { if (!config.widget.options) config.widget.options = {}; config.widget.options.forceInput = inputData[1].forceInput; } - if(widgetCreated && inputData[1]?.defaultInput && config?.widget) { + if (widgetCreated && inputData[1]?.defaultInput && config?.widget) { if (!config.widget.options) config.widget.options = {}; config.widget.options.defaultInput = inputData[1].defaultInput; } @@ -1269,7 +1269,7 @@ export class ComfyApp { for (const o in nodeData["output"]) { const output = nodeData["output"][o]; const outputName = nodeData["output_name"][o] || output; - const outputShape = nodeData["output_is_list"][o] ? LiteGraph.GRID_SHAPE : LiteGraph.CIRCLE_SHAPE ; + const outputShape = nodeData["output_is_list"][o] ? LiteGraph.GRID_SHAPE : LiteGraph.CIRCLE_SHAPE; this.addOutput(outputName, output, { shape: outputShape }); } @@ -1307,11 +1307,9 @@ export class ComfyApp { let reset_invalid_values = false; if (!graphData) { - if (typeof structuredClone === "undefined") - { + if (typeof structuredClone === "undefined") { graphData = JSON.parse(JSON.stringify(defaultGraph)); - }else - { + } else { graphData = structuredClone(defaultGraph); } reset_invalid_values = true; @@ -1508,6 +1506,7 @@ export class ComfyApp { output[String(node.id)] = { inputs, + title: node.title, class_type: node.comfyClass, }; } @@ -1540,9 +1539,9 @@ export class ComfyApp { else if (error.response) { let message = error.response.error.message; if (error.response.error.details) - message += ": " + error.response.error.details; + message += ": " + error.response.error.details; for (const [nodeID, nodeError] of Object.entries(error.response.node_errors)) { - message += "\n" + nodeError.class_type + ":" + message += "\n" + nodeError.class_type + ":" for (const errorReason of nodeError.errors) { message += "\n - " + errorReason.message + ": " + errorReason.details } @@ -1668,22 +1667,22 @@ export class ComfyApp { async refreshComboInNodes() { const defs = await api.getNodeDefs(); - for(let nodeNum in this.graph._nodes) { + for (let nodeNum in this.graph._nodes) { const node = this.graph._nodes[nodeNum]; const def = defs[node.type]; // HOTFIX: The current patch is designed to prevent the rest of the code from breaking due to primitive nodes, // and additional work is needed to consider the primitive logic in the refresh logic. - if(!def) + if (!def) continue; - for(const widgetNum in node.widgets) { + for (const widgetNum in node.widgets) { const widget = node.widgets[widgetNum] - if(widget.type == "combo" && def["input"]["required"][widget.name] !== undefined) { + if (widget.type == "combo" && def["input"]["required"][widget.name] !== undefined) { widget.options.values = def["input"]["required"][widget.name][0]; - if(widget.name != 'image' && !widget.options.values.includes(widget.value)) { + if (widget.name != 'image' && !widget.options.values.includes(widget.value)) { widget.value = widget.options.values[0]; widget.callback(widget.value); }