mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 03:01:54 +00:00
[feat] Allow opening workflows with same name as new tabs (#7104)
When importing a workflow file that has the same name as an existing open workflow, create a new tab with a unique suffix (2), (3), etc. instead of silently failing or replacing the existing workflow. - Add forceNew parameter to createTemporary() in workflowStore - Always create new temporary workflow when importing via file picker - Remove logic that looked up persisted workflows by name during import https://github.com/user-attachments/assets/9c9aebd3-37c2-464f-9fb4-9ef871ec2673 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7104-feat-Allow-opening-workflows-with-same-name-as-new-tabs-2bd6d73d365081cd9182eaa35bf37c29) by [Unito](https://www.unito.io)
This commit is contained in:
committed by
GitHub
parent
d50a2fabc0
commit
c6988380c2
@@ -310,23 +310,29 @@ export const useWorkflowService = () => {
|
|||||||
value: string | ComfyWorkflow | null,
|
value: string | ComfyWorkflow | null,
|
||||||
workflowData: ComfyWorkflowJSON
|
workflowData: ComfyWorkflowJSON
|
||||||
) => {
|
) => {
|
||||||
// Use workspaceStore here as it is patched in unit tests.
|
|
||||||
const workflowStore = useWorkspaceStore().workflow
|
const workflowStore = useWorkspaceStore().workflow
|
||||||
if (typeof value === 'string') {
|
|
||||||
const workflow = workflowStore.getWorkflowByPath(
|
|
||||||
ComfyWorkflow.basePath + appendJsonExt(value)
|
|
||||||
)
|
|
||||||
if (workflow?.isPersisted) {
|
|
||||||
const loadedWorkflow = await workflowStore.openWorkflow(workflow)
|
|
||||||
loadedWorkflow.changeTracker.restore()
|
|
||||||
loadedWorkflow.changeTracker.reset(workflowData)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === null || typeof value === 'string') {
|
if (value === null || typeof value === 'string') {
|
||||||
const path = value as string | null
|
const path = value as string | null
|
||||||
const tempWorkflow = workflowStore.createTemporary(
|
|
||||||
|
// Check if a persisted workflow with this path exists
|
||||||
|
if (path) {
|
||||||
|
const fullPath = ComfyWorkflow.basePath + appendJsonExt(path)
|
||||||
|
const existingWorkflow = workflowStore.getWorkflowByPath(fullPath)
|
||||||
|
|
||||||
|
// If the workflow exists and is NOT loaded yet (restoration case),
|
||||||
|
// use the existing workflow instead of creating a new one.
|
||||||
|
// If it IS loaded, this is a re-import case - create new with suffix.
|
||||||
|
if (existingWorkflow?.isPersisted && !existingWorkflow.isLoaded) {
|
||||||
|
const loadedWorkflow =
|
||||||
|
await workflowStore.openWorkflow(existingWorkflow)
|
||||||
|
loadedWorkflow.changeTracker.reset(workflowData)
|
||||||
|
loadedWorkflow.changeTracker.restore()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tempWorkflow = workflowStore.createNewTemporary(
|
||||||
path ? appendJsonExt(path) : undefined,
|
path ? appendJsonExt(path) : undefined,
|
||||||
workflowData
|
workflowData
|
||||||
)
|
)
|
||||||
@@ -334,7 +340,6 @@ export const useWorkflowService = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// value is a ComfyWorkflow.
|
|
||||||
const loadedWorkflow = await workflowStore.openWorkflow(value)
|
const loadedWorkflow = await workflowStore.openWorkflow(value)
|
||||||
loadedWorkflow.changeTracker.reset(workflowData)
|
loadedWorkflow.changeTracker.reset(workflowData)
|
||||||
loadedWorkflow.changeTracker.restore()
|
loadedWorkflow.changeTracker.restore()
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ interface WorkflowStore {
|
|||||||
path?: string,
|
path?: string,
|
||||||
workflowData?: ComfyWorkflowJSON
|
workflowData?: ComfyWorkflowJSON
|
||||||
) => ComfyWorkflow
|
) => ComfyWorkflow
|
||||||
|
createNewTemporary: (
|
||||||
|
path?: string,
|
||||||
|
workflowData?: ComfyWorkflowJSON
|
||||||
|
) => ComfyWorkflow
|
||||||
renameWorkflow: (workflow: ComfyWorkflow, newPath: string) => Promise<void>
|
renameWorkflow: (workflow: ComfyWorkflow, newPath: string) => Promise<void>
|
||||||
deleteWorkflow: (workflow: ComfyWorkflow) => Promise<void>
|
deleteWorkflow: (workflow: ComfyWorkflow) => Promise<void>
|
||||||
saveWorkflow: (workflow: ComfyWorkflow) => Promise<void>
|
saveWorkflow: (workflow: ComfyWorkflow) => Promise<void>
|
||||||
@@ -365,25 +369,15 @@ export const useWorkflowStore = defineStore('workflow', () => {
|
|||||||
return workflow
|
return workflow
|
||||||
}
|
}
|
||||||
|
|
||||||
const createTemporary = (path?: string, workflowData?: ComfyWorkflowJSON) => {
|
/**
|
||||||
const fullPath = getUnconflictedPath(
|
* Helper to create a new temporary workflow
|
||||||
ComfyWorkflow.basePath + (path ?? 'Unsaved Workflow.json')
|
*/
|
||||||
)
|
const createNewWorkflow = (
|
||||||
const existingWorkflow = workflows.value.find((w) => w.fullFilename == path)
|
path: string,
|
||||||
if (
|
workflowData?: ComfyWorkflowJSON
|
||||||
path &&
|
): ComfyWorkflow => {
|
||||||
workflowData &&
|
|
||||||
existingWorkflow?.changeTracker &&
|
|
||||||
!existingWorkflow.directory.startsWith(
|
|
||||||
ComfyWorkflow.basePath.slice(0, -1)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
existingWorkflow.changeTracker.reset(workflowData)
|
|
||||||
return existingWorkflow
|
|
||||||
}
|
|
||||||
|
|
||||||
const workflow = new ComfyWorkflow({
|
const workflow = new ComfyWorkflow({
|
||||||
path: fullPath,
|
path,
|
||||||
modified: Date.now(),
|
modified: Date.now(),
|
||||||
size: -1
|
size: -1
|
||||||
})
|
})
|
||||||
@@ -396,6 +390,47 @@ export const useWorkflowStore = defineStore('workflow', () => {
|
|||||||
return workflow
|
return workflow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a temporary workflow, attempting to reuse an existing workflow if conditions match
|
||||||
|
*/
|
||||||
|
const createTemporary = (path?: string, workflowData?: ComfyWorkflowJSON) => {
|
||||||
|
const fullPath = getUnconflictedPath(
|
||||||
|
ComfyWorkflow.basePath + (path ?? 'Unsaved Workflow.json')
|
||||||
|
)
|
||||||
|
|
||||||
|
// Try to reuse an existing loaded workflow with the same filename
|
||||||
|
// that is not stored in the workflows directory
|
||||||
|
if (path && workflowData) {
|
||||||
|
const existingWorkflow = workflows.value.find(
|
||||||
|
(w) => w.fullFilename === path
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
existingWorkflow?.changeTracker &&
|
||||||
|
!existingWorkflow.directory.startsWith(
|
||||||
|
ComfyWorkflow.basePath.slice(0, -1)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
existingWorkflow.changeTracker.reset(workflowData)
|
||||||
|
return existingWorkflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createNewWorkflow(fullPath, workflowData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new temporary workflow without attempting to reuse existing workflows
|
||||||
|
*/
|
||||||
|
const createNewTemporary = (
|
||||||
|
path?: string,
|
||||||
|
workflowData?: ComfyWorkflowJSON
|
||||||
|
): ComfyWorkflow => {
|
||||||
|
const fullPath = getUnconflictedPath(
|
||||||
|
ComfyWorkflow.basePath + (path ?? 'Unsaved Workflow.json')
|
||||||
|
)
|
||||||
|
return createNewWorkflow(fullPath, workflowData)
|
||||||
|
}
|
||||||
|
|
||||||
const closeWorkflow = async (workflow: ComfyWorkflow) => {
|
const closeWorkflow = async (workflow: ComfyWorkflow) => {
|
||||||
openWorkflowPaths.value = openWorkflowPaths.value.filter(
|
openWorkflowPaths.value = openWorkflowPaths.value.filter(
|
||||||
(path) => path !== workflow.path
|
(path) => path !== workflow.path
|
||||||
@@ -777,6 +812,7 @@ export const useWorkflowStore = defineStore('workflow', () => {
|
|||||||
isBusy,
|
isBusy,
|
||||||
closeWorkflow,
|
closeWorkflow,
|
||||||
createTemporary,
|
createTemporary,
|
||||||
|
createNewTemporary,
|
||||||
renameWorkflow,
|
renameWorkflow,
|
||||||
deleteWorkflow,
|
deleteWorkflow,
|
||||||
saveAs,
|
saveAs,
|
||||||
|
|||||||
Reference in New Issue
Block a user