mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 03:01:54 +00:00
feat: hide capture button when 'On Run' mode is selected in webcam widget
- Add updateVueWidgetOptions to GraphNodeManager to update widget options and trigger Vue reactivity - Implement capture button visibility toggle based on capture_on_queue value - Default capture mode to 'Manually' (false) - Use Vue watch to reactively hide/show capture button when mode changes
This commit is contained in:
@@ -75,6 +75,13 @@ export interface GraphNodeManager {
|
|||||||
// Access to original LiteGraph nodes (non-reactive)
|
// Access to original LiteGraph nodes (non-reactive)
|
||||||
getNode(id: string): LGraphNode | undefined
|
getNode(id: string): LGraphNode | undefined
|
||||||
|
|
||||||
|
// Update widget options (e.g., hidden, disabled) - triggers Vue reactivity
|
||||||
|
updateVueWidgetOptions(
|
||||||
|
nodeId: string,
|
||||||
|
widgetName: string,
|
||||||
|
options: Record<string, unknown>
|
||||||
|
): void
|
||||||
|
|
||||||
// Lifecycle methods
|
// Lifecycle methods
|
||||||
cleanup(): void
|
cleanup(): void
|
||||||
}
|
}
|
||||||
@@ -298,6 +305,35 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates Vue state when widget options change (e.g., hidden, disabled)
|
||||||
|
*/
|
||||||
|
const updateVueWidgetOptions = (
|
||||||
|
nodeId: string,
|
||||||
|
widgetName: string,
|
||||||
|
options: Record<string, unknown>
|
||||||
|
): void => {
|
||||||
|
try {
|
||||||
|
const currentData = vueNodeData.get(nodeId)
|
||||||
|
if (!currentData?.widgets) return
|
||||||
|
|
||||||
|
const updatedWidgets = currentData.widgets.map((w) =>
|
||||||
|
w.name === widgetName
|
||||||
|
? { ...w, options: { ...w.options, ...options } }
|
||||||
|
: w
|
||||||
|
)
|
||||||
|
// Create a completely new object to ensure Vue reactivity triggers
|
||||||
|
const updatedData = {
|
||||||
|
...currentData,
|
||||||
|
widgets: updatedWidgets
|
||||||
|
}
|
||||||
|
|
||||||
|
vueNodeData.set(nodeId, updatedData)
|
||||||
|
} catch (error) {
|
||||||
|
// Ignore widget update errors to prevent cascade failures
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a wrapped callback for a widget that maintains LiteGraph/Vue sync
|
* Creates a wrapped callback for a widget that maintains LiteGraph/Vue sync
|
||||||
*/
|
*/
|
||||||
@@ -624,6 +660,7 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
|
|||||||
return {
|
return {
|
||||||
vueNodeData,
|
vueNodeData,
|
||||||
getNode,
|
getNode,
|
||||||
|
updateVueWidgetOptions,
|
||||||
cleanup
|
cleanup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,9 +58,11 @@ import {
|
|||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
ref,
|
ref,
|
||||||
toRaw
|
toRaw,
|
||||||
|
watch
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
|
|
||||||
|
import { useVueNodeLifecycle } from '@/composables/graph/useVueNodeLifecycle'
|
||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||||
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
|
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
|
||||||
@@ -70,6 +72,8 @@ import { api } from '@/scripts/api'
|
|||||||
import { app } from '@/scripts/app'
|
import { app } from '@/scripts/app'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
|
||||||
|
const { nodeManager } = useVueNodeLifecycle()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
widget: SimplifiedWidget<string | number | undefined>
|
widget: SimplifiedWidget<string | number | undefined>
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
@@ -149,7 +153,10 @@ function applyWidgetVisibility(
|
|||||||
// Mutate in place to preserve object identity for serializeValue closure
|
// Mutate in place to preserve object identity for serializeValue closure
|
||||||
widget.type = 'selectToggle'
|
widget.type = 'selectToggle'
|
||||||
widget.label = 'Capture Image'
|
widget.label = 'Capture Image'
|
||||||
widget.value = widget.value ?? false
|
// Default to false (Manual mode) - only set if undefined/null
|
||||||
|
if (widget.value === undefined || widget.value === null) {
|
||||||
|
widget.value = false
|
||||||
|
}
|
||||||
widget.options = {
|
widget.options = {
|
||||||
...widget.options,
|
...widget.options,
|
||||||
hidden,
|
hidden,
|
||||||
@@ -196,6 +203,53 @@ function createActionWidget({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateCaptureButtonVisibility(isOnRunMode: boolean) {
|
||||||
|
withLitegraphNode((node) => {
|
||||||
|
// Update the LiteGraph widget options
|
||||||
|
const captureWidget = node.widgets?.find(
|
||||||
|
(w) => w.name === CAPTURE_WIDGET_NAME
|
||||||
|
)
|
||||||
|
if (captureWidget) {
|
||||||
|
captureWidget.options = {
|
||||||
|
...captureWidget.options,
|
||||||
|
hidden: isOnRunMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Vue state directly to trigger reactivity
|
||||||
|
nodeManager.value?.updateVueWidgetOptions(
|
||||||
|
String(node.id),
|
||||||
|
CAPTURE_WIDGET_NAME,
|
||||||
|
{ hidden: isOnRunMode }
|
||||||
|
)
|
||||||
|
|
||||||
|
app.graph.setDirtyCanvas(true, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computed to get capture_on_queue widget value from Vue state
|
||||||
|
const captureOnQueueValue = computed(() => {
|
||||||
|
const vueNodeData = nodeManager.value?.vueNodeData.get(props.nodeId)
|
||||||
|
const widget = vueNodeData?.widgets?.find(
|
||||||
|
(w) => w.name === 'capture_on_queue'
|
||||||
|
)
|
||||||
|
return widget?.value === true
|
||||||
|
})
|
||||||
|
|
||||||
|
function setupCaptureOnQueueWatcher() {
|
||||||
|
// Set initial visibility
|
||||||
|
updateCaptureButtonVisibility(captureOnQueueValue.value)
|
||||||
|
|
||||||
|
// Watch for changes using Vue reactivity
|
||||||
|
watch(
|
||||||
|
captureOnQueueValue,
|
||||||
|
(isOnRunMode) => {
|
||||||
|
updateCaptureButtonVisibility(isOnRunMode)
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function removeWidgetsByName(names: string[]) {
|
function removeWidgetsByName(names: string[]) {
|
||||||
withLitegraphNode((node) => {
|
withLitegraphNode((node) => {
|
||||||
if (!node.widgets?.length) return
|
if (!node.widgets?.length) return
|
||||||
@@ -288,6 +342,12 @@ function setupSerializeValue() {
|
|||||||
|
|
||||||
function showWidgets() {
|
function showWidgets() {
|
||||||
withLitegraphNode((node) => {
|
withLitegraphNode((node) => {
|
||||||
|
// Get current capture_on_queue value to determine initial button visibility
|
||||||
|
const captureOnQueueWidget = node.widgets?.find(
|
||||||
|
(w) => w.name === 'capture_on_queue'
|
||||||
|
)
|
||||||
|
const isOnRunMode = captureOnQueueWidget?.value === true
|
||||||
|
|
||||||
updateNodeWidgets(node, (widgets) => {
|
updateNodeWidgets(node, (widgets) => {
|
||||||
const sanitizedWidgets = widgets
|
const sanitizedWidgets = widgets
|
||||||
.map((widget) => applyWidgetVisibility(widget, false))
|
.map((widget) => applyWidgetVisibility(widget, false))
|
||||||
@@ -304,8 +364,19 @@ function showWidgets() {
|
|||||||
onClick: () => captureImage(node)
|
onClick: () => captureImage(node)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Hide capture button if in "On Run" mode
|
||||||
|
if (isOnRunMode) {
|
||||||
|
captureWidget.options = {
|
||||||
|
...captureWidget.options,
|
||||||
|
hidden: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [...sanitizedWidgets, captureWidget]
|
return [...sanitizedWidgets, captureWidget]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Set up watcher to toggle capture button visibility when mode changes
|
||||||
|
setupCaptureOnQueueWatcher()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user