mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-11 02:20:08 +00:00
[feat] Update GraphCanvas with VueNodeData typing
- Import VueNodeData type for proper typing - Update handleNodeSelect function signature - Remove debug comments - Fix lint issues 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -39,18 +39,21 @@
|
||||
>
|
||||
<!-- Vue nodes rendered based on graph nodes -->
|
||||
<VueGraphNode
|
||||
v-for="node in nodesToRender"
|
||||
:key="node.id"
|
||||
:node="node"
|
||||
:position="nodePositions.get(String(node.id))"
|
||||
:size="nodeSizes.get(String(node.id))"
|
||||
:selected="canvasStore.canvas?.selectedItems?.has(node) || false"
|
||||
v-for="nodeData in nodesToRender"
|
||||
:key="nodeData.id"
|
||||
:node-data="nodeData"
|
||||
:position="nodePositions.get(nodeData.id)"
|
||||
:size="nodeSizes.get(nodeData.id)"
|
||||
:selected="nodeData.selected"
|
||||
:readonly="false"
|
||||
:executing="executionStore.executingNodeId === node.id"
|
||||
:error="executionStore.lastExecutionError?.node_id === String(node.id) ? 'Execution error' : null"
|
||||
:data-node-id="node.id"
|
||||
@select="handleNodeSelect"
|
||||
@widget-change="handleWidgetChange"
|
||||
:executing="executionStore.executingNodeId === nodeData.id"
|
||||
:error="
|
||||
executionStore.lastExecutionError?.node_id === nodeData.id
|
||||
? 'Execution error'
|
||||
: null
|
||||
"
|
||||
:data-node-id="nodeData.id"
|
||||
@node-click="handleNodeSelect"
|
||||
/>
|
||||
</TransformPane>
|
||||
|
||||
@@ -63,69 +66,133 @@
|
||||
<div class="space-y-2 text-xs">
|
||||
<div>
|
||||
<label class="flex items-center gap-2">
|
||||
<input type="checkbox" v-model="transformPaneEnabled" />
|
||||
<input v-model="debugOverrideVueNodes" type="checkbox" />
|
||||
<span>Enable TransformPane</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Canvas Metrics -->
|
||||
<div class="pt-2 border-t border-surface-200 dark-theme:border-surface-700">
|
||||
<div
|
||||
class="pt-2 border-t border-surface-200 dark-theme:border-surface-700"
|
||||
>
|
||||
<h4 class="font-semibold mb-1">Canvas State</h4>
|
||||
<p class="text-muted">Status: {{ canvasStore.canvas ? 'Ready' : 'Not Ready' }}</p>
|
||||
<p class="text-muted">Viewport: {{ Math.round(canvasViewport.width) }}x{{ Math.round(canvasViewport.height) }}</p>
|
||||
<p class="text-muted">
|
||||
Status: {{ canvasStore.canvas ? 'Ready' : 'Not Ready' }}
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
Viewport: {{ Math.round(canvasViewport.width) }}x{{
|
||||
Math.round(canvasViewport.height)
|
||||
}}
|
||||
</p>
|
||||
<template v-if="canvasStore.canvas?.ds">
|
||||
<p class="text-muted">Offset: ({{ Math.round(canvasStore.canvas.ds.offset[0]) }}, {{ Math.round(canvasStore.canvas.ds.offset[1]) }})</p>
|
||||
<p class="text-muted">Scale: {{ canvasStore.canvas.ds.scale?.toFixed(3) || 1 }}</p>
|
||||
<p class="text-muted">
|
||||
Offset: ({{ Math.round(canvasStore.canvas.ds.offset[0]) }},
|
||||
{{ Math.round(canvasStore.canvas.ds.offset[1]) }})
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
Scale: {{ canvasStore.canvas.ds.scale?.toFixed(3) || 1 }}
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Node Metrics -->
|
||||
<div class="pt-2 border-t border-surface-200 dark-theme:border-surface-700">
|
||||
<div
|
||||
class="pt-2 border-t border-surface-200 dark-theme:border-surface-700"
|
||||
>
|
||||
<h4 class="font-semibold mb-1">Graph Metrics</h4>
|
||||
<p class="text-muted">Total Nodes: {{ comfyApp.graph?.nodes?.length || 0 }}</p>
|
||||
<p class="text-muted">Selected Nodes: {{ canvasStore.canvas?.selectedItems?.size || 0 }}</p>
|
||||
<p class="text-muted">
|
||||
Total Nodes: {{ comfyApp.graph?.nodes?.length || 0 }}
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
Selected Nodes: {{ canvasStore.canvas?.selectedItems?.size || 0 }}
|
||||
</p>
|
||||
<p class="text-muted">Vue Nodes Rendered: {{ vueNodesCount }}</p>
|
||||
<p class="text-muted">Nodes in Viewport: {{ nodesInViewport }}</p>
|
||||
<p class="text-muted">Culled Nodes: {{ performanceMetrics.culledCount }}</p>
|
||||
<p class="text-muted">Cull Percentage: {{ Math.round(((vueNodesCount - nodesInViewport) / Math.max(vueNodesCount, 1)) * 100) }}%</p>
|
||||
<p class="text-muted">
|
||||
Culled Nodes: {{ performanceMetrics.culledCount }}
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
Cull Percentage:
|
||||
{{
|
||||
Math.round(
|
||||
((vueNodesCount - nodesInViewport) / Math.max(vueNodesCount, 1)) *
|
||||
100
|
||||
)
|
||||
}}%
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Performance Metrics -->
|
||||
<div class="pt-2 border-t border-surface-200 dark-theme:border-surface-700">
|
||||
<div
|
||||
class="pt-2 border-t border-surface-200 dark-theme:border-surface-700"
|
||||
>
|
||||
<h4 class="font-semibold mb-1">Performance</h4>
|
||||
<p class="text-muted" v-memo="[currentFPS]">FPS: {{ currentFPS }}</p>
|
||||
<p class="text-muted" v-memo="[Math.round(lastTransformTime)]">Transform Update: {{ Math.round(lastTransformTime) }}ms</p>
|
||||
<p class="text-muted" v-memo="[Math.round(performanceMetrics.updateTime)]">Lifecycle Update: {{ Math.round(performanceMetrics.updateTime) }}ms</p>
|
||||
<p class="text-muted" v-memo="[rafActive]">RAF Active: {{ rafActive ? 'Yes' : 'No' }}</p>
|
||||
<p class="text-muted" v-memo="[performanceMetrics.adaptiveQuality]">Adaptive Quality: {{ performanceMetrics.adaptiveQuality ? 'On' : 'Off' }}</p>
|
||||
<p v-memo="[currentFPS]" class="text-muted">FPS: {{ currentFPS }}</p>
|
||||
<p v-memo="[Math.round(lastTransformTime)]" class="text-muted">
|
||||
Transform Update: {{ Math.round(lastTransformTime) }}ms
|
||||
</p>
|
||||
<p
|
||||
v-memo="[Math.round(performanceMetrics.updateTime)]"
|
||||
class="text-muted"
|
||||
>
|
||||
Lifecycle Update: {{ Math.round(performanceMetrics.updateTime) }}ms
|
||||
</p>
|
||||
<p v-memo="[rafActive]" class="text-muted">
|
||||
RAF Active: {{ rafActive ? 'Yes' : 'No' }}
|
||||
</p>
|
||||
<p v-memo="[performanceMetrics.adaptiveQuality]" class="text-muted">
|
||||
Adaptive Quality:
|
||||
{{ performanceMetrics.adaptiveQuality ? 'On' : 'Off' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature Flags Status -->
|
||||
<div
|
||||
v-if="isDevModeEnabled"
|
||||
class="pt-2 border-t border-surface-200 dark-theme:border-surface-700"
|
||||
>
|
||||
<h4 class="font-semibold mb-1">Feature Flags</h4>
|
||||
<p class="text-muted text-xs">
|
||||
Vue Nodes: {{ shouldRenderVueNodes ? 'Enabled' : 'Disabled' }}
|
||||
</p>
|
||||
<p class="text-muted text-xs">
|
||||
Viewport Culling:
|
||||
{{ isViewportCullingEnabled ? 'Enabled' : 'Disabled' }}
|
||||
</p>
|
||||
<p class="text-muted text-xs">
|
||||
Dev Mode: {{ isDevModeEnabled ? 'Enabled' : 'Disabled' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Node Rendering Options -->
|
||||
<div class="pt-2 border-t border-surface-200 dark-theme:border-surface-700" v-if="transformPaneEnabled">
|
||||
<h4 class="font-semibold mb-1">Rendering Options</h4>
|
||||
<div
|
||||
v-if="transformPaneEnabled"
|
||||
class="pt-2 border-t border-surface-200 dark-theme:border-surface-700"
|
||||
>
|
||||
<h4 class="font-semibold mb-1">Debug Overrides</h4>
|
||||
<label class="flex items-center gap-2 mb-1">
|
||||
<input type="checkbox" v-model="renderAllNodes" />
|
||||
<span>Render All Nodes as Vue</span>
|
||||
<input v-model="renderAllNodes" type="checkbox" />
|
||||
<span>Force Render All Nodes</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 mb-1">
|
||||
<input type="checkbox" v-model="viewportCullingEnabled" />
|
||||
<span>Viewport Culling</span>
|
||||
<input v-model="viewportCullingEnabled" type="checkbox" />
|
||||
<span>Debug: Viewport Culling</span>
|
||||
</label>
|
||||
<div class="ml-4 mb-1" v-if="viewportCullingEnabled">
|
||||
<div v-if="viewportCullingEnabled" class="ml-4 mb-1">
|
||||
<label class="text-xs">
|
||||
Culling Margin: {{ (cullingMargin * 100).toFixed(0) }}%
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
v-model.number="cullingMargin"
|
||||
min="0"
|
||||
max="1"
|
||||
<input
|
||||
v-model.number="cullingMargin"
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
<label class="flex items-center gap-2">
|
||||
<input type="checkbox" v-model="showPerformanceOverlay" />
|
||||
<input v-model="showPerformanceOverlay" type="checkbox" />
|
||||
<span>Show Performance Overlay</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -149,7 +216,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { LGraphNode } from '@comfyorg/litegraph'
|
||||
import { useEventListener, whenever } from '@vueuse/core'
|
||||
import { computed, onMounted, onUnmounted, reactive, ref, shallowRef, watch, watchEffect } from 'vue'
|
||||
import {
|
||||
computed,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
reactive,
|
||||
ref,
|
||||
shallowRef,
|
||||
watch,
|
||||
watchEffect
|
||||
} from 'vue'
|
||||
|
||||
import LiteGraphCanvasSplitterOverlay from '@/components/LiteGraphCanvasSplitterOverlay.vue'
|
||||
import BottomPanel from '@/components/bottomPanel/BottomPanel.vue'
|
||||
@@ -165,11 +241,18 @@ import VueGraphNode from '@/components/graph/vueNodes/LGraphNode.vue'
|
||||
import NodeSearchboxPopover from '@/components/searchbox/NodeSearchBoxPopover.vue'
|
||||
import SideToolbar from '@/components/sidebar/SideToolbar.vue'
|
||||
import SecondRowWorkflowTabs from '@/components/topbar/SecondRowWorkflowTabs.vue'
|
||||
import { useTransformState } from '@/composables/element/useTransformState'
|
||||
import { useChainCallback } from '@/composables/functional/useChainCallback'
|
||||
import { useGraphNodeManager } from '@/composables/graph/useGraphNodeManager'
|
||||
import type {
|
||||
NodeState,
|
||||
VueNodeData
|
||||
} from '@/composables/graph/useGraphNodeManager'
|
||||
import { useNodeBadge } from '@/composables/node/useNodeBadge'
|
||||
import { useCanvasDrop } from '@/composables/useCanvasDrop'
|
||||
import { useContextMenuTranslation } from '@/composables/useContextMenuTranslation'
|
||||
import { useCopy } from '@/composables/useCopy'
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import { useGlobalLitegraph } from '@/composables/useGlobalLitegraph'
|
||||
import { useLitegraphSettings } from '@/composables/useLitegraphSettings'
|
||||
import { usePaste } from '@/composables/usePaste'
|
||||
@@ -193,9 +276,6 @@ import { useToastStore } from '@/stores/toastStore'
|
||||
import { useWorkflowStore } from '@/stores/workflowStore'
|
||||
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
|
||||
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
||||
import { useGraphNodeManager } from '@/composables/graph/useGraphNodeManager'
|
||||
import { useTransformState } from '@/composables/element/useTransformState'
|
||||
import type { NodeState } from '@/composables/graph/useGraphNodeManager'
|
||||
|
||||
const emit = defineEmits<{
|
||||
ready: []
|
||||
@@ -221,8 +301,19 @@ const selectionToolboxEnabled = computed(() =>
|
||||
settingStore.get('Comfy.Canvas.SelectionToolbox')
|
||||
)
|
||||
|
||||
// TransformPane development feature flag
|
||||
const transformPaneEnabled = ref(true) // Default to true
|
||||
// Feature flags
|
||||
const {
|
||||
shouldRenderVueNodes,
|
||||
isViewportCullingEnabled,
|
||||
cullingMargin: featureCullingMargin,
|
||||
isDevModeEnabled
|
||||
} = useFeatureFlags()
|
||||
|
||||
// TransformPane enabled when Vue nodes are enabled OR debug override
|
||||
const debugOverrideVueNodes = ref(true) // Default to true for development
|
||||
const transformPaneEnabled = computed(
|
||||
() => shouldRenderVueNodes.value || debugOverrideVueNodes.value
|
||||
)
|
||||
// Account for browser zoom/DPI scaling
|
||||
const getActualViewport = () => {
|
||||
// Get the actual canvas element dimensions which account for zoom
|
||||
@@ -242,7 +333,6 @@ const getActualViewport = () => {
|
||||
|
||||
const canvasViewport = ref(getActualViewport())
|
||||
|
||||
|
||||
// Debug metrics - use shallowRef for frequently updating values
|
||||
const vueNodesCount = shallowRef(0)
|
||||
const nodesInViewport = shallowRef(0)
|
||||
@@ -263,7 +353,9 @@ const updateFPS = () => {
|
||||
frameCount++
|
||||
const currentTime = performance.now()
|
||||
if (currentTime >= lastTime + 1000) {
|
||||
currentFPS.value = Math.round((frameCount * 1000) / (currentTime - lastTime))
|
||||
currentFPS.value = Math.round(
|
||||
(frameCount * 1000) / (currentTime - lastTime)
|
||||
)
|
||||
frameCount = 0
|
||||
lastTime = currentTime
|
||||
}
|
||||
@@ -299,7 +391,7 @@ watch(canvasRef, () => {
|
||||
|
||||
// Vue node lifecycle management - initialize after graph is ready
|
||||
let nodeManager: ReturnType<typeof useGraphNodeManager> | null = null
|
||||
const reactiveNodes = ref<Map<string, LGraphNode>>(new Map())
|
||||
const vueNodeData = ref<Map<string, any>>(new Map())
|
||||
const nodeState = ref<Map<string, NodeState>>(new Map())
|
||||
const nodePositions = ref<Map<string, { x: number; y: number }>>(new Map())
|
||||
const nodeSizes = ref<Map<string, { width: number; height: number }>>(new Map())
|
||||
@@ -315,105 +407,155 @@ const performanceMetrics = reactive({
|
||||
// Initialize node manager when graph becomes available
|
||||
const initializeNodeManager = () => {
|
||||
if (!comfyApp.graph || nodeManager) {
|
||||
return
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
nodeManager = useGraphNodeManager(comfyApp.graph)
|
||||
|
||||
// Instead of copying, just use the manager's reactive maps directly
|
||||
reactiveNodes.value = nodeManager.reactiveNodes as Map<string, LGraphNode>
|
||||
|
||||
// Use the manager's reactive maps directly
|
||||
vueNodeData.value = nodeManager.vueNodeData as Map<string, any>
|
||||
nodeState.value = nodeManager.nodeState as Map<string, NodeState>
|
||||
nodePositions.value = nodeManager.nodePositions as Map<string, { x: number; y: number }>
|
||||
nodeSizes.value = nodeManager.nodeSizes as Map<string, { width: number; height: number }>
|
||||
|
||||
nodePositions.value = nodeManager.nodePositions as Map<
|
||||
string,
|
||||
{ x: number; y: number }
|
||||
>
|
||||
nodeSizes.value = nodeManager.nodeSizes as Map<
|
||||
string,
|
||||
{ width: number; height: number }
|
||||
>
|
||||
|
||||
detectChangesInRAF = nodeManager.detectChangesInRAF
|
||||
Object.assign(performanceMetrics, nodeManager.performanceMetrics)
|
||||
|
||||
}
|
||||
|
||||
// Watch for graph availability
|
||||
watch(() => comfyApp.graph, (graph) => {
|
||||
if (graph) {
|
||||
initializeNodeManager()
|
||||
}
|
||||
}, { immediate: true })
|
||||
watch(
|
||||
() => comfyApp.graph,
|
||||
(graph) => {
|
||||
if (graph) {
|
||||
initializeNodeManager()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// Transform state for viewport culling
|
||||
const { isNodeInViewport } = useTransformState()
|
||||
|
||||
// Viewport culling settings
|
||||
const viewportCullingEnabled = ref(false) // Default to false for testing
|
||||
const cullingMargin = ref(0.2)
|
||||
// Viewport culling settings - use feature flags as defaults but allow debug override
|
||||
const viewportCullingEnabled = ref(false) // Debug override, starts false for testing
|
||||
const cullingMargin = ref(0.2) // Debug override
|
||||
|
||||
// Initialize from feature flags
|
||||
watch(
|
||||
isViewportCullingEnabled,
|
||||
(enabled) => {
|
||||
viewportCullingEnabled.value = enabled
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
featureCullingMargin,
|
||||
(margin) => {
|
||||
cullingMargin.value = margin
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// Replace problematic computed property with proper reactive system
|
||||
const nodesToRender = computed(() => {
|
||||
// Access performanceMetrics to trigger on RAF updates
|
||||
const updateCount = performanceMetrics.updateTime
|
||||
|
||||
console.log('[GraphCanvas] Computing nodesToRender. renderAllNodes:', renderAllNodes.value, 'reactiveNodes size:', reactiveNodes.value.size, 'updateCount:', updateCount)
|
||||
|
||||
console.log(
|
||||
'[GraphCanvas] Computing nodesToRender. renderAllNodes:',
|
||||
renderAllNodes.value,
|
||||
'vueNodeData size:',
|
||||
vueNodeData.value.size,
|
||||
'updateCount:',
|
||||
updateCount,
|
||||
'transformPaneEnabled:',
|
||||
transformPaneEnabled.value,
|
||||
'shouldRenderVueNodes:',
|
||||
shouldRenderVueNodes.value
|
||||
)
|
||||
if (!renderAllNodes.value || !comfyApp.graph) {
|
||||
console.log(
|
||||
'[GraphCanvas] Early return - renderAllNodes:',
|
||||
renderAllNodes.value,
|
||||
'graph:',
|
||||
!!comfyApp.graph
|
||||
)
|
||||
return []
|
||||
}
|
||||
|
||||
const allNodes = Array.from(reactiveNodes.value.values())
|
||||
|
||||
|
||||
const allNodes = Array.from(vueNodeData.value.values())
|
||||
|
||||
// Apply viewport culling
|
||||
if (viewportCullingEnabled.value) {
|
||||
const filtered = allNodes.filter(node => {
|
||||
if (viewportCullingEnabled.value && nodeManager) {
|
||||
const filtered = allNodes.filter((nodeData) => {
|
||||
const originalNode = nodeManager?.getNode(nodeData.id)
|
||||
if (!originalNode) return false
|
||||
|
||||
const inViewport = isNodeInViewport(
|
||||
node.pos,
|
||||
node.size,
|
||||
originalNode.pos,
|
||||
originalNode.size,
|
||||
canvasViewport.value,
|
||||
cullingMargin.value
|
||||
)
|
||||
|
||||
// Don't update the readonly state directly
|
||||
// The culling state is just for metrics, not needed for rendering
|
||||
|
||||
|
||||
return inViewport
|
||||
})
|
||||
return filtered
|
||||
}
|
||||
|
||||
|
||||
return allNodes
|
||||
})
|
||||
|
||||
// Remove side effects from computed - use watchers instead
|
||||
watch(() => reactiveNodes.value.size, (count) => {
|
||||
vueNodesCount.value = count
|
||||
}, { immediate: true })
|
||||
watch(
|
||||
() => vueNodeData.value.size,
|
||||
(count) => {
|
||||
vueNodesCount.value = count
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(() => nodesToRender.value.length, (count) => {
|
||||
nodesInViewport.value = count
|
||||
})
|
||||
watch(
|
||||
() => nodesToRender.value.length,
|
||||
(count) => {
|
||||
nodesInViewport.value = count
|
||||
}
|
||||
)
|
||||
|
||||
// Integrate change detection with TransformPane RAF
|
||||
const handleTransformUpdate = (time: number) => {
|
||||
lastTransformTime.value = time
|
||||
// Detect node changes during transform updates
|
||||
detectChangesInRAF()
|
||||
|
||||
|
||||
// Update performance metrics
|
||||
performanceMetrics.frameTime = time
|
||||
|
||||
// Force update of nodesToRender to trigger reactivity
|
||||
nodesToRender.value.length // Access to trigger computed
|
||||
}
|
||||
|
||||
// This watcher was removed - no need to hack canvas rendering for Vue nodes
|
||||
void nodesToRender.value.length
|
||||
}
|
||||
|
||||
// Node event handlers
|
||||
const handleNodeSelect = (node: LGraphNode) => {
|
||||
if (!canvasStore.canvas) return
|
||||
canvasStore.canvas.selectNode(node)
|
||||
}
|
||||
const handleNodeSelect = (event: PointerEvent, nodeData: VueNodeData) => {
|
||||
if (!canvasStore.canvas || !nodeManager) return
|
||||
|
||||
const handleWidgetChange = ({ node, widget, value }: { node: LGraphNode, widget: any, value: any }) => {
|
||||
// Update widget value
|
||||
widget.value = value
|
||||
// Trigger node update
|
||||
node.onWidgetChanged?.(widget.name, value, null, widget)
|
||||
const node = nodeManager.getNode(nodeData.id)
|
||||
if (!node) return
|
||||
|
||||
if (!event.ctrlKey && !event.metaKey) {
|
||||
canvasStore.canvas.deselectAllNodes()
|
||||
}
|
||||
|
||||
canvasStore.canvas.selectNode(node)
|
||||
node.selected = true
|
||||
|
||||
canvasStore.updateSelectedItems()
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
@@ -575,7 +717,7 @@ useLitegraphSettings()
|
||||
useNodeBadge()
|
||||
|
||||
onMounted(async () => {
|
||||
useGlobalLitegraph()
|
||||
useGlobalLitegraph()
|
||||
useContextMenuTranslation()
|
||||
useCopy()
|
||||
usePaste()
|
||||
@@ -615,7 +757,7 @@ onMounted(async () => {
|
||||
window.graph = comfyApp.graph
|
||||
|
||||
comfyAppReady.value = true
|
||||
|
||||
|
||||
// Initialize node manager after setup is complete
|
||||
if (comfyApp.graph) {
|
||||
initializeNodeManager()
|
||||
|
||||
Reference in New Issue
Block a user