[Refactor] Convert dialogService to composable (#2058)

This commit is contained in:
Chenlei Hu
2024-12-26 00:26:01 -05:00
committed by GitHub
parent 4e554503c0
commit f69e88bf41
8 changed files with 176 additions and 171 deletions

View File

@@ -1,117 +1,15 @@
// This module is mocked in tests-ui/
// Import vue components here to avoid tests-ui/ reporting errors
// about importing primevue components.
import { useDialogStore, type ShowDialogOptions } from '@/stores/dialogStore'
import type { ExecutionErrorWsMessage } from '@/types/apiTypes'
import type { MissingNodeType } from '@/types/comfy'
import LoadWorkflowWarning from '@/components/dialog/content/LoadWorkflowWarning.vue'
import MissingModelsWarning from '@/components/dialog/content/MissingModelsWarning.vue'
import SettingDialogContent from '@/components/dialog/content/SettingDialogContent.vue'
import SettingDialogHeader from '@/components/dialog/header/SettingDialogHeader.vue'
import type { ExecutionErrorWsMessage } from '@/types/apiTypes'
import ExecutionErrorDialogContent from '@/components/dialog/content/ExecutionErrorDialogContent.vue'
import TemplateWorkflowsContent from '@/components/templates/TemplateWorkflowsContent.vue'
import PromptDialogContent from '@/components/dialog/content/PromptDialogContent.vue'
import ConfirmationDialogContent from '@/components/dialog/content/ConfirmationDialogContent.vue'
import { t } from '@/i18n'
import type { MissingNodeType } from '@/types/comfy'
export function showLoadWorkflowWarning(props: {
missingNodeTypes: MissingNodeType[]
[key: string]: any
}) {
const dialogStore = useDialogStore()
dialogStore.showDialog({
key: 'global-load-workflow-warning',
component: LoadWorkflowWarning,
props
})
}
export function showMissingModelsWarning(props: {
missingModels: any[]
paths: Record<string, string[]>
[key: string]: any
}) {
const dialogStore = useDialogStore()
dialogStore.showDialog({
key: 'global-missing-models-warning',
component: MissingModelsWarning,
props
})
}
export function showSettingsDialog(
panel?: 'about' | 'keybinding' | 'extension' | 'server-config'
) {
const props = panel ? { props: { defaultPanel: panel } } : undefined
useDialogStore().showDialog({
key: 'global-settings',
headerComponent: SettingDialogHeader,
component: SettingDialogContent,
...props
})
}
export function showAboutDialog() {
useDialogStore().showDialog({
key: 'global-settings',
headerComponent: SettingDialogHeader,
component: SettingDialogContent,
props: {
defaultPanel: 'about'
}
})
}
export function showExecutionErrorDialog(error: ExecutionErrorWsMessage) {
useDialogStore().showDialog({
key: 'global-execution-error',
component: ExecutionErrorDialogContent,
props: {
error
}
})
}
export function showTemplateWorkflowsDialog() {
useDialogStore().showDialog({
key: 'global-template-workflows',
title: t('templateWorkflows.title'),
component: TemplateWorkflowsContent
})
}
export async function showPromptDialog({
title,
message,
defaultValue = ''
}: {
title: string
message: string
defaultValue?: string
}): Promise<string | null> {
const dialogStore = useDialogStore()
return new Promise((resolve) => {
dialogStore.showDialog({
key: 'global-prompt',
title,
component: PromptDialogContent,
props: {
message,
defaultValue,
onConfirm: (value: string) => {
resolve(value)
}
},
dialogComponentProps: {
onClose: () => {
resolve(null)
}
}
})
})
}
export type ConfirmationDialogType =
| 'overwrite'
@@ -119,43 +17,151 @@ export type ConfirmationDialogType =
| 'dirtyClose'
| 'reinstall'
/**
*
* @returns `true` if the user confirms the dialog,
* `false` if denied (e.g. no in yes/no/cancel), or
* `null` if the dialog is cancelled or closed
*/
export async function showConfirmationDialog({
title,
type,
message,
itemList = []
}: {
/** Dialog heading */
title: string
/** Pre-configured dialog type */
type: ConfirmationDialogType
/** The main message body */
message: string
/** Displayed as an unorderd list immediately below the message body */
itemList?: string[]
}): Promise<boolean | null> {
return new Promise((resolve) => {
const options: ShowDialogOptions = {
key: 'global-prompt',
title,
component: ConfirmationDialogContent,
props: {
message,
type,
itemList,
onConfirm: resolve
},
dialogComponentProps: {
onClose: () => resolve(null)
}
}
export const useDialogService = () => {
const dialogStore = useDialogStore()
function showLoadWorkflowWarning(props: {
missingNodeTypes: MissingNodeType[]
[key: string]: any
}) {
dialogStore.showDialog({
key: 'global-load-workflow-warning',
component: LoadWorkflowWarning,
props
})
}
useDialogStore().showDialog(options)
})
function showMissingModelsWarning(props: {
missingModels: any[]
paths: Record<string, string[]>
[key: string]: any
}) {
dialogStore.showDialog({
key: 'global-missing-models-warning',
component: MissingModelsWarning,
props
})
}
function showSettingsDialog(
panel?: 'about' | 'keybinding' | 'extension' | 'server-config'
) {
const props = panel ? { props: { defaultPanel: panel } } : undefined
dialogStore.showDialog({
key: 'global-settings',
headerComponent: SettingDialogHeader,
component: SettingDialogContent,
...props
})
}
function showAboutDialog() {
dialogStore.showDialog({
key: 'global-settings',
headerComponent: SettingDialogHeader,
component: SettingDialogContent,
props: {
defaultPanel: 'about'
}
})
}
function showExecutionErrorDialog(error: ExecutionErrorWsMessage) {
dialogStore.showDialog({
key: 'global-execution-error',
component: ExecutionErrorDialogContent,
props: {
error
}
})
}
function showTemplateWorkflowsDialog() {
dialogStore.showDialog({
key: 'global-template-workflows',
title: t('templateWorkflows.title'),
component: TemplateWorkflowsContent
})
}
async function showPromptDialog({
title,
message,
defaultValue = ''
}: {
title: string
message: string
defaultValue?: string
}): Promise<string | null> {
return new Promise((resolve) => {
dialogStore.showDialog({
key: 'global-prompt',
title,
component: PromptDialogContent,
props: {
message,
defaultValue,
onConfirm: (value: string) => {
resolve(value)
}
},
dialogComponentProps: {
onClose: () => {
resolve(null)
}
}
})
})
}
/**
* @returns `true` if the user confirms the dialog,
* `false` if denied (e.g. no in yes/no/cancel), or
* `null` if the dialog is cancelled or closed
*/
async function showConfirmationDialog({
title,
type,
message,
itemList = []
}: {
/** Dialog heading */
title: string
/** Pre-configured dialog type */
type: ConfirmationDialogType
/** The main message body */
message: string
/** Displayed as an unorderd list immediately below the message body */
itemList?: string[]
}): Promise<boolean | null> {
return new Promise((resolve) => {
const options: ShowDialogOptions = {
key: 'global-prompt',
title,
component: ConfirmationDialogContent,
props: {
message,
type,
itemList,
onConfirm: resolve
},
dialogComponentProps: {
onClose: () => resolve(null)
}
}
dialogStore.showDialog(options)
})
}
return {
showLoadWorkflowWarning,
showMissingModelsWarning,
showSettingsDialog,
showAboutDialog,
showExecutionErrorDialog,
showTemplateWorkflowsDialog,
showPromptDialog,
showConfirmationDialog
}
}

View File

@@ -1,7 +1,7 @@
import { downloadBlob } from '@/scripts/utils'
import { useSettingStore } from '@/stores/settingStore'
import { useWorkflowStore, ComfyWorkflow } from '@/stores/workflowStore'
import { showConfirmationDialog, showPromptDialog } from './dialogService'
import { useDialogService } from './dialogService'
import { app } from '@/scripts/app'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { LGraphCanvas } from '@comfyorg/litegraph'
@@ -16,10 +16,11 @@ export const useWorkflowService = () => {
const settingStore = useSettingStore()
const workflowStore = useWorkflowStore()
const toastStore = useToastStore()
const dialogService = useDialogService()
async function getFilename(defaultName: string): Promise<string | null> {
if (settingStore.get('Comfy.PromptFilename')) {
let filename = await showPromptDialog({
let filename = await dialogService.showPromptDialog({
title: t('workflowService.exportWorkflow'),
message: t('workflowService.enterFilename') + ':',
defaultValue: defaultName
@@ -57,7 +58,7 @@ export const useWorkflowService = () => {
* @param workflow The workflow to save
*/
const saveWorkflowAs = async (workflow: ComfyWorkflow) => {
const newFilename = await showPromptDialog({
const newFilename = await dialogService.showPromptDialog({
title: t('workflowService.saveWorkflow'),
message: t('workflowService.enterFilename') + ':',
defaultValue: workflow.filename
@@ -69,7 +70,7 @@ export const useWorkflowService = () => {
const existingWorkflow = workflowStore.getWorkflowByPath(newPath)
if (existingWorkflow && !existingWorkflow.isTemporary) {
const res = await showConfirmationDialog({
const res = await dialogService.showConfirmationDialog({
title: t('sideToolbar.workflowTab.confirmOverwriteTitle'),
type: 'overwrite',
message: t('sideToolbar.workflowTab.confirmOverwrite'),
@@ -178,7 +179,7 @@ export const useWorkflowService = () => {
}
if (workflow.isModified && options.warnIfUnsaved) {
const confirmed = await showConfirmationDialog({
const confirmed = await dialogService.showConfirmationDialog({
title: t('sideToolbar.workflowTab.dirtyCloseTitle'),
type: 'dirtyClose',
message: t('sideToolbar.workflowTab.dirtyClose'),
@@ -222,7 +223,7 @@ export const useWorkflowService = () => {
let confirmed: boolean | null = bypassConfirm || silent
if (!confirmed) {
confirmed = await showConfirmationDialog({
confirmed = await dialogService.showConfirmationDialog({
title: t('sideToolbar.workflowTab.confirmDeleteTitle'),
type: 'delete',
message: t('sideToolbar.workflowTab.confirmDelete'),