From 2852720b2cfb8a51d04c3d946b5fc62a687b3353 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Sat, 25 Jan 2025 16:58:50 -0500 Subject: [PATCH] [Refactor] Extract workflow/workflow tabs restore into a composable (#2350) --- src/components/graph/GraphCanvas.vue | 117 ++--------------------- src/hooks/workflowPersistenceHooks.ts | 130 ++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 110 deletions(-) create mode 100644 src/hooks/workflowPersistenceHooks.ts diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index b8c181667..14d642908 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -54,25 +54,24 @@ import SideToolbar from '@/components/sidebar/SideToolbar.vue' import SecondRowWorkflowTabs from '@/components/topbar/SecondRowWorkflowTabs.vue' import { CORE_SETTINGS } from '@/constants/coreSettings' import { usePragmaticDroppable } from '@/hooks/dndHooks' +import { useWorkflowPersistence } from '@/hooks/workflowPersistenceHooks' import { i18n } from '@/i18n' import { api } from '@/scripts/api' import { app as comfyApp } from '@/scripts/app' import { ChangeTracker } from '@/scripts/changeTracker' -import { getStorageValue, setStorageValue } from '@/scripts/utils' import { IS_CONTROL_WIDGET, updateControlWidgetLabel } from '@/scripts/widgets' import { useColorPaletteService } from '@/services/colorPaletteService' import { useLitegraphService } from '@/services/litegraphService' import { useWorkflowService } from '@/services/workflowService' import { useCommandStore } from '@/stores/commandStore' import { useCanvasStore } from '@/stores/graphStore' -import { ComfyModelDef, useModelStore } from '@/stores/modelStore' +import { ComfyModelDef } from '@/stores/modelStore' import { ModelNodeProvider, useModelToNodeStore } from '@/stores/modelToNodeStore' import { ComfyNodeDefImpl, useNodeDefStore } from '@/stores/nodeDefStore' import { useSettingStore } from '@/stores/settingStore' -import { useWorkflowStore } from '@/stores/workflowStore' import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import { useWorkspaceStore } from '@/stores/workspaceStore' import type { RenderedTreeExplorerNode } from '@/types/treeExplorerTypes' @@ -96,29 +95,6 @@ const canvasMenuEnabled = computed(() => ) const tooltipEnabled = computed(() => settingStore.get('Comfy.EnableTooltips')) -const storedWorkflows = JSON.parse( - getStorageValue('Comfy.OpenWorkflowsPaths') || '[]' -) -const storedActiveIndex = JSON.parse( - getStorageValue('Comfy.ActiveWorkflowIndex') || '-1' -) -const openWorkflows = computed(() => workspaceStore?.workflow?.openWorkflows) -const activeWorkflow = computed(() => workspaceStore?.workflow?.activeWorkflow) -const restoreState = computed<{ paths: string[]; activeIndex: number }>(() => { - if (!openWorkflows.value || !activeWorkflow.value) { - return { paths: [], activeIndex: -1 } - } - - const paths = openWorkflows.value - .filter((workflow) => workflow?.isPersisted && !workflow.isModified) - .map((workflow) => workflow.path) - const activeIndex = openWorkflows.value.findIndex( - (workflow) => workflow.path === activeWorkflow.value?.path - ) - - return { paths, activeIndex } -}) - watchEffect(() => { const canvasInfoEnabled = settingStore.get('Comfy.Graph.CanvasInfo') if (canvasStore.canvas) { @@ -270,27 +246,6 @@ watch( } ) -const workflowStore = useWorkflowStore() -const persistCurrentWorkflow = () => { - const workflow = JSON.stringify(comfyApp.serializeGraph()) - localStorage.setItem('workflow', workflow) - if (api.clientId) { - sessionStorage.setItem(`workflow:${api.clientId}`, workflow) - } -} - -watchEffect(() => { - if (workflowStore.activeWorkflow) { - const workflow = workflowStore.activeWorkflow - setStorageValue('Comfy.PreviousWorkflow', workflow.key) - // When the activeWorkflow changes, the graph has already been loaded. - // Saving the current state of the graph to the localStorage. - persistCurrentWorkflow() - } -}) - -api.addEventListener('graphChanged', persistCurrentWorkflow) - usePragmaticDroppable(() => canvasRef.value, { onDrop: (event) => { const loc = event.location.current.input @@ -360,57 +315,9 @@ const loadCustomNodesI18n = async () => { } } -const loadWorkflowFromStorage = async (json: string, workflowName: string) => { - if (!json) return false - const workflow = JSON.parse(json) - await comfyApp.loadGraphData(workflow, true, true, workflowName) - return true -} - -const loadPreviousWorkflowFromStorage = async () => { - const workflowName = getStorageValue('Comfy.PreviousWorkflow') - const clientId = api.initialClientId ?? api.clientId - - // Try loading from session storage first - if (clientId) { - const sessionWorkflow = sessionStorage.getItem(`workflow:${clientId}`) - if (await loadWorkflowFromStorage(sessionWorkflow, workflowName)) { - return true - } - } - - // Fall back to local storage - const localWorkflow = localStorage.getItem('workflow') - return await loadWorkflowFromStorage(localWorkflow, workflowName) -} - -const loadDefaultWorkflow = async () => { - const settingStore = useSettingStore() - - if (!settingStore.get('Comfy.TutorialCompleted')) { - await settingStore.set('Comfy.TutorialCompleted', true) - // Load model folders to ensure the missing models' corresponding folders - // can be correctly identified. - await useModelStore().loadModelFolders() - await useWorkflowService().loadTutorialWorkflow() - } else { - await comfyApp.loadGraphData() - } -} - -const restorePreviousWorkflow = async () => { - try { - const restored = await loadPreviousWorkflowFromStorage() - if (!restored) { - await loadDefaultWorkflow() - } - } catch (err) { - console.error('Error loading previous workflow', err) - await loadDefaultWorkflow() - } -} - const comfyAppReady = ref(false) +const workflowPersistence = useWorkflowPersistence() + onMounted(async () => { // Backward compatible // Assign all properties of lg to window @@ -450,19 +357,9 @@ onMounted(async () => { 'Comfy.CustomColorPalettes' ) - // Restore workflow from storage - await restorePreviousWorkflow() - const isRestorable = storedWorkflows?.length > 0 && storedActiveIndex >= 0 - if (isRestorable) - workflowStore.openWorkflowsInBackground({ - left: storedWorkflows.slice(0, storedActiveIndex), - right: storedWorkflows.slice(storedActiveIndex) - }) - - watch(restoreState, ({ paths, activeIndex }) => { - setStorageValue('Comfy.OpenWorkflowsPaths', JSON.stringify(paths)) - setStorageValue('Comfy.ActiveWorkflowIndex', JSON.stringify(activeIndex)) - }) + // Restore workflow and workflow tabs state from storage + await workflowPersistence.restorePreviousWorkflow() + workflowPersistence.restoreWorkflowTabsState() // Start watching for locale change after the initial value is loaded. watch( diff --git a/src/hooks/workflowPersistenceHooks.ts b/src/hooks/workflowPersistenceHooks.ts new file mode 100644 index 000000000..eeb879ab7 --- /dev/null +++ b/src/hooks/workflowPersistenceHooks.ts @@ -0,0 +1,130 @@ +import { computed, watch, watchEffect } from 'vue' + +import { api } from '@/scripts/api' +import { app as comfyApp } from '@/scripts/app' +import { getStorageValue, setStorageValue } from '@/scripts/utils' +import { useWorkflowService } from '@/services/workflowService' +import { useModelStore } from '@/stores/modelStore' +import { useSettingStore } from '@/stores/settingStore' +import { useWorkflowStore } from '@/stores/workflowStore' + +export function useWorkflowPersistence() { + const workflowStore = useWorkflowStore() + const settingStore = useSettingStore() + + const persistCurrentWorkflow = () => { + const workflow = JSON.stringify(comfyApp.serializeGraph()) + localStorage.setItem('workflow', workflow) + if (api.clientId) { + sessionStorage.setItem(`workflow:${api.clientId}`, workflow) + } + } + + const loadWorkflowFromStorage = async ( + json: string | null, + workflowName: string | null + ) => { + if (!json) return false + const workflow = JSON.parse(json) + await comfyApp.loadGraphData(workflow, true, true, workflowName) + return true + } + + const loadPreviousWorkflowFromStorage = async () => { + const workflowName = getStorageValue('Comfy.PreviousWorkflow') + const clientId = api.initialClientId ?? api.clientId + + // Try loading from session storage first + if (clientId) { + const sessionWorkflow = sessionStorage.getItem(`workflow:${clientId}`) + if (await loadWorkflowFromStorage(sessionWorkflow, workflowName)) { + return true + } + } + + // Fall back to local storage + const localWorkflow = localStorage.getItem('workflow') + return await loadWorkflowFromStorage(localWorkflow, workflowName) + } + + const loadDefaultWorkflow = async () => { + if (!settingStore.get('Comfy.TutorialCompleted')) { + await settingStore.set('Comfy.TutorialCompleted', true) + await useModelStore().loadModelFolders() + await useWorkflowService().loadTutorialWorkflow() + } else { + await comfyApp.loadGraphData() + } + } + + const restorePreviousWorkflow = async () => { + try { + const restored = await loadPreviousWorkflowFromStorage() + if (!restored) { + await loadDefaultWorkflow() + } + } catch (err) { + console.error('Error loading previous workflow', err) + await loadDefaultWorkflow() + } + } + + // Setup watchers + watchEffect(() => { + if (workflowStore.activeWorkflow) { + const workflow = workflowStore.activeWorkflow + setStorageValue('Comfy.PreviousWorkflow', workflow.key) + // When the activeWorkflow changes, the graph has already been loaded. + // Saving the current state of the graph to the localStorage. + persistCurrentWorkflow() + } + }) + api.addEventListener('graphChanged', persistCurrentWorkflow) + + // Restore workflow tabs states + const openWorkflows = computed(() => workflowStore.openWorkflows) + const activeWorkflow = computed(() => workflowStore.activeWorkflow) + const restoreState = computed<{ paths: string[]; activeIndex: number }>( + () => { + if (!openWorkflows.value || !activeWorkflow.value) { + return { paths: [], activeIndex: -1 } + } + + const paths = openWorkflows.value + .filter((workflow) => workflow?.isPersisted && !workflow.isModified) + .map((workflow) => workflow.path) + const activeIndex = openWorkflows.value.findIndex( + (workflow) => workflow.path === activeWorkflow.value?.path + ) + + return { paths, activeIndex } + } + ) + + // Get storage values before setting watchers + const storedWorkflows = JSON.parse( + getStorageValue('Comfy.OpenWorkflowsPaths') || '[]' + ) + const storedActiveIndex = JSON.parse( + getStorageValue('Comfy.ActiveWorkflowIndex') || '-1' + ) + watch(restoreState, ({ paths, activeIndex }) => { + setStorageValue('Comfy.OpenWorkflowsPaths', JSON.stringify(paths)) + setStorageValue('Comfy.ActiveWorkflowIndex', JSON.stringify(activeIndex)) + }) + + const restoreWorkflowTabsState = () => { + const isRestorable = storedWorkflows?.length > 0 && storedActiveIndex >= 0 + if (isRestorable) { + workflowStore.openWorkflowsInBackground({ + left: storedWorkflows.slice(0, storedActiveIndex), + right: storedWorkflows.slice(storedActiveIndex) + }) + } + } + + return { + restorePreviousWorkflow, + restoreWorkflowTabsState + } +}