Преглед изворни кода

feat: Support custom delay timeout (#397)

MystiPanda пре 1 година
родитељ
комит
8efa815eb9

+ 2 - 1
src-tauri/src/cmds.rs

@@ -249,8 +249,9 @@ pub mod uwp {
 pub async fn clash_api_get_proxy_delay(
     name: String,
     url: Option<String>,
+    timeout: i32,
 ) -> 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),
         Err(err) => Err(err.to_string()),
     }

+ 4 - 0
src-tauri/src/config/verge.rs

@@ -81,6 +81,9 @@ pub struct IVerge {
     /// 默认的延迟测试连接
     pub default_latency_test: Option<String>,
 
+    /// 默认的延迟测试超时时间
+    pub default_latency_timeout: Option<i32>,
+
     /// 是否使用内部的脚本支持,默认为真
     pub enable_builtin_enhanced: Option<bool>,
 
@@ -222,6 +225,7 @@ impl IVerge {
 
         patch!(auto_close_connection);
         patch!(default_latency_test);
+        patch!(default_latency_timeout);
         patch!(enable_builtin_enhanced);
         patch!(proxy_layout_column);
         patch!(test_list);

+ 6 - 2
src-tauri/src/core/clash_api.rs

@@ -44,7 +44,11 @@ pub struct DelayRes {
 
 /// 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 = 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
         .get(&url)
         .headers(headers)
-        .query(&[("timeout", "10000"), ("url", &test_url)]);
+        .query(&[("timeout", &format!("{timeout}")), ("url", &test_url)]);
     let response = builder.send().await?;
 
     Ok(response.json::<DelayRes>().await?)

+ 2 - 1
src/components/proxy/proxy-groups.tsx

@@ -25,6 +25,7 @@ export const ProxyGroups = (props: Props) => {
 
   const { verge } = useVerge();
   const { current, patchCurrent } = useProfiles();
+  const timeout = verge?.default_latency_timeout || 10000;
 
   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);
-    await delayManager.checkListDelay(names, groupName);
+    await delayManager.checkListDelay(names, groupName, timeout);
 
     onProxies();
   });

+ 6 - 3
src/components/proxy/proxy-item-mini.tsx

@@ -4,6 +4,7 @@ import { CheckCircleOutlineRounded } from "@mui/icons-material";
 import { alpha, Box, ListItemButton, styled, Typography } from "@mui/material";
 import { BaseLoading } from "@/components/base";
 import delayManager from "@/services/delay";
+import { useVerge } from "@/hooks/use-verge";
 
 interface Props {
   groupName: string;
@@ -20,6 +21,8 @@ export const ProxyItemMini = (props: Props) => {
   // -1/<=0 为 不显示
   // -2 为 loading
   const [delay, setDelay] = useState(-1);
+  const { verge } = useVerge();
+  const timeout = verge?.default_latency_timeout || 10000;
 
   useEffect(() => {
     delayManager.setListener(proxy.name, groupName, setDelay);
@@ -36,7 +39,7 @@ export const ProxyItemMini = (props: Props) => {
 
   const onDelay = useLockFn(async () => {
     setDelay(-2);
-    setDelay(await delayManager.checkDelay(proxy.name, groupName));
+    setDelay(await delayManager.checkDelay(proxy.name, groupName, timeout));
   });
 
   return (
@@ -139,14 +142,14 @@ export const ProxyItemMini = (props: Props) => {
               e.stopPropagation();
               onDelay();
             }}
-            color={delayManager.formatDelayColor(delay)}
+            color={delayManager.formatDelayColor(delay, timeout)}
             sx={({ palette }) =>
               !proxy.provider
                 ? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
                 : {}
             }
           >
-            {delayManager.formatDelay(delay)}
+            {delayManager.formatDelay(delay, timeout)}
           </Widget>
         )}
 

+ 6 - 4
src/components/proxy/proxy-item.tsx

@@ -14,6 +14,7 @@ import {
 } from "@mui/material";
 import { BaseLoading } from "@/components/base";
 import delayManager from "@/services/delay";
+import { useVerge } from "@/hooks/use-verge";
 
 interface Props {
   groupName: string;
@@ -48,7 +49,8 @@ export const ProxyItem = (props: Props) => {
   // -1/<=0 为 不显示
   // -2 为 loading
   const [delay, setDelay] = useState(-1);
-
+  const { verge } = useVerge();
+  const timeout = verge?.default_latency_timeout || 10000;
   useEffect(() => {
     delayManager.setListener(proxy.name, groupName, setDelay);
 
@@ -64,7 +66,7 @@ export const ProxyItem = (props: Props) => {
 
   const onDelay = useLockFn(async () => {
     setDelay(-2);
-    setDelay(await delayManager.checkDelay(proxy.name, groupName));
+    setDelay(await delayManager.checkDelay(proxy.name, groupName, timeout));
   });
 
   return (
@@ -149,14 +151,14 @@ export const ProxyItem = (props: Props) => {
                 e.stopPropagation();
                 onDelay();
               }}
-              color={delayManager.formatDelayColor(delay)}
+              color={delayManager.formatDelayColor(delay, timeout)}
               sx={({ palette }) =>
                 !proxy.provider
                   ? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
                   : {}
               }
             >
-              {delayManager.formatDelay(delay)}
+              {delayManager.formatDelay(delay, timeout)}
             </Widget>
           )}
 

+ 24 - 0
src/components/setting/mods/misc-viewer.tsx

@@ -25,6 +25,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
     proxyLayoutColumn: 6,
     defaultLatencyTest: "",
     autoLogClean: 0,
+    defaultLatencyTimeout: 10000,
   });
 
   useImperativeHandle(ref, () => ({
@@ -37,6 +38,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
         proxyLayoutColumn: verge?.proxy_layout_column || 6,
         defaultLatencyTest: verge?.default_latency_test || "",
         autoLogClean: verge?.auto_log_clean || 0,
+        defaultLatencyTimeout: verge?.default_latency_timeout || 10000,
       });
     },
     close: () => setOpen(false),
@@ -50,6 +52,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
         enable_builtin_enhanced: values.enableBuiltinEnhanced,
         proxy_layout_column: values.proxyLayoutColumn,
         default_latency_test: values.defaultLatencyTest,
+        default_latency_timeout: values.defaultLatencyTimeout,
         auto_log_clean: values.autoLogClean as any,
       });
       setOpen(false);
@@ -179,6 +182,27 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
             }
           />
         </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>
     </BaseDialog>
   );

+ 1 - 0
src/locales/en.json

@@ -152,6 +152,7 @@
   "Enable Builtin Enhanced": "Enable Builtin Enhanced",
   "Proxy Layout Column": "Proxy Layout Column",
   "Default Latency Test": "Default Latency Test",
+  "Defaule Latency Timeout": "Defaule Latency Timeout",
 
   "Auto Log Clean": "Auto Log Clean",
   "Never Clean": "Never Clean",

+ 1 - 0
src/locales/zh.json

@@ -152,6 +152,7 @@
   "Enable Builtin Enhanced": "开启内建增强功能",
   "Proxy Layout Column": "代理页布局列数",
   "Default Latency Test": "默认测试链接",
+  "Default Latency Timeout": "测试超时时间",
 
   "Auto Log Clean": "自动清理日志",
   "Never Clean": "不清理",

+ 10 - 2
src/services/cmds.ts

@@ -160,9 +160,17 @@ export async function openWebUrl(url: string) {
   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);
-  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) {

+ 13 - 8
src/services/delay.ts

@@ -69,12 +69,12 @@ class DelayManager {
     return -1;
   }
 
-  async checkDelay(name: string, group: string) {
+  async checkDelay(name: string, group: string, timeout: number) {
     let delay = -1;
 
     try {
       const url = this.getUrl(group);
-      const result = await cmdGetProxyDelay(name, url);
+      const result = await cmdGetProxyDelay(name, timeout, url);
       delay = result.delay;
     } catch {
       delay = 1e6; // error
@@ -84,7 +84,12 @@ class DelayManager {
     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);
     // 设置正在延迟测试中
     names.forEach((name) => this.setDelay(name, group, -2));
@@ -98,7 +103,7 @@ class DelayManager {
         const task = names.shift();
         if (!task) return;
         current += 1;
-        await this.checkDelay(task, group);
+        await this.checkDelay(task, group, timeout);
         current -= 1;
         total -= 1;
         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 > 1e5) return "Error";
-    if (delay >= 10000) return "Timeout"; // 10s
+    if (delay >= timeout) return "Timeout"; // 10s
     return `${delay}`;
   }
 
-  formatDelayColor(delay: number) {
-    if (delay >= 10000) return "error.main";
+  formatDelayColor(delay: number, timeout = 10000) {
+    if (delay >= timeout) return "error.main";
     if (delay <= 0) return "error.main";
     if (delay > 500) return "warning.main";
     return "success.main";

+ 1 - 0
src/services/types.d.ts

@@ -219,6 +219,7 @@ interface IVergeConfig {
   };
   auto_close_connection?: boolean;
   default_latency_test?: string;
+  default_latency_timeout?: number;
   enable_builtin_enhanced?: boolean;
   auto_log_clean?: 0 | 1 | 2 | 3;
   proxy_layout_column?: number;