mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 11:11:53 +00:00
[Refactor] Convert workflowService to composable (#2057)
This commit is contained in:
@@ -64,7 +64,7 @@ import { setStorageValue } from '@/scripts/utils'
|
|||||||
import { ChangeTracker } from '@/scripts/changeTracker'
|
import { ChangeTracker } from '@/scripts/changeTracker'
|
||||||
import { api } from '@/scripts/api'
|
import { api } from '@/scripts/api'
|
||||||
import { useCommandStore } from '@/stores/commandStore'
|
import { useCommandStore } from '@/stores/commandStore'
|
||||||
import { workflowService } from '@/services/workflowService'
|
import { useWorkflowService } from '@/services/workflowService'
|
||||||
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
|
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
|
||||||
import { useColorPaletteService } from '@/services/colorPaletteService'
|
import { useColorPaletteService } from '@/services/colorPaletteService'
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ onMounted(async () => {
|
|||||||
() => settingStore.get('Comfy.Locale'),
|
() => settingStore.get('Comfy.Locale'),
|
||||||
async () => {
|
async () => {
|
||||||
await useCommandStore().execute('Comfy.RefreshNodeDefinitions')
|
await useCommandStore().execute('Comfy.RefreshNodeDefinitions')
|
||||||
workflowService.reloadCurrentWorkflow()
|
useWorkflowService().reloadCurrentWorkflow()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -159,12 +159,10 @@ import { ComfyWorkflow } from '@/stores/workflowStore'
|
|||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useTreeExpansion } from '@/hooks/treeHooks'
|
import { useTreeExpansion } from '@/hooks/treeHooks'
|
||||||
import { useSettingStore } from '@/stores/settingStore'
|
import { useSettingStore } from '@/stores/settingStore'
|
||||||
import { workflowService } from '@/services/workflowService'
|
import { useWorkflowService } from '@/services/workflowService'
|
||||||
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
||||||
import { appendJsonExt } from '@/utils/formatUtil'
|
import { appendJsonExt } from '@/utils/formatUtil'
|
||||||
import { buildTree, sortedTree } from '@/utils/treeUtil'
|
import { buildTree, sortedTree } from '@/utils/treeUtil'
|
||||||
import { useConfirm } from 'primevue/useconfirm'
|
|
||||||
import { useToast } from 'primevue/usetoast'
|
|
||||||
import ConfirmDialog from 'primevue/confirmdialog'
|
import ConfirmDialog from 'primevue/confirmdialog'
|
||||||
|
|
||||||
const settingStore = useSettingStore()
|
const settingStore = useSettingStore()
|
||||||
@@ -195,6 +193,7 @@ const handleSearch = (query: string) => {
|
|||||||
|
|
||||||
const commandStore = useCommandStore()
|
const commandStore = useCommandStore()
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
|
const workflowService = useWorkflowService()
|
||||||
const workspaceStore = useWorkspaceStore()
|
const workspaceStore = useWorkspaceStore()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const expandedKeys = ref<Record<string, boolean>>({})
|
const expandedKeys = ref<Record<string, boolean>>({})
|
||||||
@@ -234,9 +233,6 @@ const openWorkflowsTree = computed(() =>
|
|||||||
buildTree(workflowStore.openWorkflows, (workflow) => [workflow.key])
|
buildTree(workflowStore.openWorkflows, (workflow) => [workflow.key])
|
||||||
)
|
)
|
||||||
|
|
||||||
const confirm = useConfirm()
|
|
||||||
const toast = useToast()
|
|
||||||
|
|
||||||
const renderTreeNode = (
|
const renderTreeNode = (
|
||||||
node: TreeNode,
|
node: TreeNode,
|
||||||
type: WorkflowTreeType
|
type: WorkflowTreeType
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import { ComfyWorkflow } from '@/stores/workflowStore'
|
|||||||
import { useWorkflowStore } from '@/stores/workflowStore'
|
import { useWorkflowStore } from '@/stores/workflowStore'
|
||||||
import Button from 'primevue/button'
|
import Button from 'primevue/button'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { workflowService } from '@/services/workflowService'
|
import { useWorkflowService } from '@/services/workflowService'
|
||||||
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
||||||
import { usePragmaticDraggable, usePragmaticDroppable } from '@/hooks/dndHooks'
|
import { usePragmaticDraggable, usePragmaticDroppable } from '@/hooks/dndHooks'
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ const workflowTabRef = ref<HTMLElement | null>(null)
|
|||||||
const closeWorkflows = async (options: WorkflowOption[]) => {
|
const closeWorkflows = async (options: WorkflowOption[]) => {
|
||||||
for (const opt of options) {
|
for (const opt of options) {
|
||||||
if (
|
if (
|
||||||
!(await workflowService.closeWorkflow(opt.workflow, {
|
!(await useWorkflowService().closeWorkflow(opt.workflow, {
|
||||||
warnIfUnsaved: !workspaceStore.shiftDown
|
warnIfUnsaved: !workspaceStore.shiftDown
|
||||||
}))
|
}))
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import { useCommandStore } from '@/stores/commandStore'
|
|||||||
import SelectButton from 'primevue/selectbutton'
|
import SelectButton from 'primevue/selectbutton'
|
||||||
import Button from 'primevue/button'
|
import Button from 'primevue/button'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { workflowService } from '@/services/workflowService'
|
import { useWorkflowService } from '@/services/workflowService'
|
||||||
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
||||||
import ContextMenu from 'primevue/contextmenu'
|
import ContextMenu from 'primevue/contextmenu'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
@@ -51,6 +51,7 @@ const props = defineProps<{
|
|||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const workspaceStore = useWorkspaceStore()
|
const workspaceStore = useWorkspaceStore()
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
|
const workflowService = useWorkflowService()
|
||||||
const rightClickedTab = ref<WorkflowOption>(null)
|
const rightClickedTab = ref<WorkflowOption>(null)
|
||||||
const menu = ref()
|
const menu = ref()
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
showSettingsDialog,
|
showSettingsDialog,
|
||||||
showTemplateWorkflowsDialog
|
showTemplateWorkflowsDialog
|
||||||
} from '@/services/dialogService'
|
} from '@/services/dialogService'
|
||||||
import { workflowService } from '@/services/workflowService'
|
import { useWorkflowService } from '@/services/workflowService'
|
||||||
import type { ComfyCommand } from '@/stores/commandStore'
|
import type { ComfyCommand } from '@/stores/commandStore'
|
||||||
import { useTitleEditorStore } from '@/stores/graphStore'
|
import { useTitleEditorStore } from '@/stores/graphStore'
|
||||||
import { useQueueSettingsStore, useQueueStore } from '@/stores/queueStore'
|
import { useQueueSettingsStore, useQueueStore } from '@/stores/queueStore'
|
||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
import { useSearchBoxStore } from '@/stores/workspace/searchBoxStore'
|
import { useSearchBoxStore } from '@/stores/workspace/searchBoxStore'
|
||||||
|
|
||||||
export function useCoreCommands(): ComfyCommand[] {
|
export function useCoreCommands(): ComfyCommand[] {
|
||||||
|
const workflowService = useWorkflowService()
|
||||||
const getTracker = () => useWorkflowStore()?.activeWorkflow?.changeTracker
|
const getTracker = () => useWorkflowStore()?.activeWorkflow?.changeTracker
|
||||||
|
|
||||||
const getSelectedNodes = (): LGraphNode[] => {
|
const getSelectedNodes = (): LGraphNode[] => {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ import { KeyComboImpl, useKeybindingStore } from '@/stores/keybindingStore'
|
|||||||
import { useCommandStore } from '@/stores/commandStore'
|
import { useCommandStore } from '@/stores/commandStore'
|
||||||
import { shallowReactive } from 'vue'
|
import { shallowReactive } from 'vue'
|
||||||
import { type IBaseWidget } from '@comfyorg/litegraph/dist/types/widgets'
|
import { type IBaseWidget } from '@comfyorg/litegraph/dist/types/widgets'
|
||||||
import { workflowService } from '@/services/workflowService'
|
import { useWorkflowService } from '@/services/workflowService'
|
||||||
import { useWidgetStore } from '@/stores/widgetStore'
|
import { useWidgetStore } from '@/stores/widgetStore'
|
||||||
import { deserialiseAndCreate } from '@/extensions/core/vintageClipboard'
|
import { deserialiseAndCreate } from '@/extensions/core/vintageClipboard'
|
||||||
import { st } from '@/i18n'
|
import { st } from '@/i18n'
|
||||||
@@ -2041,7 +2041,7 @@ export class ComfyApp {
|
|||||||
graphData = validatedGraphData ?? graphData
|
graphData = validatedGraphData ?? graphData
|
||||||
}
|
}
|
||||||
|
|
||||||
workflowService.beforeLoadNewGraph()
|
useWorkflowService().beforeLoadNewGraph()
|
||||||
|
|
||||||
const missingNodeTypes: MissingNodeType[] = []
|
const missingNodeTypes: MissingNodeType[] = []
|
||||||
const missingModels = []
|
const missingModels = []
|
||||||
@@ -2207,8 +2207,11 @@ export class ComfyApp {
|
|||||||
'afterConfigureGraph',
|
'afterConfigureGraph',
|
||||||
missingNodeTypes
|
missingNodeTypes
|
||||||
)
|
)
|
||||||
// @ts-expect-error zod types issue. Will be fixed after we enable ts-strict
|
await useWorkflowService().afterLoadNewGraph(
|
||||||
await workflowService.afterLoadNewGraph(workflow, this.graph.serialize())
|
workflow,
|
||||||
|
// @ts-expect-error zod types issue. Will be fixed after we enable ts-strict
|
||||||
|
this.graph.serialize()
|
||||||
|
)
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
this.graph.setDirtyCanvas(true, true)
|
this.graph.setDirtyCanvas(true, true)
|
||||||
})
|
})
|
||||||
@@ -2522,10 +2525,10 @@ export class ComfyApp {
|
|||||||
} else if (pngInfo?.parameters) {
|
} else if (pngInfo?.parameters) {
|
||||||
// Note: Not putting this in `importA1111` as it is mostly not used
|
// Note: Not putting this in `importA1111` as it is mostly not used
|
||||||
// by external callers, and `importA1111` has no access to `app`.
|
// by external callers, and `importA1111` has no access to `app`.
|
||||||
workflowService.beforeLoadNewGraph()
|
useWorkflowService().beforeLoadNewGraph()
|
||||||
importA1111(this.graph, pngInfo.parameters)
|
importA1111(this.graph, pngInfo.parameters)
|
||||||
// @ts-expect-error zod type issue on ComfyWorkflowJSON. Should be resolved after enabling ts-strict globally.
|
// @ts-expect-error zod type issue on ComfyWorkflowJSON. Should be resolved after enabling ts-strict globally.
|
||||||
workflowService.afterLoadNewGraph(fileName, this.serializeGraph())
|
useWorkflowService().afterLoadNewGraph(fileName, this.serializeGraph())
|
||||||
} else {
|
} else {
|
||||||
this.showErrorOnFileLoad(file)
|
this.showErrorOnFileLoad(file)
|
||||||
}
|
}
|
||||||
@@ -2609,7 +2612,7 @@ export class ComfyApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadApiJson(apiData, fileName: string) {
|
loadApiJson(apiData, fileName: string) {
|
||||||
workflowService.beforeLoadNewGraph()
|
useWorkflowService().beforeLoadNewGraph()
|
||||||
|
|
||||||
const missingNodeTypes = Object.values(apiData).filter(
|
const missingNodeTypes = Object.values(apiData).filter(
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -2701,7 +2704,7 @@ export class ComfyApp {
|
|||||||
app.graph.arrange()
|
app.graph.arrange()
|
||||||
|
|
||||||
// @ts-expect-error zod type issue on ComfyWorkflowJSON. Should be resolved after enabling ts-strict globally.
|
// @ts-expect-error zod type issue on ComfyWorkflowJSON. Should be resolved after enabling ts-strict globally.
|
||||||
workflowService.afterLoadNewGraph(fileName, this.serializeGraph())
|
useWorkflowService().afterLoadNewGraph(fileName, this.serializeGraph())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { LiteGraph } from '@comfyorg/litegraph'
|
|||||||
import { api } from './api'
|
import { api } from './api'
|
||||||
import { getFromPngFile } from './metadata/png'
|
import { getFromPngFile } from './metadata/png'
|
||||||
import { getFromFlacFile } from './metadata/flac'
|
import { getFromFlacFile } from './metadata/flac'
|
||||||
import { workflowService } from '@/services/workflowService'
|
|
||||||
|
|
||||||
// Original functions left in for backwards compatibility
|
// Original functions left in for backwards compatibility
|
||||||
export function getPngMetadata(file: File): Promise<Record<string, string>> {
|
export function getPngMetadata(file: File): Promise<Record<string, string>> {
|
||||||
|
|||||||
@@ -12,34 +12,36 @@ import { appendJsonExt } from '@/utils/formatUtil'
|
|||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
import { useToastStore } from '@/stores/toastStore'
|
import { useToastStore } from '@/stores/toastStore'
|
||||||
|
|
||||||
async function getFilename(defaultName: string): Promise<string | null> {
|
export const useWorkflowService = () => {
|
||||||
if (useSettingStore().get('Comfy.PromptFilename')) {
|
const settingStore = useSettingStore()
|
||||||
let filename = await showPromptDialog({
|
const workflowStore = useWorkflowStore()
|
||||||
title: t('workflowService.exportWorkflow'),
|
const toastStore = useToastStore()
|
||||||
message: t('workflowService.enterFilename') + ':',
|
|
||||||
defaultValue: defaultName
|
|
||||||
})
|
|
||||||
if (!filename) return null
|
|
||||||
if (!filename.toLowerCase().endsWith('.json')) {
|
|
||||||
filename += '.json'
|
|
||||||
}
|
|
||||||
return filename
|
|
||||||
}
|
|
||||||
return defaultName
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(huchenlei): Auto Error Handling for all methods.
|
async function getFilename(defaultName: string): Promise<string | null> {
|
||||||
export const workflowService = {
|
if (settingStore.get('Comfy.PromptFilename')) {
|
||||||
|
let filename = await showPromptDialog({
|
||||||
|
title: t('workflowService.exportWorkflow'),
|
||||||
|
message: t('workflowService.enterFilename') + ':',
|
||||||
|
defaultValue: defaultName
|
||||||
|
})
|
||||||
|
if (!filename) return null
|
||||||
|
if (!filename.toLowerCase().endsWith('.json')) {
|
||||||
|
filename += '.json'
|
||||||
|
}
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
return defaultName
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Export the current workflow as a JSON file
|
* Export the current workflow as a JSON file
|
||||||
* @param filename The filename to save the workflow as
|
* @param filename The filename to save the workflow as
|
||||||
* @param promptProperty The property of the prompt to export
|
* @param promptProperty The property of the prompt to export
|
||||||
*/
|
*/
|
||||||
async exportWorkflow(
|
const exportWorkflow = async (
|
||||||
filename: string,
|
filename: string,
|
||||||
promptProperty: 'workflow' | 'output'
|
promptProperty: 'workflow' | 'output'
|
||||||
): Promise<void> {
|
): Promise<void> => {
|
||||||
const workflow = useWorkflowStore().activeWorkflow
|
const workflow = workflowStore.activeWorkflow
|
||||||
if (workflow?.path) {
|
if (workflow?.path) {
|
||||||
filename = workflow.filename
|
filename = workflow.filename
|
||||||
}
|
}
|
||||||
@@ -49,12 +51,12 @@ export const workflowService = {
|
|||||||
const file = await getFilename(filename)
|
const file = await getFilename(filename)
|
||||||
if (!file) return
|
if (!file) return
|
||||||
downloadBlob(file, blob)
|
downloadBlob(file, blob)
|
||||||
},
|
}
|
||||||
/**
|
/**
|
||||||
* Save a workflow as a new file
|
* Save a workflow as a new file
|
||||||
* @param workflow The workflow to save
|
* @param workflow The workflow to save
|
||||||
*/
|
*/
|
||||||
async saveWorkflowAs(workflow: ComfyWorkflow) {
|
const saveWorkflowAs = async (workflow: ComfyWorkflow) => {
|
||||||
const newFilename = await showPromptDialog({
|
const newFilename = await showPromptDialog({
|
||||||
title: t('workflowService.saveWorkflow'),
|
title: t('workflowService.saveWorkflow'),
|
||||||
message: t('workflowService.enterFilename') + ':',
|
message: t('workflowService.enterFilename') + ':',
|
||||||
@@ -64,7 +66,6 @@ export const workflowService = {
|
|||||||
|
|
||||||
const newPath = workflow.directory + '/' + appendJsonExt(newFilename)
|
const newPath = workflow.directory + '/' + appendJsonExt(newFilename)
|
||||||
const newKey = newPath.substring(ComfyWorkflow.basePath.length)
|
const newKey = newPath.substring(ComfyWorkflow.basePath.length)
|
||||||
const workflowStore = useWorkflowStore()
|
|
||||||
const existingWorkflow = workflowStore.getWorkflowByPath(newPath)
|
const existingWorkflow = workflowStore.getWorkflowByPath(newPath)
|
||||||
|
|
||||||
if (existingWorkflow && !existingWorkflow.isTemporary) {
|
if (existingWorkflow && !existingWorkflow.isTemporary) {
|
||||||
@@ -78,73 +79,73 @@ export const workflowService = {
|
|||||||
if (res !== true) return
|
if (res !== true) return
|
||||||
|
|
||||||
if (existingWorkflow.path === workflow.path) {
|
if (existingWorkflow.path === workflow.path) {
|
||||||
await this.saveWorkflow(workflow)
|
await saveWorkflow(workflow)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const deleted = await this.deleteWorkflow(existingWorkflow, true)
|
const deleted = await deleteWorkflow(existingWorkflow, true)
|
||||||
if (!deleted) return
|
if (!deleted) return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workflow.isTemporary) {
|
if (workflow.isTemporary) {
|
||||||
await this.renameWorkflow(workflow, newPath)
|
await renameWorkflow(workflow, newPath)
|
||||||
await workflowStore.saveWorkflow(workflow)
|
await workflowStore.saveWorkflow(workflow)
|
||||||
} else {
|
} else {
|
||||||
const tempWorkflow = workflowStore.createTemporary(
|
const tempWorkflow = workflowStore.createTemporary(
|
||||||
newKey,
|
newKey,
|
||||||
workflow.activeState as ComfyWorkflowJSON
|
workflow.activeState as ComfyWorkflowJSON
|
||||||
)
|
)
|
||||||
await this.openWorkflow(tempWorkflow)
|
await openWorkflow(tempWorkflow)
|
||||||
await workflowStore.saveWorkflow(tempWorkflow)
|
await workflowStore.saveWorkflow(tempWorkflow)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a workflow
|
* Save a workflow
|
||||||
* @param workflow The workflow to save
|
* @param workflow The workflow to save
|
||||||
*/
|
*/
|
||||||
async saveWorkflow(workflow: ComfyWorkflow) {
|
const saveWorkflow = async (workflow: ComfyWorkflow) => {
|
||||||
if (workflow.isTemporary) {
|
if (workflow.isTemporary) {
|
||||||
await this.saveWorkflowAs(workflow)
|
await saveWorkflowAs(workflow)
|
||||||
} else {
|
} else {
|
||||||
await useWorkflowStore().saveWorkflow(workflow)
|
await workflowStore.saveWorkflow(workflow)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the default workflow
|
* Load the default workflow
|
||||||
*/
|
*/
|
||||||
async loadDefaultWorkflow() {
|
const loadDefaultWorkflow = async () => {
|
||||||
await app.loadGraphData(defaultGraph)
|
await app.loadGraphData(defaultGraph)
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a blank workflow
|
* Load a blank workflow
|
||||||
*/
|
*/
|
||||||
async loadBlankWorkflow() {
|
const loadBlankWorkflow = async () => {
|
||||||
await app.loadGraphData(blankGraph)
|
await app.loadGraphData(blankGraph)
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload the current workflow
|
* Reload the current workflow
|
||||||
* This is used to refresh the node definitions update, e.g. when the locale changes.
|
* This is used to refresh the node definitions update, e.g. when the locale changes.
|
||||||
*/
|
*/
|
||||||
async reloadCurrentWorkflow() {
|
const reloadCurrentWorkflow = async () => {
|
||||||
const workflow = useWorkflowStore().activeWorkflow
|
const workflow = workflowStore.activeWorkflow
|
||||||
if (workflow) {
|
if (workflow) {
|
||||||
await this.openWorkflow(workflow, { force: true })
|
await openWorkflow(workflow, { force: true })
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a workflow in the current workspace
|
* Open a workflow in the current workspace
|
||||||
* @param workflow The workflow to open
|
* @param workflow The workflow to open
|
||||||
* @param options The options for opening the workflow
|
* @param options The options for opening the workflow
|
||||||
*/
|
*/
|
||||||
async openWorkflow(
|
const openWorkflow = async (
|
||||||
workflow: ComfyWorkflow,
|
workflow: ComfyWorkflow,
|
||||||
options: { force: boolean } = { force: false }
|
options: { force: boolean } = { force: false }
|
||||||
) {
|
) => {
|
||||||
if (useWorkflowStore().isActive(workflow) && !options.force) return
|
if (workflowStore.isActive(workflow) && !options.force) return
|
||||||
|
|
||||||
const loadFromRemote = !workflow.isLoaded
|
const loadFromRemote = !workflow.isLoaded
|
||||||
if (loadFromRemote) {
|
if (loadFromRemote) {
|
||||||
@@ -161,17 +162,17 @@ export const workflowService = {
|
|||||||
showMissingNodesDialog: loadFromRemote
|
showMissingNodesDialog: loadFromRemote
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close a workflow with confirmation if there are unsaved changes
|
* Close a workflow with confirmation if there are unsaved changes
|
||||||
* @param workflow The workflow to close
|
* @param workflow The workflow to close
|
||||||
* @returns true if the workflow was closed, false if the user cancelled
|
* @returns true if the workflow was closed, false if the user cancelled
|
||||||
*/
|
*/
|
||||||
async closeWorkflow(
|
const closeWorkflow = async (
|
||||||
workflow: ComfyWorkflow,
|
workflow: ComfyWorkflow,
|
||||||
options: { warnIfUnsaved: boolean } = { warnIfUnsaved: true }
|
options: { warnIfUnsaved: boolean } = { warnIfUnsaved: true }
|
||||||
): Promise<boolean> {
|
): Promise<boolean> => {
|
||||||
if (!workflow.isLoaded) {
|
if (!workflow.isLoaded) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -187,38 +188,37 @@ export const workflowService = {
|
|||||||
if (confirmed === null) return false
|
if (confirmed === null) return false
|
||||||
|
|
||||||
if (confirmed === true) {
|
if (confirmed === true) {
|
||||||
await this.saveWorkflow(workflow)
|
await saveWorkflow(workflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowStore = useWorkflowStore()
|
|
||||||
// If this is the last workflow, create a new default temporary workflow
|
// If this is the last workflow, create a new default temporary workflow
|
||||||
if (workflowStore.openWorkflows.length === 1) {
|
if (workflowStore.openWorkflows.length === 1) {
|
||||||
await this.loadDefaultWorkflow()
|
await loadDefaultWorkflow()
|
||||||
}
|
}
|
||||||
// If this is the active workflow, load the next workflow
|
// If this is the active workflow, load the next workflow
|
||||||
if (workflowStore.isActive(workflow)) {
|
if (workflowStore.isActive(workflow)) {
|
||||||
await this.loadNextOpenedWorkflow()
|
await loadNextOpenedWorkflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
await workflowStore.closeWorkflow(workflow)
|
await workflowStore.closeWorkflow(workflow)
|
||||||
return true
|
return true
|
||||||
},
|
}
|
||||||
|
|
||||||
async renameWorkflow(workflow: ComfyWorkflow, newPath: string) {
|
const renameWorkflow = async (workflow: ComfyWorkflow, newPath: string) => {
|
||||||
await useWorkflowStore().renameWorkflow(workflow, newPath)
|
await workflowStore.renameWorkflow(workflow, newPath)
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a workflow
|
* Delete a workflow
|
||||||
* @param workflow The workflow to delete
|
* @param workflow The workflow to delete
|
||||||
* @returns `true` if the workflow was deleted, `false` if the user cancelled
|
* @returns `true` if the workflow was deleted, `false` if the user cancelled
|
||||||
*/
|
*/
|
||||||
async deleteWorkflow(
|
const deleteWorkflow = async (
|
||||||
workflow: ComfyWorkflow,
|
workflow: ComfyWorkflow,
|
||||||
silent = false
|
silent = false
|
||||||
): Promise<boolean> {
|
): Promise<boolean> => {
|
||||||
const bypassConfirm = !useSettingStore().get('Comfy.Workflow.ConfirmDelete')
|
const bypassConfirm = !settingStore.get('Comfy.Workflow.ConfirmDelete')
|
||||||
let confirmed: boolean | null = bypassConfirm || silent
|
let confirmed: boolean | null = bypassConfirm || silent
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -231,23 +231,22 @@ export const workflowService = {
|
|||||||
if (!confirmed) return false
|
if (!confirmed) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowStore = useWorkflowStore()
|
|
||||||
if (workflowStore.isOpen(workflow)) {
|
if (workflowStore.isOpen(workflow)) {
|
||||||
const closed = await this.closeWorkflow(workflow, {
|
const closed = await closeWorkflow(workflow, {
|
||||||
warnIfUnsaved: !confirmed
|
warnIfUnsaved: !confirmed
|
||||||
})
|
})
|
||||||
if (!closed) return false
|
if (!closed) return false
|
||||||
}
|
}
|
||||||
await workflowStore.deleteWorkflow(workflow)
|
await workflowStore.deleteWorkflow(workflow)
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
useToastStore().add({
|
toastStore.add({
|
||||||
severity: 'info',
|
severity: 'info',
|
||||||
summary: t('sideToolbar.workflowTab.deleted'),
|
summary: t('sideToolbar.workflowTab.deleted'),
|
||||||
life: 1000
|
life: 1000
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called before loading a new graph.
|
* This method is called before loading a new graph.
|
||||||
@@ -259,30 +258,30 @@ export const workflowService = {
|
|||||||
* This function is used to save the current workflow states before loading
|
* This function is used to save the current workflow states before loading
|
||||||
* a new graph.
|
* a new graph.
|
||||||
*/
|
*/
|
||||||
beforeLoadNewGraph() {
|
const beforeLoadNewGraph = () => {
|
||||||
// Use workspaceStore here as it is patched in jest tests.
|
// Use workspaceStore here as it is patched in jest tests.
|
||||||
const workflowStore = useWorkspaceStore().workflow
|
const workflowStore = useWorkspaceStore().workflow
|
||||||
const activeWorkflow = workflowStore.activeWorkflow
|
const activeWorkflow = workflowStore.activeWorkflow
|
||||||
if (activeWorkflow) {
|
if (activeWorkflow) {
|
||||||
activeWorkflow.changeTracker.store()
|
activeWorkflow.changeTracker.store()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the active workflow after the new graph is loaded.
|
* Set the active workflow after the new graph is loaded.
|
||||||
*
|
*
|
||||||
* The call relationship is
|
* The call relationship is
|
||||||
* workflowService.openWorkflow -> app.loadGraphData -> workflowService.afterLoadNewGraph
|
* useWorkflowService().openWorkflow -> app.loadGraphData -> useWorkflowService().afterLoadNewGraph
|
||||||
* app.loadApiJson -> workflowService.afterLoadNewGraph
|
* app.loadApiJson -> useWorkflowService().afterLoadNewGraph
|
||||||
* app.importA1111 -> workflowService.afterLoadNewGraph
|
* app.importA1111 -> useWorkflowService().afterLoadNewGraph
|
||||||
*
|
*
|
||||||
* @param value The value to set as the active workflow.
|
* @param value The value to set as the active workflow.
|
||||||
* @param workflowData The initial workflow data loaded to the graph editor.
|
* @param workflowData The initial workflow data loaded to the graph editor.
|
||||||
*/
|
*/
|
||||||
async afterLoadNewGraph(
|
const afterLoadNewGraph = async (
|
||||||
value: string | ComfyWorkflow | null,
|
value: string | ComfyWorkflow | null,
|
||||||
workflowData: ComfyWorkflowJSON
|
workflowData: ComfyWorkflowJSON
|
||||||
) {
|
) => {
|
||||||
// Use workspaceStore here as it is patched in jest tests.
|
// Use workspaceStore here as it is patched in jest tests.
|
||||||
const workflowStore = useWorkspaceStore().workflow
|
const workflowStore = useWorkspaceStore().workflow
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
@@ -311,12 +310,12 @@ export const workflowService = {
|
|||||||
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()
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert the given workflow into the current graph editor.
|
* Insert the given workflow into the current graph editor.
|
||||||
*/
|
*/
|
||||||
async insertWorkflow(workflow: ComfyWorkflow) {
|
const insertWorkflow = async (workflow: ComfyWorkflow) => {
|
||||||
const loadedWorkflow = await workflow.load()
|
const loadedWorkflow = await workflow.load()
|
||||||
const data = loadedWorkflow.initialState
|
const data = loadedWorkflow.initialState
|
||||||
const old = localStorage.getItem('litegrapheditor_clipboard')
|
const old = localStorage.getItem('litegrapheditor_clipboard')
|
||||||
@@ -334,27 +333,46 @@ export const workflowService = {
|
|||||||
if (old !== null) {
|
if (old !== null) {
|
||||||
localStorage.setItem('litegrapheditor_clipboard', old)
|
localStorage.setItem('litegrapheditor_clipboard', old)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
async loadNextOpenedWorkflow() {
|
const loadNextOpenedWorkflow = async () => {
|
||||||
const nextWorkflow = useWorkflowStore().openedWorkflowIndexShift(1)
|
const nextWorkflow = workflowStore.openedWorkflowIndexShift(1)
|
||||||
if (nextWorkflow) {
|
if (nextWorkflow) {
|
||||||
await this.openWorkflow(nextWorkflow)
|
await openWorkflow(nextWorkflow)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
async loadPreviousOpenedWorkflow() {
|
const loadPreviousOpenedWorkflow = async () => {
|
||||||
const previousWorkflow = useWorkflowStore().openedWorkflowIndexShift(-1)
|
const previousWorkflow = workflowStore.openedWorkflowIndexShift(-1)
|
||||||
if (previousWorkflow) {
|
if (previousWorkflow) {
|
||||||
await this.openWorkflow(previousWorkflow)
|
await openWorkflow(previousWorkflow)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes an existing workflow and duplicates it with a new name
|
* Takes an existing workflow and duplicates it with a new name
|
||||||
*/
|
*/
|
||||||
async duplicateWorkflow(workflow: ComfyWorkflow) {
|
const duplicateWorkflow = async (workflow: ComfyWorkflow) => {
|
||||||
const state = JSON.parse(JSON.stringify(workflow.activeState))
|
const state = JSON.parse(JSON.stringify(workflow.activeState))
|
||||||
await app.loadGraphData(state, true, true, workflow.filename)
|
await app.loadGraphData(state, true, true, workflow.filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
exportWorkflow,
|
||||||
|
saveWorkflowAs,
|
||||||
|
saveWorkflow,
|
||||||
|
loadDefaultWorkflow,
|
||||||
|
loadBlankWorkflow,
|
||||||
|
reloadCurrentWorkflow,
|
||||||
|
openWorkflow,
|
||||||
|
closeWorkflow,
|
||||||
|
renameWorkflow,
|
||||||
|
deleteWorkflow,
|
||||||
|
insertWorkflow,
|
||||||
|
loadNextOpenedWorkflow,
|
||||||
|
loadPreviousOpenedWorkflow,
|
||||||
|
duplicateWorkflow,
|
||||||
|
afterLoadNewGraph,
|
||||||
|
beforeLoadNewGraph
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user