diff --git a/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png b/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png index b8de43d059..2e0e795fad 100644 Binary files a/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png and b/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png b/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png index ed2e63d047..07ca314be7 100644 Binary files a/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png and b/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png index db3883b5bc..15091b9fb0 100644 Binary files a/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.png index 4df1c65ac0..95c2fc57f5 100644 Binary files a/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png b/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png index 7fe1f3aa3b..3bb6445a1c 100644 Binary files a/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png and b/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.png index 46544631b6..699c76e7f2 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png index 251c07a08a..9de2771ccc 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png index c876d8af37..d440df84fc 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png index 015c2479da..2549fbc20c 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.png index 5b37aad716..d0d9ad0f6d 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.png differ diff --git a/src/components/toast/VueNodesMigrationToast.vue b/src/components/toast/VueNodesMigrationToast.vue new file mode 100644 index 0000000000..ae86f74e66 --- /dev/null +++ b/src/components/toast/VueNodesMigrationToast.vue @@ -0,0 +1,48 @@ + + + diff --git a/src/composables/graph/useVueNodeLifecycle.ts b/src/composables/graph/useVueNodeLifecycle.ts index fbce66dce6..d2c8cf6780 100644 --- a/src/composables/graph/useVueNodeLifecycle.ts +++ b/src/composables/graph/useVueNodeLifecycle.ts @@ -4,6 +4,7 @@ import { shallowRef, watch } from 'vue' import { useGraphNodeManager } from '@/composables/graph/useGraphNodeManager' import type { GraphNodeManager } from '@/composables/graph/useGraphNodeManager' import { useVueFeatureFlags } from '@/composables/useVueFeatureFlags' +import { useVueNodesMigrationDismissed } from '@/composables/useVueNodesMigrationDismissed' import type { LGraphNode } from '@/lib/litegraph/src/litegraph' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations' @@ -11,6 +12,7 @@ import { layoutStore } from '@/renderer/core/layout/store/layoutStore' import { useLayoutSync } from '@/renderer/core/layout/sync/useLayoutSync' import { ensureCorrectLayoutScale } from '@/renderer/extensions/vueNodes/layout/ensureCorrectLayoutScale' import { app as comfyApp } from '@/scripts/app' +import { useToastStore } from '@/platform/updates/common/toastStore' function useVueNodeLifecycleIndividual() { const canvasStore = useCanvasStore() @@ -21,6 +23,8 @@ function useVueNodeLifecycleIndividual() { const { startSync } = useLayoutSync() + const isVueNodeToastDismissed = useVueNodesMigrationDismissed() + const initializeNodeManager = () => { // Use canvas graph if available (handles subgraph contexts), fallback to app graph const activeGraph = comfyApp.canvas?.graph @@ -75,11 +79,20 @@ function useVueNodeLifecycleIndividual() { // Watch for Vue nodes enabled state changes watch( () => shouldRenderVueNodes.value && Boolean(comfyApp.canvas?.graph), - (enabled) => { + (enabled, wasEnabled) => { if (enabled) { initializeNodeManager() ensureCorrectLayoutScale() + + if (!wasEnabled && !isVueNodeToastDismissed.value) { + useToastStore().add({ + group: 'vue-nodes-migration', + severity: 'info', + life: 0 + }) + } } else { + comfyApp.canvas?.setDirty(true, true) disposeNodeManagerAndSyncs() } }, diff --git a/src/composables/useVueNodesMigrationDismissed.ts b/src/composables/useVueNodesMigrationDismissed.ts new file mode 100644 index 0000000000..1d72760fc8 --- /dev/null +++ b/src/composables/useVueNodesMigrationDismissed.ts @@ -0,0 +1,8 @@ +import { createSharedComposable, useLocalStorage } from '@vueuse/core' + +// Browser storage events don't fire in the same tab, so separate +// useLocalStorage() calls create isolated reactive refs. Use shared +// composable to ensure all components use the same ref instance. +export const useVueNodesMigrationDismissed = createSharedComposable(() => + useLocalStorage('comfy.vueNodesMigration.dismissed', false) +) diff --git a/src/locales/en/main.json b/src/locales/en/main.json index c4a3c7b0e2..e23dbd0d71 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -1820,8 +1820,12 @@ } } }, + "vueNodesMigration": { + "message": "Prefer the classic node design?", + "button": "Open Settings" + }, "vueNodesBanner": { "message": "Nodes just got a new look and feel", "tryItOut": "Try it out" } -} \ No newline at end of file +} diff --git a/src/platform/settings/constants/coreSettings.ts b/src/platform/settings/constants/coreSettings.ts index 2b8eba44c9..b2f70776ad 100644 --- a/src/platform/settings/constants/coreSettings.ts +++ b/src/platform/settings/constants/coreSettings.ts @@ -1057,17 +1057,17 @@ export const CORE_SETTINGS: SettingParams[] = [ */ { id: 'Comfy.VueNodes.Enabled', - name: 'Enable Vue node rendering (hidden)', - type: 'hidden', + name: 'Modern Node Design (Vue Nodes)', + type: 'boolean', tooltip: - 'Render nodes as Vue components instead of canvas. Hidden; toggle via Experimental keybinding.', + 'Modern: DOM-based rendering with enhanced interactivity, native browser features, and updated visual design. Classic: Traditional canvas rendering.', defaultValue: false, experimental: true, versionAdded: '1.27.1' }, { id: 'Comfy.VueNodes.AutoScaleLayout', - name: 'Auto-scale layout for Vue nodes', + name: 'Auto-scale layout (Vue nodes)', tooltip: 'Automatically scale node positions when switching to Vue rendering to prevent overlap', type: 'boolean', diff --git a/src/views/GraphView.vue b/src/views/GraphView.vue index 6bb8645855..5cacf47474 100644 --- a/src/views/GraphView.vue +++ b/src/views/GraphView.vue @@ -15,6 +15,7 @@ + @@ -40,6 +41,7 @@ import UnloadWindowConfirmDialog from '@/components/dialog/UnloadWindowConfirmDi import GraphCanvas from '@/components/graph/GraphCanvas.vue' import GlobalToast from '@/components/toast/GlobalToast.vue' import RerouteMigrationToast from '@/components/toast/RerouteMigrationToast.vue' +import VueNodesMigrationToast from '@/components/toast/VueNodesMigrationToast.vue' import { useBrowserTabTitle } from '@/composables/useBrowserTabTitle' import { useCoreCommands } from '@/composables/useCoreCommands' import { useErrorHandling } from '@/composables/useErrorHandling'