mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 04:43:44 +08:00
feat: Support custom delay timeout (#397)
This commit is contained in:
parent
5106d77c77
commit
d1d9620a61
@ -249,8 +249,9 @@ pub mod uwp {
|
|||||||
pub async fn clash_api_get_proxy_delay(
|
pub async fn clash_api_get_proxy_delay(
|
||||||
name: String,
|
name: String,
|
||||||
url: Option<String>,
|
url: Option<String>,
|
||||||
|
timeout: i32,
|
||||||
) -> CmdResult<clash_api::DelayRes> {
|
) -> CmdResult<clash_api::DelayRes> {
|
||||||
match clash_api::get_proxy_delay(name, url).await {
|
match clash_api::get_proxy_delay(name, url, timeout).await {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(err) => Err(err.to_string()),
|
Err(err) => Err(err.to_string()),
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,9 @@ pub struct IVerge {
|
|||||||
/// 默认的延迟测试连接
|
/// 默认的延迟测试连接
|
||||||
pub default_latency_test: Option<String>,
|
pub default_latency_test: Option<String>,
|
||||||
|
|
||||||
|
/// 默认的延迟测试超时时间
|
||||||
|
pub default_latency_timeout: Option<i32>,
|
||||||
|
|
||||||
/// 是否使用内部的脚本支持,默认为真
|
/// 是否使用内部的脚本支持,默认为真
|
||||||
pub enable_builtin_enhanced: Option<bool>,
|
pub enable_builtin_enhanced: Option<bool>,
|
||||||
|
|
||||||
@ -222,6 +225,7 @@ impl IVerge {
|
|||||||
|
|
||||||
patch!(auto_close_connection);
|
patch!(auto_close_connection);
|
||||||
patch!(default_latency_test);
|
patch!(default_latency_test);
|
||||||
|
patch!(default_latency_timeout);
|
||||||
patch!(enable_builtin_enhanced);
|
patch!(enable_builtin_enhanced);
|
||||||
patch!(proxy_layout_column);
|
patch!(proxy_layout_column);
|
||||||
patch!(test_list);
|
patch!(test_list);
|
||||||
|
@ -44,7 +44,11 @@ pub struct DelayRes {
|
|||||||
|
|
||||||
/// GET /proxies/{name}/delay
|
/// GET /proxies/{name}/delay
|
||||||
/// 获取代理延迟
|
/// 获取代理延迟
|
||||||
pub async fn get_proxy_delay(name: String, test_url: Option<String>) -> Result<DelayRes> {
|
pub async fn get_proxy_delay(
|
||||||
|
name: String,
|
||||||
|
test_url: Option<String>,
|
||||||
|
timeout: i32,
|
||||||
|
) -> Result<DelayRes> {
|
||||||
let (url, headers) = clash_client_info()?;
|
let (url, headers) = clash_client_info()?;
|
||||||
let url = format!("{url}/proxies/{name}/delay");
|
let url = format!("{url}/proxies/{name}/delay");
|
||||||
|
|
||||||
@ -57,7 +61,7 @@ pub async fn get_proxy_delay(name: String, test_url: Option<String>) -> Result<D
|
|||||||
let builder = client
|
let builder = client
|
||||||
.get(&url)
|
.get(&url)
|
||||||
.headers(headers)
|
.headers(headers)
|
||||||
.query(&[("timeout", "10000"), ("url", &test_url)]);
|
.query(&[("timeout", &format!("{timeout}")), ("url", &test_url)]);
|
||||||
let response = builder.send().await?;
|
let response = builder.send().await?;
|
||||||
|
|
||||||
Ok(response.json::<DelayRes>().await?)
|
Ok(response.json::<DelayRes>().await?)
|
||||||
|
@ -25,6 +25,7 @@ export const ProxyGroups = (props: Props) => {
|
|||||||
|
|
||||||
const { verge } = useVerge();
|
const { verge } = useVerge();
|
||||||
const { current, patchCurrent } = useProfiles();
|
const { current, patchCurrent } = useProfiles();
|
||||||
|
const timeout = verge?.default_latency_timeout || 10000;
|
||||||
|
|
||||||
const virtuosoRef = useRef<VirtuosoHandle>(null);
|
const virtuosoRef = useRef<VirtuosoHandle>(null);
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ export const ProxyGroups = (props: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const names = proxies.filter((p) => !p!.provider).map((p) => p!.name);
|
const names = proxies.filter((p) => !p!.provider).map((p) => p!.name);
|
||||||
await delayManager.checkListDelay(names, groupName);
|
await delayManager.checkListDelay(names, groupName, timeout);
|
||||||
|
|
||||||
onProxies();
|
onProxies();
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,7 @@ import { CheckCircleOutlineRounded } from "@mui/icons-material";
|
|||||||
import { alpha, Box, ListItemButton, styled, Typography } from "@mui/material";
|
import { alpha, Box, ListItemButton, styled, Typography } from "@mui/material";
|
||||||
import { BaseLoading } from "@/components/base";
|
import { BaseLoading } from "@/components/base";
|
||||||
import delayManager from "@/services/delay";
|
import delayManager from "@/services/delay";
|
||||||
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
groupName: string;
|
groupName: string;
|
||||||
@ -20,6 +21,8 @@ export const ProxyItemMini = (props: Props) => {
|
|||||||
// -1/<=0 为 不显示
|
// -1/<=0 为 不显示
|
||||||
// -2 为 loading
|
// -2 为 loading
|
||||||
const [delay, setDelay] = useState(-1);
|
const [delay, setDelay] = useState(-1);
|
||||||
|
const { verge } = useVerge();
|
||||||
|
const timeout = verge?.default_latency_timeout || 10000;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
delayManager.setListener(proxy.name, groupName, setDelay);
|
delayManager.setListener(proxy.name, groupName, setDelay);
|
||||||
@ -36,7 +39,7 @@ export const ProxyItemMini = (props: Props) => {
|
|||||||
|
|
||||||
const onDelay = useLockFn(async () => {
|
const onDelay = useLockFn(async () => {
|
||||||
setDelay(-2);
|
setDelay(-2);
|
||||||
setDelay(await delayManager.checkDelay(proxy.name, groupName));
|
setDelay(await delayManager.checkDelay(proxy.name, groupName, timeout));
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -139,14 +142,14 @@ export const ProxyItemMini = (props: Props) => {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onDelay();
|
onDelay();
|
||||||
}}
|
}}
|
||||||
color={delayManager.formatDelayColor(delay)}
|
color={delayManager.formatDelayColor(delay, timeout)}
|
||||||
sx={({ palette }) =>
|
sx={({ palette }) =>
|
||||||
!proxy.provider
|
!proxy.provider
|
||||||
? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
|
? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{delayManager.formatDelay(delay)}
|
{delayManager.formatDelay(delay, timeout)}
|
||||||
</Widget>
|
</Widget>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { BaseLoading } from "@/components/base";
|
import { BaseLoading } from "@/components/base";
|
||||||
import delayManager from "@/services/delay";
|
import delayManager from "@/services/delay";
|
||||||
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
groupName: string;
|
groupName: string;
|
||||||
@ -48,7 +49,8 @@ export const ProxyItem = (props: Props) => {
|
|||||||
// -1/<=0 为 不显示
|
// -1/<=0 为 不显示
|
||||||
// -2 为 loading
|
// -2 为 loading
|
||||||
const [delay, setDelay] = useState(-1);
|
const [delay, setDelay] = useState(-1);
|
||||||
|
const { verge } = useVerge();
|
||||||
|
const timeout = verge?.default_latency_timeout || 10000;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
delayManager.setListener(proxy.name, groupName, setDelay);
|
delayManager.setListener(proxy.name, groupName, setDelay);
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ export const ProxyItem = (props: Props) => {
|
|||||||
|
|
||||||
const onDelay = useLockFn(async () => {
|
const onDelay = useLockFn(async () => {
|
||||||
setDelay(-2);
|
setDelay(-2);
|
||||||
setDelay(await delayManager.checkDelay(proxy.name, groupName));
|
setDelay(await delayManager.checkDelay(proxy.name, groupName, timeout));
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -149,14 +151,14 @@ export const ProxyItem = (props: Props) => {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onDelay();
|
onDelay();
|
||||||
}}
|
}}
|
||||||
color={delayManager.formatDelayColor(delay)}
|
color={delayManager.formatDelayColor(delay, timeout)}
|
||||||
sx={({ palette }) =>
|
sx={({ palette }) =>
|
||||||
!proxy.provider
|
!proxy.provider
|
||||||
? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
|
? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{delayManager.formatDelay(delay)}
|
{delayManager.formatDelay(delay, timeout)}
|
||||||
</Widget>
|
</Widget>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
proxyLayoutColumn: 6,
|
proxyLayoutColumn: 6,
|
||||||
defaultLatencyTest: "",
|
defaultLatencyTest: "",
|
||||||
autoLogClean: 0,
|
autoLogClean: 0,
|
||||||
|
defaultLatencyTimeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@ -37,6 +38,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
proxyLayoutColumn: verge?.proxy_layout_column || 6,
|
proxyLayoutColumn: verge?.proxy_layout_column || 6,
|
||||||
defaultLatencyTest: verge?.default_latency_test || "",
|
defaultLatencyTest: verge?.default_latency_test || "",
|
||||||
autoLogClean: verge?.auto_log_clean || 0,
|
autoLogClean: verge?.auto_log_clean || 0,
|
||||||
|
defaultLatencyTimeout: verge?.default_latency_timeout || 10000,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
close: () => setOpen(false),
|
close: () => setOpen(false),
|
||||||
@ -50,6 +52,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
enable_builtin_enhanced: values.enableBuiltinEnhanced,
|
enable_builtin_enhanced: values.enableBuiltinEnhanced,
|
||||||
proxy_layout_column: values.proxyLayoutColumn,
|
proxy_layout_column: values.proxyLayoutColumn,
|
||||||
default_latency_test: values.defaultLatencyTest,
|
default_latency_test: values.defaultLatencyTest,
|
||||||
|
default_latency_timeout: values.defaultLatencyTimeout,
|
||||||
auto_log_clean: values.autoLogClean as any,
|
auto_log_clean: values.autoLogClean as any,
|
||||||
});
|
});
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
@ -179,6 +182,27 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
|
<ListItemText primary={t("Default Latency Timeout")} />
|
||||||
|
<TextField
|
||||||
|
size="small"
|
||||||
|
type="number"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
sx={{ width: 250 }}
|
||||||
|
value={values.defaultLatencyTimeout}
|
||||||
|
placeholder="http://1.1.1.1"
|
||||||
|
onChange={(e) =>
|
||||||
|
setValues((v) => ({
|
||||||
|
...v,
|
||||||
|
defaultLatencyTimeout: parseInt(e.target.value),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
|
@ -152,6 +152,7 @@
|
|||||||
"Enable Builtin Enhanced": "Enable Builtin Enhanced",
|
"Enable Builtin Enhanced": "Enable Builtin Enhanced",
|
||||||
"Proxy Layout Column": "Proxy Layout Column",
|
"Proxy Layout Column": "Proxy Layout Column",
|
||||||
"Default Latency Test": "Default Latency Test",
|
"Default Latency Test": "Default Latency Test",
|
||||||
|
"Defaule Latency Timeout": "Defaule Latency Timeout",
|
||||||
|
|
||||||
"Auto Log Clean": "Auto Log Clean",
|
"Auto Log Clean": "Auto Log Clean",
|
||||||
"Never Clean": "Never Clean",
|
"Never Clean": "Never Clean",
|
||||||
|
@ -152,6 +152,7 @@
|
|||||||
"Enable Builtin Enhanced": "开启内建增强功能",
|
"Enable Builtin Enhanced": "开启内建增强功能",
|
||||||
"Proxy Layout Column": "代理页布局列数",
|
"Proxy Layout Column": "代理页布局列数",
|
||||||
"Default Latency Test": "默认测试链接",
|
"Default Latency Test": "默认测试链接",
|
||||||
|
"Default Latency Timeout": "测试超时时间",
|
||||||
|
|
||||||
"Auto Log Clean": "自动清理日志",
|
"Auto Log Clean": "自动清理日志",
|
||||||
"Never Clean": "不清理",
|
"Never Clean": "不清理",
|
||||||
|
@ -160,9 +160,17 @@ export async function openWebUrl(url: string) {
|
|||||||
return invoke<void>("open_web_url", { url });
|
return invoke<void>("open_web_url", { url });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cmdGetProxyDelay(name: string, url?: string) {
|
export async function cmdGetProxyDelay(
|
||||||
|
name: string,
|
||||||
|
timeout: number,
|
||||||
|
url?: string
|
||||||
|
) {
|
||||||
name = encodeURIComponent(name);
|
name = encodeURIComponent(name);
|
||||||
return invoke<{ delay: number }>("clash_api_get_proxy_delay", { name, url });
|
return invoke<{ delay: number }>("clash_api_get_proxy_delay", {
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
timeout,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cmdTestDelay(url: string) {
|
export async function cmdTestDelay(url: string) {
|
||||||
|
@ -69,12 +69,12 @@ class DelayManager {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkDelay(name: string, group: string) {
|
async checkDelay(name: string, group: string, timeout: number) {
|
||||||
let delay = -1;
|
let delay = -1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = this.getUrl(group);
|
const url = this.getUrl(group);
|
||||||
const result = await cmdGetProxyDelay(name, url);
|
const result = await cmdGetProxyDelay(name, timeout, url);
|
||||||
delay = result.delay;
|
delay = result.delay;
|
||||||
} catch {
|
} catch {
|
||||||
delay = 1e6; // error
|
delay = 1e6; // error
|
||||||
@ -84,7 +84,12 @@ class DelayManager {
|
|||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkListDelay(nameList: string[], group: string, concurrency = 36) {
|
async checkListDelay(
|
||||||
|
nameList: string[],
|
||||||
|
group: string,
|
||||||
|
timeout: number,
|
||||||
|
concurrency = 36
|
||||||
|
) {
|
||||||
const names = nameList.filter(Boolean);
|
const names = nameList.filter(Boolean);
|
||||||
// 设置正在延迟测试中
|
// 设置正在延迟测试中
|
||||||
names.forEach((name) => this.setDelay(name, group, -2));
|
names.forEach((name) => this.setDelay(name, group, -2));
|
||||||
@ -98,7 +103,7 @@ class DelayManager {
|
|||||||
const task = names.shift();
|
const task = names.shift();
|
||||||
if (!task) return;
|
if (!task) return;
|
||||||
current += 1;
|
current += 1;
|
||||||
await this.checkDelay(task, group);
|
await this.checkDelay(task, group, timeout);
|
||||||
current -= 1;
|
current -= 1;
|
||||||
total -= 1;
|
total -= 1;
|
||||||
if (total <= 0) resolve(null);
|
if (total <= 0) resolve(null);
|
||||||
@ -108,15 +113,15 @@ class DelayManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formatDelay(delay: number) {
|
formatDelay(delay: number, timeout = 10000) {
|
||||||
if (delay <= 0) return "Error";
|
if (delay <= 0) return "Error";
|
||||||
if (delay > 1e5) return "Error";
|
if (delay > 1e5) return "Error";
|
||||||
if (delay >= 10000) return "Timeout"; // 10s
|
if (delay >= timeout) return "Timeout"; // 10s
|
||||||
return `${delay}`;
|
return `${delay}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatDelayColor(delay: number) {
|
formatDelayColor(delay: number, timeout = 10000) {
|
||||||
if (delay >= 10000) return "error.main";
|
if (delay >= timeout) return "error.main";
|
||||||
if (delay <= 0) return "error.main";
|
if (delay <= 0) return "error.main";
|
||||||
if (delay > 500) return "warning.main";
|
if (delay > 500) return "warning.main";
|
||||||
return "success.main";
|
return "success.main";
|
||||||
|
1
src/services/types.d.ts
vendored
1
src/services/types.d.ts
vendored
@ -219,6 +219,7 @@ interface IVergeConfig {
|
|||||||
};
|
};
|
||||||
auto_close_connection?: boolean;
|
auto_close_connection?: boolean;
|
||||||
default_latency_test?: string;
|
default_latency_test?: string;
|
||||||
|
default_latency_timeout?: number;
|
||||||
enable_builtin_enhanced?: boolean;
|
enable_builtin_enhanced?: boolean;
|
||||||
auto_log_clean?: 0 | 1 | 2 | 3;
|
auto_log_clean?: 0 | 1 | 2 | 3;
|
||||||
proxy_layout_column?: number;
|
proxy_layout_column?: number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user