feat(settings): add first-run confirmation dialogs for proxy and usage features

Prevent accidental activation of advanced features by showing a one-time
info dialog. Once confirmed, the flag is persisted in settings.json and
the dialog never appears again.

- Proxy: confirmation when toggling proxy server ON for the first time
- Usage: confirmation when enabling usage query inside UsageScriptModal
- Enhanced ConfirmDialog with "info" variant (blue icon + default button)
- Added i18n translations for zh, en, ja
This commit is contained in:
Jason
2026-02-21 21:27:26 +08:00
parent 6b4ba64bbd
commit 5ebc879f09
8 changed files with 119 additions and 10 deletions
+12 -3
View File
@@ -7,7 +7,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { AlertTriangle } from "lucide-react";
import { AlertTriangle, Info } from "lucide-react";
import { useTranslation } from "react-i18next";
interface ConfirmDialogProps {
@@ -16,6 +16,7 @@ interface ConfirmDialogProps {
message: string;
confirmText?: string;
cancelText?: string;
variant?: "destructive" | "info";
onConfirm: () => void;
onCancel: () => void;
}
@@ -26,11 +27,16 @@ export function ConfirmDialog({
message,
confirmText,
cancelText,
variant = "destructive",
onConfirm,
onCancel,
}: ConfirmDialogProps) {
const { t } = useTranslation();
const IconComponent = variant === "info" ? Info : AlertTriangle;
const iconClass =
variant === "info" ? "h-5 w-5 text-blue-500" : "h-5 w-5 text-destructive";
return (
<Dialog
open={isOpen}
@@ -43,7 +49,7 @@ export function ConfirmDialog({
<DialogContent className="max-w-sm" zIndex="alert">
<DialogHeader className="space-y-3 border-b-0 bg-transparent pb-0">
<DialogTitle className="flex items-center gap-2 text-lg font-semibold">
<AlertTriangle className="h-5 w-5 text-destructive" />
<IconComponent className={iconClass} />
{title}
</DialogTitle>
<DialogDescription className="whitespace-pre-line text-sm leading-relaxed">
@@ -54,7 +60,10 @@ export function ConfirmDialog({
<Button variant="outline" onClick={onCancel}>
{cancelText || t("common.cancel")}
</Button>
<Button variant="destructive" onClick={onConfirm}>
<Button
variant={variant === "info" ? "default" : "destructive"}
onClick={onConfirm}
>
{confirmText || t("common.confirm")}
</Button>
</DialogFooter>