fix: prevent page crash when deleting an agent (#514)

This commit is contained in:
paisley
2026-03-16 10:47:30 +08:00
committed by GitHub
Unverified
parent 9e10c12f67
commit 158e84ce8f
5 changed files with 46 additions and 9 deletions

View File

@@ -2,7 +2,7 @@
* ConfirmDialog - In-DOM confirmation dialog (replaces window.confirm)
* Keeps focus within the renderer to avoid Windows focus loss after native dialogs.
*/
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
@@ -13,8 +13,9 @@ interface ConfirmDialogProps {
confirmLabel?: string;
cancelLabel?: string;
variant?: 'default' | 'destructive';
onConfirm: () => void;
onConfirm: () => void | Promise<void>;
onCancel: () => void;
onError?: (error: unknown) => void;
}
export function ConfirmDialog({
@@ -26,8 +27,19 @@ export function ConfirmDialog({
variant = 'default',
onConfirm,
onCancel,
onError,
}: ConfirmDialogProps) {
const cancelRef = useRef<HTMLButtonElement>(null);
const [confirming, setConfirming] = useState(false);
const [prevOpen, setPrevOpen] = useState(open);
// Reset confirming when dialog closes (during render to avoid setState-in-effect)
if (prevOpen !== open) {
setPrevOpen(open);
if (!open) {
setConfirming(false);
}
}
useEffect(() => {
if (open && cancelRef.current) {
@@ -38,12 +50,27 @@ export function ConfirmDialog({
if (!open) return null;
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Escape') {
if (e.key === 'Escape' && !confirming) {
e.preventDefault();
onCancel();
}
};
const handleConfirm = () => {
if (confirming) return;
const result = onConfirm();
if (result instanceof Promise) {
setConfirming(true);
result.catch((error) => {
if (onError) {
onError(error);
}
}).finally(() => {
setConfirming(false);
});
}
};
return (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
@@ -68,12 +95,14 @@ export function ConfirmDialog({
ref={cancelRef}
variant="outline"
onClick={onCancel}
disabled={confirming}
>
{cancelLabel}
</Button>
<Button
variant={variant === 'destructive' ? 'destructive' : 'default'}
onClick={onConfirm}
onClick={handleConfirm}
disabled={confirming}
>
{confirmLabel}
</Button>