diff --git a/src/components/sidebar/SidebarHelpCenterIcon.vue b/src/components/sidebar/SidebarHelpCenterIcon.vue index b8d8cea396..ac90764802 100644 --- a/src/components/sidebar/SidebarHelpCenterIcon.vue +++ b/src/components/sidebar/SidebarHelpCenterIcon.vue @@ -64,12 +64,12 @@ import { storeToRefs } from 'pinia' import { computed, onMounted, toRefs } from 'vue' import HelpCenterMenuContent from '@/components/helpcenter/HelpCenterMenuContent.vue' +import { useNodeConflictDialog } from '@/composables/useNodeConflictDialog' import { useSettingStore } from '@/platform/settings/settingStore' import { useTelemetry } from '@/platform/telemetry' import { useReleaseStore } from '@/platform/updates/common/releaseStore' import ReleaseNotificationToast from '@/platform/updates/components/ReleaseNotificationToast.vue' import WhatsNewPopup from '@/platform/updates/components/WhatsNewPopup.vue' -import { useDialogService } from '@/services/dialogService' import { useHelpCenterStore } from '@/stores/helpCenterStore' import { useConflictAcknowledgment } from '@/workbench/extensions/manager/composables/useConflictAcknowledgment' import { useConflictDetection } from '@/workbench/extensions/manager/composables/useConflictDetection' @@ -84,7 +84,7 @@ const { shouldShowRedDot: showReleaseRedDot } = storeToRefs(releaseStore) const conflictDetection = useConflictDetection() -const { showNodeConflictDialog } = useDialogService() +const { show: showNodeConflictDialog } = useNodeConflictDialog() // Use conflict acknowledgment state from composable - call only once const { shouldShowRedDot: shouldShowConflictRedDot, markConflictsAsSeen } = diff --git a/src/composables/useMissingNodesDialog.ts b/src/composables/useMissingNodesDialog.ts new file mode 100644 index 0000000000..b0fa7b5521 --- /dev/null +++ b/src/composables/useMissingNodesDialog.ts @@ -0,0 +1,29 @@ +import MissingNodesContent from '@/components/dialog/content/MissingNodesContent.vue' +import MissingNodesFooter from '@/components/dialog/content/MissingNodesFooter.vue' +import MissingNodesHeader from '@/components/dialog/content/MissingNodesHeader.vue' +import { useDialogService } from '@/services/dialogService' +import { useDialogStore } from '@/stores/dialogStore' +import type { ComponentProps } from 'vue-component-type-helpers' + +const DIALOG_KEY = 'global-missing-nodes' + +export const useMissingNodesDialog = () => { + const dialogService = useDialogService() + const dialogStore = useDialogStore() + + function hide() { + dialogStore.closeDialog({ key: DIALOG_KEY }) + } + + function show(props: ComponentProps) { + dialogService.showSmallDialog({ + key: DIALOG_KEY, + headerComponent: MissingNodesHeader, + footerComponent: MissingNodesFooter, + component: MissingNodesContent, + props + }) + } + + return { show, hide } +} diff --git a/src/composables/useNodeConflictDialog.ts b/src/composables/useNodeConflictDialog.ts new file mode 100644 index 0000000000..481c00ae91 --- /dev/null +++ b/src/composables/useNodeConflictDialog.ts @@ -0,0 +1,48 @@ +import NodeConflictDialogContent from '@/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue' +import NodeConflictFooter from '@/workbench/extensions/manager/components/manager/NodeConflictFooter.vue' +import NodeConflictHeader from '@/workbench/extensions/manager/components/manager/NodeConflictHeader.vue' +import { useDialogService } from '@/services/dialogService' +import { useDialogStore } from '@/stores/dialogStore' +import type { DialogComponentProps } from '@/stores/dialogStore' +import type { ConflictDetectionResult } from '@/workbench/extensions/manager/types/conflictDetectionTypes' + +const DIALOG_KEY = 'global-node-conflict' + +export const useNodeConflictDialog = () => { + const dialogService = useDialogService() + const dialogStore = useDialogStore() + + function hide() { + dialogStore.closeDialog({ key: DIALOG_KEY }) + } + + function show( + options: { + showAfterWhatsNew?: boolean + conflictedPackages?: ConflictDetectionResult[] + dialogComponentProps?: DialogComponentProps + buttonText?: string + onButtonClick?: () => void + } = {} + ) { + const { buttonText, onButtonClick, showAfterWhatsNew, conflictedPackages } = + options + + return dialogService.showSmallDialog({ + key: DIALOG_KEY, + headerComponent: NodeConflictHeader, + footerComponent: NodeConflictFooter, + component: NodeConflictDialogContent, + props: { + showAfterWhatsNew, + conflictedPackages + }, + footerProps: { + buttonText, + onButtonClick + } + }) + } + + return { show, hide } +} diff --git a/src/scripts/app.ts b/src/scripts/app.ts index 728e35d05d..c72c381cd2 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -42,6 +42,7 @@ import { isComboInputSpecV2 } from '@/schemas/nodeDefSchema' import { type BaseDOMWidget, DOMWidgetImpl } from '@/scripts/domWidget' +import { useMissingNodesDialog } from '@/composables/useMissingNodesDialog' import { useDialogService } from '@/services/dialogService' import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription' import { useExtensionService } from '@/services/extensionService' @@ -1018,7 +1019,7 @@ export class ComfyApp { private showMissingNodesError(missingNodeTypes: MissingNodeType[]) { if (useSettingStore().get('Comfy.Workflow.ShowMissingNodesWarning')) { - useDialogService().showLoadWorkflowWarning({ missingNodeTypes }) + useMissingNodesDialog().show({ missingNodeTypes }) } } diff --git a/src/services/dialogService.ts b/src/services/dialogService.ts index ff08ad1549..78bf60dc85 100644 --- a/src/services/dialogService.ts +++ b/src/services/dialogService.ts @@ -2,9 +2,6 @@ import { merge } from 'es-toolkit/compat' import type { Component } from 'vue' import ApiNodesSignInContent from '@/components/dialog/content/ApiNodesSignInContent.vue' -import MissingNodesContent from '@/components/dialog/content/MissingNodesContent.vue' -import MissingNodesFooter from '@/components/dialog/content/MissingNodesFooter.vue' -import MissingNodesHeader from '@/components/dialog/content/MissingNodesHeader.vue' import ConfirmationDialogContent from '@/components/dialog/content/ConfirmationDialogContent.vue' import ErrorDialogContent from '@/components/dialog/content/ErrorDialogContent.vue' import MissingModelsWarning from '@/components/dialog/content/MissingModelsWarning.vue' @@ -30,10 +27,6 @@ import ManagerProgressFooter from '@/workbench/extensions/manager/components/Man import ManagerProgressHeader from '@/workbench/extensions/manager/components/ManagerProgressHeader.vue' import ManagerDialogContent from '@/workbench/extensions/manager/components/manager/ManagerDialogContent.vue' import ManagerHeader from '@/workbench/extensions/manager/components/manager/ManagerHeader.vue' -import NodeConflictDialogContent from '@/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue' -import NodeConflictFooter from '@/workbench/extensions/manager/components/manager/NodeConflictFooter.vue' -import NodeConflictHeader from '@/workbench/extensions/manager/components/manager/NodeConflictHeader.vue' -import type { ConflictDetectionResult } from '@/workbench/extensions/manager/types/conflictDetectionTypes' import type { ComponentProps } from 'vue-component-type-helpers' export type ConfirmationDialogType = @@ -47,32 +40,6 @@ export type ConfirmationDialogType = export const useDialogService = () => { const dialogStore = useDialogStore() - function showLoadWorkflowWarning( - props: ComponentProps - ) { - dialogStore.showDialog({ - key: 'global-missing-nodes', - headerComponent: MissingNodesHeader, - footerComponent: MissingNodesFooter, - component: MissingNodesContent, - dialogComponentProps: { - closable: true, - pt: { - root: { class: 'bg-base-background border-border-default' }, - header: { class: '!p-0 !m-0' }, - content: { class: '!p-0 overflow-y-hidden' }, - footer: { class: '!p-0' }, - pcCloseButton: { - root: { - class: '!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5' - } - } - } - }, - props - }) - } - function showMissingModelsWarning( props: InstanceType['$props'] ) { @@ -449,6 +416,44 @@ export const useDialogService = () => { } } + function showSmallDialog(options: { + key: string + component: T + headerComponent?: Component + footerComponent?: Component + props?: ComponentProps + footerProps?: Record + dialogComponentProps?: DialogComponentProps + }) { + const smallDialogDefaultProps: DialogComponentProps = { + closable: true, + pt: { + root: { class: 'bg-base-background border-border-default' }, + header: { class: '!p-0 !m-0' }, + content: { class: '!p-0 overflow-y-hidden' }, + footer: { class: '!p-0' }, + pcCloseButton: { + root: { + class: '!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5' + } + } + } + } + + return dialogStore.showDialog({ + key: options.key, + component: options.component, + headerComponent: options.headerComponent, + footerComponent: options.footerComponent, + props: options.props, + footerProps: options.footerProps, + dialogComponentProps: merge( + smallDialogDefaultProps, + options.dialogComponentProps || {} + ) + }) + } + function showLayoutDialog(options: { key: string component: Component @@ -481,54 +486,6 @@ export const useDialogService = () => { }) } - function showNodeConflictDialog( - options: { - showAfterWhatsNew?: boolean - conflictedPackages?: ConflictDetectionResult[] - dialogComponentProps?: DialogComponentProps - buttonText?: string - onButtonClick?: () => void - } = {} - ) { - const { - dialogComponentProps, - buttonText, - onButtonClick, - showAfterWhatsNew, - conflictedPackages - } = options - - return dialogStore.showDialog({ - key: 'global-node-conflict', - headerComponent: NodeConflictHeader, - footerComponent: NodeConflictFooter, - component: NodeConflictDialogContent, - dialogComponentProps: { - closable: true, - pt: { - header: { class: '!p-0 !m-0' }, - content: { class: '!p-0 overflow-y-hidden' }, - footer: { class: '!p-0' }, - pcCloseButton: { - root: { - class: - '!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5 bg-dialog-surface text-white' - } - } - }, - ...dialogComponentProps - }, - props: { - showAfterWhatsNew, - conflictedPackages - }, - footerProps: { - buttonText, - onButtonClick - } - }) - } - async function showSubscriptionRequiredDialog() { if (!isCloud || !window.__CONFIG__?.subscription_required) { return @@ -542,7 +499,6 @@ export const useDialogService = () => { } return { - showLoadWorkflowWarning, showMissingModelsWarning, showSettingsDialog, showAboutDialog, @@ -560,7 +516,7 @@ export const useDialogService = () => { confirm, toggleManagerDialog, toggleManagerProgressDialog, - showLayoutDialog, - showNodeConflictDialog + showSmallDialog, + showLayoutDialog } } diff --git a/src/stores/dialogStore.ts b/src/stores/dialogStore.ts index d2bac36758..5d6fcec12a 100644 --- a/src/stores/dialogStore.ts +++ b/src/stores/dialogStore.ts @@ -205,12 +205,19 @@ export const useDialogStore = defineStore('dialog', () => { function showDialog(options: ShowDialogOptions) { const dialogKey = options.key || genDialogKey() - - let dialog = dialogStack.value.find((d) => d.key === dialogKey) - + const existingIndex = dialogStack.value.findIndex( + (d) => d.key === dialogKey + ) + let dialog = + existingIndex !== -1 ? dialogStack.value[existingIndex] : undefined if (dialog) { - dialog.visible = true - riseDialog(dialog) + if (!dialog.visible) { + dialogStack.value.splice(existingIndex, 1) + dialog = createDialog({ ...options, key: dialogKey }) + } else { + dialog.visible = true + riseDialog(dialog) + } } else { dialog = createDialog({ ...options, key: dialogKey }) } diff --git a/src/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue b/src/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue index 61fb2520a5..ea763808f0 100644 --- a/src/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue +++ b/src/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue @@ -14,7 +14,7 @@
{{ packageName }} @@ -60,7 +60,10 @@
-
+
{{ getConflictMessage(conflict, t) @@ -105,7 +108,9 @@
-
+
{{ conflictResult.package_name }} @@ -230,8 +235,3 @@ const toggleExtensionsPanel = () => { importFailedExpanded.value = false } - diff --git a/src/workbench/extensions/manager/components/manager/NodeConflictHeader.vue b/src/workbench/extensions/manager/components/manager/NodeConflictHeader.vue index 368a1229fb..daff3281f6 100644 --- a/src/workbench/extensions/manager/components/manager/NodeConflictHeader.vue +++ b/src/workbench/extensions/manager/components/manager/NodeConflictHeader.vue @@ -1,10 +1,8 @@