diff --git a/src_web/comfyui/base_node.ts b/src_web/comfyui/base_node.ts index 4c501b0..02b9e3b 100644 --- a/src_web/comfyui/base_node.ts +++ b/src_web/comfyui/base_node.ts @@ -25,7 +25,7 @@ import {defineProperty} from "rgthree/common/shared_utils.js"; * A base node with standard methods, directly extending the LGraphNode. * This can be used for ui-nodes and a further base for server nodes. */ -abstract class RgthreeBaseNode extends LGraphNode { +export abstract class RgthreeBaseNode extends LGraphNode { /** * Action strings that can be exposed and triggered from other nodes, like Fast Actions Button. */ diff --git a/src_web/comfyui/bookmark.ts b/src_web/comfyui/bookmark.ts index e637e1c..508076b 100644 --- a/src_web/comfyui/bookmark.ts +++ b/src_web/comfyui/bookmark.ts @@ -6,7 +6,7 @@ import {app} from "scripts/app.js"; import {RgthreeBaseVirtualNode} from "./base_node.js"; import {SERVICE as KEY_EVENT_SERVICE} from "./services/key_events_services.js"; import {NodeTypesString} from "./constants.js"; -import {getClosestOrSelf, queryOne} from "rgthree/common/utils_dom.js"; +import {getClosestOrSelf, query} from "rgthree/common/utils_dom.js"; /** * A bookmark node. Can be placed anywhere in the workflow, and given a shortcut key that will @@ -108,7 +108,7 @@ export class Bookmark extends RgthreeBaseVirtualNode { * keys down for the user. Note, blocks drag if the return is truthy. */ override onMouseDown(event: CanvasMouseEvent, pos: Point, graphCanvas: LGraphCanvas): boolean { - const input = queryOne(".graphdialog > input.value"); + const input = query(".graphdialog > input.value"); if (input && input.value === this.widgets[0]?.value) { input.addEventListener("keydown", (e) => { // ComfyUI swallows keydown on inputs, so we need to call out to rgthree to use downkeys. diff --git a/src_web/comfyui/comfy_ui_bar.ts b/src_web/comfyui/comfy_ui_bar.ts index c23219a..9c8bf09 100644 --- a/src_web/comfyui/comfy_ui_bar.ts +++ b/src_web/comfyui/comfy_ui_bar.ts @@ -2,7 +2,7 @@ import {app} from "scripts/app.js"; import { ComfyButtonGroup } from "scripts/ui/components/buttonGroup.js"; import { ComfyButton } from "scripts/ui/components/button.js"; import { iconGear, iconStarFilled, logoRgthree } from "rgthree/common/media/svgs.js"; -import { createElement, empty, queryOne } from "rgthree/common/utils_dom.js"; +import { createElement, empty, query } from "rgthree/common/utils_dom.js"; import { SERVICE as BOOKMARKS_SERVICE } from "./services/bookmarks_services.js"; import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js"; import { ComfyPopup } from "scripts/ui/components/popup.js"; diff --git a/src_web/comfyui/config.ts b/src_web/comfyui/config.ts index 33dc41f..1932eaa 100644 --- a/src_web/comfyui/config.ts +++ b/src_web/comfyui/config.ts @@ -1,6 +1,6 @@ import {app} from "scripts/app.js"; import { RgthreeDialog, RgthreeDialogOptions } from "rgthree/common/dialog.js"; -import { createElement as $el, query as $$ } from "rgthree/common/utils_dom.js"; +import { createElement as $el, queryAll as $$ } from "rgthree/common/utils_dom.js"; import { checkmark, logoRgthree } from "rgthree/common/media/svgs.js"; import { LogLevel, rgthree } from "./rgthree.js"; import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js"; diff --git a/src_web/comfyui/dialog_info.ts b/src_web/comfyui/dialog_info.ts index 6e0a95e..438dd25 100644 --- a/src_web/comfyui/dialog_info.ts +++ b/src_web/comfyui/dialog_info.ts @@ -4,8 +4,8 @@ import { empty, appendChildren, getClosestOrSelf, - queryOne, query, + queryAll, setAttributes, } from "rgthree/common/utils_dom.js"; import { @@ -83,7 +83,7 @@ abstract class RgthreeInfoDialog extends RgthreeDialog { this.setContent(this.getInfoContent()); this.setTitle(this.modelInfo?.["name"] || this.modelInfo?.["file"] || "Unknown"); } else if (action === "copy-trained-words") { - const selected = query(".-rgthree-is-selected", target.closest("tr")!); + const selected = queryAll(".-rgthree-is-selected", target.closest("tr")!); const text = selected.map((el) => el.getAttribute("data-word")).join(", "); await navigator.clipboard.writeText(text); rgthree.showMessage({ @@ -98,12 +98,12 @@ abstract class RgthreeInfoDialog extends RgthreeDialog { target?.classList.toggle("-rgthree-is-selected"); const tr = target.closest("tr"); if (tr) { - const span = queryOne("td:first-child > *", tr)!; - let small = queryOne("small", span); + const span = query("td:first-child > *", tr)!; + let small = query("small", span); if (!small) { small = $el("small", {parent: span}); } - const num = query(".-rgthree-is-selected", tr).length; + const num = queryAll(".-rgthree-is-selected", tr).length; small.innerHTML = num ? `${num} selected | Copy` : ""; @@ -111,7 +111,7 @@ abstract class RgthreeInfoDialog extends RgthreeDialog { } } else if (action === "edit-row") { const tr = target!.closest("tr")!; - const td = queryOne("td:nth-child(2)", tr)!; + const td = query("td:nth-child(2)", tr)!; const input = td.querySelector("input,textarea"); if (!input) { const fieldName = tr.dataset["fieldName"] as string; @@ -300,7 +300,7 @@ abstract class RgthreeInfoDialog extends RgthreeDialog { const div = $el("div", {html}); if (rgthree.isDevMode()) { - setAttributes(queryOne('[stub="menu"]', div)!, { + setAttributes(query('[stub="menu"]', div)!, { children: [ new MenuButton({ icon: dotdotdot, @@ -395,7 +395,7 @@ function getTrainedWordsMarkup(words: RgthreeModelInfo["trainedWords"]) { */ function saveEditableRow(info: RgthreeModelInfo, tr: HTMLElement, saving = true): boolean { const fieldName = tr.dataset["fieldName"] as "file"; - const input = queryOne("input,textarea", tr)!; + const input = query("input,textarea", tr)!; let newValue = info[fieldName] ?? ""; let modified = false; if (saving) { @@ -411,7 +411,7 @@ function saveEditableRow(info: RgthreeModelInfo, tr: HTMLElement, saving = true) modified = true; } tr.classList.remove("-rgthree-editing"); - const td = queryOne("td:nth-child(2)", tr)!; + const td = query("td:nth-child(2)", tr)!; appendChildren(empty(td), [$el("span", {text: newValue})]); return modified; } diff --git a/src_web/comfyui/rgthree.ts b/src_web/comfyui/rgthree.ts index f4abdab..fc5ad43 100644 --- a/src_web/comfyui/rgthree.ts +++ b/src_web/comfyui/rgthree.ts @@ -32,7 +32,7 @@ import { iconStarFilled, logoRgthree, } from "rgthree/common/media/svgs.js"; -import {createElement, query, queryOne} from "rgthree/common/utils_dom.js"; +import {createElement, queryAll, query} from "rgthree/common/utils_dom.js"; import { ISerialisedNode } from "@comfyorg/litegraph/dist/types/serialisation.js"; export enum LogLevel { @@ -333,15 +333,15 @@ class Rgthree extends EventTarget { } // Handle both cases in case someone hasn't updated. Can probably just assume // `isUpdatedComfyBodyClasses` is true in the near future. - const isUpdatedComfyBodyClasses = !!queryOne(".comfyui-body-top"); + const isUpdatedComfyBodyClasses = !!query(".comfyui-body-top"); const position = CONFIG_SERVICE.getConfigValue("features.progress_bar.position"); this.progressBarEl.classList.toggle("rgthree-pos-bottom", position === "bottom"); // If ComfyUI is updated with the body segments, then use that. if (isUpdatedComfyBodyClasses) { if (position === "bottom") { - queryOne(".comfyui-body-bottom")!.appendChild(this.progressBarEl); + query(".comfyui-body-bottom")!.appendChild(this.progressBarEl); } else { - queryOne(".comfyui-body-top")!.appendChild(this.progressBarEl); + query(".comfyui-body-top")!.appendChild(this.progressBarEl); } } else { document.body.appendChild(this.progressBarEl); @@ -872,7 +872,7 @@ class Rgthree extends EventTarget { } // If we have a dialog open then we want to append the message to the dialog so they show over // the modal. - const dialogs = query("dialog[open]"); + const dialogs = queryAll("dialog[open]"); if (dialogs.length) { let dialog = dialogs[dialogs.length - 1]!; dialog.appendChild(container); diff --git a/src_web/comfyui/utils.ts b/src_web/comfyui/utils.ts index b77280a..1647095 100644 --- a/src_web/comfyui/utils.ts +++ b/src_web/comfyui/utils.ts @@ -1,6 +1,6 @@ import type { Vector2, - LGraphCanvas, + LGraphCanvas as TLGraphCanvas, LLink, LGraph, IContextMenuOptions, @@ -79,7 +79,7 @@ export function addMenuItem( ) { const oldGetExtraMenuOptions = node.prototype.getExtraMenuOptions; node.prototype.getExtraMenuOptions = function ( - canvas: LGraphCanvas, + canvas: TLGraphCanvas, menuOptions: IContextMenuValue[], ) { oldGetExtraMenuOptions && oldGetExtraMenuOptions.apply(this, [canvas, menuOptions]); @@ -90,10 +90,10 @@ export function addMenuItem( /** * Waits for the canvas to be available on app using a single promise. */ -let canvasResolver: Resolver | null = null; +let canvasResolver: Resolver | null = null; export function waitForCanvas() { if (canvasResolver === null) { - canvasResolver = getResolver(); + canvasResolver = getResolver(); function _waitForCanvas() { if (!canvasResolver!.completed) { if (app?.canvas) { @@ -961,3 +961,20 @@ export function getOutputNodes(nodes: LGraphNode[]) { }) || [] ); } + +/** + * Gets a full color string, including parsing from the LGraphCanvas data. + */ +export function getFullColor(color?: string, liteGraphKey: 'groupcolor'|'color'|'bgcolor' = 'color') { + if (!color) { + return ''; + } + if (LGraphCanvas.node_colors[color]) { + color = LGraphCanvas.node_colors[color]![liteGraphKey]; + } + color = color.replace("#", "").toLocaleLowerCase(); + if (color.length === 3) { + color = color.replace(/(.)(.)(.)/, "$1$1$2$2$3$3"); + } + return `#${color}`; +} diff --git a/src_web/comfyui/utils_canvas.ts b/src_web/comfyui/utils_canvas.ts index 7010e26..bbbc8c5 100644 --- a/src_web/comfyui/utils_canvas.ts +++ b/src_web/comfyui/utils_canvas.ts @@ -114,6 +114,7 @@ export function drawRoundedRectangle( ) { const lowQuality = isLowQuality(); options = {...options}; + ctx.save(); ctx.strokeStyle = options.colorStroke || LiteGraph.WIDGET_OUTLINE_COLOR; ctx.fillStyle = options.colorBackground || LiteGraph.WIDGET_BGCOLOR; ctx.beginPath(); @@ -126,6 +127,7 @@ export function drawRoundedRectangle( ); ctx.fill(); !lowQuality && ctx.stroke(); + ctx.restore(); } type DrawNumberWidgetPartOptions = { diff --git a/src_web/common/utils_dom.ts b/src_web/common/utils_dom.ts index 8216ed5..f33fe70 100644 --- a/src_web/common/utils_dom.ts +++ b/src_web/common/utils_dom.ts @@ -38,19 +38,21 @@ const RGX_STRING_CONTENT_TO_SQUARES = '(.*?)(\\[|\\])'; const RGX_ATTRS_MAYBE_OPEN = new RegExp(`\\[${RGX_STRING_CONTENT_TO_SQUARES}`, 'gi'); const RGX_ATTRS_FOLLOW_OPEN = new RegExp(`^${RGX_STRING_CONTENT_TO_SQUARES}`, 'gi'); -export function query(selectors: K, parent?: HTMLElement|Document): Array; -export function query(selectors: K, parent?: HTMLElement|Document): Array; -export function query(selectors: K, parent?: HTMLElement|Document): Array; -export function query(selectors: string, parent?: HTMLElement|Document): Array; -export function query(selectors: string, parent: HTMLElement|Document = document) { +type QueryParent = HTMLElement|Document|DocumentFragment; + +export function queryAll(selectors: K, parent?: QueryParent): Array; +export function queryAll(selectors: K, parent?: QueryParent): Array; +export function queryAll(selectors: K, parent?: QueryParent): Array; +export function queryAll(selectors: string, parent?: QueryParent): Array; +export function queryAll(selectors: string, parent: QueryParent = document) { return Array.from(parent.querySelectorAll(selectors)).filter(n => !!n); } -export function queryOne(selectors: K, parent?: HTMLElement|Document): HTMLElementTagNameMap[K] | null; -export function queryOne(selectors: K, parent?: HTMLElement|Document): SVGElementTagNameMap[K] | null; -export function queryOne(selectors: K, parent?: HTMLElement|Document): MathMLElementTagNameMap[K] | null; -export function queryOne(selectors: string, parent?: HTMLElement|Document): T | null; -export function queryOne(selectors: string, parent: HTMLElement|Document = document) { +export function query(selectors: K, parent?: QueryParent): HTMLElementTagNameMap[K] | null; +export function query(selectors: K, parent?: QueryParent): SVGElementTagNameMap[K] | null; +export function query(selectors: K, parent?: QueryParent): MathMLElementTagNameMap[K] | null; +export function query(selectors: string, parent?: QueryParent): T | null; +export function query(selectors: string, parent: QueryParent = document) { return parent.querySelector(selectors) ?? null; } @@ -80,12 +82,17 @@ export function createElement(selectorOrMarkup: string, a const tag = getSelectorTag(selector) || "div"; element = document.createElement(tag); selector = selector.replace(RGX_TAG, "$2"); + const brackets = selector.match(/(\[[^\]]+\])/g) || []; + for (const bracket of brackets) { + selector = selector.replace(bracket, ''); + } // Turn id and classname into [attr]s that can be nested selector = selector.replace(RGX_ATTR_ID, '[id="$1"]'); selector = selector.replace( RGX_ATTR_CLASS, (match, p1, p2) => `${p1}[class="${p2.replace(/\./g, " ")}"]`, ); + selector += brackets.join(''); } const selectorAttrs = getSelectorAttributes(selector); @@ -313,7 +320,7 @@ function setStyles(element: HTMLElement, styles: {[name: string]: string|number} return element; } -function setStyle(element: HTMLElement, name: string, value: string|number|null) { +export function setStyle(element: HTMLElement, name: string, value: string|number|null) { // Note: Old IE uses 'styleFloat' name = (name.indexOf('float') > -1 ? 'cssFloat' : name); // Camelcase diff --git a/src_web/typings/litegraph.d.ts b/src_web/typings/litegraph.d.ts index eabced1..7fdb517 100644 --- a/src_web/typings/litegraph.d.ts +++ b/src_web/typings/litegraph.d.ts @@ -19,6 +19,19 @@ declare module "@comfyorg/litegraph" { rgthree_status?: "WARN" | "ERROR"; } + interface LGraph { + // @rgthree (Fix): `result` arg is optional in impl. + findNodesByType(type: string, result?: LGraphNode[]): LGraphNode[]; + } + + interface LGraphNode { + // @rgthree (Fix): Implementation allows a falsy value to be returned and it will suppress the + // menu all together. + // NOTE: [🤮] We can't actually augment this because it's a return.. but keeping here because + // this is how it's actually implemented. + // getSlotMenuOptions?(this: LGraphNode, slot: IFoundSlot): IContextMenuValue[] | void; + } + interface LGraphCanvas { // @rgthree (Fix): At one point this was in ComfyUI's app.js. I don't see it now... perhaps it's // been removed? We were using it in rgthree-comfy. diff --git a/src_web/typings/rgthree.d.ts b/src_web/typings/rgthree.d.ts index 4731590..52d3103 100644 --- a/src_web/typings/rgthree.d.ts +++ b/src_web/typings/rgthree.d.ts @@ -3,22 +3,40 @@ */ import type { LGraphNode, Vector2 } from "@comfyorg/litegraph"; import type { CanvasMouseEvent } from "@comfyorg/litegraph/dist/types/events.js"; -import type {RgthreeBaseVirtualNode} from '../comfyui/base_node.js' +import type { RgthreeBaseNode, RgthreeBaseVirtualNode } from '../comfyui/base_node.js' export type AdjustedMouseCustomEvent = CustomEvent<{ originalEvent: CanvasMouseEvent }>; export type Constructor = new(...args: any[]) => T; +export interface RgthreeBaseNodeConstructor extends Constructor { + static type: string; + static category: string; + static comfyClass: string; + static exposedActions: string[]; +} + +export interface RgthreeBaseVirtualNodeConstructor extends Constructor { + static type: string; + static category: string; + static _category: string; +} + export interface RgthreeBaseServerNodeConstructor extends Constructor { - static nodeType: LGraphNodeConstructor; - static nodeData: ComfyNodeDef; + static nodeType: ComfyNodeConstructor; + static nodeData: ComfyObjectInfo; static __registeredForOverride__: boolean; onRegisteredForOverride(comfyClass: any, rgthreeClass: any) : void; } - -export type RgthreeModelInfo = { +export type RgthreeModelInfoDetails = { file?: string; + path?: string; + hasInfoFile?: boolean; + image?: string; +} + +export type RgthreeModelInfo = RgthreeModelInfoDetails & { name?: string; type?: string; baseModel?: string; diff --git a/web/comfyui/base_node.js b/web/comfyui/base_node.js index 3d77c0d..93ed364 100644 --- a/web/comfyui/base_node.js +++ b/web/comfyui/base_node.js @@ -5,7 +5,7 @@ import { addHelpMenuItem } from "./utils.js"; import { RgthreeHelpDialog } from "../../rgthree/common/dialog.js"; import { importIndividualNodesInnerOnDragDrop, importIndividualNodesInnerOnDragOver, } from "./feature_import_individual_nodes.js"; import { defineProperty } from "../../rgthree/common/shared_utils.js"; -class RgthreeBaseNode extends LGraphNode { +export class RgthreeBaseNode extends LGraphNode { constructor(title = RgthreeBaseNode.title, skipOnConstructedCall = true) { super(title); this.comfyClass = "__NEED_COMFY_CLASS__"; diff --git a/web/comfyui/bookmark.js b/web/comfyui/bookmark.js index c7eeacd..cb9631b 100644 --- a/web/comfyui/bookmark.js +++ b/web/comfyui/bookmark.js @@ -2,7 +2,7 @@ import { app } from "../../scripts/app.js"; import { RgthreeBaseVirtualNode } from "./base_node.js"; import { SERVICE as KEY_EVENT_SERVICE } from "./services/key_events_services.js"; import { NodeTypesString } from "./constants.js"; -import { getClosestOrSelf, queryOne } from "../../rgthree/common/utils_dom.js"; +import { getClosestOrSelf, query } from "../../rgthree/common/utils_dom.js"; export class Bookmark extends RgthreeBaseVirtualNode { get _collapsed_width() { return this.___collapsed_width; @@ -61,7 +61,7 @@ export class Bookmark extends RgthreeBaseVirtualNode { } onMouseDown(event, pos, graphCanvas) { var _a; - const input = queryOne(".graphdialog > input.value"); + const input = query(".graphdialog > input.value"); if (input && input.value === ((_a = this.widgets[0]) === null || _a === void 0 ? void 0 : _a.value)) { input.addEventListener("keydown", (e) => { KEY_EVENT_SERVICE.handleKeyDownOrUp(e); diff --git a/web/comfyui/config.js b/web/comfyui/config.js index 9636e9f..f92995d 100644 --- a/web/comfyui/config.js +++ b/web/comfyui/config.js @@ -1,6 +1,6 @@ import { app } from "../../scripts/app.js"; import { RgthreeDialog } from "../../rgthree/common/dialog.js"; -import { createElement as $el, query as $$ } from "../../rgthree/common/utils_dom.js"; +import { createElement as $el, queryAll as $$ } from "../../rgthree/common/utils_dom.js"; import { checkmark, logoRgthree } from "../../rgthree/common/media/svgs.js"; import { rgthree } from "./rgthree.js"; import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js"; diff --git a/web/comfyui/dialog_info.js b/web/comfyui/dialog_info.js index 9bc88f7..6f3d19f 100644 --- a/web/comfyui/dialog_info.js +++ b/web/comfyui/dialog_info.js @@ -1,5 +1,5 @@ import { RgthreeDialog } from "../../rgthree/common/dialog.js"; -import { createElement as $el, empty, appendChildren, getClosestOrSelf, queryOne, query, setAttributes, } from "../../rgthree/common/utils_dom.js"; +import { createElement as $el, empty, appendChildren, getClosestOrSelf, query, queryAll, setAttributes, } from "../../rgthree/common/utils_dom.js"; import { logoCivitai, link, pencilColored, diskColored, dotdotdot, } from "../../rgthree/common/media/svgs.js"; import { LORA_INFO_SERVICE } from "../../rgthree/common/model_info_service.js"; import { rgthree } from "./rgthree.js"; @@ -57,7 +57,7 @@ class RgthreeInfoDialog extends RgthreeDialog { this.setTitle(((_a = this.modelInfo) === null || _a === void 0 ? void 0 : _a["name"]) || ((_b = this.modelInfo) === null || _b === void 0 ? void 0 : _b["file"]) || "Unknown"); } else if (action === "copy-trained-words") { - const selected = query(".-rgthree-is-selected", target.closest("tr")); + const selected = queryAll(".-rgthree-is-selected", target.closest("tr")); const text = selected.map((el) => el.getAttribute("data-word")).join(", "); await navigator.clipboard.writeText(text); rgthree.showMessage({ @@ -71,12 +71,12 @@ class RgthreeInfoDialog extends RgthreeDialog { target === null || target === void 0 ? void 0 : target.classList.toggle("-rgthree-is-selected"); const tr = target.closest("tr"); if (tr) { - const span = queryOne("td:first-child > *", tr); - let small = queryOne("small", span); + const span = query("td:first-child > *", tr); + let small = query("small", span); if (!small) { small = $el("small", { parent: span }); } - const num = query(".-rgthree-is-selected", tr).length; + const num = queryAll(".-rgthree-is-selected", tr).length; small.innerHTML = num ? `${num} selected | Copy` : ""; @@ -84,7 +84,7 @@ class RgthreeInfoDialog extends RgthreeDialog { } else if (action === "edit-row") { const tr = target.closest("tr"); - const td = queryOne("td:nth-child(2)", tr); + const td = query("td:nth-child(2)", tr); const input = td.querySelector("input,textarea"); if (!input) { const fieldName = tr.dataset["fieldName"]; @@ -185,7 +185,7 @@ class RgthreeInfoDialog extends RgthreeDialog { `; const div = $el("div", { html }); if (rgthree.isDevMode()) { - setAttributes(queryOne('[stub="menu"]', div), { + setAttributes(query('[stub="menu"]', div), { children: [ new MenuButton({ icon: dotdotdot, @@ -255,7 +255,7 @@ function getTrainedWordsMarkup(words) { function saveEditableRow(info, tr, saving = true) { var _a; const fieldName = tr.dataset["fieldName"]; - const input = queryOne("input,textarea", tr); + const input = query("input,textarea", tr); let newValue = (_a = info[fieldName]) !== null && _a !== void 0 ? _a : ""; let modified = false; if (saving) { @@ -271,7 +271,7 @@ function saveEditableRow(info, tr, saving = true) { modified = true; } tr.classList.remove("-rgthree-editing"); - const td = queryOne("td:nth-child(2)", tr); + const td = query("td:nth-child(2)", tr); appendChildren(empty(td), [$el("span", { text: newValue })]); return modified; } diff --git a/web/comfyui/rgthree.js b/web/comfyui/rgthree.js index 30f182d..e135dcd 100644 --- a/web/comfyui/rgthree.js +++ b/web/comfyui/rgthree.js @@ -9,7 +9,7 @@ import { NodeTypesString, addRgthree, getNodeTypeStrings } from "./constants.js" import { RgthreeProgressBar } from "../../rgthree/common/progress_bar.js"; import { RgthreeConfigDialog } from "./config.js"; import { iconGear, iconNode, iconReplace, iconStarFilled, logoRgthree, } from "../../rgthree/common/media/svgs.js"; -import { createElement, query, queryOne } from "../../rgthree/common/utils_dom.js"; +import { createElement, queryAll, query } from "../../rgthree/common/utils_dom.js"; export var LogLevel; (function (LogLevel) { LogLevel[LogLevel["IMPORTANT"] = 1] = "IMPORTANT"; @@ -203,15 +203,15 @@ class Rgthree extends EventTarget { } }); } - const isUpdatedComfyBodyClasses = !!queryOne(".comfyui-body-top"); + const isUpdatedComfyBodyClasses = !!query(".comfyui-body-top"); const position = CONFIG_SERVICE.getConfigValue("features.progress_bar.position"); this.progressBarEl.classList.toggle("rgthree-pos-bottom", position === "bottom"); if (isUpdatedComfyBodyClasses) { if (position === "bottom") { - queryOne(".comfyui-body-bottom").appendChild(this.progressBarEl); + query(".comfyui-body-bottom").appendChild(this.progressBarEl); } else { - queryOne(".comfyui-body-top").appendChild(this.progressBarEl); + query(".comfyui-body-top").appendChild(this.progressBarEl); } } else { @@ -596,7 +596,7 @@ class Rgthree extends EventTarget { container.classList.add("rgthree-top-messages-container"); document.body.appendChild(container); } - const dialogs = query("dialog[open]"); + const dialogs = queryAll("dialog[open]"); if (dialogs.length) { let dialog = dialogs[dialogs.length - 1]; dialog.appendChild(container); diff --git a/web/comfyui/utils.js b/web/comfyui/utils.js index 5cde1c7..ce8d117 100644 --- a/web/comfyui/utils.js +++ b/web/comfyui/utils.js @@ -640,3 +640,16 @@ export function getOutputNodes(nodes) { return (n.mode != LiteGraph.NEVER && ((_a = n.constructor.nodeData) === null || _a === void 0 ? void 0 : _a.output_node)); })) || []); } +export function getFullColor(color, liteGraphKey = 'color') { + if (!color) { + return ''; + } + if (LGraphCanvas.node_colors[color]) { + color = LGraphCanvas.node_colors[color][liteGraphKey]; + } + color = color.replace("#", "").toLocaleLowerCase(); + if (color.length === 3) { + color = color.replace(/(.)(.)(.)/, "$1$1$2$2$3$3"); + } + return `#${color}`; +} diff --git a/web/comfyui/utils_canvas.js b/web/comfyui/utils_canvas.js index b8884a5..b45df66 100644 --- a/web/comfyui/utils_canvas.js +++ b/web/comfyui/utils_canvas.js @@ -57,12 +57,14 @@ export function drawNodeWidget(ctx, options) { export function drawRoundedRectangle(ctx, options) { const lowQuality = isLowQuality(); options = { ...options }; + ctx.save(); ctx.strokeStyle = options.colorStroke || LiteGraph.WIDGET_OUTLINE_COLOR; ctx.fillStyle = options.colorBackground || LiteGraph.WIDGET_BGCOLOR; ctx.beginPath(); ctx.roundRect(options.posX, options.posY, options.width, options.height, lowQuality ? [0] : options.borderRadius ? [options.borderRadius] : [options.height * 0.5]); ctx.fill(); !lowQuality && ctx.stroke(); + ctx.restore(); } export function drawNumberWidgetPart(ctx, options) { const arrowWidth = 9; diff --git a/web/common/utils_dom.js b/web/common/utils_dom.js index 9557681..6f60524 100644 --- a/web/common/utils_dom.js +++ b/web/common/utils_dom.js @@ -29,10 +29,10 @@ const RGX_ATTR_CLASS = new RegExp(`(^|\\S)\\.([a-z0-9_\\-\\.]+)`, 'gi'); const RGX_STRING_CONTENT_TO_SQUARES = '(.*?)(\\[|\\])'; const RGX_ATTRS_MAYBE_OPEN = new RegExp(`\\[${RGX_STRING_CONTENT_TO_SQUARES}`, 'gi'); const RGX_ATTRS_FOLLOW_OPEN = new RegExp(`^${RGX_STRING_CONTENT_TO_SQUARES}`, 'gi'); -export function query(selectors, parent = document) { +export function queryAll(selectors, parent = document) { return Array.from(parent.querySelectorAll(selectors)).filter(n => !!n); } -export function queryOne(selectors, parent = document) { +export function query(selectors, parent = document) { var _a; return (_a = parent.querySelector(selectors)) !== null && _a !== void 0 ? _a : null; } @@ -56,8 +56,13 @@ export function createElement(selectorOrMarkup, attrs) { const tag = getSelectorTag(selector) || "div"; element = document.createElement(tag); selector = selector.replace(RGX_TAG, "$2"); + const brackets = selector.match(/(\[[^\]]+\])/g) || []; + for (const bracket of brackets) { + selector = selector.replace(bracket, ''); + } selector = selector.replace(RGX_ATTR_ID, '[id="$1"]'); selector = selector.replace(RGX_ATTR_CLASS, (match, p1, p2) => `${p1}[class="${p2.replace(/\./g, " ")}"]`); + selector += brackets.join(''); } const selectorAttrs = getSelectorAttributes(selector); if (selectorAttrs) { @@ -272,7 +277,7 @@ function setStyles(element, styles = null) { } return element; } -function setStyle(element, name, value) { +export function setStyle(element, name, value) { name = (name.indexOf('float') > -1 ? 'cssFloat' : name); if (name.indexOf('-') != -1) { name = name.replace(/-\D/g, (match) => {