Adds a context menu to progress bar so people can access settings and turn it off if they'd like.
This commit is contained in:
@@ -6,7 +6,7 @@ import { RgthreeDialog, RgthreeDialogOptions } from "rgthree/common/dialog.js";
|
||||
import { rgthreeApi } from "rgthree/common/rgthree_api.js";
|
||||
import { getObjectValue, setObjectValue } from "rgthree/common/shared_utils.js";
|
||||
import { createElement as $el, querySelectorAll as $$ } from "rgthree/common/utils_dom.js";
|
||||
import { logoRgthree } from "rgthree/common/media/svgs.js";
|
||||
import { checkmark, logoRgthree } from "rgthree/common/media/svgs.js";
|
||||
import { rgthree } from "./rgthree.js";
|
||||
|
||||
/** Types of config used as a hint for the form handling. */
|
||||
@@ -198,7 +198,7 @@ export class RgthreeConfigDialog extends RgthreeDialog {
|
||||
this.close();
|
||||
rgthree.showMessage({
|
||||
id: "config-success",
|
||||
message: "Successfully saved rgthree-comfy config!",
|
||||
message: `${checkmark} Successfully saved rgthree-comfy settings!`,
|
||||
timeout: 4000,
|
||||
});
|
||||
($$(".save-button", this.element)[0] as HTMLButtonElement).disabled = true;
|
||||
|
||||
@@ -52,6 +52,20 @@
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
.rgthree-top-messages-container > div > div > span {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.rgthree-top-messages-container > div > div > span svg {
|
||||
width: 20px;
|
||||
height: auto;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.rgthree-top-messages-container > div > div > span svg.icon-checkmark {
|
||||
fill: #2e9720;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container [type="warn"]::before {
|
||||
content: "⚠️";
|
||||
@@ -394,12 +408,16 @@ body.rgthree-dialog-open > *:not(.rgthree-dialog):not(.rgthree-top-messages-cont
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy,
|
||||
.litegraph.litecontextmenu .litemenu-entry.rgthree-contextmenu-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy svg,
|
||||
.litegraph.litecontextmenu .litemenu-entry.rgthree-contextmenu-item svg {
|
||||
fill: currentColor;
|
||||
width: auto;
|
||||
@@ -410,9 +428,10 @@ body.rgthree-dialog-open > *:not(.rgthree-dialog):not(.rgthree-top-messages-cont
|
||||
fill: rgb(227, 179, 65);
|
||||
}
|
||||
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy,
|
||||
.litegraph.litecontextmenu .litemenu-entry.rgthree-contextmenu-label {
|
||||
color: #dde;
|
||||
background-color: #090909 !important;
|
||||
background-color: #212121 !important;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
cursor: default;
|
||||
@@ -420,6 +439,13 @@ body.rgthree-dialog-open > *:not(.rgthree-dialog):not(.rgthree-top-messages-cont
|
||||
padding: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy {
|
||||
font-size: 1.1em;
|
||||
color: #fff;
|
||||
background-color: #090909 !important;
|
||||
justify-content: center;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
rgthree-progress-bar {
|
||||
display: block;
|
||||
|
||||
+127
-80
@@ -1,8 +1,11 @@
|
||||
import {
|
||||
type LGraphCanvas as TLGraphCanvas,
|
||||
type LGraphNode,
|
||||
type SerializedLGraphNode,
|
||||
type serializedLGraph,
|
||||
import type {
|
||||
LGraphCanvas as TLGraphCanvas,
|
||||
LGraphNode,
|
||||
SerializedLGraphNode,
|
||||
serializedLGraph,
|
||||
LiteGraph as TLiteGraph,
|
||||
ContextMenuItem,
|
||||
LGraph as TLGraph,
|
||||
} from "typings/litegraph.js";
|
||||
// @ts-ignore
|
||||
import { app } from "../../scripts/app.js";
|
||||
@@ -16,9 +19,9 @@ import { replaceNode, waitForCanvas, waitForGraph } from "./utils.js";
|
||||
import { NodeTypesString } from "./constants.js";
|
||||
import { RgthreeProgressBar } from "rgthree/common/progress_bar.js";
|
||||
import { RgthreeConfigDialog } from "./config.js";
|
||||
import { querySelectorAll as $$ } from "rgthree/common/utils_dom.js";
|
||||
import { iconGear, iconReplace, iconStarFilled, logoRgthree } from "rgthree/common/media/svgs.js";
|
||||
|
||||
declare const LiteGraph: typeof TLiteGraph;
|
||||
declare const LGraphCanvas: typeof TLGraphCanvas;
|
||||
|
||||
export enum LogLevel {
|
||||
@@ -139,6 +142,7 @@ class Rgthree extends EventTarget {
|
||||
/** Exposes the ComfyUI api instance on rgthree. */
|
||||
readonly api = api;
|
||||
private settingsDialog: RgthreeConfigDialog | null = null;
|
||||
private progressBarEl: RgthreeProgressBar | null = null;
|
||||
|
||||
/** Are any functional keys pressed in this given moment? */
|
||||
ctrlKey = false;
|
||||
@@ -154,7 +158,7 @@ class Rgthree extends EventTarget {
|
||||
|
||||
processingQueue = false;
|
||||
loadingApiJson = false;
|
||||
replacingReroute: number|null = null;
|
||||
replacingReroute: number | null = null;
|
||||
|
||||
// Comfy/LiteGraph states so nodes and tell what the hell is going on.
|
||||
canvasCurrentlyCopyingToClipboard = false;
|
||||
@@ -192,19 +196,55 @@ class Rgthree extends EventTarget {
|
||||
* Initializes the top progress bar, if it's configured.
|
||||
*/
|
||||
initializeProgressBar() {
|
||||
let bar = $$(RgthreeProgressBar.NAME)[0];
|
||||
if (CONFIG_SERVICE.getConfigValue("features.progress_bar.enabled")) {
|
||||
if (!bar) {
|
||||
bar = RgthreeProgressBar.create();
|
||||
document.body.appendChild(bar);
|
||||
if (!this.progressBarEl) {
|
||||
this.progressBarEl = RgthreeProgressBar.create();
|
||||
|
||||
this.progressBarEl.addEventListener("contextmenu", async (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
this.progressBarEl.addEventListener("pointerdown", async (e) => {
|
||||
LiteGraph.closeAllContextMenus();
|
||||
if (e.button == 2) {
|
||||
const canvas = await waitForCanvas();
|
||||
new LiteGraph.ContextMenu(
|
||||
this.getRgthreeContextMenuItems(),
|
||||
{
|
||||
title: `<div class="rgthree-contextmenu-item rgthree-contextmenu-title-rgthree-comfy">${logoRgthree} rgthree-comfy</div>`,
|
||||
left: e.clientX,
|
||||
top: 5,
|
||||
},
|
||||
canvas.getCanvasWindow(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (e.button == 0) {
|
||||
const nodeId = this.progressBarEl?.currentNodeId;
|
||||
if (nodeId) {
|
||||
const [canvas, graph] = await Promise.all([waitForCanvas(), waitForGraph()]);
|
||||
const node = graph.getNodeById(Number(nodeId));
|
||||
if (node) {
|
||||
canvas.centerOnNode(node);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!this.progressBarEl!.parentElement) {
|
||||
document.body.appendChild(this.progressBarEl);
|
||||
}
|
||||
const height = CONFIG_SERVICE.getConfigValue("features.progress_bar.height") || 14;
|
||||
bar.style.height = `${height}px`;
|
||||
this.progressBarEl.style.height = `${height}px`;
|
||||
const fontSize = Math.max(10, Number(height) - 10);
|
||||
bar.style.fontSize = `${fontSize}px`;
|
||||
bar.style.fontWeight = fontSize <= 12 ? 'bold' : 'normal';
|
||||
this.progressBarEl.style.fontSize = `${fontSize}px`;
|
||||
this.progressBarEl.style.fontWeight = fontSize <= 12 ? "bold" : "normal";
|
||||
} else {
|
||||
bar?.remove();
|
||||
this.progressBarEl?.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,79 +300,18 @@ class Rgthree extends EventTarget {
|
||||
* Initializes hooks specific to an rgthree-comfy context menu on the root menu.
|
||||
*/
|
||||
private async initializeContextMenu() {
|
||||
const graph = await waitForGraph();
|
||||
const that = this;
|
||||
setTimeout(() => {
|
||||
setTimeout(async () => {
|
||||
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions;
|
||||
LGraphCanvas.prototype.getCanvasMenuOptions = function (...args: any[]) {
|
||||
const options = getCanvasMenuOptions.apply(this, [...args] as any);
|
||||
|
||||
const selectedNodes = Object.values(this.selected_nodes || {});
|
||||
let rerouteNodes: LGraphNode[] = [];
|
||||
if (selectedNodes.length) {
|
||||
rerouteNodes = selectedNodes.filter((n) => n.type === "Reroute");
|
||||
} else {
|
||||
rerouteNodes = graph._nodes.filter((n) => n.type == "Reroute");
|
||||
}
|
||||
const rerouteLabel = selectedNodes.length ? "selected" : "all";
|
||||
|
||||
options.push(null); // Divider
|
||||
options.push({
|
||||
content: logoRgthree + `rgthree-comfy`,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-main-rgthree-comfy",
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-main-item-rgthree-comfy",
|
||||
submenu: {
|
||||
options: [
|
||||
{
|
||||
content: "Actions",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconGear + "Open rgthree-comfy Settings",
|
||||
disabled: !!that.settingsDialog,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args: any[]) => {
|
||||
that.settingsDialog = new RgthreeConfigDialog().show();
|
||||
that.settingsDialog.addEventListener("close", (e) => {
|
||||
that.settingsDialog = null;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
content: iconReplace + ` Convert ${rerouteLabel} Reroutes`,
|
||||
disabled: !rerouteNodes.length,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args: any[]) => {
|
||||
const msg =
|
||||
`Convert ${rerouteLabel} ComfyUI Reroutes to Reroute (rgthree) nodes? \n` +
|
||||
`(First save a copy of your workflow & check reroute connections afterwards)`;
|
||||
if (!window.confirm(msg)) {
|
||||
return;
|
||||
}
|
||||
(async () => {
|
||||
for (const node of [...rerouteNodes]) {
|
||||
if (node.type == "Reroute") {
|
||||
that.replacingReroute = node.id;
|
||||
await replaceNode(node, NodeTypesString.REROUTE);
|
||||
that.replacingReroute = null;
|
||||
}
|
||||
}
|
||||
})();
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "More...",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconStarFilled + "Star on Github",
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-github",
|
||||
callback: (...args: any[]) => {
|
||||
window.open("https://github.com/rgthree/rgthree-comfy", "_blank");
|
||||
},
|
||||
},
|
||||
],
|
||||
options: that.getRgthreeContextMenuItems(),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -341,6 +320,74 @@ class Rgthree extends EventTarget {
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard menu items for an rgthree-comfy context menu.
|
||||
*/
|
||||
private getRgthreeContextMenuItems(): ContextMenuItem[] {
|
||||
const [canvas, graph] = [app.canvas as TLGraphCanvas, app.graph as TLGraph];
|
||||
const selectedNodes = Object.values(canvas.selected_nodes || {});
|
||||
let rerouteNodes: LGraphNode[] = [];
|
||||
if (selectedNodes.length) {
|
||||
rerouteNodes = selectedNodes.filter((n) => n.type === "Reroute");
|
||||
} else {
|
||||
rerouteNodes = graph._nodes.filter((n) => n.type == "Reroute");
|
||||
}
|
||||
const rerouteLabel = selectedNodes.length ? "selected" : "all";
|
||||
|
||||
return [
|
||||
{
|
||||
content: "Actions",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconGear + "Settings (rgthree-comfy)",
|
||||
disabled: !!this.settingsDialog,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args: any[]) => {
|
||||
this.settingsDialog = new RgthreeConfigDialog().show();
|
||||
this.settingsDialog.addEventListener("close", (e) => {
|
||||
this.settingsDialog = null;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
content: iconReplace + ` Convert ${rerouteLabel} Reroutes`,
|
||||
disabled: !rerouteNodes.length,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args: any[]) => {
|
||||
const msg =
|
||||
`Convert ${rerouteLabel} ComfyUI Reroutes to Reroute (rgthree) nodes? \n` +
|
||||
`(First save a copy of your workflow & check reroute connections afterwards)`;
|
||||
if (!window.confirm(msg)) {
|
||||
return;
|
||||
}
|
||||
(async () => {
|
||||
for (const node of [...rerouteNodes]) {
|
||||
if (node.type == "Reroute") {
|
||||
this.replacingReroute = node.id;
|
||||
await replaceNode(node, NodeTypesString.REROUTE);
|
||||
this.replacingReroute = null;
|
||||
}
|
||||
}
|
||||
})();
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "More...",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconStarFilled + "Star on Github",
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-github",
|
||||
callback: (...args: any[]) => {
|
||||
window.open("https://github.com/rgthree/rgthree-comfy", "_blank");
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a bunch of hooks into ComfyUI and/or LiteGraph itself so we can either keep state or
|
||||
* context on what's happening so nodes can respond appropriately. This is usually to fix broken
|
||||
@@ -516,7 +563,7 @@ class Rgthree extends EventTarget {
|
||||
messageContainer.setAttribute("type", data.type || "info");
|
||||
|
||||
const message = document.createElement("span");
|
||||
message.innerText = data.message;
|
||||
message.innerHTML = data.message;
|
||||
messageContainer.appendChild(message);
|
||||
|
||||
for (let a = 0; a < (data.actions || []).length; a++) {
|
||||
|
||||
@@ -29,4 +29,11 @@ export const iconReplace = `
|
||||
export const iconGear = `
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7848 0.449982C13.8239 0.449982 14.7167 1.16546 14.9122 2.15495L14.9991 2.59495C15.3408 4.32442 17.1859 5.35722 18.9016 4.7794L19.3383 4.63233C20.3199 4.30175 21.4054 4.69358 21.9249 5.56605L22.7097 6.88386C23.2293 7.75636 23.0365 8.86366 22.2504 9.52253L21.9008 9.81555C20.5267 10.9672 20.5267 13.0328 21.9008 14.1844L22.2504 14.4774C23.0365 15.1363 23.2293 16.2436 22.7097 17.1161L21.925 18.4339C21.4054 19.3064 20.3199 19.6982 19.3382 19.3676L18.9017 19.2205C17.1859 18.6426 15.3408 19.6754 14.9991 21.405L14.9122 21.845C14.7167 22.8345 13.8239 23.55 12.7848 23.55H11.2152C10.1761 23.55 9.28331 22.8345 9.08781 21.8451L9.00082 21.4048C8.65909 19.6754 6.81395 18.6426 5.09822 19.2205L4.66179 19.3675C3.68016 19.6982 2.59465 19.3063 2.07505 18.4338L1.2903 17.1161C0.770719 16.2436 0.963446 15.1363 1.74956 14.4774L2.09922 14.1844C3.47324 13.0327 3.47324 10.9672 2.09922 9.8156L1.74956 9.52254C0.963446 8.86366 0.77072 7.75638 1.2903 6.8839L2.07508 5.56608C2.59466 4.69359 3.68014 4.30176 4.66176 4.63236L5.09831 4.77939C6.81401 5.35722 8.65909 4.32449 9.00082 2.59506L9.0878 2.15487C9.28331 1.16542 10.176 0.449982 11.2152 0.449982H12.7848ZM12 15.3C13.8225 15.3 15.3 13.8225 15.3 12C15.3 10.1774 13.8225 8.69998 12 8.69998C10.1774 8.69998 8.69997 10.1774 8.69997 12C8.69997 13.8225 10.1774 15.3 12 15.3Z" />
|
||||
</svg>`
|
||||
</svg>`
|
||||
|
||||
export const checkmark = `
|
||||
<svg viewBox="0 0 32 32" fill="currentColor" class="icon-checkmark">
|
||||
<g transform="translate(-518.000000, -1039.000000)">
|
||||
<path d="M548.783,1040.2 C547.188,1038.57 544.603,1038.57 543.008,1040.2 L528.569,1054.92 L524.96,1051.24 C523.365,1049.62 520.779,1049.62 519.185,1051.24 C517.59,1052.87 517.59,1055.51 519.185,1057.13 L525.682,1063.76 C527.277,1065.39 529.862,1065.39 531.457,1063.76 L548.783,1046.09 C550.378,1044.46 550.378,1041.82 548.783,1040.2"></path>
|
||||
</g>
|
||||
</svg>`;
|
||||
@@ -241,18 +241,20 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
|
||||
private connected: boolean = false;
|
||||
|
||||
/** The currentNodeId so outside callers can see what we're currently executing against. */
|
||||
get currentNodeId() {
|
||||
const prompt = this.currentPromptExecution;
|
||||
const nodeId = prompt?.errorDetails?.node_id || prompt?.currentlyExecuting?.nodeId;
|
||||
return nodeId || null;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
private maybeGetComfyGraph(): TLGraph | null {
|
||||
return ((window as any)?.app?.graph as TLGraph) || null;
|
||||
}
|
||||
private maybeGetComfyCanvas(): TLGraphCanvas | null {
|
||||
return ((window as any)?.app?.canvas as TLGraphCanvas) || null;
|
||||
}
|
||||
|
||||
private onProgressUpdate(e: CustomEvent<{ queue: number; prompt: PromptExecution }>) {
|
||||
if (!this.connected) return;
|
||||
|
||||
const prompt = e.detail.prompt;
|
||||
this.currentPromptExecution = prompt;
|
||||
|
||||
@@ -313,10 +315,17 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.connected) {
|
||||
SERVICE.addEventListener("progress-update", this.onProgressUpdateBound as EventListener);
|
||||
this.connected = true;
|
||||
}
|
||||
// We were already connected, so we just need to reset.
|
||||
if (this.shadow) {
|
||||
this.progressTextEl.innerText = 'Idle';
|
||||
this.progressNodesEl.style.width = `0%`;
|
||||
this.progressStepsEl.style.width = `0%`;
|
||||
return;
|
||||
}
|
||||
SERVICE.addEventListener("progress-update", this.onProgressUpdateBound as EventListener);
|
||||
|
||||
this.shadow = this.attachShadow({ mode: "open" });
|
||||
const sheet = new CSSStyleSheet();
|
||||
@@ -403,12 +412,6 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
this.progressTextEl = document.createElement("span");
|
||||
this.progressTextEl.innerText = "Idle";
|
||||
this.shadow.appendChild(this.progressTextEl);
|
||||
|
||||
overlayEl.addEventListener("click", (e: MouseEvent) => {
|
||||
this.onClick(e);
|
||||
});
|
||||
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
@@ -416,28 +419,6 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
SERVICE.removeEventListener("progress-update", this.onProgressUpdateBound as EventListener);
|
||||
}
|
||||
|
||||
onClick(e: PointerEvent | MouseEvent) {
|
||||
const prompt = this.currentPromptExecution;
|
||||
const nodeId = prompt?.errorDetails?.node_id || prompt?.currentlyExecuting?.nodeId;
|
||||
if (!nodeId) return;
|
||||
|
||||
const graph = this.maybeGetComfyGraph();
|
||||
const canvas = this.maybeGetComfyCanvas();
|
||||
if (graph && canvas) {
|
||||
const node = graph.getNodeById(Number(nodeId));
|
||||
if (node) {
|
||||
canvas.centerOnNode(node);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateProgress() {
|
||||
if (!this.shadow) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(RgthreeProgressBar.NAME, RgthreeProgressBar);
|
||||
|
||||
Vendored
+6
@@ -188,6 +188,10 @@ export interface IContextMenuOptions {
|
||||
autoopen?: boolean;
|
||||
title?: string;
|
||||
extra?: any;
|
||||
// @rgthree
|
||||
left?: number;
|
||||
// @rgthree
|
||||
top?: number;
|
||||
}
|
||||
|
||||
export type ContextMenuItem = IContextMenuItem | null;
|
||||
@@ -392,6 +396,8 @@ export const LiteGraph: {
|
||||
ContextMenu: typeof ContextMenu;
|
||||
extendClass<A, B>(target: A, origin: B): A & B;
|
||||
getParameterNames(func: string): string[];
|
||||
// @rgthree
|
||||
closeAllContextMenus(ref_window?: Window): void;
|
||||
};
|
||||
|
||||
export type serializedLGraph<
|
||||
|
||||
@@ -4,7 +4,7 @@ import { RgthreeDialog } from "../../rgthree/common/dialog.js";
|
||||
import { rgthreeApi } from "../../rgthree/common/rgthree_api.js";
|
||||
import { getObjectValue, setObjectValue } from "../../rgthree/common/shared_utils.js";
|
||||
import { createElement as $el, querySelectorAll as $$ } from "../../rgthree/common/utils_dom.js";
|
||||
import { logoRgthree } from "../../rgthree/common/media/svgs.js";
|
||||
import { checkmark, logoRgthree } from "../../rgthree/common/media/svgs.js";
|
||||
import { rgthree } from "./rgthree.js";
|
||||
var ConfigType;
|
||||
(function (ConfigType) {
|
||||
@@ -156,7 +156,7 @@ export class RgthreeConfigDialog extends RgthreeDialog {
|
||||
this.close();
|
||||
rgthree.showMessage({
|
||||
id: "config-success",
|
||||
message: "Successfully saved rgthree-comfy config!",
|
||||
message: `${checkmark} Successfully saved rgthree-comfy settings!`,
|
||||
timeout: 4000,
|
||||
});
|
||||
$$(".save-button", this.element)[0].disabled = true;
|
||||
|
||||
+27
-1
@@ -52,6 +52,20 @@
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
.rgthree-top-messages-container > div > div > span {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.rgthree-top-messages-container > div > div > span svg {
|
||||
width: 20px;
|
||||
height: auto;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.rgthree-top-messages-container > div > div > span svg.icon-checkmark {
|
||||
fill: #2e9720;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container [type="warn"]::before {
|
||||
content: "⚠️";
|
||||
@@ -394,12 +408,16 @@ body.rgthree-dialog-open > *:not(.rgthree-dialog):not(.rgthree-top-messages-cont
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy,
|
||||
.litegraph.litecontextmenu .litemenu-entry.rgthree-contextmenu-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy svg,
|
||||
.litegraph.litecontextmenu .litemenu-entry.rgthree-contextmenu-item svg {
|
||||
fill: currentColor;
|
||||
width: auto;
|
||||
@@ -410,9 +428,10 @@ body.rgthree-dialog-open > *:not(.rgthree-dialog):not(.rgthree-top-messages-cont
|
||||
fill: rgb(227, 179, 65);
|
||||
}
|
||||
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy,
|
||||
.litegraph.litecontextmenu .litemenu-entry.rgthree-contextmenu-label {
|
||||
color: #dde;
|
||||
background-color: #090909 !important;
|
||||
background-color: #212121 !important;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
cursor: default;
|
||||
@@ -420,6 +439,13 @@ body.rgthree-dialog-open > *:not(.rgthree-dialog):not(.rgthree-top-messages-cont
|
||||
padding: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.litegraph.litecontextmenu .litemenu-title .rgthree-contextmenu-title-rgthree-comfy {
|
||||
font-size: 1.1em;
|
||||
color: #fff;
|
||||
background-color: #090909 !important;
|
||||
justify-content: center;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
rgthree-progress-bar {
|
||||
display: block;
|
||||
|
||||
+108
-73
@@ -7,7 +7,6 @@ import { replaceNode, waitForCanvas, waitForGraph } from "./utils.js";
|
||||
import { NodeTypesString } from "./constants.js";
|
||||
import { RgthreeProgressBar } from "../../rgthree/common/progress_bar.js";
|
||||
import { RgthreeConfigDialog } from "./config.js";
|
||||
import { querySelectorAll as $$ } from "../../rgthree/common/utils_dom.js";
|
||||
import { iconGear, iconReplace, iconStarFilled, logoRgthree } from "../../rgthree/common/media/svgs.js";
|
||||
export var LogLevel;
|
||||
(function (LogLevel) {
|
||||
@@ -82,6 +81,7 @@ class Rgthree extends EventTarget {
|
||||
super();
|
||||
this.api = api;
|
||||
this.settingsDialog = null;
|
||||
this.progressBarEl = null;
|
||||
this.ctrlKey = false;
|
||||
this.altKey = false;
|
||||
this.metaKey = false;
|
||||
@@ -117,20 +117,52 @@ class Rgthree extends EventTarget {
|
||||
}));
|
||||
}
|
||||
initializeProgressBar() {
|
||||
let bar = $$(RgthreeProgressBar.NAME)[0];
|
||||
var _a;
|
||||
if (CONFIG_SERVICE.getConfigValue("features.progress_bar.enabled")) {
|
||||
if (!bar) {
|
||||
bar = RgthreeProgressBar.create();
|
||||
document.body.appendChild(bar);
|
||||
if (!this.progressBarEl) {
|
||||
this.progressBarEl = RgthreeProgressBar.create();
|
||||
this.progressBarEl.addEventListener("contextmenu", async (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
this.progressBarEl.addEventListener("pointerdown", async (e) => {
|
||||
var _a;
|
||||
LiteGraph.closeAllContextMenus();
|
||||
if (e.button == 2) {
|
||||
const canvas = await waitForCanvas();
|
||||
new LiteGraph.ContextMenu(this.getRgthreeContextMenuItems(), {
|
||||
title: `<div class="rgthree-contextmenu-item rgthree-contextmenu-title-rgthree-comfy">${logoRgthree} rgthree-comfy</div>`,
|
||||
left: e.clientX,
|
||||
top: 5,
|
||||
}, canvas.getCanvasWindow());
|
||||
return;
|
||||
}
|
||||
if (e.button == 0) {
|
||||
const nodeId = (_a = this.progressBarEl) === null || _a === void 0 ? void 0 : _a.currentNodeId;
|
||||
if (nodeId) {
|
||||
const [canvas, graph] = await Promise.all([waitForCanvas(), waitForGraph()]);
|
||||
const node = graph.getNodeById(Number(nodeId));
|
||||
if (node) {
|
||||
canvas.centerOnNode(node);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!this.progressBarEl.parentElement) {
|
||||
document.body.appendChild(this.progressBarEl);
|
||||
}
|
||||
const height = CONFIG_SERVICE.getConfigValue("features.progress_bar.height") || 14;
|
||||
bar.style.height = `${height}px`;
|
||||
this.progressBarEl.style.height = `${height}px`;
|
||||
const fontSize = Math.max(10, Number(height) - 10);
|
||||
bar.style.fontSize = `${fontSize}px`;
|
||||
bar.style.fontWeight = fontSize <= 12 ? 'bold' : 'normal';
|
||||
this.progressBarEl.style.fontSize = `${fontSize}px`;
|
||||
this.progressBarEl.style.fontWeight = fontSize <= 12 ? "bold" : "normal";
|
||||
}
|
||||
else {
|
||||
bar === null || bar === void 0 ? void 0 : bar.remove();
|
||||
(_a = this.progressBarEl) === null || _a === void 0 ? void 0 : _a.remove();
|
||||
}
|
||||
}
|
||||
async initializeGraphAndCanvasHooks() {
|
||||
@@ -157,83 +189,86 @@ class Rgthree extends EventTarget {
|
||||
};
|
||||
}
|
||||
async initializeContextMenu() {
|
||||
const graph = await waitForGraph();
|
||||
const that = this;
|
||||
setTimeout(() => {
|
||||
setTimeout(async () => {
|
||||
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions;
|
||||
LGraphCanvas.prototype.getCanvasMenuOptions = function (...args) {
|
||||
const options = getCanvasMenuOptions.apply(this, [...args]);
|
||||
const selectedNodes = Object.values(this.selected_nodes || {});
|
||||
let rerouteNodes = [];
|
||||
if (selectedNodes.length) {
|
||||
rerouteNodes = selectedNodes.filter((n) => n.type === "Reroute");
|
||||
}
|
||||
else {
|
||||
rerouteNodes = graph._nodes.filter((n) => n.type == "Reroute");
|
||||
}
|
||||
const rerouteLabel = selectedNodes.length ? "selected" : "all";
|
||||
options.push(null);
|
||||
options.push({
|
||||
content: logoRgthree + `rgthree-comfy`,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-main-rgthree-comfy",
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-main-item-rgthree-comfy",
|
||||
submenu: {
|
||||
options: [
|
||||
{
|
||||
content: "Actions",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconGear + "Open rgthree-comfy Settings",
|
||||
disabled: !!that.settingsDialog,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args) => {
|
||||
that.settingsDialog = new RgthreeConfigDialog().show();
|
||||
that.settingsDialog.addEventListener("close", (e) => {
|
||||
that.settingsDialog = null;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
content: iconReplace + ` Convert ${rerouteLabel} Reroutes`,
|
||||
disabled: !rerouteNodes.length,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args) => {
|
||||
const msg = `Convert ${rerouteLabel} ComfyUI Reroutes to Reroute (rgthree) nodes? \n` +
|
||||
`(First save a copy of your workflow & check reroute connections afterwards)`;
|
||||
if (!window.confirm(msg)) {
|
||||
return;
|
||||
}
|
||||
(async () => {
|
||||
for (const node of [...rerouteNodes]) {
|
||||
if (node.type == "Reroute") {
|
||||
that.replacingReroute = node.id;
|
||||
await replaceNode(node, NodeTypesString.REROUTE);
|
||||
that.replacingReroute = null;
|
||||
}
|
||||
}
|
||||
})();
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "More...",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconStarFilled + "Star on Github",
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-github",
|
||||
callback: (...args) => {
|
||||
window.open("https://github.com/rgthree/rgthree-comfy", "_blank");
|
||||
},
|
||||
},
|
||||
],
|
||||
options: that.getRgthreeContextMenuItems(),
|
||||
},
|
||||
});
|
||||
return options;
|
||||
};
|
||||
}, 1000);
|
||||
}
|
||||
getRgthreeContextMenuItems() {
|
||||
const [canvas, graph] = [app.canvas, app.graph];
|
||||
const selectedNodes = Object.values(canvas.selected_nodes || {});
|
||||
let rerouteNodes = [];
|
||||
if (selectedNodes.length) {
|
||||
rerouteNodes = selectedNodes.filter((n) => n.type === "Reroute");
|
||||
}
|
||||
else {
|
||||
rerouteNodes = graph._nodes.filter((n) => n.type == "Reroute");
|
||||
}
|
||||
const rerouteLabel = selectedNodes.length ? "selected" : "all";
|
||||
return [
|
||||
{
|
||||
content: "Actions",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconGear + "Settings (rgthree-comfy)",
|
||||
disabled: !!this.settingsDialog,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args) => {
|
||||
this.settingsDialog = new RgthreeConfigDialog().show();
|
||||
this.settingsDialog.addEventListener("close", (e) => {
|
||||
this.settingsDialog = null;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
content: iconReplace + ` Convert ${rerouteLabel} Reroutes`,
|
||||
disabled: !rerouteNodes.length,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: (...args) => {
|
||||
const msg = `Convert ${rerouteLabel} ComfyUI Reroutes to Reroute (rgthree) nodes? \n` +
|
||||
`(First save a copy of your workflow & check reroute connections afterwards)`;
|
||||
if (!window.confirm(msg)) {
|
||||
return;
|
||||
}
|
||||
(async () => {
|
||||
for (const node of [...rerouteNodes]) {
|
||||
if (node.type == "Reroute") {
|
||||
this.replacingReroute = node.id;
|
||||
await replaceNode(node, NodeTypesString.REROUTE);
|
||||
this.replacingReroute = null;
|
||||
}
|
||||
}
|
||||
})();
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "More...",
|
||||
disabled: true,
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-label",
|
||||
},
|
||||
{
|
||||
content: iconStarFilled + "Star on Github",
|
||||
className: "rgthree-contextmenu-item rgthree-contextmenu-github",
|
||||
callback: (...args) => {
|
||||
window.open("https://github.com/rgthree/rgthree-comfy", "_blank");
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
initializeComfyUIHooks() {
|
||||
const rgthree = this;
|
||||
const queuePrompt = app.queuePrompt;
|
||||
@@ -361,7 +396,7 @@ class Rgthree extends EventTarget {
|
||||
const messageContainer = document.createElement("div");
|
||||
messageContainer.setAttribute("type", data.type || "info");
|
||||
const message = document.createElement("span");
|
||||
message.innerText = data.message;
|
||||
message.innerHTML = data.message;
|
||||
messageContainer.appendChild(message);
|
||||
for (let a = 0; a < (data.actions || []).length; a++) {
|
||||
const action = data.actions[a];
|
||||
|
||||
@@ -24,3 +24,9 @@ export const iconGear = `
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7848 0.449982C13.8239 0.449982 14.7167 1.16546 14.9122 2.15495L14.9991 2.59495C15.3408 4.32442 17.1859 5.35722 18.9016 4.7794L19.3383 4.63233C20.3199 4.30175 21.4054 4.69358 21.9249 5.56605L22.7097 6.88386C23.2293 7.75636 23.0365 8.86366 22.2504 9.52253L21.9008 9.81555C20.5267 10.9672 20.5267 13.0328 21.9008 14.1844L22.2504 14.4774C23.0365 15.1363 23.2293 16.2436 22.7097 17.1161L21.925 18.4339C21.4054 19.3064 20.3199 19.6982 19.3382 19.3676L18.9017 19.2205C17.1859 18.6426 15.3408 19.6754 14.9991 21.405L14.9122 21.845C14.7167 22.8345 13.8239 23.55 12.7848 23.55H11.2152C10.1761 23.55 9.28331 22.8345 9.08781 21.8451L9.00082 21.4048C8.65909 19.6754 6.81395 18.6426 5.09822 19.2205L4.66179 19.3675C3.68016 19.6982 2.59465 19.3063 2.07505 18.4338L1.2903 17.1161C0.770719 16.2436 0.963446 15.1363 1.74956 14.4774L2.09922 14.1844C3.47324 13.0327 3.47324 10.9672 2.09922 9.8156L1.74956 9.52254C0.963446 8.86366 0.77072 7.75638 1.2903 6.8839L2.07508 5.56608C2.59466 4.69359 3.68014 4.30176 4.66176 4.63236L5.09831 4.77939C6.81401 5.35722 8.65909 4.32449 9.00082 2.59506L9.0878 2.15487C9.28331 1.16542 10.176 0.449982 11.2152 0.449982H12.7848ZM12 15.3C13.8225 15.3 15.3 13.8225 15.3 12C15.3 10.1774 13.8225 8.69998 12 8.69998C10.1774 8.69998 8.69997 10.1774 8.69997 12C8.69997 13.8225 10.1774 15.3 12 15.3Z" />
|
||||
</svg>`;
|
||||
export const checkmark = `
|
||||
<svg viewBox="0 0 32 32" fill="currentColor" class="icon-checkmark">
|
||||
<g transform="translate(-518.000000, -1039.000000)">
|
||||
<path d="M548.783,1040.2 C547.188,1038.57 544.603,1038.57 543.008,1040.2 L528.569,1054.92 L524.96,1051.24 C523.365,1049.62 520.779,1049.62 519.185,1051.24 C517.59,1052.87 517.59,1055.51 519.185,1057.13 L525.682,1063.76 C527.277,1065.39 529.862,1065.39 531.457,1063.76 L548.783,1046.09 C550.378,1044.46 550.378,1041.82 548.783,1040.2"></path>
|
||||
</g>
|
||||
</svg>`;
|
||||
|
||||
+15
-35
@@ -155,6 +155,12 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
static create() {
|
||||
return document.createElement(RgthreeProgressBar.NAME);
|
||||
}
|
||||
get currentNodeId() {
|
||||
var _a, _b;
|
||||
const prompt = this.currentPromptExecution;
|
||||
const nodeId = ((_a = prompt === null || prompt === void 0 ? void 0 : prompt.errorDetails) === null || _a === void 0 ? void 0 : _a.node_id) || ((_b = prompt === null || prompt === void 0 ? void 0 : prompt.currentlyExecuting) === null || _b === void 0 ? void 0 : _b.nodeId);
|
||||
return nodeId || null;
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.shadow = null;
|
||||
@@ -162,16 +168,10 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
this.onProgressUpdateBound = this.onProgressUpdate.bind(this);
|
||||
this.connected = false;
|
||||
}
|
||||
maybeGetComfyGraph() {
|
||||
var _a;
|
||||
return ((_a = window === null || window === void 0 ? void 0 : window.app) === null || _a === void 0 ? void 0 : _a.graph) || null;
|
||||
}
|
||||
maybeGetComfyCanvas() {
|
||||
var _a;
|
||||
return ((_a = window === null || window === void 0 ? void 0 : window.app) === null || _a === void 0 ? void 0 : _a.canvas) || null;
|
||||
}
|
||||
onProgressUpdate(e) {
|
||||
var _a, _b, _c, _d;
|
||||
if (!this.connected)
|
||||
return;
|
||||
const prompt = e.detail.prompt;
|
||||
this.currentPromptExecution = prompt;
|
||||
if (prompt === null || prompt === void 0 ? void 0 : prompt.errorDetails) {
|
||||
@@ -222,10 +222,16 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
}
|
||||
}
|
||||
connectedCallback() {
|
||||
if (!this.connected) {
|
||||
SERVICE.addEventListener("progress-update", this.onProgressUpdateBound);
|
||||
this.connected = true;
|
||||
}
|
||||
if (this.shadow) {
|
||||
this.progressTextEl.innerText = 'Idle';
|
||||
this.progressNodesEl.style.width = `0%`;
|
||||
this.progressStepsEl.style.width = `0%`;
|
||||
return;
|
||||
}
|
||||
SERVICE.addEventListener("progress-update", this.onProgressUpdateBound);
|
||||
this.shadow = this.attachShadow({ mode: "open" });
|
||||
const sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync(`
|
||||
@@ -307,37 +313,11 @@ export class RgthreeProgressBar extends HTMLElement {
|
||||
this.progressTextEl = document.createElement("span");
|
||||
this.progressTextEl.innerText = "Idle";
|
||||
this.shadow.appendChild(this.progressTextEl);
|
||||
overlayEl.addEventListener("click", (e) => {
|
||||
this.onClick(e);
|
||||
});
|
||||
this.connected = true;
|
||||
}
|
||||
disconnectedCallback() {
|
||||
this.connected = false;
|
||||
SERVICE.removeEventListener("progress-update", this.onProgressUpdateBound);
|
||||
}
|
||||
onClick(e) {
|
||||
var _a, _b;
|
||||
const prompt = this.currentPromptExecution;
|
||||
const nodeId = ((_a = prompt === null || prompt === void 0 ? void 0 : prompt.errorDetails) === null || _a === void 0 ? void 0 : _a.node_id) || ((_b = prompt === null || prompt === void 0 ? void 0 : prompt.currentlyExecuting) === null || _b === void 0 ? void 0 : _b.nodeId);
|
||||
if (!nodeId)
|
||||
return;
|
||||
const graph = this.maybeGetComfyGraph();
|
||||
const canvas = this.maybeGetComfyCanvas();
|
||||
if (graph && canvas) {
|
||||
const node = graph.getNodeById(Number(nodeId));
|
||||
if (node) {
|
||||
canvas.centerOnNode(node);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
updateProgress() {
|
||||
if (!this.shadow) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
RgthreeProgressBar.NAME = "rgthree-progress-bar";
|
||||
customElements.define(RgthreeProgressBar.NAME, RgthreeProgressBar);
|
||||
|
||||
Reference in New Issue
Block a user