[Refactor] Convert workflowService to composable (#2057)

This commit is contained in:
Chenlei Hu
2024-12-26 00:11:27 -05:00
committed by GitHub
parent c00d665aa5
commit 4e554503c0
8 changed files with 119 additions and 101 deletions

View File

@@ -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()
} }
) )

View File

@@ -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

View File

@@ -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
})) }))
) { ) {

View File

@@ -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()

View File

@@ -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[] => {

View File

@@ -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())
} }
/** /**

View File

@@ -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>> {

View File

@@ -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
}
} }