mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-04 23:53:45 +08:00
refactor: external toggle control logic & disable external-controller by default
This commit is contained in:
parent
d4a42f4ede
commit
d84b5456ff
@ -50,7 +50,6 @@ impl IClashTemp {
|
||||
map.insert("allow-lan".into(), false.into());
|
||||
map.insert("ipv6".into(), true.into());
|
||||
map.insert("mode".into(), "rule".into());
|
||||
map.insert("external-controller".into(), "127.0.0.1:9097".into());
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
map.insert("external-controller-unix".into(), "mihomo.sock".into());
|
||||
#[cfg(target_os = "windows")]
|
||||
@ -216,6 +215,10 @@ impl IClashTemp {
|
||||
Some(val_str) => {
|
||||
let val_str = val_str.trim();
|
||||
|
||||
if val_str.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let val = match val_str.starts_with(':') {
|
||||
true => format!("127.0.0.1{val_str}"),
|
||||
false => val_str.to_owned(),
|
||||
@ -227,11 +230,15 @@ impl IClashTemp {
|
||||
}
|
||||
None => None,
|
||||
})
|
||||
.unwrap_or("127.0.0.1:9097".into())
|
||||
.unwrap_or_else(|| String::new())
|
||||
}
|
||||
|
||||
pub fn guard_client_ctrl(config: &Mapping) -> String {
|
||||
let value = Self::guard_server_ctrl(config);
|
||||
if value.is_empty() {
|
||||
return value;
|
||||
}
|
||||
|
||||
match SocketAddr::from_str(value.as_str()) {
|
||||
Ok(mut socket) => {
|
||||
if socket.ip().is_unspecified() {
|
||||
@ -239,7 +246,7 @@ impl IClashTemp {
|
||||
}
|
||||
socket.to_string()
|
||||
}
|
||||
Err(_) => "127.0.0.1:9097".into(),
|
||||
Err(_) => String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,12 +285,12 @@ fn test_clash_info() {
|
||||
|
||||
assert_eq!(
|
||||
IClashTemp(IClashTemp::guard(Mapping::new())).get_client_info(),
|
||||
get_result(7897, "127.0.0.1:9097")
|
||||
get_result(7897, "")
|
||||
);
|
||||
|
||||
assert_eq!(get_case("", ""), get_result(7897, "127.0.0.1:9097"));
|
||||
assert_eq!(get_case("", ""), get_result(7897, ""));
|
||||
|
||||
assert_eq!(get_case(65537, ""), get_result(1, "127.0.0.1:9097"));
|
||||
assert_eq!(get_case(65537, ""), get_result(1, ""));
|
||||
|
||||
assert_eq!(
|
||||
get_case(8888, "127.0.0.1:8888"),
|
||||
@ -292,7 +299,7 @@ fn test_clash_info() {
|
||||
|
||||
assert_eq!(
|
||||
get_case(8888, " :98888 "),
|
||||
get_result(8888, "127.0.0.1:9097")
|
||||
get_result(8888, "")
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@ -317,7 +324,7 @@ fn test_clash_info() {
|
||||
|
||||
assert_eq!(
|
||||
get_case(8888, "192.168.1.1:80800"),
|
||||
get_result(8888, "127.0.0.1:9097")
|
||||
get_result(8888, "")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,9 @@ import { useLockFn } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { List, ListItem, ListItemText, TextField, Typography, Box } from "@mui/material";
|
||||
import { useClashInfo } from "@/hooks/use-clash";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useClash } from "@/hooks/use-clash";
|
||||
|
||||
export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
@ -12,43 +13,39 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
|
||||
const { clashInfo, patchInfo } = useClashInfo();
|
||||
const { verge, patchVerge } = useVerge();
|
||||
const { clash } = useClash();
|
||||
|
||||
const [controller, setController] = useState(clashInfo?.server || "");
|
||||
const [secret, setSecret] = useState(clashInfo?.secret || "");
|
||||
const [controller, setController] = useState("");
|
||||
const [secret, setSecret] = useState("");
|
||||
|
||||
// 获取外部控制器开关状态
|
||||
const [enableController, setEnableController] = useState(() => {
|
||||
const savedState = localStorage.getItem("enable_external_controller");
|
||||
if (savedState !== null) {
|
||||
return savedState === "true";
|
||||
}
|
||||
return verge?.enable_external_controller ?? true;
|
||||
});
|
||||
const enableController = Boolean(clash?.["external-controller"] && clash?.["external-controller"] !== "");
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: () => {
|
||||
setOpen(true);
|
||||
setController(clashInfo?.server || "");
|
||||
setSecret(clashInfo?.secret || "");
|
||||
// 从localStorage更新开关状态
|
||||
const savedState = localStorage.getItem("enable_external_controller");
|
||||
if (savedState !== null) {
|
||||
setEnableController(savedState === "true");
|
||||
} else {
|
||||
setEnableController(verge?.enable_external_controller ?? true);
|
||||
}
|
||||
setController(clash?.["external-controller"] || "");
|
||||
setSecret(clash?.secret || "");
|
||||
},
|
||||
close: () => setOpen(false),
|
||||
}));
|
||||
|
||||
const onSave = useLockFn(async () => {
|
||||
try {
|
||||
// 只有在启用外部控制器时才更新配置
|
||||
if (enableController) {
|
||||
await patchInfo({ "external-controller": controller, secret });
|
||||
}
|
||||
Notice.success(t("External Controller Settings Saved"), 1000);
|
||||
setOpen(false);
|
||||
const promises = [];
|
||||
promises.push(
|
||||
patchInfo({
|
||||
"external-controller": controller || "127.0.0.1:9097",
|
||||
secret
|
||||
})
|
||||
);
|
||||
|
||||
// 同步verge配置
|
||||
if (controller && controller !== "") {
|
||||
promises.push(patchVerge({ enable_external_controller: true }));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
Notice.success(t("External Controller Settings Saved"), 1000);
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString(), 4000);
|
||||
}
|
||||
@ -61,6 +58,7 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
contentSx={{ width: 400 }}
|
||||
okBtn={t("Save")}
|
||||
cancelBtn={t("Cancel")}
|
||||
disableOk={!enableController}
|
||||
onClose={() => setOpen(false)}
|
||||
onCancel={() => setOpen(false)}
|
||||
onOk={onSave}
|
||||
@ -81,7 +79,7 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
size="small"
|
||||
sx={{ width: 175 }}
|
||||
value={controller}
|
||||
placeholder="Required"
|
||||
placeholder="127.0.0.1:9097"
|
||||
onChange={(e) => setController(e.target.value)}
|
||||
disabled={!enableController}
|
||||
/>
|
||||
|
@ -44,6 +44,7 @@ const SettingClash = ({ onError }: Props) => {
|
||||
"log-level": logLevel,
|
||||
"unified-delay": unifiedDelay,
|
||||
dns,
|
||||
"external-controller": externalController
|
||||
} = clash ?? {};
|
||||
|
||||
const { enable_random_port = false, verge_mixed_port } = verge ?? {};
|
||||
@ -59,15 +60,6 @@ const SettingClash = ({ onError }: Props) => {
|
||||
return verge?.enable_dns_settings ?? false;
|
||||
});
|
||||
|
||||
// 添加外部控制器开关状态
|
||||
const [enableController, setEnableController] = useState(() => {
|
||||
const savedState = localStorage.getItem("enable_external_controller");
|
||||
if (savedState !== null) {
|
||||
return savedState === "true";
|
||||
}
|
||||
return verge?.enable_external_controller ?? true;
|
||||
});
|
||||
|
||||
const { addListener } = useListen();
|
||||
|
||||
const webRef = useRef<DialogRef>(null);
|
||||
@ -118,25 +110,14 @@ const SettingClash = ({ onError }: Props) => {
|
||||
}
|
||||
});
|
||||
|
||||
// 处理外部控制器开关状态变化
|
||||
const handleControllerToggle = useLockFn(async (enable: boolean) => {
|
||||
try {
|
||||
setEnableController(enable);
|
||||
localStorage.setItem("enable_external_controller", String(enable));
|
||||
await patchVerge({ enable_external_controller: enable });
|
||||
if (!enable) {
|
||||
await patchInfo({ "external-controller": "", secret: "" });
|
||||
} else {
|
||||
// 如果开启,恢复默认值或之前的值
|
||||
const server = clashInfo?.server || "127.0.0.1:9097";
|
||||
await patchInfo({ "external-controller": server, secret: clashInfo?.secret || "" });
|
||||
// 同步外部控制器配置和开关状态
|
||||
useEffect(() => {
|
||||
const hasController = Boolean(externalController && externalController !== "");
|
||||
const isEnabled = Boolean(verge?.enable_external_controller);
|
||||
if (hasController !== isEnabled) {
|
||||
patchVerge({ enable_external_controller: hasController });
|
||||
}
|
||||
} catch (err: any) {
|
||||
setEnableController(!enable);
|
||||
localStorage.setItem("enable_external_controller", String(!enable));
|
||||
Notice.error(err.message || err.toString());
|
||||
}
|
||||
});
|
||||
}, [externalController, verge?.enable_external_controller]);
|
||||
|
||||
return (
|
||||
<SettingList title={t("Clash Setting")}>
|
||||
@ -286,26 +267,49 @@ const SettingClash = ({ onError }: Props) => {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Switch
|
||||
edge="end"
|
||||
checked={enableController}
|
||||
onChange={(_, checked) => handleControllerToggle(checked)}
|
||||
/>
|
||||
<GuardState
|
||||
// 依据配置文件中是否有值来决定开关状态
|
||||
value={Boolean(externalController && externalController !== "")}
|
||||
valueProps="checked"
|
||||
onCatch={onError}
|
||||
onFormat={onSwitchFormat}
|
||||
onChange={(e) => {
|
||||
onChangeVerge({ enable_external_controller: e });
|
||||
onChangeData({
|
||||
"external-controller": e ? (externalController || "127.0.0.1:9097") : ""
|
||||
});
|
||||
}}
|
||||
onGuard={async (e) => {
|
||||
const promises = [
|
||||
patchVerge({ enable_external_controller: e })
|
||||
];
|
||||
|
||||
if (!e) {
|
||||
// 如果禁用,清空配置
|
||||
promises.push(patchClash({ "external-controller": "" }));
|
||||
} else if (!externalController || externalController === "") {
|
||||
promises.push(patchClash({ "external-controller": "127.0.0.1:9097" }));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}}
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem
|
||||
onClick={enableController ? () => webRef.current?.open() : undefined}
|
||||
onClick={(externalController && externalController !== "") ? () => webRef.current?.open() : undefined}
|
||||
label={
|
||||
<Typography
|
||||
component="span"
|
||||
color={!enableController ? "text.disabled" : "text.primary"}
|
||||
color={(!externalController || externalController === "") ? "text.disabled" : "text.primary"}
|
||||
sx={{ fontSize: "inherit" }}
|
||||
>
|
||||
{t("Web UI")}
|
||||
</Typography>
|
||||
}
|
||||
extra={
|
||||
!enableController && (
|
||||
(!externalController || externalController === "") && (
|
||||
<TooltipIcon
|
||||
title={t("Web UI info")}
|
||||
sx={{ opacity: "0.7" }}
|
||||
|
Loading…
x
Reference in New Issue
Block a user