mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 02:32:18 +00:00
Fix i18n workaround breaks node configure & subgraphs
- Copy *only* the i18n values from the node into the configure data - Do not replace the inputs / outputs properties of the configure data - Do not pass existing input / output objects to the parent `configure` method - Removes need for extensions to workaround this peculiar behaviour - Drastically simplifies code
This commit is contained in:
@@ -13,11 +13,8 @@ import {
|
|||||||
} from '@comfyorg/litegraph'
|
} from '@comfyorg/litegraph'
|
||||||
import type {
|
import type {
|
||||||
ExportedSubgraphInstance,
|
ExportedSubgraphInstance,
|
||||||
ISerialisableNodeInput,
|
|
||||||
ISerialisableNodeOutput,
|
|
||||||
ISerialisedNode
|
ISerialisedNode
|
||||||
} from '@comfyorg/litegraph/dist/types/serialisation'
|
} from '@comfyorg/litegraph/dist/types/serialisation'
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
import { useNodeAnimatedImage } from '@/composables/node/useNodeAnimatedImage'
|
import { useNodeAnimatedImage } from '@/composables/node/useNodeAnimatedImage'
|
||||||
import { useNodeCanvasImagePreview } from '@/composables/node/useNodeCanvasImagePreview'
|
import { useNodeCanvasImagePreview } from '@/composables/node/useNodeCanvasImagePreview'
|
||||||
@@ -249,51 +246,35 @@ export const useLitegraphService = () => {
|
|||||||
* and 'localized_name' information from the original node definition.
|
* and 'localized_name' information from the original node definition.
|
||||||
*/
|
*/
|
||||||
override configure(data: ISerialisedNode): void {
|
override configure(data: ISerialisedNode): void {
|
||||||
const RESERVED_KEYS = ['name', 'type', 'shape', 'localized_name']
|
|
||||||
|
|
||||||
// Note: input name is unique in a node definition, so we can lookup
|
// Note: input name is unique in a node definition, so we can lookup
|
||||||
// input by name.
|
// input by name.
|
||||||
const inputByName = new Map<string, ISerialisableNodeInput>(
|
const thisInputsByName = new Map(this.inputs?.map((x) => [x.name, x]))
|
||||||
data.inputs?.map((input) => [input.name, input]) ?? []
|
|
||||||
)
|
for (const input of data.inputs ?? []) {
|
||||||
// Inputs defined by the node definition.
|
const currentInput = thisInputsByName.get(input.name)
|
||||||
const definedInputNames = new Set(
|
if (!currentInput) continue
|
||||||
this.inputs.map((input) => input.name)
|
|
||||||
)
|
input.name = currentInput.name
|
||||||
const definedInputs = this.inputs.map((input) => {
|
input.type = currentInput.type
|
||||||
const inputData = inputByName.get(input.name)
|
input.shape = currentInput.shape
|
||||||
return inputData
|
input.localized_name = currentInput.localized_name
|
||||||
? {
|
|
||||||
...inputData,
|
// Whether the input has associated widget follows the original node
|
||||||
// Whether the input has associated widget follows the
|
// definition.
|
||||||
// original node definition.
|
input.widget = currentInput.widget
|
||||||
..._.pick(input, RESERVED_KEYS.concat('widget'))
|
}
|
||||||
}
|
|
||||||
: input
|
|
||||||
})
|
|
||||||
// Extra inputs that potentially dynamically added by custom js logic.
|
|
||||||
const extraInputs = data.inputs?.filter(
|
|
||||||
(input) => !definedInputNames.has(input.name)
|
|
||||||
)
|
|
||||||
data.inputs = [...definedInputs, ...(extraInputs ?? [])]
|
|
||||||
|
|
||||||
// Note: output name is not unique, so we cannot lookup output by name.
|
// Note: output name is not unique, so we cannot lookup output by name.
|
||||||
// Use index instead.
|
// Use index instead.
|
||||||
data.outputs = _.zip(this.outputs, data.outputs).map(
|
for (const [index, output] of data.outputs?.entries() ?? []) {
|
||||||
([output, outputData]) => {
|
const currentOutput = this.outputs.at(index)
|
||||||
// If there are extra outputs in the serialised node, use them directly.
|
if (!currentOutput) continue
|
||||||
// There are currently custom nodes that dynamically add outputs via
|
|
||||||
// js logic.
|
|
||||||
if (!output) return outputData as ISerialisableNodeOutput
|
|
||||||
|
|
||||||
return outputData
|
output.name = currentOutput.name
|
||||||
? {
|
output.type = currentOutput.type
|
||||||
...outputData,
|
output.shape = currentOutput.shape
|
||||||
..._.pick(output, RESERVED_KEYS)
|
output.localized_name = currentOutput.localized_name
|
||||||
}
|
}
|
||||||
: output
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
data.widgets_values = migrateWidgetsValues(
|
data.widgets_values = migrateWidgetsValues(
|
||||||
ComfyNode.nodeData.inputs,
|
ComfyNode.nodeData.inputs,
|
||||||
@@ -504,57 +485,35 @@ export const useLitegraphService = () => {
|
|||||||
* and 'localized_name' information from the original node definition.
|
* and 'localized_name' information from the original node definition.
|
||||||
*/
|
*/
|
||||||
override configure(data: ISerialisedNode): void {
|
override configure(data: ISerialisedNode): void {
|
||||||
const RESERVED_KEYS = ['name', 'type', 'shape', 'localized_name']
|
|
||||||
|
|
||||||
// Note: input name is unique in a node definition, so we can lookup
|
// Note: input name is unique in a node definition, so we can lookup
|
||||||
// input by name.
|
// input by name.
|
||||||
const inputByName = new Map<string, ISerialisableNodeInput>(
|
const thisInputsByName = new Map(this.inputs?.map((x) => [x.name, x]))
|
||||||
data.inputs?.map((input) => [input.name, input]) ?? []
|
|
||||||
)
|
for (const input of data.inputs ?? []) {
|
||||||
// Inputs defined by the node definition.
|
const currentInput = thisInputsByName.get(input.name)
|
||||||
const definedInputNames = new Set(
|
if (!currentInput) continue
|
||||||
this.inputs.map((input) => input.name)
|
|
||||||
)
|
input.name = currentInput.name
|
||||||
const definedInputs = this.inputs.map((input) => {
|
input.type = currentInput.type
|
||||||
const inputData = inputByName.get(input.name)
|
input.shape = currentInput.shape
|
||||||
return inputData
|
input.localized_name = currentInput.localized_name
|
||||||
? {
|
|
||||||
...inputData,
|
// Whether the input has associated widget follows the original node
|
||||||
// Whether the input has associated widget follows the
|
// definition.
|
||||||
// original node definition.
|
input.widget = currentInput.widget
|
||||||
..._.pick(input, RESERVED_KEYS.concat('widget'))
|
}
|
||||||
}
|
|
||||||
: input
|
|
||||||
})
|
|
||||||
// Extra inputs that potentially dynamically added by custom js logic.
|
|
||||||
const extraInputs = data.inputs?.filter(
|
|
||||||
(input) => !definedInputNames.has(input.name)
|
|
||||||
)
|
|
||||||
data.inputs = [...definedInputs, ...(extraInputs ?? [])]
|
|
||||||
|
|
||||||
// Note: output name is not unique, so we cannot lookup output by name.
|
// Note: output name is not unique, so we cannot lookup output by name.
|
||||||
// Use index instead.
|
// Use index instead.
|
||||||
data.outputs = _.zip(this.outputs, data.outputs).map(
|
for (const [index, output] of data.outputs?.entries() ?? []) {
|
||||||
([output, outputData]) => {
|
const currentOutput = this.outputs.at(index)
|
||||||
// If there are extra outputs in the serialised node, use them directly.
|
if (!currentOutput) continue
|
||||||
// There are currently custom nodes that dynamically add outputs via
|
|
||||||
// js logic.
|
|
||||||
if (!output) return outputData as ISerialisableNodeOutput
|
|
||||||
|
|
||||||
return outputData
|
output.name = currentOutput.name
|
||||||
? {
|
output.type = currentOutput.type
|
||||||
...outputData,
|
output.shape = currentOutput.shape
|
||||||
..._.pick(output, RESERVED_KEYS)
|
output.localized_name = currentOutput.localized_name
|
||||||
}
|
}
|
||||||
: output
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
data.widgets_values = migrateWidgetsValues(
|
|
||||||
ComfyNode.nodeData.inputs,
|
|
||||||
this.widgets ?? [],
|
|
||||||
data.widgets_values ?? []
|
|
||||||
)
|
|
||||||
|
|
||||||
super.configure(data)
|
super.configure(data)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user