fix: prevent page crash when deleting an agent (#514)
This commit is contained in:
committed by
GitHub
Unverified
parent
9e10c12f67
commit
158e84ce8f
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user