fix: spin out workflow tab/load stability regressions (#9345)

## Summary

Spin out workflow tab/load stability fixes from the share-by-url branch
so they can merge independently and reduce regression risk.

## Changes

- **What**: Fixes duplicate tabs on repeated same-workflow loads by
making active-workflow reload idempotent in `afterLoadNewGraph`; fixes
tab flicker on save/rename by removing async detach/attach gaps in
`workflowStore`; hardens duplicate workflow path by loading before clone
and assigning a new workflow `id`.

## Review Focus

Please review the idempotency gate in `afterLoadNewGraph`
(`activeState.id === workflowData.id`) and the save/rename path update
sequencing in `workflowStore` to confirm behavior remains correct for
restoration and re-import flows.

## Screenshots (if applicable)

N/A (workflow logic and tests only)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9345-fix-spin-out-workflow-tab-load-stability-regressions-3186d73d365081fe922bdc61dcf8d8f8)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-03-04 17:35:18 -08:00
committed by GitHub
parent f5e1330228
commit 5327fef29f
3 changed files with 205 additions and 17 deletions

View File

@@ -479,12 +479,15 @@ export const useWorkflowStore = defineStore('workflow', () => {
const wasBookmarked = bookmarkStore.isBookmarked(oldPath)
const draftStore = useWorkflowDraftStore()
const openIndex = detachWorkflow(workflow)
// Perform the actual rename operation first
try {
await workflow.rename(newPath)
} finally {
attachWorkflow(workflow, openIndex)
await workflow.rename(newPath)
// Synchronously swap old path for new path in lookup and open paths
// to avoid a tab flicker caused by an async gap between detach/attach.
delete workflowLookup.value[oldPath]
workflowLookup.value[workflow.path] = workflow
const openIndex = openWorkflowPaths.value.indexOf(oldPath)
if (openIndex !== -1) {
openWorkflowPaths.value.splice(openIndex, 1, workflow.path)
}
draftStore.moveDraft(oldPath, newPath, workflow.key)
@@ -525,13 +528,11 @@ export const useWorkflowStore = defineStore('workflow', () => {
const saveWorkflow = async (workflow: ComfyWorkflow) => {
isBusy.value = true
try {
// Detach the workflow and re-attach to force refresh the tree objects.
await workflow.save()
// Synchronously detach and re-attach to force refresh the tree objects
// without an async gap that would cause the tab to disappear.
const openIndex = detachWorkflow(workflow)
try {
await workflow.save()
} finally {
attachWorkflow(workflow, openIndex)
}
attachWorkflow(workflow, openIndex)
} finally {
isBusy.value = false
}