mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-07 14:09:59 +00:00
refactor: parallelize bootstrap and simplify lifecycle with VueUse (#8307)
## Summary Refactors bootstrap and lifecycle management to parallelize initialization, use Vue best practices, and fix a logout state bug. ## Changes ### Bootstrap Store (`bootstrapStore.ts`) - Extract early bootstrap logic into a dedicated store using `useAsyncState` - Parallelize settings, i18n, and workflow sync loading (previously sequential) - Handle multi-user login scenarios by deferring settings/workflows until authenticated ### GraphCanvas Refactoring - Move non-DOM composables (`useGlobalLitegraph`, `useCopy`, `usePaste`, etc.) to script setup level for earlier initialization - Move `watch` and `whenever` declarations outside `onMounted` (Vue best practice) - Use `until()` from VueUse to await bootstrap store readiness instead of direct async calls ### GraphView Simplification - Replace manual `addEventListener`/`removeEventListener` with `useEventListener` - Replace `setInterval` with `useIntervalFn` for automatic cleanup - Move core command registration to script setup level ### Bug Fix Using `router.push()` for logout caused `isSettingsReady` to persist as `true`, making new users inherit the previous user's cached settings. Reverted to `window.location.reload()` with TODOs for future store reset implementation. ## Testing - Verified login/logout cycle clears settings correctly - Verified bootstrap sequence completes without errors --------- Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import _ from 'es-toolkit/compat'
|
||||
import { until, useAsyncState } from '@vueuse/core'
|
||||
import { defineStore } from 'pinia'
|
||||
import { computed, markRaw, ref, shallowRef, watch } from 'vue'
|
||||
import type { Raw } from 'vue'
|
||||
@@ -531,48 +532,72 @@ export const useWorkflowStore = defineStore('workflow', () => {
|
||||
workflow.isPersisted && !workflow.path.startsWith('subgraphs/')
|
||||
)
|
||||
)
|
||||
const syncWorkflows = async (dir: string = '') => {
|
||||
await syncEntities(
|
||||
dir ? 'workflows/' + dir : 'workflows',
|
||||
workflowLookup.value,
|
||||
(file) =>
|
||||
new ComfyWorkflow({
|
||||
path: file.path,
|
||||
modified: file.modified,
|
||||
size: file.size
|
||||
}),
|
||||
(existingWorkflow, file) => {
|
||||
const isActiveWorkflow =
|
||||
activeWorkflow.value?.path === existingWorkflow.path
|
||||
|
||||
const nextLastModified = Math.max(
|
||||
existingWorkflow.lastModified,
|
||||
file.modified
|
||||
)
|
||||
const {
|
||||
isReady: isSyncReady,
|
||||
isLoading: isSyncLoading,
|
||||
execute: executeSyncWorkflows
|
||||
} = useAsyncState(
|
||||
async (dir: string = '') => {
|
||||
await syncEntities(
|
||||
dir ? 'workflows/' + dir : 'workflows',
|
||||
workflowLookup.value,
|
||||
(file) =>
|
||||
new ComfyWorkflow({
|
||||
path: file.path,
|
||||
modified: file.modified,
|
||||
size: file.size
|
||||
}),
|
||||
(existingWorkflow, file) => {
|
||||
const isActiveWorkflow =
|
||||
activeWorkflow.value?.path === existingWorkflow.path
|
||||
|
||||
const isMetadataUnchanged =
|
||||
nextLastModified === existingWorkflow.lastModified &&
|
||||
file.size === existingWorkflow.size
|
||||
const nextLastModified = Math.max(
|
||||
existingWorkflow.lastModified,
|
||||
file.modified
|
||||
)
|
||||
|
||||
if (!isMetadataUnchanged) {
|
||||
existingWorkflow.lastModified = nextLastModified
|
||||
existingWorkflow.size = file.size
|
||||
}
|
||||
const isMetadataUnchanged =
|
||||
nextLastModified === existingWorkflow.lastModified &&
|
||||
file.size === existingWorkflow.size
|
||||
|
||||
// Never unload the active workflow - it may contain unsaved in-memory edits.
|
||||
if (isActiveWorkflow) {
|
||||
return
|
||||
}
|
||||
if (!isMetadataUnchanged) {
|
||||
existingWorkflow.lastModified = nextLastModified
|
||||
existingWorkflow.size = file.size
|
||||
}
|
||||
|
||||
// If nothing changed, keep any loaded content cached.
|
||||
if (isMetadataUnchanged) {
|
||||
return
|
||||
}
|
||||
// Never unload the active workflow - it may contain unsaved in-memory edits.
|
||||
if (isActiveWorkflow) {
|
||||
return
|
||||
}
|
||||
|
||||
existingWorkflow.unload()
|
||||
},
|
||||
/* exclude */ (workflow) => workflow.isTemporary
|
||||
)
|
||||
// If nothing changed, keep any loaded content cached.
|
||||
if (isMetadataUnchanged) {
|
||||
return
|
||||
}
|
||||
|
||||
existingWorkflow.unload()
|
||||
},
|
||||
/* exclude */ (workflow) => workflow.isTemporary
|
||||
)
|
||||
},
|
||||
undefined,
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
async function syncWorkflows(dir: string = '') {
|
||||
return executeSyncWorkflows(0, dir)
|
||||
}
|
||||
|
||||
async function loadWorkflows(): Promise<void> {
|
||||
if (isSyncReady.value) return
|
||||
|
||||
if (isSyncLoading.value) {
|
||||
await until(isSyncLoading).toBe(false)
|
||||
return
|
||||
}
|
||||
|
||||
await syncWorkflows()
|
||||
}
|
||||
|
||||
const bookmarkStore = useWorkflowBookmarkStore()
|
||||
@@ -884,6 +909,7 @@ export const useWorkflowStore = defineStore('workflow', () => {
|
||||
modifiedWorkflows,
|
||||
getWorkflowByPath,
|
||||
syncWorkflows,
|
||||
loadWorkflows,
|
||||
|
||||
isSubgraphActive,
|
||||
activeSubgraph,
|
||||
|
||||
Reference in New Issue
Block a user