mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-03 22:59:14 +00:00
track execution progress in vue nodes
This commit is contained in:
@@ -46,7 +46,6 @@
|
||||
:position="nodePositions.get(nodeData.id)"
|
||||
:size="nodeSizes.get(nodeData.id)"
|
||||
:readonly="false"
|
||||
:executing="executionStore.executingNodeId === nodeData.id"
|
||||
:error="
|
||||
executionStore.lastExecutionError?.node_id === nodeData.id
|
||||
? 'Execution error'
|
||||
@@ -118,6 +117,7 @@ import TransformPane from '@/renderer/core/layout/TransformPane.vue'
|
||||
import MiniMap from '@/renderer/extensions/minimap/MiniMap.vue'
|
||||
import VueGraphNode from '@/renderer/extensions/vueNodes/components/LGraphNode.vue'
|
||||
import { useNodeEventHandlers } from '@/renderer/extensions/vueNodes/composables/useNodeEventHandlers'
|
||||
import { useExecutionStateProvider } from '@/renderer/extensions/vueNodes/execution/useExecutionStateProvider'
|
||||
import { UnauthorizedError, api } from '@/scripts/api'
|
||||
import { app as comfyApp } from '@/scripts/app'
|
||||
import { ChangeTracker } from '@/scripts/changeTracker'
|
||||
@@ -205,6 +205,9 @@ const selectedNodeIds = computed(
|
||||
)
|
||||
provide(SelectedNodeIdsKey, selectedNodeIds)
|
||||
|
||||
// Provide execution state to all Vue nodes
|
||||
useExecutionStateProvider()
|
||||
|
||||
watchEffect(() => {
|
||||
nodeDefStore.showDeprecated = settingStore.get('Comfy.Node.ShowDeprecated')
|
||||
})
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
import type { InjectionKey, Ref } from 'vue'
|
||||
|
||||
import type { NodeProgressState } from '@/schemas/apiSchema'
|
||||
|
||||
/**
|
||||
* Injection key for providing selected node IDs to Vue node components.
|
||||
* Contains a reactive Set of selected node IDs (as strings).
|
||||
*/
|
||||
export const SelectedNodeIdsKey: InjectionKey<Ref<Set<string>>> =
|
||||
Symbol('selectedNodeIds')
|
||||
|
||||
/**
|
||||
* Injection key for providing executing node IDs to Vue node components.
|
||||
* Contains a reactive Set of currently executing node IDs (as strings).
|
||||
*/
|
||||
export const ExecutingNodeIdsKey: InjectionKey<Ref<Set<string>>> =
|
||||
Symbol('executingNodeIds')
|
||||
|
||||
/**
|
||||
* Injection key for providing node progress states to Vue node components.
|
||||
* Contains a reactive Record of node IDs to their current progress state.
|
||||
*/
|
||||
export const NodeProgressStatesKey: InjectionKey<
|
||||
Ref<Record<string, NodeProgressState>>
|
||||
> = Symbol('nodeProgressStates')
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
'lg-node absolute rounded-2xl',
|
||||
// border
|
||||
'border border-solid border-sand-100 dark-theme:border-charcoal-300',
|
||||
!!executing && 'border-blue-500 dark-theme:border-blue-500',
|
||||
!!executing && 'border-blue-100 dark-theme:border-blue-100',
|
||||
!!(error || nodeData.hasErrors) && 'border-error',
|
||||
// hover
|
||||
'hover:ring-7 ring-gray-500/50 dark-theme:ring-gray-500/20',
|
||||
@@ -20,7 +20,7 @@
|
||||
'outline-transparent -outline-offset-2 outline-2',
|
||||
!!isSelected && 'outline-black dark-theme:outline-white',
|
||||
!!(isSelected && executing) &&
|
||||
'outline-blue-500 dark-theme:outline-blue-500',
|
||||
'outline-blue-100 dark-theme:outline-blue-100',
|
||||
!!(isSelected && (error || nodeData.hasErrors)) && 'outline-error',
|
||||
{
|
||||
'animate-pulse': executing,
|
||||
@@ -141,6 +141,7 @@ import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
|
||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
import { SelectedNodeIdsKey } from '@/renderer/core/canvas/injectionKeys'
|
||||
import { useNodeExecutionState } from '@/renderer/extensions/vueNodes/execution/useNodeExecutionState'
|
||||
import { useNodeLayout } from '@/renderer/extensions/vueNodes/layout/useNodeLayout'
|
||||
import { LODLevel, useLOD } from '@/renderer/extensions/vueNodes/lod/useLOD'
|
||||
import { ExecutedWsMessage } from '@/schemas/apiSchema'
|
||||
@@ -162,8 +163,6 @@ interface LGraphNodeProps {
|
||||
position?: { x: number; y: number }
|
||||
size?: { width: number; height: number }
|
||||
readonly?: boolean
|
||||
executing?: boolean
|
||||
progress?: number
|
||||
error?: string | null
|
||||
zoomLevel?: number
|
||||
}
|
||||
@@ -202,6 +201,9 @@ const isSelected = computed(() => {
|
||||
return selectedNodeIds.value.has(props.nodeData.id)
|
||||
})
|
||||
|
||||
// Use execution state composable
|
||||
const { executing, progress } = useNodeExecutionState(props.nodeData.id)
|
||||
|
||||
// LOD (Level of Detail) system based on zoom level
|
||||
const zoomRef = toRef(() => props.zoomLevel ?? 1)
|
||||
const {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { computed, provide } from 'vue'
|
||||
|
||||
import {
|
||||
ExecutingNodeIdsKey,
|
||||
NodeProgressStatesKey
|
||||
} from '@/renderer/core/canvas/injectionKeys'
|
||||
import { useExecutionStore } from '@/stores/executionStore'
|
||||
|
||||
/**
|
||||
* Composable for providing execution state to Vue node children
|
||||
*
|
||||
* This composable sets up the execution state providers that can be injected
|
||||
* by child Vue nodes using useNodeExecutionState.
|
||||
*
|
||||
* Should be used in the parent component that manages Vue nodes (e.g., GraphCanvas).
|
||||
*/
|
||||
export const useExecutionStateProvider = () => {
|
||||
const executionStore = useExecutionStore()
|
||||
|
||||
// Convert execution store data to the format expected by Vue nodes
|
||||
const executingNodeIds = computed(
|
||||
() => new Set(executionStore.executingNodeIds.map(String))
|
||||
)
|
||||
|
||||
const nodeProgressStates = computed(() => executionStore.nodeProgressStates)
|
||||
|
||||
// Provide the execution state to all child Vue nodes
|
||||
provide(ExecutingNodeIdsKey, executingNodeIds)
|
||||
provide(NodeProgressStatesKey, nodeProgressStates)
|
||||
|
||||
return {
|
||||
executingNodeIds,
|
||||
nodeProgressStates
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import { computed, inject, ref } from 'vue'
|
||||
|
||||
import {
|
||||
ExecutingNodeIdsKey,
|
||||
NodeProgressStatesKey
|
||||
} from '@/renderer/core/canvas/injectionKeys'
|
||||
import type { NodeProgressState } from '@/schemas/apiSchema'
|
||||
|
||||
/**
|
||||
* Composable for managing execution state of Vue-based nodes
|
||||
*
|
||||
* Provides reactive access to execution state and progress for a specific node
|
||||
* by injecting execution data from the parent GraphCanvas provider.
|
||||
*
|
||||
* @param nodeId - The ID of the node to track execution state for
|
||||
* @returns Object containing reactive execution state and progress
|
||||
*/
|
||||
export const useNodeExecutionState = (nodeId: string) => {
|
||||
// Inject execution state from parent GraphCanvas
|
||||
const executingNodeIds = inject(ExecutingNodeIdsKey, ref(new Set<string>()))
|
||||
const nodeProgressStates = inject(
|
||||
NodeProgressStatesKey,
|
||||
ref<Record<string, NodeProgressState>>({})
|
||||
)
|
||||
|
||||
// Computed execution state - only re-evaluates when this node's execution state changes
|
||||
const executing = computed(() => {
|
||||
return executingNodeIds.value.has(nodeId)
|
||||
})
|
||||
|
||||
// Computed progress state - returns progress percentage (0-1) or undefined
|
||||
const progress = computed(() => {
|
||||
const state = nodeProgressStates.value[nodeId]
|
||||
return state?.max > 0 ? state.value / state.max : undefined
|
||||
})
|
||||
|
||||
// Raw progress state for advanced use cases
|
||||
const progressState = computed(() => nodeProgressStates.value[nodeId])
|
||||
|
||||
// Convenience computed for progress display
|
||||
const progressPercentage = computed(() => {
|
||||
const prog = progress.value
|
||||
return prog !== undefined ? Math.round(prog * 100) : undefined
|
||||
})
|
||||
|
||||
// Execution state details
|
||||
const executionState = computed(() => {
|
||||
const state = progressState.value
|
||||
if (!state) return 'idle'
|
||||
return state.state // 'pending' | 'running' | 'finished' | 'error'
|
||||
})
|
||||
|
||||
return {
|
||||
/**
|
||||
* Whether this node is currently executing
|
||||
*/
|
||||
executing,
|
||||
|
||||
/**
|
||||
* Progress as a decimal (0-1) or undefined if no progress available
|
||||
*/
|
||||
progress,
|
||||
|
||||
/**
|
||||
* Progress as a percentage (0-100) or undefined if no progress available
|
||||
*/
|
||||
progressPercentage,
|
||||
|
||||
/**
|
||||
* Raw progress state object from execution store
|
||||
*/
|
||||
progressState,
|
||||
|
||||
/**
|
||||
* Current execution state: 'idle' | 'pending' | 'running' | 'finished' | 'error'
|
||||
*/
|
||||
executionState
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ export const useExecutionStore = defineStore('execution', () => {
|
||||
|
||||
// Easily access all currently executing node IDs
|
||||
const executingNodeIds = computed<NodeId[]>(() => {
|
||||
return Object.entries(nodeProgressStates)
|
||||
return Object.entries(nodeProgressStates.value)
|
||||
.filter(([_, state]) => state.state === 'running')
|
||||
.map(([nodeId, _]) => nodeId)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user