merge main into rh-test

This commit is contained in:
bymyself
2025-09-28 15:33:29 -07:00
parent 1c0f151d02
commit ff0c15b119
1317 changed files with 85439 additions and 18373 deletions

View File

@@ -1,7 +1,19 @@
import axios from 'axios'
import { debounce } from 'es-toolkit/compat'
import { get } from 'es-toolkit/compat'
import defaultClientFeatureFlags from '@/config/clientFeatureFlags.json'
import defaultClientFeatureFlags from '@/config/clientFeatureFlags.json' with { type: 'json' }
import type {
ModelFile,
ModelFolderInfo
} from '@/platform/assets/schemas/assetSchema'
import { useToastStore } from '@/platform/updates/common/toastStore'
import { type WorkflowTemplates } from '@/platform/workflow/templates/types/template'
import type {
ComfyApiWorkflow,
ComfyWorkflowJSON,
NodeId
} from '@/platform/workflow/validation/schemas/workflowSchema'
import type {
DisplayComponentWsMessage,
EmbeddingsResponse,
@@ -33,16 +45,9 @@ import type {
User,
UserDataFullInfo
} from '@/schemas/apiSchema'
import type {
ComfyApiWorkflow,
ComfyWorkflowJSON,
NodeId
} from '@/schemas/comfyWorkflowSchema'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
import { useToastStore } from '@/stores/toastStore'
import type { NodeExecutionId } from '@/types/nodeIdentification'
import { WorkflowTemplates } from '@/types/workflowTemplateTypes'
interface QueuePromptRequestBody {
client_id: string
@@ -788,11 +793,28 @@ export class ComfyApi extends EventTarget {
/**
* Gets the index of core workflow templates.
* @param locale Optional locale code (e.g., 'en', 'fr', 'zh') to load localized templates
*/
async getCoreWorkflowTemplates(): Promise<WorkflowTemplates[]> {
const res = await axios.get(this.fileURL('/templates/index.json'))
const contentType = res.headers['content-type']
return contentType?.includes('application/json') ? res.data : []
async getCoreWorkflowTemplates(
locale?: string
): Promise<WorkflowTemplates[]> {
const fileName =
locale && locale !== 'en' ? `index.${locale}.json` : 'index.json'
try {
const res = await axios.get(this.fileURL(`/templates/${fileName}`))
const contentType = res.headers['content-type']
return contentType?.includes('application/json') ? res.data : []
} catch (error) {
// Fallback to default English version if localized version doesn't exist
if (locale && locale !== 'en') {
console.warn(
`Localized templates for '${locale}' not found, falling back to English`
)
return this.getCoreWorkflowTemplates()
}
console.error('Error loading core workflow templates:', error)
return []
}
}
/**
@@ -864,14 +886,14 @@ export class ComfyApi extends EventTarget {
* Gets a list of model folder keys (eg ['checkpoints', 'loras', ...])
* @returns The list of model folder keys
*/
async getModelFolders(): Promise<{ name: string; folders: string[] }[]> {
async getModelFolders(): Promise<ModelFolderInfo[]> {
const res = await this.fetchApi(`/experiment/models`)
if (res.status === 404) {
return []
}
const folderBlacklist = ['configs', 'custom_nodes']
return (await res.json()).filter(
(folder: string) => !folderBlacklist.includes(folder)
(folder: ModelFolderInfo) => !folderBlacklist.includes(folder.name)
)
}
@@ -880,9 +902,7 @@ export class ComfyApi extends EventTarget {
* @param {string} folder The folder to list models from, such as 'checkpoints'
* @returns The list of model filenames within the specified folder
*/
async getModels(
folder: string
): Promise<{ name: string; pathIndex: number }[]> {
async getModels(folder: string): Promise<ModelFile[]> {
const res = await this.fetchApi(`/experiment/models/${folder}`)
if (res.status === 404) {
return []
@@ -1263,7 +1283,63 @@ export class ComfyApi extends EventTarget {
}
async getFolderPaths(): Promise<Record<string, string[]>> {
return (await axios.get(this.internalURL('/folder_paths'))).data
const response = await axios
.get(this.internalURL('/folder_paths'))
.catch(() => null)
if (!response) {
return {} // Fallback: no filesystem paths known when API unavailable
}
return response.data
}
/* Frees memory by unloading models and optionally freeing execution cache
* @param {Object} options - The options object
* @param {boolean} options.freeExecutionCache - If true, also frees execution cache
*/
async freeMemory(options: { freeExecutionCache: boolean }) {
try {
let mode = ''
if (options.freeExecutionCache) {
mode = '{"unload_models": true, "free_memory": true}'
} else {
mode = '{"unload_models": true}'
}
const res = await this.fetchApi(`/free`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: mode
})
if (res.status === 200) {
if (options.freeExecutionCache) {
useToastStore().add({
severity: 'success',
summary: 'Models and Execution Cache have been cleared.',
life: 3000
})
} else {
useToastStore().add({
severity: 'success',
summary: 'Models have been unloaded.',
life: 3000
})
}
} else {
useToastStore().add({
severity: 'error',
summary:
'Unloading of models failed. Installed ComfyUI may be an outdated version.',
life: 5000
})
}
} catch (error) {
useToastStore().add({
severity: 'error',
summary: 'An error occurred while trying to unload models.',
life: 5000
})
}
}
/**
@@ -1277,21 +1353,21 @@ export class ComfyApi extends EventTarget {
/**
* Checks if the server supports a specific feature.
* @param featureName The name of the feature to check
* @param featureName The name of the feature to check (supports dot notation for nested values)
* @returns true if the feature is supported, false otherwise
*/
serverSupportsFeature(featureName: string): boolean {
return this.serverFeatureFlags[featureName] === true
return get(this.serverFeatureFlags, featureName) === true
}
/**
* Gets a server feature flag value.
* @param featureName The name of the feature to get
* @param featureName The name of the feature to get (supports dot notation for nested values)
* @param defaultValue The default value if the feature is not found
* @returns The feature value or default
*/
getServerFeature<T = unknown>(featureName: string, defaultValue?: T): T {
return (this.serverFeatureFlags[featureName] ?? defaultValue) as T
return get(this.serverFeatureFlags, featureName, defaultValue) as T
}
/**

View File

@@ -3,7 +3,6 @@ import type { ToastMessageOptions } from 'primevue/toast'
import { reactive } from 'vue'
import { useCanvasPositionConversion } from '@/composables/element/useCanvasPositionConversion'
import { useWorkflowValidation } from '@/composables/useWorkflowValidation'
import { st, t } from '@/i18n'
import {
LGraph,
@@ -14,23 +13,29 @@ import {
} from '@/lib/litegraph/src/litegraph'
import type { Vector2 } from '@/lib/litegraph/src/litegraph'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useToastStore } from '@/platform/updates/common/toastStore'
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
import { ComfyWorkflow } from '@/platform/workflow/management/stores/workflowStore'
import { useWorkflowValidation } from '@/platform/workflow/validation/composables/useWorkflowValidation'
import {
type ComfyApiWorkflow,
type ComfyWorkflowJSON,
type ModelFile,
type NodeId,
isSubgraphDefinition
} from '@/platform/workflow/validation/schemas/workflowSchema'
import type {
ExecutionErrorWsMessage,
NodeError,
ResultItem
} from '@/schemas/apiSchema'
import {
ComfyApiWorkflow,
type ComfyWorkflowJSON,
type ModelFile,
type NodeId,
isSubgraphDefinition
} from '@/schemas/comfyWorkflowSchema'
import {
type ComfyNodeDef as ComfyNodeDefV1,
isComboInputSpecV1,
isComboInputSpecV2
} from '@/schemas/nodeDefSchema'
import { type BaseDOMWidget, DOMWidgetImpl } from '@/scripts/domWidget'
import { getFromWebmFile } from '@/scripts/metadata/ebml'
import { getGltfBinaryMetadata } from '@/scripts/metadata/gltf'
import { getFromIsobmffFile } from '@/scripts/metadata/isobmff'
@@ -41,7 +46,6 @@ import { useDialogService } from '@/services/dialogService'
import { useExtensionService } from '@/services/extensionService'
import { useLitegraphService } from '@/services/litegraphService'
import { useSubgraphService } from '@/services/subgraphService'
import { useWorkflowService } from '@/services/workflowService'
import { useApiKeyAuthStore } from '@/stores/apiKeyAuthStore'
import { useCommandStore } from '@/stores/commandStore'
import { useDomWidgetStore } from '@/stores/domWidgetStore'
@@ -52,16 +56,14 @@ import { useNodeOutputStore } from '@/stores/imagePreviewStore'
import { KeyComboImpl, useKeybindingStore } from '@/stores/keybindingStore'
import { useModelStore } from '@/stores/modelStore'
import { SYSTEM_NODE_DEFS, useNodeDefStore } from '@/stores/nodeDefStore'
import { useSettingStore } from '@/stores/settingStore'
import { useToastStore } from '@/stores/toastStore'
import { useSubgraphStore } from '@/stores/subgraphStore'
import { useWidgetStore } from '@/stores/widgetStore'
import { ComfyWorkflow } from '@/stores/workflowStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import type { ComfyExtension, MissingNodeType } from '@/types/comfy'
import { ExtensionManager } from '@/types/extensionTypes'
import { type ExtensionManager } from '@/types/extensionTypes'
import type { NodeExecutionId } from '@/types/nodeIdentification'
import { ColorAdjustOptions, adjustColor } from '@/utils/colorUtil'
import { type ColorAdjustOptions, adjustColor } from '@/utils/colorUtil'
import { graphToPrompt } from '@/utils/executionUtil'
import { forEachNode } from '@/utils/graphTraversalUtil'
import {
@@ -155,11 +157,22 @@ export class ComfyApp {
// @ts-expect-error fixme ts strict error
_nodeOutputs: Record<string, any>
nodePreviewImages: Record<string, string[]>
// @ts-expect-error fixme ts strict error
#graph: LGraph
private rootGraphInternal: LGraph | undefined
// TODO: Migrate internal usage to the
/** @deprecated Use {@link rootGraph} instead */
get graph() {
return this.#graph
return this.rootGraphInternal!
}
get rootGraph(): LGraph | undefined {
if (!this.rootGraphInternal) {
console.error('ComfyApp graph accessed before initialization')
}
return this.rootGraphInternal
}
// @ts-expect-error fixme ts strict error
canvas: LGraphCanvas
dragOverNode: LGraphNode | null = null
@@ -602,7 +615,10 @@ export class ComfyApp {
const keybindingStore = useKeybindingStore()
const keybinding = keybindingStore.getKeybinding(keyCombo)
if (keybinding && keybinding.targetElementId === 'graph-canvas') {
if (
keybinding &&
keybinding.targetElementId === 'graph-canvas-container'
) {
useCommandStore().execute(keybinding.commandId)
this.graph.change()
@@ -657,7 +673,7 @@ export class ComfyApp {
if (opacity) adjustments.opacity = opacity
if (useColorPaletteStore().completedActivePalette.light_theme) {
adjustments.lightness = 0.5
if (old_bgcolor) adjustments.lightness = 0.5
// Lighten title bar of colored nodes on light theme
if (old_color) {
@@ -768,8 +784,7 @@ export class ComfyApp {
}
}
#addAfterConfigureHandler() {
const { graph } = this
private addAfterConfigureHandler(graph: LGraph) {
const { onConfigure } = graph
graph.onConfigure = function (...args) {
fixLinkInputSlots(this)
@@ -805,16 +820,17 @@ export class ComfyApp {
this.resizeCanvas()
await useWorkspaceStore().workflow.syncWorkflows()
await useSubgraphStore().fetchSubgraphs()
await useExtensionService().loadExtensions()
this.#addProcessKeyHandler()
this.#addConfigureHandler()
this.#addApiUpdateHandlers()
this.#graph = new LGraph()
const graph = new LGraph()
// Register the subgraph - adds type wrapper for Litegraph's `createNode` factory
this.graph.events.addEventListener('subgraph-created', (e) => {
graph.events.addEventListener('subgraph-created', (e) => {
try {
const { subgraph, data } = e.detail
useSubgraphService().registerNewSubgraph(subgraph, data)
@@ -828,9 +844,10 @@ export class ComfyApp {
}
})
this.#addAfterConfigureHandler()
this.addAfterConfigureHandler(graph)
this.canvas = new LGraphCanvas(canvasEl, this.graph)
this.rootGraphInternal = graph
this.canvas = new LGraphCanvas(canvasEl, graph)
// Make canvas states reactive so we can observe changes on them.
this.canvas.state = reactive(this.canvas.state)
@@ -843,22 +860,29 @@ export class ComfyApp {
this.canvas.canvas.addEventListener<'litegraph:set-graph'>(
'litegraph:set-graph',
(e) => {
// Assertion: Not yet defined in litegraph.
const { newGraph } = e.detail
const nodeSet = new Set(newGraph.nodes)
const widgetStore = useDomWidgetStore()
// Assertions: UnwrapRef
for (const { widget } of widgetStore.activeWidgetStates) {
if (!nodeSet.has(widget.node)) {
widgetStore.deactivateWidget(widget.id)
}
}
const activeWidgets: Record<
string,
BaseDOMWidget<object | string>
> = Object.fromEntries(
newGraph.nodes
.flatMap((node) => node.widgets ?? [])
.filter((w) => w instanceof DOMWidgetImpl)
.map((w) => [w.id, w])
)
for (const { widget } of widgetStore.inactiveWidgetStates) {
if (nodeSet.has(widget.node)) {
widgetStore.activateWidget(widget.id)
for (const [
widgetId,
widgetState
] of widgetStore.widgetStates.entries()) {
if (widgetId in activeWidgets) {
widgetState.active = true
widgetState.widget = activeWidgets[widgetId]
} else {
widgetState.active = false
}
}
}
@@ -913,7 +937,7 @@ export class ComfyApp {
LiteGraph.registered_node_types
)) {
// Skip if we already have a backend definition or system definition
if (name in defs || name in SYSTEM_NODE_DEFS) {
if (name in defs || name in SYSTEM_NODE_DEFS || node.skip_list) {
continue
}
@@ -1080,6 +1104,8 @@ export class ComfyApp {
checkForRerouteMigration = false
} = {}
) {
useWorkflowService().beforeLoadNewGraph()
if (clean !== false) {
this.clean()
}
@@ -1115,7 +1141,6 @@ export class ComfyApp {
severity: 'warn'
})
}
useWorkflowService().beforeLoadNewGraph()
useSubgraphService().loadSubgraphs(graphData)
const missingNodeTypes: MissingNodeType[] = []
@@ -1132,6 +1157,13 @@ export class ComfyApp {
nodes: ComfyWorkflowJSON['nodes'],
path: string = ''
) => {
if (!Array.isArray(nodes)) {
console.warn(
'Workflow nodes data is missing or invalid, skipping node processing',
{ nodes, path }
)
return
}
for (let n of nodes) {
// Patch T2IAdapterLoader to ControlNetLoader since they are the same node now
if (n.type == 'T2IAdapterLoader') n.type = 'ControlNetLoader'
@@ -1790,14 +1822,19 @@ export class ComfyApp {
* Clean current state
*/
clean() {
this.nodeOutputs = {}
const { revokeAllPreviews } = useNodeOutputStore()
revokeAllPreviews()
const nodeOutputStore = useNodeOutputStore()
nodeOutputStore.resetAllOutputsAndPreviews()
const executionStore = useExecutionStore()
executionStore.lastNodeErrors = null
executionStore.lastExecutionError = null
useDomWidgetStore().clear()
// Subgraph does not properly implement `clear` and the parent class's
// (`LGraph`) `clear` breaks the subgraph structure.
if (this.graph && !this.canvas.subgraph) {
this.graph.clear()
}
}
clientPosToCanvasPos(pos: Vector2): Vector2 {

View File

@@ -3,11 +3,15 @@ import * as jsondiffpatch from 'jsondiffpatch'
import log from 'loglevel'
import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'
import {
ComfyWorkflow,
useWorkflowStore
} from '@/platform/workflow/management/stores/workflowStore'
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { ExecutedWsMessage } from '@/schemas/apiSchema'
import type { ComfyWorkflowJSON } from '@/schemas/comfyWorkflowSchema'
import { useExecutionStore } from '@/stores/executionStore'
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
import { useSubgraphNavigationStore } from '@/stores/subgraphNavigationStore'
import { ComfyWorkflow, useWorkflowStore } from '@/stores/workflowStore'
import { api } from './api'
import type { ComfyApp } from './app'
@@ -83,7 +87,7 @@ export class ChangeTracker {
app.canvas.ds.offset = this.ds.offset
}
if (this.nodeOutputs) {
app.nodeOutputs = this.nodeOutputs
useNodeOutputStore().restoreOutputs(this.nodeOutputs)
}
if (this.subgraphState) {
const { navigation } = this.subgraphState

View File

@@ -1,4 +1,4 @@
import type { ComfyWorkflowJSON } from '@/schemas/comfyWorkflowSchema'
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
export const defaultGraph: ComfyWorkflowJSON = {
last_node_id: 9,

View File

@@ -55,7 +55,7 @@ export interface DOMWidget<T extends HTMLElement, V extends object | string>
* - widget: Reference to the widget instance
* - onUpdate:modelValue: The update handler for v-model
*/
export type ComponentWidgetCustomProps = Record<string, unknown>
type ComponentWidgetCustomProps = Record<string, unknown>
/**
* Standard props that are handled separately by DomWidget.vue and should be
@@ -375,17 +375,3 @@ LGraphNode.prototype.addDOMWidget = function <
return widget
}
/**
* Prunes widgets that are no longer in the graph.
* @param nodes The nodes to prune widgets for.
*/
export const pruneWidgets = (nodes: LGraphNode[]) => {
const nodeSet = new Set(nodes)
const domWidgetStore = useDomWidgetStore()
for (const { widget } of domWidgetStore.widgetStates.values()) {
if (!nodeSet.has(widget.node)) {
domWidgetStore.unregisterWidget(widget.id)
}
}
}

View File

@@ -1,9 +1,9 @@
import { useChainCallback } from '@/composables/functional/useChainCallback'
import { useBooleanWidget } from '@/composables/widgets/useBooleanWidget'
import { useFloatWidget } from '@/composables/widgets/useFloatWidget'
import { useStringWidget } from '@/composables/widgets/useStringWidget'
import { LGraphNode } from '@/lib/litegraph/src/litegraph'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useBooleanWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useBooleanWidget'
import { useFloatWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useFloatWidget'
import { useStringWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useStringWidget'
const StringWidget = useStringWidget()
const FloatWidget = useFloatWidget()

View File

@@ -2,7 +2,7 @@ import {
type AvifIinfBox,
type AvifIlocBox,
type AvifInfeBox,
ComfyMetadata,
type ComfyMetadata,
ComfyMetadataTags,
type IsobmffBoxContentRange
} from '@/types/metadataTypes'
@@ -319,7 +319,7 @@ function parseAvifMetadata(buffer: ArrayBuffer): ComfyMetadata {
}
// @ts-expect-error fixme ts strict error
export function parseExifData(exifData) {
function parseExifData(exifData) {
// Check for the correct TIFF header (0x4949 for little-endian or 0x4D4D for big-endian)
const isLittleEndian = String.fromCharCode(...exifData.slice(0, 2)) === 'II'

View File

@@ -1,14 +1,14 @@
import {
type ComfyApiWorkflow,
type ComfyWorkflowJSON
} from '@/schemas/comfyWorkflowSchema'
} from '@/platform/workflow/validation/schemas/workflowSchema'
import {
ComfyMetadata,
type ComfyMetadata,
ComfyMetadataTags,
EbmlElementRange,
EbmlTagPosition,
TextRange,
VInt
type EbmlElementRange,
type EbmlTagPosition,
type TextRange,
type VInt
} from '@/types/metadataTypes'
const WEBM_SIGNATURE = [0x1a, 0x45, 0xdf, 0xa3]

View File

@@ -1,3 +1,4 @@
/** @knipIgnoreUnusedButUsedByCustomNodes */
export function getFromFlacBuffer(buffer: ArrayBuffer): Record<string, string> {
const dataView = new DataView(buffer)

View File

@@ -1,14 +1,14 @@
import {
ComfyApiWorkflow,
ComfyWorkflowJSON
} from '@/schemas/comfyWorkflowSchema'
type ComfyApiWorkflow,
type ComfyWorkflowJSON
} from '@/platform/workflow/validation/schemas/workflowSchema'
import {
ASCII,
ComfyMetadata,
type ComfyMetadata,
ComfyMetadataTags,
GltfChunkHeader,
GltfHeader,
GltfJsonData,
type GltfChunkHeader,
type GltfHeader,
type GltfJsonData,
GltfSizeBytes
} from '@/types/metadataTypes'

View File

@@ -1,12 +1,12 @@
import {
ComfyApiWorkflow,
ComfyWorkflowJSON
} from '@/schemas/comfyWorkflowSchema'
type ComfyApiWorkflow,
type ComfyWorkflowJSON
} from '@/platform/workflow/validation/schemas/workflowSchema'
import {
ASCII,
ComfyMetadata,
type ComfyMetadata,
ComfyMetadataTags,
IsobmffBoxContentRange
type IsobmffBoxContentRange
} from '@/types/metadataTypes'
// Set max read high, as atoms are stored near end of file

View File

@@ -1,3 +1,4 @@
/** @knipIgnoreUnusedButUsedByCustomNodes */
export function getFromPngBuffer(buffer: ArrayBuffer) {
// Get the PNG data as a Uint8Array
const pngData = new Uint8Array(buffer)

View File

@@ -1,4 +1,4 @@
import { ComfyMetadata } from '@/types/metadataTypes'
import { type ComfyMetadata } from '@/types/metadataTypes'
export async function getSvgMetadata(file: File): Promise<ComfyMetadata> {
const text = await file.text()

View File

@@ -1,9 +1,9 @@
import { WORKFLOW_ACCEPT_STRING } from '@/constants/supportedWorkflowFormats'
import { type StatusWsMessageStatus, TaskItem } from '@/schemas/apiSchema'
import { useSettingStore } from '@/platform/settings/settingStore'
import { WORKFLOW_ACCEPT_STRING } from '@/platform/workflow/core/types/formats'
import { type StatusWsMessageStatus, type TaskItem } from '@/schemas/apiSchema'
import { useDialogService } from '@/services/dialogService'
import { useLitegraphService } from '@/services/litegraphService'
import { useCommandStore } from '@/stores/commandStore'
import { useSettingStore } from '@/stores/settingStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { api } from './api'
@@ -640,7 +640,6 @@ export class ComfyUI {
confirm('Clear workflow?')
) {
app.clean()
app.graph.clear()
useLitegraphService().resetView()
api.dispatchCustomEvent('graphCleared')
}

View File

@@ -1,10 +1,10 @@
import { Settings } from '@/schemas/apiSchema'
import { type Settings } from '@/schemas/apiSchema'
import type { ComfyApp } from '@/scripts/app'
import type { ComfyComponent } from '.'
import { $el } from '../../ui'
import { prop } from '../../utils'
import { ClassList, applyClasses, toggleElement } from '../utils'
import { type ClassList, applyClasses, toggleElement } from '../utils'
import type { ComfyPopup } from './popup'
type ComfyButtonProps = {

View File

@@ -1,6 +1,6 @@
import { $el } from '../../ui'
import { prop } from '../../utils'
import { ClassList, applyClasses } from '../utils'
import { type ClassList, applyClasses } from '../utils'
export class ComfyPopup extends EventTarget {
element = $el('div.comfyui-popup')

View File

@@ -1,9 +1,9 @@
import { t } from '@/i18n'
import { useSettingStore } from '@/platform/settings/settingStore'
import type { SettingParams } from '@/platform/settings/types'
import { useToastStore } from '@/platform/updates/common/toastStore'
import type { Settings } from '@/schemas/apiSchema'
import type { ComfyApp } from '@/scripts/app'
import { useSettingStore } from '@/stores/settingStore'
import { useToastStore } from '@/stores/toastStore'
import type { SettingParams } from '@/types/settingTypes'
import { ComfyDialog } from './dialog'

View File

@@ -17,6 +17,7 @@ export function clone<T>(obj: T): T {
}
/**
* @knipIgnoreUnusedButUsedByCustomNodes
* @deprecated Use `applyTextReplacements` from `@/utils/searchAndReplace` instead
* There are external callers to this function, so we need to keep it for now
*/
@@ -24,6 +25,7 @@ export function applyTextReplacements(app: ComfyApp, value: string): string {
return _applyTextReplacements(app.graph, value)
}
/** @knipIgnoreUnusedButUsedByCustomNodes */
export async function addStylesheet(
urlOrFile: string,
relativeTo?: string

View File

@@ -1,10 +1,4 @@
import { useBooleanWidget } from '@/composables/widgets/useBooleanWidget'
import { useComboWidget } from '@/composables/widgets/useComboWidget'
import { useFloatWidget } from '@/composables/widgets/useFloatWidget'
import { useImageUploadWidget } from '@/composables/widgets/useImageUploadWidget'
import { useIntWidget } from '@/composables/widgets/useIntWidget'
import { useMarkdownWidget } from '@/composables/widgets/useMarkdownWidget'
import { useStringWidget } from '@/composables/widgets/useStringWidget'
import '@/core/graph/subgraph/proxyWidget'
import { t } from '@/i18n'
import { type LGraphNode, isComboWidget } from '@/lib/litegraph/src/litegraph'
import type {
@@ -12,10 +6,26 @@ import type {
IComboWidget,
IStringWidget
} from '@/lib/litegraph/src/types/widgets'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useBooleanWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useBooleanWidget'
import { useChartWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useChartWidget'
import { useColorWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useColorWidget'
import { useComboWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useComboWidget'
import { useFileUploadWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useFileUploadWidget'
import { useFloatWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useFloatWidget'
import { useGalleriaWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useGalleriaWidget'
import { useImageCompareWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useImageCompareWidget'
import { useImageUploadWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useImageUploadWidget'
import { useIntWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useIntWidget'
import { useMarkdownWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget'
import { useMultiSelectWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useMultiSelectWidget'
import { useSelectButtonWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useSelectButtonWidget'
import { useStringWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useStringWidget'
import { useTextareaWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useTextareaWidget'
import { useTreeSelectWidget } from '@/renderer/extensions/vueNodes/widgets/composables/useTreeSelectWidget'
import { transformInputSpecV1ToV2 } from '@/schemas/nodeDef/migration'
import type { InputSpec as InputSpecV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
import type { InputSpec } from '@/schemas/nodeDefSchema'
import { useSettingStore } from '@/stores/settingStore'
import type { ComfyApp } from './app'
import './domWidget'
@@ -130,7 +140,6 @@ export function addValueControlWidgets(
valueControl.tooltip =
'Allows the linked widget to be changed automatically, for example randomizing the noise seed.'
// @ts-ignore index with symbol
valueControl[IS_CONTROL_WIDGET] = true
updateControlWidgetLabel(valueControl)
const widgets: [IComboWidget, ...IStringWidget[]] = [valueControl]
@@ -263,12 +272,10 @@ export function addValueControlWidgets(
valueControl.beforeQueued = () => {
if (controlValueRunBefore()) {
// Don't run on first execution
// @ts-ignore index with symbol
if (valueControl[HAS_EXECUTED]) {
applyWidgetControl()
}
}
// @ts-ignore index with symbol
valueControl[HAS_EXECUTED] = true
}
@@ -288,5 +295,14 @@ export const ComfyWidgets: Record<string, ComfyWidgetConstructor> = {
STRING: transformWidgetConstructorV2ToV1(useStringWidget()),
MARKDOWN: transformWidgetConstructorV2ToV1(useMarkdownWidget()),
COMBO: transformWidgetConstructorV2ToV1(useComboWidget()),
IMAGEUPLOAD: useImageUploadWidget()
IMAGEUPLOAD: useImageUploadWidget(),
FILEUPLOAD: transformWidgetConstructorV2ToV1(useFileUploadWidget()),
COLOR: transformWidgetConstructorV2ToV1(useColorWidget()),
IMAGECOMPARE: transformWidgetConstructorV2ToV1(useImageCompareWidget()),
TREESELECT: transformWidgetConstructorV2ToV1(useTreeSelectWidget()),
MULTISELECT: transformWidgetConstructorV2ToV1(useMultiSelectWidget()),
CHART: transformWidgetConstructorV2ToV1(useChartWidget()),
GALLERIA: transformWidgetConstructorV2ToV1(useGalleriaWidget()),
SELECTBUTTON: transformWidgetConstructorV2ToV1(useSelectButtonWidget()),
TEXTAREA: transformWidgetConstructorV2ToV1(useTextareaWidget())
}