diff --git a/.github/workflows/test-browser-exp.yaml b/.github/workflows/test-browser-exp.yaml index 7be884d31..1f96bc805 100644 --- a/.github/workflows/test-browser-exp.yaml +++ b/.github/workflows/test-browser-exp.yaml @@ -24,6 +24,11 @@ jobs: repository: "Comfy-Org/ComfyUI_frontend" path: "ComfyUI_frontend" ref: ${{ github.head_ref }} + - name: Checkout ComfyUI_devtools + uses: actions/checkout@v4 + with: + repository: "Comfy-Org/ComfyUI_devtools" + path: "ComfyUI/custom_nodes/ComfyUI_devtools" - uses: actions/setup-node@v3 with: node-version: lts/* diff --git a/browser_tests/ComfyPage.ts b/browser_tests/ComfyPage.ts index ec0302641..525b8d9c0 100644 --- a/browser_tests/ComfyPage.ts +++ b/browser_tests/ComfyPage.ts @@ -3,7 +3,7 @@ import { test as base } from '@playwright/test' import dotenv from 'dotenv' dotenv.config() import * as fs from 'fs' -import * as path from 'path' +import { NodeBadgeMode } from '../src/types/nodeSource' interface Position { x: number @@ -202,6 +202,13 @@ export class ComfyPage { // Reset view to force re-rendering of canvas. So that info fields like fps // become hidden. await this.resetView() + + // Hide all badges by default. + await this.setSetting('Comfy.NodeBadge.NodeIdBadgeMode', NodeBadgeMode.None) + await this.setSetting( + 'Comfy.NodeBadge.NodeSourceBadgeMode', + NodeBadgeMode.None + ) } public assetPath(fileName: string) { diff --git a/browser_tests/assets/execution_error.json b/browser_tests/assets/execution_error.json index 76139d2b8..f18793b02 100644 --- a/browser_tests/assets/execution_error.json +++ b/browser_tests/assets/execution_error.json @@ -5,10 +5,10 @@ { "id": 14, "type": "PreviewImage", - "pos": [ - 858, - -41 - ], + "pos": { + "0": 300, + "1": 60 + }, "size": { "0": 213.8594970703125, "1": 50.65289306640625 @@ -23,6 +23,7 @@ "link": 15 } ], + "outputs": [], "properties": { "Node name for S&R": "PreviewImage" } @@ -30,10 +31,10 @@ { "id": 17, "type": "DevToolsErrorRaiseNode", - "pos": [ - 477, - -40 - ], + "pos": { + "0": 20, + "1": 60 + }, "size": { "0": 210, "1": 26 @@ -41,6 +42,7 @@ "flags": {}, "order": 0, "mode": 0, + "inputs": [], "outputs": [ { "name": "IMAGE", @@ -71,10 +73,10 @@ "config": {}, "extra": { "ds": { - "scale": 1.2100000000000006, + "scale": 1, "offset": [ - -266.1038310281165, - 337.94335447664554 + 117.20766722169206, + 472.69035116826046 ] } }, diff --git a/browser_tests/nodeBadge.spec.ts b/browser_tests/nodeBadge.spec.ts new file mode 100644 index 000000000..df97c4d16 --- /dev/null +++ b/browser_tests/nodeBadge.spec.ts @@ -0,0 +1,79 @@ +import { expect } from '@playwright/test' +import { comfyPageFixture as test } from './ComfyPage' +import type { ComfyApp } from '../src/scripts/app' +import { NodeBadgeMode } from '../src/types/nodeSource' + +test.describe('Node Badge', () => { + test('Can add badge', async ({ comfyPage }) => { + await comfyPage.page.evaluate(() => { + const LGraphBadge = window['LGraphBadge'] + const app = window['app'] as ComfyApp + const graph = app.graph + // @ts-expect-error - accessing private property + const nodes = graph._nodes + + for (const node of nodes) { + node.badges = [new LGraphBadge({ text: 'Test Badge' })] + } + + graph.setDirtyCanvas(true, true) + }) + + await expect(comfyPage.canvas).toHaveScreenshot('node-badge.png') + }) + + test('Can add multiple badges', async ({ comfyPage }) => { + await comfyPage.page.evaluate(() => { + const LGraphBadge = window['LGraphBadge'] + const app = window['app'] as ComfyApp + const graph = app.graph + // @ts-expect-error - accessing private property + const nodes = graph._nodes + + for (const node of nodes) { + node.badges = [ + new LGraphBadge({ text: 'Test Badge 1' }), + new LGraphBadge({ text: 'Test Badge 2' }) + ] + } + + graph.setDirtyCanvas(true, true) + }) + + await expect(comfyPage.canvas).toHaveScreenshot('node-badge-multiple.png') + }) + + test('Can add badge left-side', async ({ comfyPage }) => { + await comfyPage.page.evaluate(() => { + const LGraphBadge = window['LGraphBadge'] + const app = window['app'] as ComfyApp + const graph = app.graph + // @ts-expect-error - accessing private property + const nodes = graph._nodes + + for (const node of nodes) { + node.badges = [new LGraphBadge({ text: 'Test Badge' })] + // @ts-expect-error - Enum value + node.badgePosition = 'top-left' + } + + graph.setDirtyCanvas(true, true) + }) + + await expect(comfyPage.canvas).toHaveScreenshot('node-badge-left.png') + }) +}) + +test.describe('Node source badge', () => { + Object.values(NodeBadgeMode).forEach(async (mode) => { + test(`Shows node badges (${mode})`, async ({ comfyPage }) => { + // Execution error workflow has both custom node and core node. + await comfyPage.loadWorkflow('execution_error') + await comfyPage.setSetting('Comfy.NodeBadge.NodeSourceBadgeMode', mode) + await comfyPage.setSetting('Comfy.NodeBadge.NodeIdBadgeMode', mode) + await comfyPage.nextFrame() + await comfyPage.resetView() + await expect(comfyPage.canvas).toHaveScreenshot(`node-badge-${mode}.png`) + }) + }) +}) diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-2x-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-2x-linux.png new file mode 100644 index 000000000..0639a6434 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-2x-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png new file mode 100644 index 000000000..cb20b794b Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-2x-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-2x-linux.png new file mode 100644 index 000000000..f5db50e5f Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-2x-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png new file mode 100644 index 000000000..a8c5b98d6 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-2x-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-2x-linux.png new file mode 100644 index 000000000..ea51f39a5 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-2x-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png new file mode 100644 index 000000000..bccfe3bdd Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-2x-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-2x-linux.png new file mode 100644 index 000000000..ca2aab45f Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-2x-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png new file mode 100644 index 000000000..9d54848a1 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-2x-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-2x-linux.png new file mode 100644 index 000000000..eba530904 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-2x-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png new file mode 100644 index 000000000..fa1d6ed89 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-2x-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-2x-linux.png new file mode 100644 index 000000000..3502fef7e Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-2x-linux.png differ diff --git a/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png new file mode 100644 index 000000000..5e39b99a2 Binary files /dev/null and b/browser_tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png differ diff --git a/package-lock.json b/package-lock.json index eda5253b8..b659554f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.2.48", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.2.1", - "@comfyorg/litegraph": "^0.7.65", + "@comfyorg/litegraph": "^0.7.67", "@primevue/themes": "^4.0.5", "@vitejs/plugin-vue": "^5.0.5", "@vueuse/core": "^11.0.0", @@ -1909,9 +1909,9 @@ "dev": true }, "node_modules/@comfyorg/litegraph": { - "version": "0.7.65", - "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.7.65.tgz", - "integrity": "sha512-Yau14XPptHRmk/2My46mfkQBrZhZgtib75mghgwPelt2oRrk+O4OrhtbPQRzYoll7LmJAA7cHA9YI+zZbJ6IaA==", + "version": "0.7.67", + "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.7.67.tgz", + "integrity": "sha512-X8eRpBmSGTahJteNFDG9P0IsHXOk4QDU3p3iWPhk0rGfTnl4RZ8YcJ8MVo7zRgF3qxxX/Tcw4RpelhnjBJe4Gg==", "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { diff --git a/package.json b/package.json index a4abea1e2..4baa7f778 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ }, "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.2.1", - "@comfyorg/litegraph": "^0.7.65", + "@comfyorg/litegraph": "^0.7.67", "@primevue/themes": "^4.0.5", "@vitejs/plugin-vue": "^5.0.5", "@vueuse/core": "^11.0.0", diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index ea84887e7..350bc5f43 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -32,7 +32,8 @@ import { LGraphGroup, DragAndScale, LGraphCanvas, - ContextMenu + ContextMenu, + LGraphBadge } from '@comfyorg/litegraph' import type { RenderedTreeExplorerNode } from '@/types/treeExplorerTypes' import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore' @@ -98,6 +99,7 @@ onMounted(async () => { window['DragAndScale'] = DragAndScale window['LGraphCanvas'] = LGraphCanvas window['ContextMenu'] = ContextMenu + window['LGraphBadge'] = LGraphBadge comfyApp.vueAppReady = true diff --git a/src/extensions/core/colorPalette.ts b/src/extensions/core/colorPalette.ts index 3a9781954..354cdcfa0 100644 --- a/src/extensions/core/colorPalette.ts +++ b/src/extensions/core/colorPalette.ts @@ -5,7 +5,7 @@ import { LGraphCanvas, LiteGraph } from '@comfyorg/litegraph' // Manage color palettes -const colorPalettes: ColorPalettes = { +export const colorPalettes: ColorPalettes = { dark: { id: 'dark', name: 'Dark (Default)', @@ -52,7 +52,10 @@ const colorPalettes: ColorPalettes = { LINK_COLOR: '#9A9', EVENT_LINK_COLOR: '#A86', - CONNECTING_LINK_COLOR: '#AFA' + CONNECTING_LINK_COLOR: '#AFA', + + BADGE_FG_COLOR: '#FFF', + BADGE_BG_COLOR: '#0F1F0F' }, comfy_base: { 'fg-color': '#fff', @@ -114,7 +117,10 @@ const colorPalettes: ColorPalettes = { LINK_COLOR: '#4CAF50', EVENT_LINK_COLOR: '#FF9800', - CONNECTING_LINK_COLOR: '#2196F3' + CONNECTING_LINK_COLOR: '#2196F3', + + BADGE_FG_COLOR: '#000', + BADGE_BG_COLOR: '#FFF' }, comfy_base: { 'fg-color': '#222', diff --git a/src/extensions/core/contextMenuFilter.ts b/src/extensions/core/contextMenuFilter.ts index 5f44eca3e..675514f6e 100644 --- a/src/extensions/core/contextMenuFilter.ts +++ b/src/extensions/core/contextMenuFilter.ts @@ -17,9 +17,11 @@ const ext = { const filter = document.createElement('input') filter.classList.add('comfy-context-menu-filter') filter.placeholder = 'Filter list' + // @ts-expect-error ctx.root.prepend(filter) const items = Array.from( + // @ts-expect-error ctx.root.querySelectorAll('.litemenu-entry') ) as HTMLElement[] let displayedItems = [...items] @@ -61,14 +63,18 @@ const ext = { } const positionList = () => { + // @ts-expect-error const rect = ctx.root.getBoundingClientRect() // If the top is off-screen then shift the element with scaling applied if (rect.top < 0) { const scale = 1 - + // @ts-expect-error ctx.root.getBoundingClientRect().height / ctx.root.clientHeight + // @ts-expect-error const shift = (ctx.root.clientHeight * scale) / 2 + // @ts-expect-error ctx.root.style.top = -shift + 'px' } } @@ -139,6 +145,7 @@ const ext = { let top = options.event.clientY - 10 const bodyRect = document.body.getBoundingClientRect() + // @ts-expect-error const rootRect = ctx.root.getBoundingClientRect() if ( bodyRect.height && @@ -147,6 +154,7 @@ const ext = { top = Math.max(0, bodyRect.height - rootRect.height - 10) } + // @ts-expect-error ctx.root.style.top = top + 'px' positionList() } diff --git a/src/extensions/core/index.ts b/src/extensions/core/index.ts index fe0f33178..772dd5f3d 100644 --- a/src/extensions/core/index.ts +++ b/src/extensions/core/index.ts @@ -21,3 +21,4 @@ import './uploadImage' import './webcamCapture' import './widgetInputs' import './uploadAudio' +import './nodeBadge' diff --git a/src/extensions/core/nodeBadge.ts b/src/extensions/core/nodeBadge.ts new file mode 100644 index 000000000..066d181e3 --- /dev/null +++ b/src/extensions/core/nodeBadge.ts @@ -0,0 +1,117 @@ +import { app, type ComfyApp } from '@/scripts/app' +import type { ComfyExtension } from '@/types/comfy' +import type { ComfyLGraphNode } from '@/types/comfyLGraphNode' +import { LGraphBadge } from '@comfyorg/litegraph' +import { useSettingStore } from '@/stores/settingStore' +import { computed, ComputedRef, watch } from 'vue' +import { + getNodeSource as getNodeSourceFromPythonModule, + NodeBadgeMode +} from '@/types/nodeSource' +import _ from 'lodash' +import { colorPalettes } from './colorPalette' +import { BadgePosition } from '@comfyorg/litegraph' +import type { Palette } from '@/types/colorPalette' + +function getNodeSource(node: ComfyLGraphNode) { + const pythonModule = (node.constructor as typeof ComfyLGraphNode).nodeData + ?.python_module + return pythonModule ? getNodeSourceFromPythonModule(pythonModule) : null +} + +function isCoreNode(node: ComfyLGraphNode) { + return getNodeSource(node)?.type === 'core' +} + +function getNodeIdBadge(node: ComfyLGraphNode, nodeIdBadgeMode: NodeBadgeMode) { + return nodeIdBadgeMode === NodeBadgeMode.None || + (isCoreNode(node) && nodeIdBadgeMode === NodeBadgeMode.HideBuiltIn) + ? '' + : `#${node.id}` +} + +function getNodeSourceBadge( + node: ComfyLGraphNode, + nodeSourceBadgeMode: NodeBadgeMode +) { + const nodeSource = getNodeSource(node) + return nodeSourceBadgeMode === NodeBadgeMode.None || + (isCoreNode(node) && nodeSourceBadgeMode === NodeBadgeMode.HideBuiltIn) + ? '' + : nodeSource?.badgeText ?? '' +} + +class NodeBadgeExtension implements ComfyExtension { + name = 'Comfy.NodeBadge' + + constructor( + public nodeIdBadgeMode: ComputedRef | null = null, + public nodeSourceBadgeMode: ComputedRef | null = null, + public colorPalette: ComputedRef | null = null, + public defaultColorPalette: Palette | null = null + ) {} + + init(app: ComfyApp) { + if (!app.vueAppReady) { + return + } + + const settingStore = useSettingStore() + this.nodeSourceBadgeMode = computed( + () => + settingStore.get('Comfy.NodeBadge.NodeSourceBadgeMode') as NodeBadgeMode + ) + this.nodeIdBadgeMode = computed( + () => settingStore.get('Comfy.NodeBadge.NodeIdBadgeMode') as NodeBadgeMode + ) + this.colorPalette = computed( + () => colorPalettes[settingStore.get('Comfy.ColorPalette')] + ) + this.defaultColorPalette = colorPalettes['dark'] + + watch(this.nodeSourceBadgeMode, () => { + app.graph.setDirtyCanvas(true, true) + }) + + watch(this.nodeIdBadgeMode, () => { + app.graph.setDirtyCanvas(true, true) + }) + } + + nodeCreated(node: ComfyLGraphNode, app: ComfyApp) { + if (!app.vueAppReady) { + return + } + + node.badgePosition = BadgePosition.TopRight + // @ts-expect-error Disable ComfyUI-Manager's badge drawing by setting badge_enabled to true. Remove this when ComfyUI-Manager's badge drawing is removed. + node.badge_enabled = true + + const badge = computed( + () => + new LGraphBadge({ + text: _.truncate( + [ + getNodeIdBadge(node, this.nodeIdBadgeMode.value), + getNodeSourceBadge(node, this.nodeSourceBadgeMode.value) + ] + .filter((s) => s.length > 0) + .join(' '), + { + length: 25 + } + ), + fgColor: + this.colorPalette.value.colors.litegraph_base?.BADGE_FG_COLOR || + this.defaultColorPalette.colors.litegraph_base.BADGE_FG_COLOR, + bgColor: + this.colorPalette.value.colors.litegraph_base?.BADGE_BG_COLOR || + this.defaultColorPalette.colors.litegraph_base.BADGE_BG_COLOR + }) + ) + + node.badges.push(() => badge.value) + } +} + +app.registerExtension(new NodeBadgeExtension()) diff --git a/src/scripts/app.ts b/src/scripts/app.ts index c02f85e5c..d7808c294 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -51,6 +51,7 @@ import { useToastStore } from '@/stores/toastStore' import { ModelStore, useModelStore } from '@/stores/modelStore' import type { ToastMessageOptions } from 'primevue/toast' import { useWorkspaceStore } from '@/stores/workspaceStateStore' +import { ComfyLGraphNode } from '@/types/comfyLGraphNode' export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview' @@ -2007,12 +2008,12 @@ export class ComfyApp { async registerNodeDef(nodeId: string, nodeData: ComfyNodeDef) { const self = this - const node = class ComfyNode extends LGraphNode { + const node: new () => ComfyLGraphNode = class ComfyNode extends LGraphNode { static comfyClass? = nodeData.name // TODO: change to "title?" once litegraph.d.ts has been updated static title = nodeData.display_name || nodeData.name static nodeData? = nodeData - static category?: string + static category: string = nodeData.category constructor(title?: string) { super(title) @@ -2083,7 +2084,6 @@ export class ComfyApp { app.#invokeExtensionsAsync('nodeCreated', this) } } - // @ts-expect-error node.prototype.comfyClass = nodeData.name this.#addNodeContextMenuHandler(node) @@ -2092,7 +2092,6 @@ export class ComfyApp { await this.#invokeExtensionsAsync('beforeRegisterNodeDef', node, nodeData) LiteGraph.registerNodeType(nodeId, node) - node.category = nodeData.category } async registerNodesFromDefs(defs: Record) { diff --git a/src/stores/settingStore.ts b/src/stores/settingStore.ts index 63353ebda..882c5c630 100644 --- a/src/stores/settingStore.ts +++ b/src/stores/settingStore.ts @@ -10,6 +10,7 @@ import { app } from '@/scripts/app' import { ComfySettingsDialog } from '@/scripts/ui/settings' import { Settings } from '@/types/apiTypes' +import { NodeBadgeMode } from '@/types/nodeSource' import { LinkReleaseTriggerAction, LinkReleaseTriggerMode @@ -330,6 +331,22 @@ export const useSettingStore = defineStore('setting', { options: ['en', 'zh'], defaultValue: navigator.language.split('-')[0] || 'en' }) + + app.ui.settings.addSetting({ + id: 'Comfy.NodeBadge.NodeSourceBadgeMode', + name: 'Node source badge mode', + type: 'combo', + options: Object.values(NodeBadgeMode), + defaultValue: NodeBadgeMode.HideBuiltIn + }) + + app.ui.settings.addSetting({ + id: 'Comfy.NodeBadge.NodeIdBadgeMode', + name: 'Node ID badge mode', + type: 'combo', + options: [NodeBadgeMode.None, NodeBadgeMode.ShowAll], + defaultValue: NodeBadgeMode.ShowAll + }) }, set(key: K, value: Settings[K]) { diff --git a/src/types/apiTypes.ts b/src/types/apiTypes.ts index 4efc5b4e9..21007cfce 100644 --- a/src/types/apiTypes.ts +++ b/src/types/apiTypes.ts @@ -3,6 +3,7 @@ import { zComfyWorkflow, zNodeId } from './comfyWorkflow' import { fromZodError } from 'zod-validation-error' import { colorPalettesSchema } from './colorPalette' import { LinkReleaseTriggerAction } from './searchBoxTypes' +import { NodeBadgeMode } from './nodeSource' const zNodeType = z.string() const zQueueIndex = z.number() @@ -424,6 +425,10 @@ const zLinkReleaseTriggerAction = z.enum( Object.values(LinkReleaseTriggerAction) as [string, ...string[]] ) +const zNodeBadgeMode = z.enum( + Object.values(NodeBadgeMode) as [string, ...string[]] +) + const zSettings = z.record(z.any()).and( z .object({ @@ -484,7 +489,9 @@ const zSettings = z.record(z.any()).and( 'Comfy.Workflow.ModelDownload.AllowedSources': z.array(z.string()), 'Comfy.Workflow.ModelDownload.AllowedSuffixes': z.array(z.string()), 'Comfy.Node.DoubleClickTitleToEdit': z.boolean(), - 'Comfy.Window.UnloadConfirmation': z.boolean() + 'Comfy.Window.UnloadConfirmation': z.boolean(), + 'Comfy.NodeBadge.NodeSourceBadgeMode': zNodeBadgeMode, + 'Comfy.NodeBadge.NodeIdBadgeMode': zNodeBadgeMode }) .optional() ) diff --git a/src/types/colorPalette.ts b/src/types/colorPalette.ts index 7e601ba69..8e9af5ee9 100644 --- a/src/types/colorPalette.ts +++ b/src/types/colorPalette.ts @@ -52,7 +52,9 @@ const litegraphBaseSchema = z WIDGET_SECONDARY_TEXT_COLOR: z.string(), LINK_COLOR: z.string(), EVENT_LINK_COLOR: z.string(), - CONNECTING_LINK_COLOR: z.string() + CONNECTING_LINK_COLOR: z.string(), + BADGE_FG_COLOR: z.string().optional(), + BADGE_BG_COLOR: z.string().optional() }) .passthrough() diff --git a/src/types/comfyLGraphNode.ts b/src/types/comfyLGraphNode.ts new file mode 100644 index 000000000..7d4ed62ae --- /dev/null +++ b/src/types/comfyLGraphNode.ts @@ -0,0 +1,11 @@ +import type { LGraphNode } from '@comfyorg/litegraph' +import type { ComfyNodeDef } from './apiTypes' + +export declare class ComfyLGraphNode extends LGraphNode { + static comfyClass: string + static title: string + static nodeData?: ComfyNodeDef + static category: string + + constructor(title?: string) +} diff --git a/src/types/nodeSource.ts b/src/types/nodeSource.ts index 042079824..a6d5282de 100644 --- a/src/types/nodeSource.ts +++ b/src/types/nodeSource.ts @@ -3,6 +3,7 @@ export type NodeSource = { type: NodeSourceType className: string displayText: string + badgeText: string } export const getNodeSource = (python_module: string): NodeSource => { @@ -11,15 +12,23 @@ export const getNodeSource = (python_module: string): NodeSource => { return { type: 'core', className: 'comfy-core', - displayText: 'Comfy Core' + displayText: 'Comfy Core', + badgeText: '🦊' } } else if (modules[0] === 'custom_nodes') { return { type: 'custom_nodes', className: 'comfy-custom-nodes', - displayText: modules[1] + displayText: modules[1], + badgeText: modules[1] } } else { throw new Error(`Unknown node source: ${python_module}`) } } + +export enum NodeBadgeMode { + None = 'None', + ShowAll = 'Show all', + HideBuiltIn = 'Hide built-in' +}