refactor(web): migrate remove-plugin dialog to base UI AlertDialog and improve UX

- Replace deprecated Confirm component with AlertDialog primitives
- Add forceRender backdrop for proper overlay rendering
- Add success Toast notification after plugin removal
- Update "View Detail" text to "View on Marketplace" (en/zh-Hans)
- Add i18n keys for delete success message
- Prune stale eslint suppression for header-modals
This commit is contained in:
yyh
2026-03-04 22:14:19 +08:00
parent 4d7a9bc798
commit 4d9fcbec57
5 changed files with 45 additions and 27 deletions

View File

@ -4,7 +4,15 @@ import type { FC } from 'react'
import type { PluginDetail } from '../../../types'
import type { ModalStates, VersionTarget } from '../hooks'
import { useTranslation } from 'react-i18next'
import Confirm from '@/app/components/base/confirm'
import {
AlertDialog,
AlertDialogActions,
AlertDialogCancelButton,
AlertDialogConfirmButton,
AlertDialogContent,
AlertDialogDescription,
AlertDialogTitle,
} from '@/app/components/base/ui/alert-dialog'
import PluginInfo from '@/app/components/plugins/plugin-page/plugin-info'
import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place'
import { useGetLanguage } from '@/context/i18n'
@ -50,7 +58,6 @@ const HeaderModals: FC<HeaderModalsProps> = ({
return (
<>
{/* Plugin Info Modal */}
{isShowPluginInfo && (
<PluginInfo
repository={isFromGitHub ? meta?.repo : ''}
@ -60,27 +67,35 @@ const HeaderModals: FC<HeaderModalsProps> = ({
/>
)}
{/* Delete Confirm Modal */}
{isShowDeleteConfirm && (
<Confirm
isShow
title={t(`${i18nPrefix}.delete`, { ns: 'plugin' })}
content={(
<div>
<AlertDialog
open={isShowDeleteConfirm}
onOpenChange={(open) => {
if (!open)
hideDeleteConfirm()
}}
>
<AlertDialogContent backdropProps={{ forceRender: true }}>
<div className="flex flex-col gap-2 px-6 pb-4 pt-6">
<AlertDialogTitle className="text-text-primary title-2xl-semi-bold">
{t(`${i18nPrefix}.delete`, { ns: 'plugin' })}
</AlertDialogTitle>
<AlertDialogDescription className="w-full whitespace-pre-wrap break-words text-text-tertiary system-md-regular">
{t(`${i18nPrefix}.deleteContentLeft`, { ns: 'plugin' })}
<span className="system-md-semibold">{label[locale]}</span>
<span className="text-text-secondary system-md-semibold">{label[locale]}</span>
{t(`${i18nPrefix}.deleteContentRight`, { ns: 'plugin' })}
<br />
</div>
)}
onCancel={hideDeleteConfirm}
onConfirm={onDelete}
isLoading={deleting}
isDisabled={deleting}
/>
)}
</AlertDialogDescription>
</div>
<AlertDialogActions>
<AlertDialogCancelButton disabled={deleting}>
{t('operation.cancel', { ns: 'common' })}
</AlertDialogCancelButton>
<AlertDialogConfirmButton loading={deleting} disabled={deleting} onClick={onDelete}>
{t('operation.confirm', { ns: 'common' })}
</AlertDialogConfirmButton>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
{/* Update from Marketplace Modal */}
{isShowUpdateModal && (
<UpdateFromMarketplace
pluginId={detail.plugin_id}

View File

@ -3,6 +3,7 @@
import type { PluginDetail } from '../../../types'
import type { ModalStates, VersionTarget } from './use-detail-header-state'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { trackEvent } from '@/app/components/base/amplitude'
import Toast from '@/app/components/base/toast'
import { useModalContext } from '@/context/modal-context'
@ -36,6 +37,7 @@ export const usePluginOperations = ({
isFromMarketplace,
onUpdate,
}: UsePluginOperationsParams): UsePluginOperationsReturn => {
const { t } = useTranslation()
const { checkForUpdates, fetchReleases } = useGitHubReleases()
const { setShowUpdatePluginModal } = useModalContext()
const { refreshModelProviders } = useProviderContext()
@ -114,6 +116,10 @@ export const usePluginOperations = ({
if (res.success) {
modalStates.hideDeleteConfirm()
Toast.notify({
type: 'success',
message: t('action.deleteSuccess', { ns: 'plugin' }),
})
onUpdate?.(true)
if (PluginCategoryEnum.model.includes(category))

View File

@ -5317,11 +5317,6 @@
"count": 1
}
},
"app/components/plugins/plugin-detail-panel/detail-header/components/header-modals.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"app/components/plugins/plugin-detail-panel/detail-header/components/plugin-source-badge.tsx": {
"no-restricted-imports": {
"count": 1

View File

@ -3,6 +3,7 @@
"action.delete": "Remove plugin",
"action.deleteContentLeft": "Would you like to remove ",
"action.deleteContentRight": " plugin?",
"action.deleteSuccess": "Plugin removed successfully",
"action.pluginInfo": "Plugin info",
"action.usedInApps": "This plugin is being used in {{num}} apps.",
"allCategories": "All Categories",
@ -114,7 +115,7 @@
"detailPanel.operation.install": "Install",
"detailPanel.operation.remove": "Remove",
"detailPanel.operation.update": "Update",
"detailPanel.operation.viewDetail": "View Detail",
"detailPanel.operation.viewDetail": "View on Marketplace",
"detailPanel.serviceOk": "Service OK",
"detailPanel.strategyNum": "{{num}} {{strategy}} INCLUDED",
"detailPanel.switchVersion": "Switch Version",

View File

@ -3,6 +3,7 @@
"action.delete": "移除插件",
"action.deleteContentLeft": "是否要移除 ",
"action.deleteContentRight": " 插件?",
"action.deleteSuccess": "插件移除成功",
"action.pluginInfo": "插件信息",
"action.usedInApps": "此插件正在 {{num}} 个应用中使用。",
"allCategories": "所有类别",
@ -114,7 +115,7 @@
"detailPanel.operation.install": "安装",
"detailPanel.operation.remove": "移除",
"detailPanel.operation.update": "更新",
"detailPanel.operation.viewDetail": "查看详情",
"detailPanel.operation.viewDetail": "在 Marketplace 查看",
"detailPanel.serviceOk": "服务正常",
"detailPanel.strategyNum": "包含 {{num}} 个 {{strategy}}",
"detailPanel.switchVersion": "切换版本",