Feat: Remove the Nodes 2.0 Trial Banner (#7390)
## Summary The option to try it out is still in the Menu if you're looking for it. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7390-Feat-Remove-the-Nodes-2-0-Trial-Banner-2c66d73d365081c3817ad5c89dd4029b) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 109 KiB |
@@ -4,7 +4,6 @@
|
||||
synced with the stateStorage (localStorage). -->
|
||||
<LiteGraphCanvasSplitterOverlay v-if="comfyAppReady">
|
||||
<template v-if="showUI" #workflow-tabs>
|
||||
<TryVueNodeBanner />
|
||||
<div
|
||||
v-if="workflowTabsPosition === 'Topbar'"
|
||||
class="workflow-tabs-container pointer-events-auto relative h-9.5 w-full"
|
||||
@@ -161,7 +160,6 @@ import { useSearchBoxStore } from '@/stores/workspace/searchBoxStore'
|
||||
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
||||
import { isNativeWindow } from '@/utils/envUtil'
|
||||
|
||||
import TryVueNodeBanner from '../topbar/TryVueNodeBanner.vue'
|
||||
import SelectionRectangle from './SelectionRectangle.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<Toast
|
||||
group="vue-nodes-migration"
|
||||
position="bottom-center"
|
||||
class="w-auto"
|
||||
@close="handleClose"
|
||||
>
|
||||
<template #message>
|
||||
<div class="flex flex-auto items-center justify-between gap-4">
|
||||
<span class="whitespace-nowrap">{{
|
||||
t('vueNodesMigration.message')
|
||||
}}</span>
|
||||
<Button
|
||||
class="whitespace-nowrap"
|
||||
size="small"
|
||||
:label="t('vueNodesMigration.button')"
|
||||
text
|
||||
@click="switchBack"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Toast>
|
||||
<Toast
|
||||
group="vue-nodes-check-main-menu"
|
||||
position="bottom-center"
|
||||
class="w-auto"
|
||||
>
|
||||
<template #message>
|
||||
<div class="flex flex-auto items-center justify-between gap-4">
|
||||
<span class="whitespace-nowrap">{{
|
||||
t('vueNodesMigrationMainMenu.message')
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</Toast>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useToast } from 'primevue'
|
||||
import Button from 'primevue/button'
|
||||
import Toast from 'primevue/toast'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useVueNodesMigrationDismissed } from '@/composables/useVueNodesMigrationDismissed'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
|
||||
const { t } = useI18n()
|
||||
const toast = useToast()
|
||||
const isDismissed = useVueNodesMigrationDismissed()
|
||||
|
||||
const switchBack = async () => {
|
||||
await disableVueNodes()
|
||||
toast.removeGroup('vue-nodes-migration')
|
||||
isDismissed.value = true
|
||||
showMainMenuToast()
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
isDismissed.value = true
|
||||
showMainMenuToast()
|
||||
}
|
||||
|
||||
const disableVueNodes = async () => {
|
||||
await useSettingStore().set('Comfy.VueNodes.Enabled', false)
|
||||
useTelemetry()?.trackUiButtonClicked({
|
||||
button_id: `vue_nodes_migration_toast_switch_back_clicked`
|
||||
})
|
||||
}
|
||||
|
||||
const showMainMenuToast = () => {
|
||||
useToastStore().add({
|
||||
group: 'vue-nodes-check-main-menu',
|
||||
severity: 'info',
|
||||
life: 5000
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -1,74 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="showVueNodesBanner"
|
||||
class="pointer-events-auto relative w-full h-10 bg-gradient-to-r from-blue-600 to-blue-700 flex items-center justify-center px-4"
|
||||
>
|
||||
<div class="flex items-center text-sm text-white">
|
||||
<i class="icon-[lucide--rocket]"></i>
|
||||
<span class="pl-2">{{ $t('vueNodesBanner.title') }}</span>
|
||||
<span class="pl-1.5 hidden md:inline">{{
|
||||
$t('vueNodesBanner.desc')
|
||||
}}</span>
|
||||
<Button
|
||||
class="cursor-pointer bg-transparent rounded h-7 px-3 border border-white text-white ml-4 text-xs"
|
||||
@click="handleTryItOut"
|
||||
>
|
||||
{{ $t('vueNodesBanner.tryItOut') }}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
class="cursor-pointer bg-transparent border-0 outline-0 grid place-items-center absolute right-4 text-white"
|
||||
unstyled
|
||||
@click="handleDismiss"
|
||||
>
|
||||
<i class="w-5 h-5 icon-[lucide--x]"></i>
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useLocalStorage } from '@vueuse/core'
|
||||
import Button from 'primevue/button'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
|
||||
const STORAGE_KEY = 'vueNodesBannerDismissed'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const bannerDismissed = useLocalStorage(STORAGE_KEY, false)
|
||||
|
||||
const vueNodesEnabled = computed(() => {
|
||||
try {
|
||||
return settingStore.get('Comfy.VueNodes.Enabled') ?? false
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
const showVueNodesBanner = computed(() => {
|
||||
if (vueNodesEnabled.value) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (bannerDismissed.value) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
const handleDismiss = (): void => {
|
||||
bannerDismissed.value = true
|
||||
}
|
||||
|
||||
const handleTryItOut = async (): Promise<void> => {
|
||||
try {
|
||||
await settingStore.set('Comfy.VueNodes.Enabled', true)
|
||||
} catch (error) {
|
||||
console.error('Failed to enable Nodes 2.0:', error)
|
||||
} finally {
|
||||
handleDismiss()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -4,7 +4,6 @@ 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'
|
||||
@@ -13,7 +12,6 @@ import { useLayoutSync } from '@/renderer/core/layout/sync/useLayoutSync'
|
||||
import { removeNodeTitleHeight } from '@/renderer/core/layout/utils/nodeSizeUtil'
|
||||
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()
|
||||
@@ -22,10 +20,6 @@ function useVueNodeLifecycleIndividual() {
|
||||
const nodeManager = shallowRef<GraphNodeManager | null>(null)
|
||||
const { startSync } = useLayoutSync()
|
||||
|
||||
const isVueNodeToastDismissed = useVueNodesMigrationDismissed()
|
||||
|
||||
let hasShownMigrationToast = false
|
||||
|
||||
const initializeNodeManager = () => {
|
||||
// Use canvas graph if available (handles subgraph contexts), fallback to app graph
|
||||
const activeGraph = comfyApp.canvas?.graph
|
||||
@@ -83,24 +77,12 @@ function useVueNodeLifecycleIndividual() {
|
||||
// Watch for Vue nodes enabled state changes
|
||||
watch(
|
||||
() => shouldRenderVueNodes.value && Boolean(comfyApp.canvas?.graph),
|
||||
(enabled, wasEnabled) => {
|
||||
(enabled) => {
|
||||
if (enabled) {
|
||||
initializeNodeManager()
|
||||
ensureCorrectLayoutScale(
|
||||
comfyApp.canvas?.graph?.extra.workflowRendererVersion
|
||||
)
|
||||
if (
|
||||
wasEnabled === false &&
|
||||
!isVueNodeToastDismissed.value &&
|
||||
!hasShownMigrationToast
|
||||
) {
|
||||
hasShownMigrationToast = true
|
||||
useToastStore().add({
|
||||
group: 'vue-nodes-migration',
|
||||
severity: 'info',
|
||||
life: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
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)
|
||||
)
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
<GlobalToast />
|
||||
<RerouteMigrationToast />
|
||||
<VueNodesMigrationToast />
|
||||
<UnloadWindowConfirmDialog v-if="!isElectron()" />
|
||||
<MenuHamburger />
|
||||
</template>
|
||||
@@ -44,7 +43,6 @@ 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'
|
||||
|
||||