mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 02:32:18 +00:00
fix: prevent Vue reactivity from breaking LiteGraph widget private fields
Use toRaw() and markRaw() when modifying widget objects to prevent Vue's reactive proxy from wrapping them. This fixes errors when LiteGraph tries to access private class members like #value in BaseWidget.
This commit is contained in:
@@ -15,7 +15,15 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Button } from 'primevue'
|
import { Button } from 'primevue'
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
import {
|
||||||
|
computed,
|
||||||
|
markRaw,
|
||||||
|
nextTick,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted,
|
||||||
|
ref,
|
||||||
|
toRaw
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||||
@@ -44,48 +52,49 @@ function storeOriginalWidgets() {
|
|||||||
const node = litegraphNode.value
|
const node = litegraphNode.value
|
||||||
if (!node?.widgets) return
|
if (!node?.widgets) return
|
||||||
|
|
||||||
// Deep clone the original widgets to preserve their state
|
// Store raw widgets to preserve their state without reactivity
|
||||||
originalWidgets.value = [...node.widgets]
|
originalWidgets.value = node.widgets.map((w) => toRaw(w))
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideWidgets() {
|
function hideWidgets() {
|
||||||
const node = litegraphNode.value
|
const node = litegraphNode.value
|
||||||
if (!node?.widgets) return
|
if (!node?.widgets) return
|
||||||
|
|
||||||
// Create completely new widget objects to trigger shallowReactive
|
// Use toRaw to unwrap reactive proxies, then markRaw to prevent re-wrapping
|
||||||
const newWidgets = node.widgets.map((widget) => {
|
const newWidgets = node.widgets.map((widget) => {
|
||||||
|
const rawWidget = toRaw(widget)
|
||||||
const shouldHide = ['height', 'width', 'capture_on_queue'].includes(
|
const shouldHide = ['height', 'width', 'capture_on_queue'].includes(
|
||||||
widget.name
|
rawWidget.name
|
||||||
)
|
)
|
||||||
|
|
||||||
if (shouldHide) {
|
if (shouldHide) {
|
||||||
// Special handling for capture_on_queue widget
|
// Special handling for capture_on_queue widget
|
||||||
if (widget.name === 'capture_on_queue') {
|
if (rawWidget.name === 'capture_on_queue') {
|
||||||
return {
|
return markRaw({
|
||||||
...widget,
|
...rawWidget,
|
||||||
type: 'selectToggle',
|
type: 'selectToggle',
|
||||||
label: 'Capture Image',
|
label: 'Capture Image',
|
||||||
value: widget.value ?? false,
|
value: rawWidget.value ?? false,
|
||||||
options: {
|
options: {
|
||||||
...widget.options,
|
...rawWidget.options,
|
||||||
hidden: true,
|
hidden: true,
|
||||||
values: [
|
values: [
|
||||||
{ label: 'On Run', value: true },
|
{ label: 'On Run', value: true },
|
||||||
{ label: 'Manually', value: false }
|
{ label: 'Manually', value: false }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return markRaw({
|
||||||
...widget,
|
...rawWidget,
|
||||||
options: {
|
options: {
|
||||||
...widget.options,
|
...rawWidget.options,
|
||||||
hidden: true
|
hidden: true
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
return widget
|
return rawWidget
|
||||||
})
|
})
|
||||||
|
|
||||||
node.widgets = newWidgets
|
node.widgets = newWidgets
|
||||||
@@ -95,48 +104,49 @@ function restoreWidgets() {
|
|||||||
const node = litegraphNode.value
|
const node = litegraphNode.value
|
||||||
if (!node?.widgets || originalWidgets.value.length === 0) return
|
if (!node?.widgets || originalWidgets.value.length === 0) return
|
||||||
|
|
||||||
// Restore the original widgets
|
// Restore the original widgets (already raw from storage)
|
||||||
node.widgets = originalWidgets.value
|
node.widgets = originalWidgets.value.map((w) => toRaw(w))
|
||||||
}
|
}
|
||||||
|
|
||||||
function showWidgets() {
|
function showWidgets() {
|
||||||
const node = litegraphNode.value
|
const node = litegraphNode.value
|
||||||
if (!node?.widgets) return
|
if (!node?.widgets) return
|
||||||
|
|
||||||
// Create completely new widget objects to trigger shallowReactive
|
// Use toRaw to unwrap reactive proxies, then markRaw to prevent re-wrapping
|
||||||
const newWidgets = node.widgets.map((widget) => {
|
const newWidgets = node.widgets.map((widget) => {
|
||||||
|
const rawWidget = toRaw(widget)
|
||||||
const shouldShow = ['height', 'width', 'capture_on_queue'].includes(
|
const shouldShow = ['height', 'width', 'capture_on_queue'].includes(
|
||||||
widget.name
|
rawWidget.name
|
||||||
)
|
)
|
||||||
|
|
||||||
if (shouldShow) {
|
if (shouldShow) {
|
||||||
// Special handling for capture_on_queue widget
|
// Special handling for capture_on_queue widget
|
||||||
if (widget.name === 'capture_on_queue') {
|
if (rawWidget.name === 'capture_on_queue') {
|
||||||
return {
|
return markRaw({
|
||||||
...widget,
|
...rawWidget,
|
||||||
type: 'selectToggle',
|
type: 'selectToggle',
|
||||||
label: 'Capture Image',
|
label: 'Capture Image',
|
||||||
value: widget.value ?? false,
|
value: rawWidget.value ?? false,
|
||||||
options: {
|
options: {
|
||||||
...widget.options,
|
...rawWidget.options,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
values: [
|
values: [
|
||||||
{ label: 'On Run', value: true },
|
{ label: 'On Run', value: true },
|
||||||
{ label: 'Manually', value: false }
|
{ label: 'Manually', value: false }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return markRaw({
|
||||||
...widget,
|
...rawWidget,
|
||||||
options: {
|
options: {
|
||||||
...widget.options,
|
...rawWidget.options,
|
||||||
hidden: false
|
hidden: false
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
return widget
|
return rawWidget
|
||||||
})
|
})
|
||||||
|
|
||||||
node.widgets = newWidgets
|
node.widgets = newWidgets
|
||||||
|
|||||||
Reference in New Issue
Block a user