From 606985071122e4c957dcb7f96b1c12671318963a Mon Sep 17 00:00:00 2001 From: Junyan Qin Date: Mon, 1 Jun 2026 19:16:08 +0800 Subject: [PATCH] feat(web): type-aware install dialog + refresh sidebar after install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The marketplace install confirm dialog was hardcoded to "安装插件 / 确定要安装 插件 X 吗" for every type. Make it type-aware (plugin / MCP / skill) and show more info: type chip, author/name id, and version when present. Also refresh all sidebar extension lists (plugins, MCP servers, skills) when an install task completes, so the newly-installed extension appears immediately regardless of type (previously only refreshPlugins ran). Co-Authored-By: Claude Opus 4.8 (1M context) --- web/src/app/home/add-extension/page.tsx | 73 ++++++++++++++++++++----- web/src/i18n/locales/en-US.ts | 6 ++ web/src/i18n/locales/zh-Hans.ts | 6 ++ 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/web/src/app/home/add-extension/page.tsx b/web/src/app/home/add-extension/page.tsx index fa82a922..9804018c 100644 --- a/web/src/app/home/add-extension/page.tsx +++ b/web/src/app/home/add-extension/page.tsx @@ -151,6 +151,14 @@ function AddExtensionContent() { const navigate = useNavigate(); const [searchParams, setSearchParams] = useSearchParams(); const { refreshPlugins, refreshMCPServers, refreshSkills } = useSidebarData(); + + // Localized label for an extension type, used in the install dialog. + const extensionTypeLabel = (type: string) => + type === 'mcp' + ? t('market.typeMCP') + : type === 'skill' + ? t('market.typeSkill') + : t('market.typePlugin'); const { addTask, setSelectedTaskId, @@ -271,15 +279,26 @@ function AddExtensionContent() { useEffect(() => { const onComplete = (_taskId: number, success: boolean) => { if (success) { - toast.success(t('plugins.installSuccess')); + toast.success(t('addExtension.installSuccess')); + // Refresh every sidebar extension list so the newly-installed + // plugin / MCP / skill shows up immediately, regardless of type. refreshPlugins(); + refreshMCPServers(); + refreshSkills(); } }; registerOnTaskComplete(onComplete); return () => { unregisterOnTaskComplete(onComplete); }; - }, [registerOnTaskComplete, unregisterOnTaskComplete, refreshPlugins, t]); + }, [ + registerOnTaskComplete, + unregisterOnTaskComplete, + refreshPlugins, + refreshMCPServers, + refreshSkills, + t, + ]); const handleInstallPlugin = useCallback(async (plugin: PluginV4) => { setInstallInfo({ @@ -1189,22 +1208,50 @@ function AddExtensionContent() { - {t('plugins.installPlugin')} + + {t('addExtension.installTitle', { + type: extensionTypeLabel(installExtensionType), + })} + {pluginInstallStatus === PluginInstallStatus.ASK_CONFIRM && ( -
-

- {installInfo.plugin_version - ? t('plugins.askConfirm', { - name: installInfo.plugin_name, - version: installInfo.plugin_version, - }) - : t('plugins.askConfirmNoVersion', { - name: installInfo.plugin_name, - })} +

+

+ {t('addExtension.installConfirm', { + type: extensionTypeLabel(installExtensionType), + name: installInfo.plugin_name, + })}

+
+
+ + {t('addExtension.installInfoType')} + + + {extensionTypeLabel(installExtensionType)} + +
+
+ + {t('addExtension.installInfoId')} + + + {installInfo.plugin_author}/{installInfo.plugin_name} + +
+ {installInfo.plugin_version && ( +
+ + {t('addExtension.installInfoVersion')} + + + v{installInfo.plugin_version} + +
+ )} +
)} diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index ee58b4f3..faa503f8 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -1531,6 +1531,12 @@ const enUS = { }, }, addExtension: { + installTitle: 'Install {{type}}', + installConfirm: 'Install {{type}} "{{name}}"?', + installInfoType: 'Type', + installInfoId: 'ID', + installInfoVersion: 'Version', + installSuccess: 'Installed successfully', manualAdd: 'Manual Add', uploadExtension: 'Drag & drop or click to upload', uploadHint: 'Supports .zip (skills) and .lbpkg (plugins) files', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index ab7b87f5..6e2a7eb1 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -1467,6 +1467,12 @@ const zhHans = { }, }, addExtension: { + installTitle: '安装{{type}}', + installConfirm: '确定要安装{{type}} "{{name}}" 吗?', + installInfoType: '类型', + installInfoId: '标识', + installInfoVersion: '版本', + installSuccess: '安装成功', manualAdd: '手动添加', uploadExtension: '拖拽或点击上传扩展包', uploadHint: '支持 .zip(技能)和 .lbpkg(插件)文件',