mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-12 16:40:05 +00:00
Support search filtering to dynamic input types (#9388)
Previously, MatchType and Autogrow inputs would not be considered would filtering searchbox entires. For example, "Batch Images" would not show as a suggestion would dragging a noodle from a "Load Image" node. This is resolved by adding a step during nodeDef registration to precalculate a list of all input types. This may have performance implications. - Search filtering should be more performant - Initial node registration will be slower - There's additional memory cost to store this information on every node. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9388-Support-search-filtering-to-dynamic-input-types-3196d73d365081d9939eff5e167a7e83) by [Unito](https://www.unito.io)
This commit is contained in:
35
src/core/graph/widgets/dynamicTypes.ts
Normal file
35
src/core/graph/widgets/dynamicTypes.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { transformInputSpecV1ToV2 } from '@/schemas/nodeDef/migration'
|
||||
import { zAutogrowOptions, zMatchTypeOptions } from '@/schemas/nodeDefSchema'
|
||||
import type { InputSpec } from '@/schemas/nodeDefSchema'
|
||||
import type { InputSpec as InputSpecV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
||||
|
||||
const dynamicTypeResolvers: Record<
|
||||
string,
|
||||
(inputSpec: InputSpecV2) => string[]
|
||||
> = {
|
||||
COMFY_AUTOGROW_V3: resolveAutogrowType,
|
||||
COMFY_MATCHTYPE_V3: (input) =>
|
||||
zMatchTypeOptions
|
||||
.safeParse(input)
|
||||
.data?.template?.allowed_types?.split(',') ?? []
|
||||
}
|
||||
|
||||
export function resolveInputType(input: InputSpecV2): string[] {
|
||||
return input.type in dynamicTypeResolvers
|
||||
? dynamicTypeResolvers[input.type](input)
|
||||
: input.type.split(',')
|
||||
}
|
||||
|
||||
function resolveAutogrowType(rawSpec: InputSpecV2): string[] {
|
||||
const { input } = zAutogrowOptions.safeParse(rawSpec).data?.template ?? {}
|
||||
|
||||
const inputTypes: (Record<string, InputSpec> | undefined)[] = [
|
||||
input?.required,
|
||||
input?.optional
|
||||
]
|
||||
return inputTypes.flatMap((inputType) =>
|
||||
Object.entries(inputType ?? {}).flatMap(([name, v]) =>
|
||||
resolveInputType(transformInputSpecV1ToV2(v, { name }))
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -16,7 +16,8 @@ import type { ComboInputSpec, InputSpec } from '@/schemas/nodeDefSchema'
|
||||
import type { InputSpec as InputSpecV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
||||
import {
|
||||
zAutogrowOptions,
|
||||
zDynamicComboInputSpec
|
||||
zDynamicComboInputSpec,
|
||||
zMatchTypeOptions
|
||||
} from '@/schemas/nodeDefSchema'
|
||||
import { useLitegraphService } from '@/services/litegraphService'
|
||||
import { app } from '@/scripts/app'
|
||||
@@ -215,6 +216,7 @@ export function applyDynamicInputs(
|
||||
dynamicInputs[inputSpec.type](node, inputSpec)
|
||||
return true
|
||||
}
|
||||
|
||||
function spliceInputs(
|
||||
node: LGraphNode,
|
||||
startIndex: number,
|
||||
@@ -329,11 +331,10 @@ function withComfyMatchType(node: LGraphNode): asserts node is MatchTypeNode {
|
||||
function applyMatchType(node: LGraphNode, inputSpec: InputSpecV2) {
|
||||
const { addNodeInput } = useLitegraphService()
|
||||
const name = inputSpec.name
|
||||
const { allowed_types, template_id } = (
|
||||
inputSpec as InputSpecV2 & {
|
||||
template: { allowed_types: string; template_id: string }
|
||||
}
|
||||
).template
|
||||
const matchTypeSpec = zMatchTypeOptions.safeParse(inputSpec).data
|
||||
if (!matchTypeSpec) return
|
||||
|
||||
const { allowed_types, template_id } = matchTypeSpec.template
|
||||
const typedSpec = { ...inputSpec, type: allowed_types }
|
||||
addNodeInput(node, typedSpec)
|
||||
withComfyMatchType(node)
|
||||
|
||||
@@ -341,6 +341,15 @@ export const zDynamicComboInputSpec = z.tuple([
|
||||
})
|
||||
])
|
||||
|
||||
export const zMatchTypeOptions = z.object({
|
||||
...zBaseInputOptions.shape,
|
||||
type: z.literal('COMFY_MATCHTYPE_V3'),
|
||||
template: z.object({
|
||||
allowed_types: z.string(),
|
||||
template_id: z.string()
|
||||
})
|
||||
})
|
||||
|
||||
// `/object_info`
|
||||
export type ComfyInputsSpec = z.infer<typeof zComfyInputsSpec>
|
||||
export type ComfyOutputTypesSpec = z.infer<typeof zComfyOutputTypesSpec>
|
||||
|
||||
@@ -34,10 +34,7 @@ export class NodeSearchService {
|
||||
id: 'input',
|
||||
name: 'Input Type',
|
||||
invokeSequence: 'i',
|
||||
getItemOptions: (node) =>
|
||||
Object.values(node.inputs ?? []).flatMap((input) =>
|
||||
input.type.split(',')
|
||||
),
|
||||
getItemOptions: (node) => node.inputTypes,
|
||||
fuseOptions
|
||||
})
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { computed, ref, watchEffect } from 'vue'
|
||||
import { t } from '@/i18n'
|
||||
import { isPromotedWidgetView } from '@/core/graph/subgraph/promotedWidgetTypes'
|
||||
import { resolvePromotedWidgetSource } from '@/core/graph/subgraph/resolvePromotedWidgetSource'
|
||||
import { resolveInputType } from '@/core/graph/widgets/dynamicTypes'
|
||||
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import { transformNodeDefV1ToV2 } from '@/schemas/nodeDef/migration'
|
||||
@@ -98,6 +99,7 @@ export class ComfyNodeDefImpl
|
||||
|
||||
// ComfyNodeDefImpl fields
|
||||
readonly nodeSource: NodeSource
|
||||
readonly inputTypes: string[]
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -179,6 +181,9 @@ export class ComfyNodeDefImpl
|
||||
|
||||
// Initialize node source
|
||||
this.nodeSource = getNodeSource(obj.python_module, this.essentials_category)
|
||||
this.inputTypes = _.uniq(
|
||||
Object.values(this.inputs).flatMap(resolveInputType)
|
||||
)
|
||||
}
|
||||
|
||||
get nodePath(): string {
|
||||
|
||||
Reference in New Issue
Block a user