From 95166806ae751c3cc09c9f259d73e728e13fb942 Mon Sep 17 00:00:00 2001
From: yyh <92089059+lyzno1@users.noreply.github.com>
Date: Thu, 30 Jul 2026 15:07:43 +0800
Subject: [PATCH] refactor(web): remove configuration mitt context (#39796)
---
oxlint-suppressions.json | 2 +-
.../__tests__/configuration-view.spec.tsx | 106 +++++++++++++++++-
.../agent-tools/__tests__/index.spec.tsx | 37 +-----
.../config/agent/agent-tools/index.tsx | 16 ---
.../app/configuration/configuration-view.tsx | 26 ++++-
.../install-bundle/__tests__/index.spec.tsx | 5 -
.../__tests__/ready-to-install.spec.tsx | 7 ++
.../install-plugin/install-bundle/index.tsx | 11 +-
.../install-bundle/ready-to-install.tsx | 6 +-
.../steps/__tests__/install.spec.tsx | 25 -----
.../install-bundle/steps/install.tsx | 33 +-----
.../workflow/plugin-dependency/index.tsx | 15 ++-
web/context/mitt-context-provider.tsx | 15 ---
web/context/mitt-context.ts | 15 ---
14 files changed, 167 insertions(+), 152 deletions(-)
delete mode 100644 web/context/mitt-context-provider.tsx
delete mode 100644 web/context/mitt-context.ts
diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json
index aa6b95541ae..643f838f8de 100644
--- a/oxlint-suppressions.json
+++ b/oxlint-suppressions.json
@@ -458,7 +458,7 @@
"count": 2
},
"typescript/no-explicit-any": {
- "count": 9
+ "count": 7
}
},
"web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx": {
diff --git a/web/app/components/app/configuration/__tests__/configuration-view.spec.tsx b/web/app/components/app/configuration/__tests__/configuration-view.spec.tsx
index bae633b0c27..0a8e09172d8 100644
--- a/web/app/components/app/configuration/__tests__/configuration-view.spec.tsx
+++ b/web/app/components/app/configuration/__tests__/configuration-view.spec.tsx
@@ -1,9 +1,14 @@
import type { ComponentProps } from 'react'
import type { ConfigurationViewModel } from '../hooks/use-configuration'
import type AppPublisher from '@/app/components/app/app-publisher/features-wrapper'
+import type { InstallBundleCompleteCallback } from '@/app/components/plugins/install-plugin/install-bundle'
+import type { Plugin } from '@/app/components/plugins/types'
import type ConfigContext from '@/context/debug-configuration'
+import type { AgentTool } from '@/types/app'
import { fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'
+import { PluginCategoryEnum } from '@/app/components/plugins/types'
+import { CollectionType } from '@/app/components/tools/types'
import { AppModeEnum, ModelModeType } from '@/types/app'
import ConfigurationView from '../configuration-view'
@@ -48,10 +53,49 @@ vi.mock('@/app/components/base/features/new-feature-panel', () => ({
default: () =>
,
}))
+let pluginDependencyOnInstallComplete: InstallBundleCompleteCallback | undefined
vi.mock('@/app/components/workflow/plugin-dependency', () => ({
- default: () => ,
+ default: ({ onInstallComplete }: { onInstallComplete?: InstallBundleCompleteCallback }) => {
+ pluginDependencyOnInstallComplete = onInstallComplete
+ return
+ },
}))
+const createPlugin = (name: string): Plugin => ({
+ type: 'plugin',
+ org: 'vendor',
+ name,
+ plugin_id: 'vendor',
+ version: '1.0.0',
+ latest_version: '1.0.0',
+ latest_package_identifier: `vendor/${name}:1.0.0`,
+ icon: 'icon.svg',
+ verified: true,
+ label: { 'en-US': name },
+ brief: { 'en-US': name },
+ description: { 'en-US': name },
+ introduction: '',
+ repository: `https://example.com/vendor/${name}`,
+ category: PluginCategoryEnum.tool,
+ install_count: 0,
+ endpoint: { settings: [] },
+ tags: [],
+ badges: [],
+ verification: { authorized_category: 'community' },
+ from: 'marketplace',
+})
+
+const createDeletedAgentTool = (providerId: string): AgentTool => ({
+ provider_id: providerId,
+ provider_type: CollectionType.builtIn,
+ provider_name: providerId,
+ tool_name: 'search',
+ tool_label: 'Search',
+ tool_parameters: {},
+ enabled: true,
+ isDeleted: true,
+})
+
const createContextValue = (): ComponentProps['value'] => ({
appId: 'app-1',
isAPIKeySet: true,
@@ -269,6 +313,7 @@ describe('ConfigurationView', () => {
beforeEach(() => {
vi.clearAllMocks()
mockIsAgentV2Enabled.mockReturnValue(false)
+ pluginDependencyOnInstallComplete = undefined
})
it('should render a loading state before configuration data is ready', () => {
@@ -332,4 +377,63 @@ describe('ConfigurationView', () => {
expect(screen.queryByText('appDebug.legacyAgentBadge.label')).not.toBeInTheDocument()
})
+
+ it('should reinstate selected plugin tools when at least one installation succeeds', () => {
+ const contextValue = createContextValue()
+ contextValue.isAgent = true
+ const tools = [
+ createDeletedAgentTool('vendor/successful-plugin'),
+ createDeletedAgentTool('vendor/failed-plugin'),
+ createDeletedAgentTool('vendor/unselected-plugin'),
+ ]
+ contextValue.modelConfig.agentConfig.tools = tools
+
+ render()
+ if (!pluginDependencyOnInstallComplete)
+ throw new Error('Plugin completion callback not registered')
+
+ pluginDependencyOnInstallComplete(
+ [createPlugin('successful-plugin'), createPlugin('failed-plugin')],
+ [
+ { success: true, isFromMarketPlace: true },
+ { success: false, isFromMarketPlace: true },
+ ],
+ [
+ { hasInstalled: false, toInstallVersion: '1.0.0' },
+ { hasInstalled: false, toInstallVersion: '1.0.0' },
+ ],
+ )
+
+ expect(contextValue.setModelConfig).toHaveBeenCalledOnce()
+ const nextModelConfig = vi.mocked(contextValue.setModelConfig).mock.calls[0]![0]
+ expect(nextModelConfig.agentConfig.tools).toEqual([
+ expect.objectContaining({ provider_id: 'vendor/successful-plugin', isDeleted: false }),
+ expect.objectContaining({ provider_id: 'vendor/failed-plugin', isDeleted: false }),
+ expect.objectContaining({ provider_id: 'vendor/unselected-plugin', isDeleted: true }),
+ ])
+ })
+
+ it('should keep deleted tools unchanged when every installation fails', () => {
+ const contextValue = createContextValue()
+ contextValue.isAgent = true
+ contextValue.modelConfig.agentConfig.tools = [createDeletedAgentTool('vendor/failed-plugin')]
+
+ render()
+ if (!pluginDependencyOnInstallComplete)
+ throw new Error('Plugin completion callback not registered')
+
+ pluginDependencyOnInstallComplete(
+ [createPlugin('failed-plugin')],
+ [{ success: false, isFromMarketPlace: true }],
+ [{ hasInstalled: false, toInstallVersion: '1.0.0' }],
+ )
+
+ expect(contextValue.setModelConfig).not.toHaveBeenCalled()
+ })
+
+ it('should not attach the agent tool completion handler to non-agent configurations', () => {
+ render()
+
+ expect(pluginDependencyOnInstallComplete).toBeUndefined()
+ })
})
diff --git a/web/app/components/app/configuration/config/agent/agent-tools/__tests__/index.spec.tsx b/web/app/components/app/configuration/config/agent/agent-tools/__tests__/index.spec.tsx
index f47e3d94b40..757800df08f 100644
--- a/web/app/components/app/configuration/config/agent/agent-tools/__tests__/index.spec.tsx
+++ b/web/app/components/app/configuration/config/agent/agent-tools/__tests__/index.spec.tsx
@@ -8,7 +8,7 @@ import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/
import type { ToolWithProvider } from '@/app/components/workflow/types'
import type { ModelConfig } from '@/models/debug'
import type { AgentTool } from '@/types/app'
-import { act, render, screen, waitFor } from '@testing-library/react'
+import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import * as React from 'react'
import { useEffect, useMemo, useState } from 'react'
@@ -28,17 +28,6 @@ vi.mock('@/app/components/app/configuration/debug/hooks', () => ({
useFormattingChangedDispatcher: () => formattingDispatcherMock,
}))
-let pluginInstallHandler: ((names: string[]) => void) | null = null
-const subscribeMock = vi.fn((event: string, handler: any) => {
- if (event === 'plugin:install:success') pluginInstallHandler = handler
-})
-vi.mock('@/context/mitt-context', () => ({
- useMittContextSelector: (selector: any) =>
- selector({
- useSubscribe: subscribeMock,
- }),
-}))
-
let builtInTools: ToolWithProvider[] = []
let customTools: ToolWithProvider[] = []
let workflowTools: ToolWithProvider[] = []
@@ -326,7 +315,6 @@ describe('AgentTools', () => {
latestSettingPanelProps = null
settingPanelSavePayload = {}
settingPanelCredentialId = 'credential-from-panel'
- pluginInstallHandler = null
})
it('should show enabled count and provider information', () => {
@@ -493,27 +481,4 @@ describe('AgentTools', () => {
])
})
})
-
- it('should reinstate deleted tools after plugin install success event', async () => {
- const { getModelConfig } = renderAgentTools([
- createAgentTool({
- provider_id: 'provider-1',
- provider_name: 'vendor/provider-1',
- tool_name: 'search',
- tool_label: 'Search Tool',
- isDeleted: true,
- }),
- ])
- if (!pluginInstallHandler) throw new Error('Plugin handler not registered')
-
- await act(async () => {
- pluginInstallHandler?.(['provider-1'])
- })
-
- await waitFor(() => {
- expect((getModelConfig().agentConfig.tools[0] as { isDeleted: boolean }).isDeleted).toBe(
- false,
- )
- })
- })
})
diff --git a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx
index 9a4ea6422d6..add510e6274 100644
--- a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx
+++ b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx
@@ -31,7 +31,6 @@ import {
import ToolPicker from '@/app/components/workflow/block-selector/tool-picker'
import { MAX_TOOLS_NUM } from '@/config'
import ConfigContext from '@/context/debug-configuration'
-import { useMittContextSelector } from '@/context/mitt-context'
import {
useAllBuiltInTools,
useAllCustomTools,
@@ -77,21 +76,6 @@ const AgentTools: FC = () => {
collection,
}
})
- const useSubscribe = useMittContextSelector((s) => s.useSubscribe)
- const handleUpdateToolsWhenInstallToolSuccess = useCallback(
- (installedPluginNames: string[]) => {
- const newModelConfig = produce(modelConfig, (draft) => {
- draft.agentConfig.tools.forEach((item: any) => {
- if (item.isDeleted && installedPluginNames.includes(item.provider_id))
- item.isDeleted = false
- })
- })
- setModelConfig(newModelConfig)
- },
- [modelConfig, setModelConfig],
- )
- useSubscribe('plugin:install:success', handleUpdateToolsWhenInstallToolSuccess as any)
-
const handleToolSettingChange = (value: Record) => {
const newModelConfig = produce(modelConfig, (draft) => {
const tool = draft.agentConfig.tools.find(
diff --git a/web/app/components/app/configuration/configuration-view.tsx b/web/app/components/app/configuration/configuration-view.tsx
index aa0425b5cb3..52333f830f9 100644
--- a/web/app/components/app/configuration/configuration-view.tsx
+++ b/web/app/components/app/configuration/configuration-view.tsx
@@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { ConfigurationViewModel } from './hooks/use-configuration'
+import type { InstallBundleCompleteCallback } from '@/app/components/plugins/install-plugin/install-bundle'
import { CodeBracketIcon } from '@heroicons/react/20/solid'
import {
AlertDialog,
@@ -22,6 +23,7 @@ import {
DrawerViewport,
} from '@langgenius/dify-ui/drawer'
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
+import { produce } from 'immer'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import AppPublisher from '@/app/components/app/app-publisher/features-wrapper'
@@ -37,7 +39,6 @@ import Loading from '@/app/components/base/loading'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
import PluginDependency from '@/app/components/workflow/plugin-dependency'
import ConfigContext from '@/context/debug-configuration'
-import { MittProvider } from '@/context/mitt-context-provider'
import { isAgentV2Enabled } from '@/features/agent-v2/feature-flag'
import Link from '@/next/link'
import { AppModeEnum, ModelModeType } from '@/types/app'
@@ -117,6 +118,23 @@ const ConfigurationView: FC = ({
const { t } = useTranslation()
const debugWithMultipleModel = appPublisherProps.debugWithMultipleModel
const showLegacyAgentBadge = isAgentV2Enabled() && contextValue.mode === AppModeEnum.AGENT_CHAT
+ const handlePluginInstallComplete: InstallBundleCompleteCallback = (plugins, installStatus) => {
+ if (!installStatus.some((status) => status.success)) return
+
+ const installedPluginNames = plugins.map((plugin) => `${plugin.plugin_id}/${plugin.name}`)
+ const nextModelConfig = produce(contextValue.modelConfig, (draft) => {
+ draft.agentConfig.tools.forEach((tool) => {
+ if (
+ 'provider_id' in tool &&
+ tool.isDeleted &&
+ installedPluginNames.includes(tool.provider_id)
+ ) {
+ tool.isDeleted = false
+ }
+ })
+ })
+ contextValue.setModelConfig(nextModelConfig)
+ }
if (showLoading) {
return (
@@ -129,7 +147,7 @@ const ConfigurationView: FC = ({
return (
-
+ <>
@@ -312,8 +330,8 @@ const ConfigurationView: FC
= ({
onAutoAddPromptVariable={onAutoAddPromptVariable}
/>
)}
-
-
+
+ >
)
diff --git a/web/app/components/plugins/install-plugin/install-bundle/__tests__/index.spec.tsx b/web/app/components/plugins/install-plugin/install-bundle/__tests__/index.spec.tsx
index f53b12ed78e..55eb99c4e4f 100644
--- a/web/app/components/plugins/install-plugin/install-bundle/__tests__/index.spec.tsx
+++ b/web/app/components/plugins/install-plugin/install-bundle/__tests__/index.spec.tsx
@@ -188,11 +188,6 @@ vi.mock('@/config', async () => {
}
})
-// Mock mitt context
-vi.mock('@/context/mitt-context', () => ({
- useMittContextSelector: () => vi.fn(),
-}))
-
// Mock useCanInstallPluginFromMarketplace
vi.mock('@/app/components/plugins/plugin-page/use-reference-setting', () => ({
useCanInstallPluginFromMarketplace: () => ({ canInstallPluginFromMarketplace: true }),
diff --git a/web/app/components/plugins/install-plugin/install-bundle/__tests__/ready-to-install.spec.tsx b/web/app/components/plugins/install-plugin/install-bundle/__tests__/ready-to-install.spec.tsx
index bd0a8a49f33..4735718e8c7 100644
--- a/web/app/components/plugins/install-plugin/install-bundle/__tests__/ready-to-install.spec.tsx
+++ b/web/app/components/plugins/install-plugin/install-bundle/__tests__/ready-to-install.spec.tsx
@@ -100,6 +100,7 @@ describe('ReadyToInstall', () => {
const mockOnStartToInstall = vi.fn()
const mockSetIsInstalling = vi.fn()
const mockOnClose = vi.fn()
+ const mockOnInstallComplete = vi.fn()
const defaultProps = {
step: InstallStep.readyToInstall,
@@ -108,6 +109,7 @@ describe('ReadyToInstall', () => {
setIsInstalling: mockSetIsInstalling,
allPlugins: createMockDependencies(),
onClose: mockOnClose,
+ onInstallComplete: mockOnInstallComplete,
}
beforeEach(() => {
@@ -177,6 +179,11 @@ describe('ReadyToInstall', () => {
expect(screen.getByTestId('installed-step')).toBeInTheDocument()
expect(screen.getByTestId('installed-count')).toHaveTextContent('1')
expect(screen.getByTestId('installed-status-count')).toHaveTextContent('1')
+ expect(mockOnInstallComplete).toHaveBeenCalledWith(
+ [expect.objectContaining({ plugin_id: 'p1' })],
+ [expect.objectContaining({ success: true })],
+ [expect.objectContaining({ toInstallVersion: '1.0.0' })],
+ )
})
it('should pass custom plugins and status via capturedOnInstalled', () => {
diff --git a/web/app/components/plugins/install-plugin/install-bundle/index.tsx b/web/app/components/plugins/install-plugin/install-bundle/index.tsx
index 6f6587e37e6..b30538f80e2 100644
--- a/web/app/components/plugins/install-plugin/install-bundle/index.tsx
+++ b/web/app/components/plugins/install-plugin/install-bundle/index.tsx
@@ -1,6 +1,6 @@
'use client'
import type { FC } from 'react'
-import type { Dependency } from '../../types'
+import type { Dependency, InstallStatus, Plugin, VersionProps } from '../../types'
import { cn } from '@langgenius/dify-ui/cn'
import { Dialog, DialogCloseButton, DialogContent } from '@langgenius/dify-ui/dialog'
import * as React from 'react'
@@ -12,6 +12,12 @@ import ReadyToInstall from './ready-to-install'
const i18nPrefix = 'installModal'
+export type InstallBundleCompleteCallback = (
+ plugins: Plugin[],
+ installStatus: InstallStatus[],
+ versionInfo: VersionProps[],
+) => void
+
export enum InstallType {
fromLocal = 'fromLocal',
fromMarketplace = 'fromMarketplace',
@@ -23,12 +29,14 @@ type Props = Readonly<{
fromDSLPayload: Dependency[]
// plugins?: PluginDeclaration[]
onClose: () => void
+ onInstallComplete?: InstallBundleCompleteCallback
}>
const InstallBundle: FC = ({
installType = InstallType.fromMarketplace,
fromDSLPayload,
onClose,
+ onInstallComplete,
}) => {
const { t } = useTranslation()
const [step, setStep] = useState(
@@ -78,6 +86,7 @@ const InstallBundle: FC = ({
setIsInstalling={setIsInstalling}
allPlugins={fromDSLPayload}
onClose={onClose}
+ onInstallComplete={onInstallComplete}
/>
diff --git a/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx b/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx
index 99e7a1f1c12..816da2390e7 100644
--- a/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx
+++ b/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx
@@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { Dependency, InstallStatus, Plugin, VersionProps } from '../../types'
+import type { InstallBundleCompleteCallback } from './index'
import * as React from 'react'
import { useCallback, useState } from 'react'
import { InstallStep } from '../../types'
@@ -14,6 +15,7 @@ type Props = Readonly<{
setIsInstalling: (isInstalling: boolean) => void
allPlugins: Dependency[]
onClose: () => void
+ onInstallComplete?: InstallBundleCompleteCallback
isFromMarketPlace?: boolean
}>
@@ -24,6 +26,7 @@ const ReadyToInstall: FC = ({
setIsInstalling,
allPlugins,
onClose,
+ onInstallComplete,
isFromMarketPlace,
}) => {
const [installedPlugins, setInstalledPlugins] = useState([])
@@ -36,8 +39,9 @@ const ReadyToInstall: FC = ({
setInstalledVersionInfo(versionInfo)
onStepChange(InstallStep.installed)
setIsInstalling(false)
+ onInstallComplete?.(plugins, installStatus, versionInfo)
},
- [onStepChange, setIsInstalling],
+ [onInstallComplete, onStepChange, setIsInstalling],
)
return (
<>
diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install.spec.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install.spec.tsx
index dbcbf9c1533..b65acff3079 100644
--- a/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install.spec.tsx
+++ b/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install.spec.tsx
@@ -55,12 +55,6 @@ vi.mock('../../../hooks/use-refresh-plugin-list', () => ({
}),
}))
-// Mock mitt context
-const mockEmit = vi.fn()
-vi.mock('@/context/mitt-context', () => ({
- useMittContextSelector: () => mockEmit,
-}))
-
// Mock useCanInstallPluginFromMarketplace
vi.mock('@/app/components/plugins/plugin-page/use-reference-setting', () => ({
useCanInstallPluginFromMarketplace: () => ({ canInstallPluginFromMarketplace: true }),
@@ -530,25 +524,6 @@ describe('Install Component', () => {
})
})
- it('should emit plugin:install:success event on successful installation', async () => {
- render()
-
- // Select all plugins
- await act(async () => {
- fireEvent.click(screen.getByTestId('select-all-plugins'))
- })
-
- // Click install
- const installButton = screen.getByText(/plugin\.installModal\.install/i)
- await act(async () => {
- fireEvent.click(installButton)
- })
-
- await waitFor(() => {
- expect(mockEmit).toHaveBeenCalledWith('plugin:install:success', expect.any(Array))
- })
- })
-
it('should disable install button when no plugins are selected', async () => {
render()
diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx
index 39ebc7bbe43..419b07a6b6d 100644
--- a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx
+++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx
@@ -1,13 +1,7 @@
'use client'
import type { FC } from 'react'
-import type {
- Dependency,
- InstallStatus,
- InstallStatusResponse,
- Plugin,
- VersionInfo,
- VersionProps,
-} from '../../../types'
+import type { Dependency, InstallStatusResponse, Plugin, VersionInfo } from '../../../types'
+import type { InstallBundleCompleteCallback } from '../index'
import type { ExposeRefs } from './install-multi'
import { Button } from '@langgenius/dify-ui/button'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
@@ -16,7 +10,6 @@ import * as React from 'react'
import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useCanInstallPluginFromMarketplace } from '@/app/components/plugins/plugin-page/use-reference-setting'
-import { useMittContextSelector } from '@/context/mitt-context'
import { useInstallOrUpdate, usePluginTaskList } from '@/service/use-plugins'
import { TaskStatus } from '../../../types'
import checkTaskStatus from '../../base/check-task-status'
@@ -29,11 +22,7 @@ const i18nPrefix = 'installModal'
type Props = Readonly<{
allPlugins: Dependency[]
onStartToInstall?: () => void
- onInstalled: (
- plugins: Plugin[],
- installStatus: InstallStatus[],
- versionInfo: VersionProps[],
- ) => void
+ onInstalled: InstallBundleCompleteCallback
onCancel: () => void
isFromMarketPlace?: boolean
isHideButton?: boolean
@@ -48,7 +37,6 @@ const Install: FC = ({
isHideButton,
}) => {
const { t } = useTranslation()
- const emit = useMittContextSelector((s) => s.emit)
const [selectedPlugins, setSelectedPlugins] = React.useState([])
const [selectedIndexes, setSelectedIndexes] = React.useState([])
const selectedPluginsNum = selectedPlugins.length
@@ -113,12 +101,6 @@ const Install: FC = ({
const hasInstallSuccess = res.some((r) => r.status === TaskStatus.success)
if (hasInstallSuccess) {
refreshPluginList(undefined, true)
- emit(
- 'plugin:install:success',
- selectedPlugins.map((p) => {
- return `${p.plugin_id}/${p.name}`
- }),
- )
}
return
}
@@ -143,15 +125,6 @@ const Install: FC = ({
}),
)
onInstalled(selectedPlugins, installStatus, getSelectedVersionInfo())
- const hasInstallSuccess = installStatus.some((r) => r.success)
- if (hasInstallSuccess) {
- emit(
- 'plugin:install:success',
- selectedPlugins.map((p) => {
- return `${p.plugin_id}/${p.name}`
- }),
- )
- }
},
})
const handleInstall = () => {
diff --git a/web/app/components/workflow/plugin-dependency/index.tsx b/web/app/components/workflow/plugin-dependency/index.tsx
index 6fe95e0a321..21f3f648330 100644
--- a/web/app/components/workflow/plugin-dependency/index.tsx
+++ b/web/app/components/workflow/plugin-dependency/index.tsx
@@ -1,10 +1,15 @@
'use client'
+import type { InstallBundleCompleteCallback } from '@/app/components/plugins/install-plugin/install-bundle'
import { useCallback } from 'react'
import InstallBundle from '@/app/components/plugins/install-plugin/install-bundle'
import { useStore } from './store'
-const PluginDependency = () => {
+type Props = {
+ onInstallComplete?: InstallBundleCompleteCallback
+}
+
+const PluginDependency = ({ onInstallComplete }: Props) => {
const dependencies = useStore((s) => s.dependencies)
const handleCancelInstallBundle = useCallback(() => {
@@ -14,7 +19,13 @@ const PluginDependency = () => {
if (!dependencies.length) return null
- return
+ return (
+
+ )
}
export default PluginDependency
diff --git a/web/context/mitt-context-provider.tsx b/web/context/mitt-context-provider.tsx
deleted file mode 100644
index 7fee75eb5b6..00000000000
--- a/web/context/mitt-context-provider.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-'use client'
-
-import type { ReactNode } from 'react'
-import { useMitt } from '@/hooks/use-mitt'
-import { MittContext } from './mitt-context'
-
-type MittProviderProps = {
- children: ReactNode
-}
-
-export const MittProvider = ({ children }: MittProviderProps) => {
- const mitt = useMitt()
-
- return {children}
-}
diff --git a/web/context/mitt-context.ts b/web/context/mitt-context.ts
deleted file mode 100644
index 66616d70913..00000000000
--- a/web/context/mitt-context.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-'use client'
-
-import type { useMitt } from '@/hooks/use-mitt'
-import { noop } from 'es-toolkit/function'
-import { createContext, useContextSelector } from 'use-context-selector'
-
-type ContextValueType = ReturnType
-export const MittContext = createContext({
- emit: noop,
- useSubscribe: noop,
-})
-
-export function useMittContextSelector(selector: (value: ContextValueType) => T): T {
- return useContextSelector(MittContext, selector)
-}