mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-01 19:20:10 +00:00
feat: add refreshVueWidgets to sync widget changes with Vue state
- Add refreshVueWidgets function to GraphNodeManager for manually syncing LiteGraph widget changes with Vue reactive state - Use refreshVueWidgets after widget modifications (capture, retake, show) - Fixes retake button not appearing after capturing an image
This commit is contained in:
@@ -82,6 +82,9 @@ export interface GraphNodeManager {
|
||||
options: Record<string, unknown>
|
||||
): void
|
||||
|
||||
// Refresh Vue widgets from LiteGraph node - use after modifying node.widgets
|
||||
refreshVueWidgets(nodeId: string): void
|
||||
|
||||
// Lifecycle methods
|
||||
cleanup(): void
|
||||
}
|
||||
@@ -334,6 +337,38 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes Vue widget state from LiteGraph node widgets.
|
||||
* Use this after directly modifying node.widgets to sync Vue state.
|
||||
*/
|
||||
const refreshVueWidgets = (nodeId: string): void => {
|
||||
try {
|
||||
const node = nodeRefs.get(nodeId)
|
||||
const currentData = vueNodeData.get(nodeId)
|
||||
if (!node || !currentData) return
|
||||
|
||||
// Re-extract widgets from node
|
||||
const slotMetadata = new Map<string, WidgetSlotMetadata>()
|
||||
node.inputs?.forEach((input, index) => {
|
||||
if (!input?.widget?.name) return
|
||||
slotMetadata.set(input.widget.name, {
|
||||
index,
|
||||
linked: input.link != null
|
||||
})
|
||||
})
|
||||
|
||||
const freshWidgets =
|
||||
node.widgets?.map(safeWidgetMapper(node, slotMetadata)) ?? []
|
||||
|
||||
vueNodeData.set(nodeId, {
|
||||
...currentData,
|
||||
widgets: freshWidgets
|
||||
})
|
||||
} catch (error) {
|
||||
// Ignore refresh errors
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped callback for a widget that maintains LiteGraph/Vue sync
|
||||
*/
|
||||
@@ -661,6 +696,7 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
|
||||
vueNodeData,
|
||||
getNode,
|
||||
updateVueWidgetOptions,
|
||||
refreshVueWidgets,
|
||||
cleanup
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,9 @@ const processedWidgets = computed((): ProcessedWidget[] => {
|
||||
|
||||
for (const widget of widgets) {
|
||||
// Skip if widget is in the hidden list for this node type
|
||||
if (widget.options?.hidden) continue
|
||||
if (widget.options?.hidden) {
|
||||
continue
|
||||
}
|
||||
if (widget.options?.canvasOnly) continue
|
||||
if (!widget.type) continue
|
||||
if (!shouldRenderAsVue(widget)) continue
|
||||
|
||||
@@ -197,7 +197,8 @@ function createActionWidget({
|
||||
y: 100,
|
||||
options: {
|
||||
iconClass,
|
||||
serialize: false
|
||||
serialize: false,
|
||||
hidden: false
|
||||
},
|
||||
callback: onClick
|
||||
}
|
||||
@@ -256,6 +257,8 @@ function removeWidgetsByName(names: string[]) {
|
||||
updateNodeWidgets(node, (widgets) =>
|
||||
widgets.filter((widget) => !names.includes(widget.name))
|
||||
)
|
||||
// Refresh Vue state to pick up widget removal
|
||||
nodeManager.value?.refreshVueWidgets(String(node.id))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -375,6 +378,9 @@ function showWidgets() {
|
||||
return [...sanitizedWidgets, captureWidget]
|
||||
})
|
||||
|
||||
// Refresh Vue state to pick up the new widgets
|
||||
nodeManager.value?.refreshVueWidgets(String(node.id))
|
||||
|
||||
// Set up watcher to toggle capture button visibility when mode changes
|
||||
setupCaptureOnQueueWatcher()
|
||||
})
|
||||
@@ -475,6 +481,9 @@ async function captureImage(node: LGraphNode) {
|
||||
|
||||
return [...preserved, retakeWidget]
|
||||
})
|
||||
|
||||
// Refresh Vue state to pick up the new widgets
|
||||
nodeManager.value?.refreshVueWidgets(String(node.id))
|
||||
}
|
||||
|
||||
async function handleRetake() {
|
||||
|
||||
Reference in New Issue
Block a user