mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-03-24 08:08:52 +08:00
feat: show failover toggle independently on main page with confirm dialog
Add enableFailoverToggle setting to control failover toggle visibility on the main page, decoupled from proxy takeover state. First-time enable shows a ConfirmDialog (same pattern as proxy toggle). The toggle row is placed in the Auto Failover accordion section in settings.
This commit is contained in:
@@ -199,6 +199,12 @@ pub struct AppSettings {
|
||||
/// User has confirmed the stream check first-run notice
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub stream_check_confirmed: Option<bool>,
|
||||
/// Whether to show the failover toggle independently on the main page
|
||||
#[serde(default)]
|
||||
pub enable_failover_toggle: bool,
|
||||
/// User has confirmed the failover toggle first-run notice
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub failover_confirmed: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub language: Option<String>,
|
||||
|
||||
@@ -286,6 +292,8 @@ impl Default for AppSettings {
|
||||
proxy_confirmed: None,
|
||||
usage_confirmed: None,
|
||||
stream_check_confirmed: None,
|
||||
enable_failover_toggle: false,
|
||||
failover_confirmed: None,
|
||||
language: None,
|
||||
visible_apps: None,
|
||||
claude_config_dir: None,
|
||||
|
||||
18
src/App.tsx
18
src/App.tsx
@@ -981,23 +981,17 @@ function App() {
|
||||
<div className="flex flex-1 min-w-0 items-center justify-end gap-1.5">
|
||||
{currentView === "providers" &&
|
||||
activeApp !== "opencode" &&
|
||||
activeApp !== "openclaw" &&
|
||||
settingsData?.enableLocalProxy && (
|
||||
activeApp !== "openclaw" && (
|
||||
<div
|
||||
className="flex shrink-0 items-center gap-1.5"
|
||||
style={{ WebkitAppRegion: "no-drag" } as any}
|
||||
>
|
||||
<ProxyToggle activeApp={activeApp} />
|
||||
<div
|
||||
className={cn(
|
||||
"transition-all duration-300 ease-in-out overflow-hidden",
|
||||
isCurrentAppTakeoverActive
|
||||
? "opacity-100 max-w-[100px] scale-100"
|
||||
: "opacity-0 max-w-0 scale-75 pointer-events-none",
|
||||
)}
|
||||
>
|
||||
{settingsData?.enableLocalProxy && (
|
||||
<ProxyToggle activeApp={activeApp} />
|
||||
)}
|
||||
{settingsData?.enableFailoverToggle && (
|
||||
<FailoverToggle activeApp={activeApp} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { Server, Activity, Zap, Globe } from "lucide-react";
|
||||
import { Server, Activity, Zap, Globe, ShieldAlert } from "lucide-react";
|
||||
import { motion } from "framer-motion";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
@@ -16,6 +16,7 @@ import { FailoverQueueManager } from "@/components/proxy/FailoverQueueManager";
|
||||
import { RectifierConfigPanel } from "@/components/settings/RectifierConfigPanel";
|
||||
import { GlobalProxySettings } from "@/components/settings/GlobalProxySettings";
|
||||
import { ConfirmDialog } from "@/components/ConfirmDialog";
|
||||
import { ToggleRow } from "@/components/ui/toggle-row";
|
||||
import { useProxyStatus } from "@/hooks/useProxyStatus";
|
||||
import type { SettingsFormState } from "@/hooks/useSettings";
|
||||
|
||||
@@ -30,6 +31,7 @@ export function ProxyTabContent({
|
||||
}: ProxyTabContentProps) {
|
||||
const { t } = useTranslation();
|
||||
const [showProxyConfirm, setShowProxyConfirm] = useState(false);
|
||||
const [showFailoverConfirm, setShowFailoverConfirm] = useState(false);
|
||||
|
||||
const {
|
||||
isRunning,
|
||||
@@ -62,6 +64,23 @@ export function ProxyTabContent({
|
||||
}
|
||||
};
|
||||
|
||||
const handleFailoverToggleChange = (checked: boolean) => {
|
||||
if (checked && !settings?.failoverConfirmed) {
|
||||
setShowFailoverConfirm(true);
|
||||
} else {
|
||||
void onAutoSave({ enableFailoverToggle: checked });
|
||||
}
|
||||
};
|
||||
|
||||
const handleFailoverConfirm = async () => {
|
||||
setShowFailoverConfirm(false);
|
||||
try {
|
||||
await onAutoSave({ failoverConfirmed: true, enableFailoverToggle: true });
|
||||
} catch (error) {
|
||||
console.error("Failover confirm failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
@@ -131,6 +150,16 @@ export function ProxyTabContent({
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="px-6 pb-6 pt-4 border-t border-border/50">
|
||||
<div className="space-y-6">
|
||||
<ToggleRow
|
||||
icon={<ShieldAlert className="h-4 w-4 text-orange-500" />}
|
||||
title={t("settings.advanced.proxy.enableFailoverToggle")}
|
||||
description={t(
|
||||
"settings.advanced.proxy.enableFailoverToggleDescription",
|
||||
)}
|
||||
checked={settings?.enableFailoverToggle ?? false}
|
||||
onCheckedChange={handleFailoverToggleChange}
|
||||
/>
|
||||
|
||||
{!isRunning && (
|
||||
<div className="p-4 rounded-lg bg-yellow-500/10 border border-yellow-500/20">
|
||||
<p className="text-sm text-yellow-600 dark:text-yellow-400">
|
||||
@@ -274,6 +303,16 @@ export function ProxyTabContent({
|
||||
onConfirm={() => void handleProxyConfirm()}
|
||||
onCancel={() => setShowProxyConfirm(false)}
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
isOpen={showFailoverConfirm}
|
||||
variant="info"
|
||||
title={t("confirm.failover.title")}
|
||||
message={t("confirm.failover.message")}
|
||||
confirmText={t("confirm.failover.confirm")}
|
||||
onConfirm={() => void handleFailoverConfirm()}
|
||||
onCancel={() => setShowFailoverConfirm(false)}
|
||||
/>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,11 @@
|
||||
"message": "Local proxy is an advanced feature. Please make sure you understand how it works before enabling.\n\nWe recommend consulting the relevant documentation or your provider for proper configuration.",
|
||||
"confirm": "I understand, enable"
|
||||
},
|
||||
"failover": {
|
||||
"title": "Enable Failover",
|
||||
"message": "Failover is an advanced feature. Please make sure you understand how it works before enabling.\n\nWe recommend configuring provider priorities in the failover queue first.",
|
||||
"confirm": "I understand, enable"
|
||||
},
|
||||
"usage": {
|
||||
"title": "Configure Usage Query",
|
||||
"message": "Usage query requires a custom script or API parameters. Please make sure you have obtained the necessary information from your provider.\n\nIf unsure how to configure, please consult your provider's documentation first.",
|
||||
@@ -222,6 +227,8 @@
|
||||
"description": "Control proxy service toggle, view status and port info",
|
||||
"enableFeature": "Show Proxy Toggle on Main Page",
|
||||
"enableFeatureDescription": "When enabled, the proxy and failover toggles will appear at the top of the main page",
|
||||
"enableFailoverToggle": "Show Failover Toggle on Main Page",
|
||||
"enableFailoverToggleDescription": "When enabled, the failover toggle will appear independently at the top of the main page",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped"
|
||||
},
|
||||
|
||||
@@ -190,6 +190,11 @@
|
||||
"message": "ローカルプロキシは上級機能です。有効にする前に、その仕組みを理解していることをご確認ください。\n\n適切な設定方法については、関連ドキュメントまたはプロバイダーにご相談ください。",
|
||||
"confirm": "理解しました、有効にする"
|
||||
},
|
||||
"failover": {
|
||||
"title": "フェイルオーバーの有効化",
|
||||
"message": "フェイルオーバーは上級機能です。有効にする前に、その仕組みを理解していることをご確認ください。\n\nフェイルオーバーキューでプロバイダーの優先順位を先に設定することをお勧めします。",
|
||||
"confirm": "理解しました、有効にする"
|
||||
},
|
||||
"usage": {
|
||||
"title": "使用量クエリの設定",
|
||||
"message": "使用量クエリにはカスタムスクリプトまたは API パラメータが必要です。プロバイダーから必要な情報を取得していることをご確認ください。\n\n設定方法が不明な場合は、プロバイダーのドキュメントを先にご確認ください。",
|
||||
@@ -222,6 +227,8 @@
|
||||
"description": "プロキシサービスの切り替え、ステータスとポート情報を表示",
|
||||
"enableFeature": "メインページにプロキシ切り替えを表示",
|
||||
"enableFeatureDescription": "有効にすると、メインページ上部にプロキシとフェイルオーバーの切り替えが表示されます",
|
||||
"enableFailoverToggle": "メインページにフェイルオーバー切り替えを表示",
|
||||
"enableFailoverToggleDescription": "有効にすると、メインページ上部にフェイルオーバー切り替えが独立して表示されます",
|
||||
"running": "実行中",
|
||||
"stopped": "停止中"
|
||||
},
|
||||
|
||||
@@ -190,6 +190,11 @@
|
||||
"message": "本地代理是一项高级功能,启用前请确保您已了解其工作原理。\n\n建议先查阅相关文档或咨询您的供应商,以获取正确的配置方式。",
|
||||
"confirm": "我已了解,继续启用"
|
||||
},
|
||||
"failover": {
|
||||
"title": "启用故障转移功能",
|
||||
"message": "故障转移是一项高级功能,启用前请确保您已了解其工作原理。\n\n建议先在故障转移队列中配置好供应商优先级。",
|
||||
"confirm": "我已了解,继续启用"
|
||||
},
|
||||
"usage": {
|
||||
"title": "配置用量查询",
|
||||
"message": "用量查询需要配置专用的查询脚本或 API 参数,请确保您已从供应商处获取相关信息。\n\n如不确定如何配置,请先查阅供应商文档。",
|
||||
@@ -222,6 +227,8 @@
|
||||
"description": "控制代理服务开关、查看状态与端口信息",
|
||||
"enableFeature": "在主页面显示本地代理开关",
|
||||
"enableFeatureDescription": "开启后,主页面顶部将显示代理和故障转移开关",
|
||||
"enableFailoverToggle": "在主页面显示故障转移开关",
|
||||
"enableFailoverToggleDescription": "开启后,主页面顶部将独立显示故障转移开关",
|
||||
"running": "运行中",
|
||||
"stopped": "已停止"
|
||||
},
|
||||
|
||||
@@ -233,6 +233,10 @@ export interface Settings {
|
||||
usageConfirmed?: boolean;
|
||||
// User has confirmed the stream check first-run notice
|
||||
streamCheckConfirmed?: boolean;
|
||||
// Whether to show the failover toggle independently on the main page
|
||||
enableFailoverToggle?: boolean;
|
||||
// User has confirmed the failover toggle first-run notice
|
||||
failoverConfirmed?: boolean;
|
||||
// User has confirmed the auto-sync traffic warning
|
||||
autoSyncConfirmed?: boolean;
|
||||
// 首选语言(可选,默认中文)
|
||||
|
||||
Reference in New Issue
Block a user