From d074afcab7d620273bb71c6a1209c50e095aad7b Mon Sep 17 00:00:00 2001 From: ChrisColeTech Date: Sun, 1 Sep 2024 22:03:09 -0400 Subject: [PATCH] hold off on context menu --- pyproject.toml | 2 +- web/comfyui/elegant.css | 623 ------------------------------------ web/comfyui/elegant.js | 291 ----------------- web/comfyui/shared_utils.js | 115 ------- web/comfyui/svgs.js | 160 --------- web/comfyui/utils_dom.js | 291 ----------------- 6 files changed, 1 insertion(+), 1481 deletions(-) delete mode 100644 web/comfyui/elegant.css delete mode 100644 web/comfyui/elegant.js delete mode 100644 web/comfyui/shared_utils.js delete mode 100644 web/comfyui/svgs.js delete mode 100644 web/comfyui/utils_dom.js diff --git a/pyproject.toml b/pyproject.toml index 7f2c8ae..089b756 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-line-counter" description = "This custom node package for ComfyUI is designed to streamline your workflow with powerful file-counting capabilities." -version = "1.0.3" +version = "1.0.4" license = {file = "LICENSE"} [project.urls] diff --git a/web/comfyui/elegant.css b/web/comfyui/elegant.css deleted file mode 100644 index 6b58652..0000000 --- a/web/comfyui/elegant.css +++ /dev/null @@ -1,623 +0,0 @@ -.elegant-top-messages-container { - position: fixed; - z-index: 9999; - top: 0; - left: 0; - width: 100%; - height: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: start; -} - -.elegant-top-messages-container > div { - position: relative; - height: fit-content; - padding: 4px; - margin-top: -100px; /* re-set by JS */ - opacity: 0; - transition: all 0.33s ease-in-out; - z-index: 3; -} - -.elegant-top-messages-container > div:last-child { - z-index: 2; -} - -.elegant-top-messages-container > div:not(.-show) { - z-index: 1; -} - -.elegant-top-messages-container > div.-show { - opacity: 1; - margin-top: 0px !important; -} - -.elegant-top-messages-container > div.-show { - opacity: 1; - transform: translateY(0%); -} - -.elegant-top-messages-container > div > div { - position: relative; - background: #353535; - color: #fff; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - height: fit-content; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.88); - padding: 6px 12px; - border-radius: 4px; - font-family: Arial, sans-serif; - font-size: 14px; -} - -.elegant-top-messages-container > div > div > span { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} - -.elegant-top-messages-container > div > div > span svg { - width: 20px; - height: auto; - margin-right: 8px; -} - -.elegant-top-messages-container > div > div > span svg.icon-checkmark { - fill: #2e9720; -} - -.elegant-top-messages-container [type='warn']::before, -.elegant-top-messages-container [type='success']::before { - content: '⚠️'; - display: inline-block; - flex: 0 0 auto; - font-size: 18px; - margin-right: 4px; - line-height: 1; -} - -.elegant-top-messages-container [type='success']::before { - content: '🎉'; -} - -.elegant-top-messages-container a { - cursor: pointer; - text-decoration: underline; - color: #fc0; - margin-left: 4px; - display: inline-block; - line-height: 1; -} - -.elegant-top-messages-container a:hover { - color: #fc0; - text-decoration: none; -} - -/* Fix node selector being crazy long b/c of array types. */ -.litegraph.litesearchbox input, -.litegraph.litesearchbox select { - max-width: 250px; -} - -/* There's no reason for this z-index to be so high. It layers on top of things it shouldn't, - (like pythongssss' image gallery, the properties panel, etc.) */ -.comfy-multiline-input { - z-index: 1 !important; -} - -.comfy-multiline-input:focus { - z-index: 2 !important; -} - -.litegraph .dialog { - z-index: 3 !important; /* This is set to 1, but goes under the multi-line inputs, so bump it. */ -} - -:not(#fakeid) .elegant-button-reset { - position: relative; - appearance: none; - cursor: pointer; - border: 0; - background: transparent; - color: inherit; - padding: 0; - margin: 0; -} - -:not(#fakeid) .elegant-button { - --padding-top: 7px; - --padding-bottom: 9px; - --padding-x: 16px; - position: relative; - cursor: pointer; - border: 0; - border-radius: 0.25rem; - background: rgba(0, 0, 0, 0.5); - color: white; - font-family: system-ui, sans-serif; - font-size: 1rem; - line-height: 1; - white-space: nowrap; - text-decoration: none; - margin: 0.25rem; - box-shadow: 0px 0px 2px rgb(0, 0, 0); - background: #212121; - transition: all 0.1s ease-in-out; - padding: var(--padding-top) var(--padding-x) var(--padding-bottom); - display: inline-flex; - flex-direction: row; - align-items: center; - justify-content: center; -} -:not(#fakeid) .elegant-button::before, -:not(#fakeid) .elegant-button::after { - content: ''; - display: block; - position: absolute; - border-radius: 0.25rem; - left: 0; - top: 0; - width: 100%; - height: 100%; - box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.12), inset -1px -1px 0px rgba(0, 0, 0, 0.75); - background: linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.15)); - mix-blend-mode: screen; -} -:not(#fakeid) .elegant-button::after { - mix-blend-mode: multiply; -} -:not(#fakeid) .elegant-button:hover { - background: #303030; -} -:not(#fakeid) .elegant-button:active { - box-shadow: 0px 0px 0px rgba(0, 0, 0, 0); - background: #121212; - padding: calc(var(--padding-top) + 1px) calc(var(--padding-x) - 1px) - calc(var(--padding-bottom) - 1px) calc(var(--padding-x) + 1px); -} -:not(#fakeid) .elegant-button:active::before, -:not(#fakeid) .elegant-button:active::after { - box-shadow: 1px 1px 0px rgba(255, 255, 255, 0.15), inset 1px 1px 0px rgba(0, 0, 0, 0.5), - inset 1px 3px 5px rgba(0, 0, 0, 0.33); -} -:not(#fakeid) .elegant-button.-blue { - background: #346599 !important; -} -:not(#fakeid) .elegant-button.-blue:hover { - background: #3b77b8 !important; -} -:not(#fakeid) .elegant-button.-blue:active { - background: #1d5086 !important; -} -:not(#fakeid) .elegant-button.-green { - background: linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.15)), #14580b; -} -:not(#fakeid) .elegant-button.-green:hover { - background: linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.15)), #1a6d0f; -} -:not(#fakeid) .elegant-button.-green:active { - background: linear-gradient(to bottom, rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.06)), #0f3f09; -} -:not(#fakeid) .elegant-button[disabled] { - box-shadow: none; - background: #666 !important; - color: #aaa; - pointer-events: none; -} -:not(#fakeid) .elegant-button[disabled]::before, -:not(#fakeid) .elegant-button[disabled]::after { - display: none; -} - -.elegant-dialog { - outline: 0; - border: 0; - border-radius: 6px; - background: #414141; - color: #fff; - box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.05), inset -1px -1px 0px rgba(0, 0, 0, 0.5), - 2px 2px 20px rgb(0, 0, 0); - max-width: 800px; - box-sizing: border-box; - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - font-size: 1rem; - padding: 0; - max-height: calc(100% - 32px); -} -.elegant-dialog *, -.elegant-dialog *::before, -.elegant-dialog *::after { - box-sizing: inherit; -} - -.elegant-dialog-container > * { - padding: 8px 16px; -} -.elegant-dialog-container > *:first-child { - padding-top: 16px; -} -.elegant-dialog-container > *:last-child { - padding-bottom: 16px; -} - -.elegant-dialog.-iconed::after { - content: ''; - font-size: 276px; - position: absolute; - right: 0px; - bottom: 0px; - opacity: 0.15; - display: block; - width: 237px; - overflow: hidden; - height: 186px; - line-height: 1; - pointer-events: none; - z-index: -1; -} - -.elegant-dialog.-iconed.-help::after { - content: '🛟'; -} - -.elegant-dialog.-iconed.-settings::after { - content: '⚙️'; -} - -@media (max-width: 832px) { - .elegant-dialog { - max-width: calc(100% - 32px); - } -} -.elegant-dialog-container-title { - display: flex; - flex-direction: row; - align-items: center; - justify-content: start; -} - -.elegant-dialog-container-title > svg:first-child { - width: 36px; - height: 36px; - margin-right: 16px; -} - -.elegant-dialog-container-title h2 { - font-size: 1.375rem; - margin: 0; - font-weight: bold; -} - -.elegant-dialog-container-title h2 small { - font-size: 0.8125rem; - font-weight: normal; - opacity: 0.75; -} - -.elegant-dialog-container-content { - overflow: auto; - max-height: calc(100vh - 200px); /* Arbitrary height to copensate for margin, title, and footer.*/ -} - -.elegant-dialog-container-content p { - font-size: 0.8125rem; - margin-top: 0; -} - -.elegant-dialog-container-content ul li p { - margin-bottom: 4px; -} - -.elegant-dialog-container-content ul li p + p { - margin-top: 0.5em; -} - -.elegant-dialog-container-content ul li ul { - margin-top: 0.5em; - margin-bottom: 1em; -} - -.elegant-dialog-container-content p code { - display: inline-block; - padding: 2px 4px; - margin: 0px 2px; - border: 1px solid rgba(255, 255, 255, 0.25); - border-radius: 3px; - background: rgba(255, 255, 255, 0.1); -} - -.elegant-dialog-container-footer { - display: flex; - align-items: center; - justify-content: center; -} - -body.elegant-dialog-open > *:not(.elegant-dialog):not(.elegant-top-messages-container) { - filter: blur(5px); -} - -.elegant-menu { - list-style: none; - padding: 0; - margin: 0; - position: fixed; - z-index: 999999; - pointer-events: none; - opacity: 0; - transition: opacity 0.08s ease-in-out; - color: #dde; - background-color: #111; - font-size: 12px; - box-shadow: 0 0 10px black !important; -} -.elegant-menu > li { - position: relative; - padding: 4px 6px; - z-index: 9999; - white-space: nowrap; -} -.elegant-menu > li[role='button'] { - background-color: var(--comfy-menu-bg) !important; - color: var(--input-text); - cursor: pointer; -} -.elegant-menu > li[role='button']:hover { - filter: brightness(155%); -} -.elegant-menu[state^='measuring'] { - display: block; - opacity: 0; -} -.elegant-menu[state='open'] { - display: block; - opacity: 1; - pointer-events: all; -} - -.elegant-top-menu { - box-sizing: border-box; - white-space: nowrap; - background: var(--content-bg); - color: var(--content-fg); - display: flex; - flex-direction: column; -} -.elegant-top-menu * { - box-sizing: inherit; -} -.elegant-top-menu menu { - list-style: none; - padding: 0; - margin: 0; -} -.elegant-top-menu menu > li:not(#fakeid) { - list-style: none; - padding: 0; - margin: 0; -} -.elegant-top-menu menu > li:not(#fakeid) > button { - cursor: pointer; - padding: 8px 12px 8px 8px; - width: 100%; - text-align: start; - display: flex; - flex-direction: row; - align-items: center; - justify-content: start; -} -.elegant-top-menu menu > li:not(#fakeid) > button:hover { - background-color: var(--comfy-input-bg); -} -.elegant-top-menu menu > li:not(#fakeid) > button svg { - height: 16px; - width: auto; - margin-inline-end: 0.6em; -} -.elegant-top-menu menu > li:not(#fakeid) > button svg.github-star { - fill: rgb(227, 179, 65); -} -.elegant-top-menu menu > li:not(#fakeid).elegant-message { - min-height: 32px; -} -.elegant-top-menu menu > li:not(#fakeid).elegant-message > span { - padding: 8px 12px; - display: block; - width: 100%; - text-align: center; - font-style: italic; - font-size: 12px; -} - -.elegant-dialog.-settings { - width: 100%; -} - -.elegant-dialog.-settings fieldset { - border: 1px solid rgba(255, 255, 255, 0.25); - padding: 0 12px 8px; - margin-bottom: 16px; -} - -.elegant-dialog.-settings fieldset > legend { - margin-left: 8px; - padding: 0 8px; - opacity: 0.5; -} - -.elegant-dialog.-settings .formrow { - display: flex; - flex-direction: column; -} - -.elegant-dialog.-settings .formrow + .formrow { - border-top: 1px solid rgba(255, 255, 255, 0.25); -} - -.elegant-dialog.-settings .fieldrow { - display: flex; - flex-direction: row; -} - -.elegant-dialog.-settings .fieldrow > label { - flex: 1 1 auto; - user-select: none; - padding: 8px 12px 12px; -} - -.elegant-dialog.-settings .fieldrow > label span { - font-weight: bold; -} - -.elegant-dialog.-settings .fieldrow > label small { - display: block; - margin-top: 4px; - font-size: 0.6875rem; - opacity: 0.75; - padding-left: 16px; -} - -.elegant-dialog.-settings .fieldrow ~ .fieldrow { - font-size: 0.9rem; - border-top: 1px dotted rgba(255, 255, 255, 0.25); -} - -.elegant-dialog.-settings .fieldrow ~ .fieldrow label { - padding-left: 28px; -} - -.elegant-dialog.-settings .fieldrow:first-child:not(.-checked) ~ .fieldrow { - display: none; -} - -.elegant-dialog.-settings .fieldrow:hover { - background: rgba(255, 255, 255, 0.1); -} - -.elegant-dialog.-settings .fieldrow ~ .fieldrow span { - font-weight: normal; -} - -.elegant-dialog.-settings .fieldrow > .fieldrow-value { - display: flex; - align-items: center; - justify-content: end; - flex: 0 0 auto; - width: 50%; - max-width: 230px; -} - -.elegant-dialog.-settings .fieldrow.-type-boolean > .fieldrow-value { - max-width: 64px; -} - -.elegant-dialog.-settings .fieldrow.-type-number input { - width: 48px; - text-align: right; -} - -.elegant-dialog.-settings .fieldrow input[type='checkbox'] { - width: 24px; - height: 24px; - cursor: pointer; -} - -.elegant-comfyui-settings-row div { - display: flex; - flex-direction: row; - align-items: center; - justify-content: end; -} - -.elegant-comfyui-settings-row div svg { - width: 36px; - height: 36px; - margin-right: 16px; -} - -.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy, -.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-item { - display: flex; - flex-direction: row; - align-items: center; - justify-content: start; -} - -.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy svg, -.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-item svg { - fill: currentColor; - width: auto; - height: 16px; - margin-right: 6px; -} - -.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-item svg.github-star { - fill: rgb(227, 179, 65); -} - -.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy, -.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-label { - color: #dde; - background-color: #212121 !important; - margin: 0; - padding: 2px; - cursor: default; - opacity: 1; - padding: 4px; - font-weight: bold; -} - -.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy { - font-size: 1.1em; - color: #fff; - background-color: #090909 !important; - justify-content: center; - padding: 4px 8px; -} - -elegant-progress-bar { - display: block; - position: relative; - z-index: 999; - top: 0; - left: 0; - height: 14px; - font-size: 10px; - width: 100%; - overflow: hidden; - box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.25); - box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.25), 0px 1px 0px rgba(255, 255, 255, 0.125); -} - -* ~ elegant-progress-bar, -.comfyui-body-bottom elegant-progress-bar { - box-shadow: 0px -1px 0px rgb(0, 0, 0), inset 0px 1px 0px rgba(255, 255, 255, 0.15), - inset 0px -1px 0px rgba(0, 0, 0, 0.25), 0px 1px 0px rgba(255, 255, 255, 0.125); -} - -body:not([style*='grid']) elegant-progress-bar { - position: fixed; - top: 0px; - bottom: auto; -} -body:not([style*='grid']) elegant-progress-bar.elegant-pos-bottom { - top: auto; - bottom: 0px; -} - -.elegant-debug-keydowns { - display: block; - position: fixed; - z-index: 999; - top: 3px; - right: 8px; - font-size: 10px; - color: #fff; - font-family: sans-serif; -} diff --git a/web/comfyui/elegant.js b/web/comfyui/elegant.js deleted file mode 100644 index e7469bd..0000000 --- a/web/comfyui/elegant.js +++ /dev/null @@ -1,291 +0,0 @@ -import { app, ComfyApp } from '/scripts/app.js' -import { api } from '/scripts/api.js' -import { iconGear, iconNode, iconReplace, iconStarFilled } from './svgs.js' -import { injectCss } from './shared_utils.js' - -class Elegant extends EventTarget { - constructor() { - var _a, _b, _c, _d - super() - this.api = api - this.settingsDialog = null - this.progressBarEl = null - this.queueNodeIds = null - this.monitorBadLinksAlerted = false - this.monitorLinkTimeout = null - this.processingQueue = false - this.loadingApiJson = false - this.replacingReroute = null - this.processingMouseDown = false - this.processingMouseUp = false - this.processingMouseMove = false - this.lastAdjustedMouseEvent = null - this.canvasCurrentlyCopyingToClipboard = false - this.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false - this.initialGraphToPromptSerializedWorkflowBecauseComfyUIBrokeStuff = null - this.elDebugKeydowns = null - this.nodes = [] - this.isMac = !!( - ((_a = navigator.platform) === null || _a === void 0 - ? void 0 - : _a.toLocaleUpperCase().startsWith('MAC')) || - ((_c = (_b = navigator.userAgentData) === null || _b === void 0 ? void 0 : _b.platform) === - null || _c === void 0 - ? void 0 - : _c.toLocaleUpperCase().startsWith('MAC')) - ) - - this.initializeGraphAndCanvasHooks() - // Wrap the method - const originalGetNodeDefs = api.getNodeDefs.bind(api) - - api.getNodeDefs = async function (...args) { - // Trigger a custom event before calling the original method - const event = new CustomEvent('getNodeDefsCalled', { - detail: { args }, - }) - window.dispatchEvent(event) - - // Call the original method - const result = await originalGetNodeDefs(...args) - - // Optionally, you can also dispatch another event after the method completes - window.dispatchEvent( - new CustomEvent('getNodeDefsCompleted', { - detail: { result }, - }), - ) - - return result - } - - // Add event listeners - window.addEventListener('getNodeDefsCalled', (event) => {}) - - window.addEventListener('getNodeDefsCompleted', (event) => { - this.nodes = Object.values(event.detail.result).filter((n) => n.category.includes('CCTech')) - }) - - this.initializeContextMenu() - this.cssPromise = injectCss('extensions/ComfyUI-Line-counter/comfyui/elegant.css') - } - - async initializeGraphAndCanvasHooks() { - const elegant = this - const graphSerialize = LGraph.prototype.serialize - LGraph.prototype.serialize = function () { - const response = graphSerialize.apply(this, [...arguments]) - elegant.initialGraphToPromptSerializedWorkflowBecauseComfyUIBrokeStuff = response - return response - } - const processMouseDown = LGraphCanvas.prototype.processMouseDown - LGraphCanvas.prototype.processMouseDown = function (e) { - elegant.processingMouseDown = true - const returnVal = processMouseDown.apply(this, [...arguments]) - elegant.dispatchCustomEvent('on-process-mouse-down', { originalEvent: e }) - elegant.processingMouseDown = false - return returnVal - } - const adjustMouseEvent = LGraphCanvas.prototype.adjustMouseEvent - LGraphCanvas.prototype.adjustMouseEvent = function (e) { - adjustMouseEvent.apply(this, [...arguments]) - elegant.lastAdjustedMouseEvent = e - } - const copyToClipboard = LGraphCanvas.prototype.copyToClipboard - LGraphCanvas.prototype.copyToClipboard = function (nodes) { - elegant.canvasCurrentlyCopyingToClipboard = true - elegant.canvasCurrentlyCopyingToClipboardWithMultipleNodes = - Object.values(nodes || this.selected_nodes || []).length > 1 - copyToClipboard.apply(this, [...arguments]) - elegant.canvasCurrentlyCopyingToClipboard = false - elegant.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false - } - const onGroupAdd = LGraphCanvas.onGroupAdd - LGraphCanvas.onGroupAdd = function (...args) { - const graph = app.graph - onGroupAdd.apply(this, [...args]) - LGraphCanvas.onShowPropertyEditor( - {}, - null, - null, - null, - graph._groups[graph._groups.length - 1], - ) - } - } - - async invokeExtensionsAsync(method, ...args) { - return Promise.resolve() - } - dispatchCustomEvent(event, detail) { - if (detail != null) { - return this.dispatchEvent(new CustomEvent(event, { detail })) - } - return this.dispatchEvent(new CustomEvent(event)) - } - async initializeContextMenu() { - const that = this - setTimeout(async () => { - const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions - LGraphCanvas.prototype.getCanvasMenuOptions = function (...args) { - let existingOptions = getCanvasMenuOptions.apply(this, [...args]) - const options = [] - options.push(null) - options.push(null) - options.push(null) - options.push({ - content: `🤖 CCTech`, - className: 'elegant-contextmenu-item elegant-contextmenu-main-item-elegant-comfy', - submenu: { - options: that.getElegantContextMenuItems(), - }, - }) - options.push(null) - options.push(null) - let idx = null - idx = - idx || - existingOptions.findIndex((o) => { - var _a, _b - return (_b = - (_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0 - ? void 0 - : _a.startsWith) === null || _b === void 0 - ? void 0 - : _b.call(_a, 'Queue Group') - }) + 1 - idx = - idx || - existingOptions.findIndex((o) => { - var _a, _b - return (_b = - (_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0 - ? void 0 - : _a.startsWith) === null || _b === void 0 - ? void 0 - : _b.call(_a, 'Queue Selected') - }) + 1 - idx = - idx || - existingOptions.findIndex((o) => { - var _a, _b - return (_b = - (_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0 - ? void 0 - : _a.startsWith) === null || _b === void 0 - ? void 0 - : _b.call(_a, 'Convert to Group') - }) - idx = - idx || - existingOptions.findIndex((o) => { - var _a, _b - return (_b = - (_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0 - ? void 0 - : _a.startsWith) === null || _b === void 0 - ? void 0 - : _b.call(_a, 'Arrange (') - }) - idx = idx || existingOptions.findIndex((o) => !o) + 1 - idx = idx || 3 - existingOptions.splice(idx, 0, ...options) - for (let i = existingOptions.length; i > 0; i--) { - if (existingOptions[i] === null && existingOptions[i + 1] === null) { - existingOptions.splice(i, 1) - } - } - return existingOptions - } - }, 1016) - } - getElegantContextMenuItems() { - 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' - const bookmarkMenuItems = getBookmarks() ?? [] - return [ - { - content: 'Nodes', - disabled: true, - className: 'elegant-contextmenu-item elegant-contextmenu-label', - }, - { - content: iconNode + 'All', - className: 'elegant-contextmenu-item', - has_submenu: true, - submenu: { - options: this.nodes.map((n) => n.display_name), - callback: (value, options, event) => { - const nodeValue = this.nodes.find((n) => n.display_name.includes(value)) - const node = LiteGraph.createNode(nodeValue.name) - node.pos = [this.lastAdjustedMouseEvent.canvasX, this.lastAdjustedMouseEvent.canvasY] - canvas.graph.add(node) - canvas.selectNode(node) - app.graph.setDirtyCanvas(true, true) - }, - extra: { elegant_doNotNest: true }, - }, - }, - // { - // content: 'Actions', - // disabled: true, - // className: 'elegant-contextmenu-item elegant-contextmenu-label', - // }, - // { - // content: iconGear + 'Settings (coming soon)', - // disabled: true, - // className: 'elegant-contextmenu-item', - // callback: (...args) => { - // this.settingsDialog.addEventListener('close', (e) => { - // this.settingsDialog = null - // }) - // }, - // }, - ...bookmarkMenuItems, - { - content: 'More...', - disabled: true, - className: 'elegant-contextmenu-item elegant-contextmenu-label', - }, - { - content: iconStarFilled + 'Star on Github', - className: 'elegant-contextmenu-item elegant-contextmenu-github', - callback: (...args) => { - window.open('https://github.com/ChrisColeTech/', '_blank') - }, - }, - ] - } -} -function getBookmarks() { - const graph = app.graph - const bookmarks = graph._nodes - .filter((n) => n.type === 'NodeTypesString.BOOKMARK') - .sort((a, b) => a.title.localeCompare(b.title)) - .map((n) => ({ - content: `[${n.shortcutKey}] ${n.title}`, - className: 'elegant-contextmenu-item', - callback: () => { - n.canvasToBookmark() - }, - })) - return !bookmarks.length - ? [] - : [ - { - content: '🔖 Bookmarks', - disabled: true, - className: 'elegant-contextmenu-item elegant-contextmenu-label', - }, - ...bookmarks, - ] -} -export const elegant = new Elegant() -window.elegant = elegant diff --git a/web/comfyui/shared_utils.js b/web/comfyui/shared_utils.js deleted file mode 100644 index dad89f6..0000000 --- a/web/comfyui/shared_utils.js +++ /dev/null @@ -1,115 +0,0 @@ -export function getResolver(timeout = 5000) { - const resolver = {} - resolver.id = generateId(8) - resolver.completed = false - resolver.resolved = false - resolver.rejected = false - resolver.promise = new Promise((resolve, reject) => { - resolver.reject = () => { - resolver.completed = true - resolver.rejected = true - reject() - } - resolver.resolve = (data) => { - resolver.completed = true - resolver.resolved = true - resolve(data) - } - }) - resolver.timeout = setTimeout(() => { - if (!resolver.completed) { - resolver.reject() - } - }, timeout) - return resolver -} -const DEBOUNCE_FN_TO_PROMISE = new WeakMap() -export function debounce(fn, ms = 64) { - if (!DEBOUNCE_FN_TO_PROMISE.get(fn)) { - DEBOUNCE_FN_TO_PROMISE.set( - fn, - wait(ms).then(() => { - DEBOUNCE_FN_TO_PROMISE.delete(fn) - fn() - }), - ) - } - return DEBOUNCE_FN_TO_PROMISE.get(fn) -} -export function wait(ms = 16) { - if (ms === 16) { - return new Promise((resolve) => { - requestAnimationFrame(() => { - resolve() - }) - }) - } - return new Promise((resolve) => { - setTimeout(() => { - resolve() - }, ms) - }) -} -function dec2hex(dec) { - return dec.toString(16).padStart(2, '0') -} -export function generateId(length) { - const arr = new Uint8Array(length / 2) - crypto.getRandomValues(arr) - return Array.from(arr, dec2hex).join('') -} -export function getObjectValue(obj, objKey, def) { - if (!obj || !objKey) return def - const keys = objKey.split('.') - const key = keys.shift() - const found = obj[key] - if (keys.length) { - return getObjectValue(found, keys.join('.'), def) - } - return found -} -export function setObjectValue(obj, objKey, value, createMissingObjects = true) { - if (!obj || !objKey) return obj - const keys = objKey.split('.') - const key = keys.shift() - if (obj[key] === undefined) { - if (!createMissingObjects) { - return - } - obj[key] = {} - } - if (!keys.length) { - obj[key] = value - } else { - if (typeof obj[key] != 'object') { - obj[key] = {} - } - setObjectValue(obj[key], keys.join('.'), value, createMissingObjects) - } - return obj -} -export function moveArrayItem(arr, itemOrFrom, to) { - const from = typeof itemOrFrom === 'number' ? itemOrFrom : arr.indexOf(itemOrFrom) - arr.splice(to, 0, arr.splice(from, 1)[0]) -} -export function removeArrayItem(arr, itemOrIndex) { - const index = typeof itemOrIndex === 'number' ? itemOrIndex : arr.indexOf(itemOrIndex) - arr.splice(index, 1) -} -export function injectCss(href) { - if (document.querySelector(`link[href^="${href}"]`)) { - return Promise.resolve() - } - return new Promise((resolve) => { - const link = document.createElement('link') - link.setAttribute('rel', 'stylesheet') - link.setAttribute('type', 'text/css') - const timeout = setTimeout(resolve, 1000) - link.addEventListener('load', (e) => { - clearInterval(timeout) - resolve() - }) - link.href = href - document.head.appendChild(link) - }) -} diff --git a/web/comfyui/svgs.js b/web/comfyui/svgs.js deleted file mode 100644 index d21c72f..0000000 --- a/web/comfyui/svgs.js +++ /dev/null @@ -1,160 +0,0 @@ -import { createElement as $el } from './utils_dom.js' -export const logoElegant = `` -export const github = `` -export const iconStarFilled = ` - - ` -export const iconReplace = ` - - - - - ` -export const iconNode = ` - - - ` -export const iconGear = ` - - ` -export const checkmark = ` - - - - ` -export const logoCivitai = ` - - - - - - - - - - ` -export const iconOutLink = ` - - ` -export const link = ` - - ` -export const pencil = ` - - ` -export const dotdotdot = ` - - - -` -export const models = ` - - - - -` -export const pencilColored = ` - - - - - - - - - ` -export const diskColored = ` - - - - - - - -` -export const folderColored = ` - - -` -export const modelsColored = ` - - - - -` -export const legoBlocksColored = ` - - - - - - - - - - - - -` -export const legoBlockColored = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -` -export const gearColored = ` - - - - -` -export function $svg(markup, attrs) { - if (!markup.match(/^\s* !!n) -} -export function queryOne(selectors, parent = document) { - var _a - return (_a = parent.querySelector(selectors)) !== null && _a !== void 0 ? _a : null -} -export function createText(text) { - return document.createTextNode(text) -} -export function getClosestOrSelf(element, query) { - const el = element - return ( - ((el === null || el === void 0 ? void 0 : el.closest) && - ((el.matches(query) && el) || el.closest(query))) || - null - ) -} -export function createElement(selectorOrMarkup, attrs) { - const frag = getHtmlFragment(selectorOrMarkup) - let element = frag === null || frag === void 0 ? void 0 : frag.firstElementChild - let selector = '' - if (!element) { - selector = selectorOrMarkup.replace(/[\r\n]\s*/g, '') - const tag = getSelectorTag(selector) || 'div' - element = document.createElement(tag) - selector = selector.replace(RGX_TAG, '$2') - selector = selector.replace(RGX_ATTR_ID, '[id="$1"]') - selector = selector.replace( - RGX_ATTR_CLASS, - (match, p1, p2) => `${p1}[class="${p2.replace(/\./g, ' ')}"]`, - ) - } - const selectorAttrs = getSelectorAttributes(selector) - if (selectorAttrs) { - for (const attr of selectorAttrs) { - let matches = attr.substring(1, attr.length - 1).split('=') - let key = localAssertNotFalsy(matches.shift()) - let value = matches.join('=') - if (value === undefined) { - setAttribute(element, key, true) - } else { - value = value.replace(/^['"](.*)['"]$/, '$1') - setAttribute(element, key, value) - } - } - } - if (attrs) { - setAttributes(element, attrs) - } - return element -} -function getSelectorTag(str) { - return tryMatch(str, RGX_TAG) -} -function getSelectorAttributes(selector) { - RGX_ATTRS_MAYBE_OPEN.lastIndex = 0 - let attrs = [] - let result - while ((result = RGX_ATTRS_MAYBE_OPEN.exec(selector))) { - let attr = result[0] - if (attr.endsWith(']')) { - attrs.push(attr) - } else { - attr = - result[0] + getOpenAttributesRecursive(selector.substr(RGX_ATTRS_MAYBE_OPEN.lastIndex), 2) - RGX_ATTRS_MAYBE_OPEN.lastIndex += attr.length - result[0].length - attrs.push(attr) - } - } - return attrs -} -function getOpenAttributesRecursive(selectorSubstring, openCount) { - let matches = selectorSubstring.match(RGX_ATTRS_FOLLOW_OPEN) - let result = '' - if (matches && matches.length) { - result = matches[0] - openCount += result.endsWith(']') ? -1 : 1 - if (openCount > 0) { - result += getOpenAttributesRecursive(selectorSubstring.substr(result.length), openCount) - } - } - return result -} -function tryMatch(str, rgx, index = 1) { - var _a - let found = '' - try { - found = ((_a = str.match(rgx)) === null || _a === void 0 ? void 0 : _a[index]) || '' - } catch (e) { - found = '' - } - return found -} -export function setAttributes(element, data) { - let attr - for (attr in data) { - if (data.hasOwnProperty(attr)) { - setAttribute(element, attr, data[attr]) - } - } -} -function getHtmlFragment(value) { - if (value.match(/^\s*<.*?>[\s\S]*<\/[a-z0-9]+>\s*$/)) { - return document.createRange().createContextualFragment(value.trim()) - } - return null -} -function getChild(value) { - if (value instanceof Node) { - return value - } - if (typeof value === 'string') { - let child = getHtmlFragment(value) - if (child) { - return child - } - if (getSelectorTag(value)) { - return createElement(value) - } - return createText(value) - } - if (value && typeof value.toElement === 'function') { - return value.toElement() - } - return null -} -export function setAttribute(element, attribute, value) { - let isRemoving = value == null - if (attribute === 'default') { - attribute = RGX_DEFAULT_VALUE_PROP.test(element.nodeName) ? 'value' : 'text' - } - if (attribute === 'text') { - empty(element).appendChild(createText(value != null ? String(value) : '')) - } else if (attribute === 'html') { - empty(element).innerHTML += value != null ? String(value) : '' - } else if (attribute == 'style') { - if (typeof value === 'string') { - element.style.cssText = isRemoving ? '' : value != null ? String(value) : '' - } else { - for (const [styleKey, styleValue] of Object.entries(value)) { - element.style[styleKey] = styleValue - } - } - } else if (attribute == 'events') { - for (const [key, fn] of Object.entries(value)) { - addEvent(element, key, fn) - } - } else if (attribute === 'parent') { - value.appendChild(element) - } else if (attribute === 'child' || attribute === 'children') { - if (typeof value === 'string' && /^\[[^\[\]]+\]$/.test(value)) { - const parseable = value.replace(/^\[([^\[\]]+)\]$/, '["$1"]').replace(/,/g, '","') - try { - const parsed = JSON.parse(parseable) - value = parsed - } catch (e) { - console.error(e) - } - } - if (attribute === 'children') { - empty(element) - } - let children = value instanceof Array ? value : [value] - for (let child of children) { - child = getChild(child) - if (child instanceof Node) { - if (element instanceof HTMLTemplateElement) { - element.content.appendChild(child) - } else { - element.appendChild(child) - } - } - } - } else if (attribute == 'for') { - element.htmlFor = value != null ? String(value) : '' - if (isRemoving) { - element.removeAttribute('for') - } - } else if (attribute === 'class' || attribute === 'className' || attribute === 'classes') { - element.className = isRemoving ? '' : Array.isArray(value) ? value.join(' ') : String(value) - } else if (attribute === 'dataset') { - if (typeof value !== 'object') { - console.error('Expecting an object for dataset') - return - } - for (const [key, val] of Object.entries(value)) { - element.dataset[key] = String(val) - } - } else if (attribute == 'onclick' && typeof value === 'function') { - element.addEventListener('click', value) - } else if (['checked', 'disabled', 'readonly', 'required', 'selected'].includes(attribute)) { - element[attribute] = !!value - if (!value) { - element.removeAttribute(attribute) - } else { - element.setAttribute(attribute, attribute) - } - } else if (DIRECT_ATTRIBUTE_MAP.hasOwnProperty(attribute)) { - if (isRemoving) { - element.removeAttribute(DIRECT_ATTRIBUTE_MAP[attribute]) - } else { - element.setAttribute(DIRECT_ATTRIBUTE_MAP[attribute], String(value)) - } - } else if (isRemoving) { - element.removeAttribute(attribute) - } else { - let oldVal = element.getAttribute(attribute) - if (oldVal !== value) { - element.setAttribute(attribute, String(value)) - } - } -} -function addEvent(element, key, fn) { - element.addEventListener(key, fn) -} -function setStyles(element, styles = null) { - if (styles) { - for (let name in styles) { - setStyle(element, name, styles[name]) - } - } - return element -} -function setStyle(element, name, value) { - name = name.indexOf('float') > -1 ? 'cssFloat' : name - if (name.indexOf('-') != -1) { - name = name.replace(/-\D/g, (match) => { - return match.charAt(1).toUpperCase() - }) - } - if (value == String(Number(value)) && RGX_NUMERIC_STYLE.test(name)) { - value = value + RGX_NUMERIC_STYLE_UNIT - } - if (name === 'display' && typeof value !== 'string') { - value = !!value ? null : 'none' - } - element.style[name] = value === null ? null : String(value) - return element -} -export function empty(element) { - while (element.firstChild) { - element.removeChild(element.firstChild) - } - return element -} -export function appendChildren(el, children) { - children = !Array.isArray(children) ? [children] : children - for (let child of children) { - child = getChild(child) - if (child instanceof Node) { - if (el instanceof HTMLTemplateElement) { - el.content.appendChild(child) - } else { - el.appendChild(child) - } - } - } -}