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))