mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-23 16:24:06 +00:00
[Refactor] Extract workflow/workflow tabs restore into a composable (#2350)
This commit is contained in:
@@ -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(
|
||||
|
||||
130
src/hooks/workflowPersistenceHooks.ts
Normal file
130
src/hooks/workflowPersistenceHooks.ts
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user