From 244d5060580dc2ebbea3f3f3ea9377157f8cf468 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 8 May 2026 15:10:44 +0800 Subject: [PATCH] fix(web): confirm app deletion with enter key --- .../components/apps/__tests__/app-card.spec.tsx | 16 ++++++++++++++++ web/app/components/apps/app-card.tsx | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/web/app/components/apps/__tests__/app-card.spec.tsx b/web/app/components/apps/__tests__/app-card.spec.tsx index d61ca306ae..70f04cc152 100644 --- a/web/app/components/apps/__tests__/app-card.spec.tsx +++ b/web/app/components/apps/__tests__/app-card.spec.tsx @@ -725,6 +725,22 @@ describe('AppCard', () => { }) }) + it('should call deleteApp API when pressing Enter in the delete confirmation input', async () => { + render() + + fireEvent.click(screen.getByTestId('dropdown-menu-trigger')) + fireEvent.click(await screen.findByRole('menuitem', { name: 'common.operation.delete' })) + expect(await screen.findByRole('alertdialog')).toBeInTheDocument() + + const deleteInput = screen.getByRole('textbox') + fireEvent.change(deleteInput, { target: { value: mockApp.name } }) + fireEvent.keyDown(deleteInput, { key: 'Enter', code: 'Enter' }) + + await waitFor(() => { + expect(mockDeleteAppMutation).toHaveBeenCalled() + }) + }) + it('should not call onRefresh after successful delete', async () => { render() diff --git a/web/app/components/apps/app-card.tsx b/web/app/components/apps/app-card.tsx index f623f8ce53..31339fc110 100644 --- a/web/app/components/apps/app-card.tsx +++ b/web/app/components/apps/app-card.tsx @@ -250,14 +250,26 @@ const AppCard = ({ app, onlineUsers = [], onRefresh, onOpenTagManagement = () => const isDeleteConfirmDisabled = isDeleting || confirmDeleteInput !== app.name - const onDeleteDialogSubmit: React.FormEventHandler = useCallback((e) => { - e.preventDefault() + const submitDeleteConfirmation = useCallback(() => { if (isDeleteConfirmDisabled) return void onConfirmDelete() }, [isDeleteConfirmDisabled, onConfirmDelete]) + const onDeleteDialogSubmit: React.FormEventHandler = useCallback((e) => { + e.preventDefault() + submitDeleteConfirmation() + }, [submitDeleteConfirmation]) + + const onDeleteConfirmInputKeyDown: React.KeyboardEventHandler = useCallback((e) => { + if (e.key !== 'Enter' || e.nativeEvent.isComposing) + return + + e.preventDefault() + submitDeleteConfirmation() + }, [submitDeleteConfirmation]) + const handleShowEditModal = useCallback(() => { setIsOperationsMenuOpen(false) queueMicrotask(() => { @@ -652,6 +664,7 @@ const AppCard = ({ app, onlineUsers = [], onRefresh, onOpenTagManagement = () => placeholder={t('deleteAppConfirmInputPlaceholder', { ns: 'app' })} value={confirmDeleteInput} onChange={e => setConfirmDeleteInput(e.target.value)} + onKeyDown={onDeleteConfirmInputKeyDown} className="border-components-input-border-hover bg-components-input-bg-normal focus:border-components-input-border-active focus:bg-components-input-bg-active" />