Bläddra i källkod

refactor: Remove clash field filter

MystiPanda 1 år sedan
förälder
incheckning
e990530ada

+ 56 - 4
src-tauri/src/config/clash.rs

@@ -25,6 +25,8 @@ impl IClashTemp {
         let mut map = Mapping::new();
 
         map.insert("mixed-port".into(), 7897.into());
+        map.insert("socks-port".into(), 7898.into());
+        map.insert("port".into(), 7899.into());
         map.insert("log-level".into(), "info".into());
         map.insert("allow-lan".into(), false.into());
         map.insert("mode".into(), "rule".into());
@@ -35,10 +37,14 @@ impl IClashTemp {
     }
 
     fn guard(mut config: Mapping) -> Mapping {
-        let port = Self::guard_mixed_port(&config);
+        let mixed_port = Self::guard_mixed_port(&config);
+        let socks_port = Self::guard_socks_port(&config);
+        let port = Self::guard_port(&config);
         let ctrl = Self::guard_server_ctrl(&config);
 
-        config.insert("mixed-port".into(), port.into());
+        config.insert("mixed-port".into(), mixed_port.into());
+        config.insert("socks-port".into(), socks_port.into());
+        config.insert("port".into(), port.into());
         config.insert("external-controller".into(), ctrl.into());
         config
     }
@@ -61,11 +67,23 @@ impl IClashTemp {
         Self::guard_mixed_port(&self.0)
     }
 
+    #[allow(unused)]
+    pub fn get_socks_port(&self) -> u16 {
+        Self::guard_socks_port(&self.0)
+    }
+
+    #[allow(unused)]
+    pub fn get_port(&self) -> u16 {
+        Self::guard_port(&self.0)
+    }
+
     pub fn get_client_info(&self) -> ClashInfo {
         let config = &self.0;
 
         ClashInfo {
-            port: Self::guard_mixed_port(config),
+            mixed_port: Self::guard_mixed_port(config),
+            socks_port: Self::guard_socks_port(config),
+            port: Self::guard_port(config),
             server: Self::guard_client_ctrl(config),
             secret: config.get("secret").and_then(|value| match value {
                 Value::String(val_str) => Some(val_str.clone()),
@@ -91,6 +109,36 @@ impl IClashTemp {
         port
     }
 
+    pub fn guard_socks_port(config: &Mapping) -> u16 {
+        let mut port = config
+            .get("socks-port")
+            .and_then(|value| match value {
+                Value::String(val_str) => val_str.parse().ok(),
+                Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
+                _ => None,
+            })
+            .unwrap_or(7898);
+        if port == 0 {
+            port = 7898;
+        }
+        port
+    }
+
+    pub fn guard_port(config: &Mapping) -> u16 {
+        let mut port = config
+            .get("port")
+            .and_then(|value| match value {
+                Value::String(val_str) => val_str.parse().ok(),
+                Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
+                _ => None,
+            })
+            .unwrap_or(7899);
+        if port == 0 {
+            port = 7899;
+        }
+        port
+    }
+
     pub fn guard_server_ctrl(config: &Mapping) -> String {
         config
             .get("external-controller")
@@ -129,6 +177,8 @@ impl IClashTemp {
 #[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
 pub struct ClashInfo {
     /// clash core port
+    pub mixed_port: u16,
+    pub socks_port: u16,
     pub port: u16,
     /// same as `external-controller`
     pub server: String,
@@ -148,7 +198,9 @@ fn test_clash_info() {
 
     fn get_result<S: Into<String>>(port: u16, server: S) -> ClashInfo {
         ClashInfo {
-            port,
+            mixed_port: port,
+            socks_port: 7898,
+            port: 7899,
             server: server.into(),
             secret: None,
         }

+ 0 - 14
src-tauri/src/config/profiles.rs

@@ -14,9 +14,6 @@ pub struct IProfiles {
     /// same as PrfConfig.chain
     pub chain: Option<Vec<String>>,
 
-    /// record valid fields for clash
-    pub valid: Option<Vec<String>>,
-
     /// profile list
     pub items: Option<Vec<PrfItem>>,
 }
@@ -55,13 +52,6 @@ impl IProfiles {
 
     pub fn template() -> Self {
         Self {
-            valid: Some(vec![
-                "dns".into(),
-                "sub-rules".into(),
-                "unified-delay".into(),
-                "tcp-concurrent".into(),
-                "global-client-fingerprint".into(),
-            ]),
             items: Some(vec![]),
             ..Self::default()
         }
@@ -94,10 +84,6 @@ impl IProfiles {
             self.chain = Some(chain);
         }
 
-        if let Some(valid) = patch.valid {
-            self.valid = Some(valid);
-        }
-
         Ok(())
     }
 

+ 8 - 5
src-tauri/src/config/verge.rs

@@ -81,9 +81,6 @@ pub struct IVerge {
     /// 默认的延迟测试连接
     pub default_latency_test: Option<String>,
 
-    /// 支持关闭字段过滤,避免meta的新字段都被过滤掉,默认为关闭
-    pub enable_clash_fields: Option<bool>,
-
     /// 是否使用内部的脚本支持,默认为真
     pub enable_builtin_enhanced: Option<bool>,
 
@@ -106,6 +103,10 @@ pub struct IVerge {
 
     /// verge mixed port 用于覆盖 clash 的 mixed port
     pub verge_mixed_port: Option<u16>,
+
+    pub verge_socks_port: Option<u16>,
+
+    pub verge_port: Option<u16>,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
@@ -160,11 +161,12 @@ impl IVerge {
             enable_system_proxy: Some(false),
             enable_random_port: Some(false),
             verge_mixed_port: Some(7897),
+            verge_socks_port: Some(7898),
+            verge_port: Some(7899),
             enable_proxy_guard: Some(false),
             proxy_guard_duration: Some(30),
             auto_close_connection: Some(true),
             enable_builtin_enhanced: Some(true),
-            enable_clash_fields: Some(true),
             auto_log_clean: Some(3),
             ..Self::default()
         }
@@ -202,6 +204,8 @@ impl IVerge {
         patch!(enable_silent_start);
         patch!(enable_random_port);
         patch!(verge_mixed_port);
+        patch!(verge_socks_port);
+        patch!(verge_port);
         patch!(enable_system_proxy);
         patch!(enable_proxy_guard);
         patch!(system_proxy_bypass);
@@ -217,7 +221,6 @@ impl IVerge {
         patch!(enable_builtin_enhanced);
         patch!(proxy_layout_column);
         patch!(test_list);
-        patch!(enable_clash_fields);
         patch!(auto_log_clean);
         patch!(window_size_position);
     }

+ 30 - 93
src-tauri/src/enhance/field.rs

@@ -3,9 +3,9 @@ use std::collections::HashSet;
 
 pub const HANDLE_FIELDS: [&str; 9] = [
     "mode",
-    "port",
-    "socks-port",
     "mixed-port",
+    "socks-port",
+    "port",
     "allow-lan",
     "log-level",
     "ipv6",
@@ -15,71 +15,13 @@ pub const HANDLE_FIELDS: [&str; 9] = [
 
 pub const DEFAULT_FIELDS: [&str; 5] = [
     "proxies",
-    "proxy-groups",
     "proxy-providers",
-    "rules",
+    "proxy-groups",
     "rule-providers",
+    "rules",
 ];
 
-pub const OTHERS_FIELDS: [&str; 31] = [
-    "dns",
-    "tun",
-    "ebpf",
-    "hosts",
-    "script",
-    "profile",
-    "payload",
-    "tunnels",
-    "auto-redir",
-    "experimental",
-    "interface-name",
-    "routing-mark",
-    "redir-port",
-    "tproxy-port",
-    "iptables",
-    "external-ui",
-    "bind-address",
-    "authentication",
-    "tls",                       // meta
-    "sniffer",                   // meta
-    "geox-url",                  // meta
-    "listeners",                 // meta
-    "sub-rules",                 // meta
-    "geodata-mode",              // meta
-    "unified-delay",             // meta
-    "tcp-concurrent",            // meta
-    "enable-process",            // meta
-    "find-process-mode",         // meta
-    "skip-auth-prefixes",        // meta
-    "external-controller-tls",   // meta
-    "global-client-fingerprint", // meta
-];
-
-pub fn use_clash_fields() -> Vec<String> {
-    DEFAULT_FIELDS
-        .into_iter()
-        .chain(HANDLE_FIELDS)
-        .chain(OTHERS_FIELDS)
-        .map(|s| s.to_string())
-        .collect()
-}
-
-pub fn use_valid_fields(mut valid: Vec<String>) -> Vec<String> {
-    let others = Vec::from(OTHERS_FIELDS);
-
-    valid.iter_mut().for_each(|s| s.make_ascii_lowercase());
-    valid
-        .into_iter()
-        .filter(|s| others.contains(&s.as_str()))
-        .chain(DEFAULT_FIELDS.iter().map(|s| s.to_string()))
-        .collect()
-}
-
-pub fn use_filter(config: Mapping, filter: &Vec<String>, enable: bool) -> Mapping {
-    if !enable {
-        return config;
-    }
-
+pub fn use_filter(config: Mapping, filter: &Vec<String>) -> Mapping {
     let mut ret = Mapping::new();
 
     for (key, value) in config.into_iter() {
@@ -105,40 +47,35 @@ pub fn use_lowercase(config: Mapping) -> Mapping {
     ret
 }
 
-pub fn use_sort(config: Mapping, enable_filter: bool) -> Mapping {
+pub fn use_sort(config: Mapping) -> Mapping {
     let mut ret = Mapping::new();
+    HANDLE_FIELDS.into_iter().for_each(|key| {
+        let key = Value::from(key);
+        if let Some(value) = config.get(&key) {
+            ret.insert(key, value.clone());
+        }
+    });
 
-    HANDLE_FIELDS
-        .into_iter()
-        .chain(OTHERS_FIELDS)
-        .chain(DEFAULT_FIELDS)
-        .for_each(|key| {
-            let key = Value::from(key);
-            if let Some(value) = config.get(&key) {
-                ret.insert(key, value.clone());
-            }
-        });
-
-    if !enable_filter {
-        let supported_keys: HashSet<&str> = HANDLE_FIELDS
-            .into_iter()
-            .chain(OTHERS_FIELDS)
-            .chain(DEFAULT_FIELDS)
-            .collect();
+    let supported_keys: HashSet<&str> = HANDLE_FIELDS.into_iter().chain(DEFAULT_FIELDS).collect();
 
-        let config_keys: HashSet<&str> = config
-            .keys()
-            .filter_map(|e| e.as_str())
-            .into_iter()
-            .collect();
+    let config_keys: HashSet<&str> = config
+        .keys()
+        .filter_map(|e| e.as_str())
+        .into_iter()
+        .collect();
 
-        config_keys.difference(&supported_keys).for_each(|&key| {
-            let key = Value::from(key);
-            if let Some(value) = config.get(&key) {
-                ret.insert(key, value.clone());
-            }
-        });
-    }
+    config_keys.difference(&supported_keys).for_each(|&key| {
+        let key = Value::from(key);
+        if let Some(value) = config.get(&key) {
+            ret.insert(key, value.clone());
+        }
+    });
+    DEFAULT_FIELDS.into_iter().for_each(|key| {
+        let key = Value::from(key);
+        if let Some(value) = config.get(&key) {
+            ret.insert(key, value.clone());
+        }
+    });
 
     ret
 }

+ 1 - 1
src-tauri/src/enhance/merge.rs

@@ -19,7 +19,7 @@ pub fn use_merge(merge: Mapping, mut config: Mapping) -> Mapping {
         });
 
     let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string());
-    let merge = use_filter(merge, &merge_list.collect(), true);
+    let merge = use_filter(merge, &merge_list.collect());
 
     ["rules", "proxies", "proxy-groups"]
         .iter()

+ 6 - 17
src-tauri/src/enhance/mod.rs

@@ -22,19 +22,18 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
     // config.yaml 的订阅
     let clash_config = { Config::clash().latest().0.clone() };
 
-    let (clash_core, enable_tun, enable_builtin, enable_filter) = {
+    let (clash_core, enable_tun, enable_builtin) = {
         let verge = Config::verge();
         let verge = verge.latest();
         (
             verge.clash_core.clone(),
             verge.enable_tun_mode.unwrap_or(false),
             verge.enable_builtin_enhanced.unwrap_or(true),
-            verge.enable_clash_fields.unwrap_or(true),
         )
     };
 
     // 从profiles里拿东西
-    let (mut config, chain, valid) = {
+    let (mut config, chain) = {
         let profiles = Config::profiles();
         let profiles = profiles.latest();
 
@@ -49,23 +48,17 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
             None => vec![],
         };
 
-        let valid = profiles.valid.clone().unwrap_or_default();
-
-        (current, chain, valid)
+        (current, chain)
     };
 
     let mut result_map = HashMap::new(); // 保存脚本日志
     let mut exists_keys = use_keys(&config); // 保存出现过的keys
 
-    let valid = use_valid_fields(valid);
-    config = use_filter(config, &valid, enable_filter);
-
     // 处理用户的profile
     chain.into_iter().for_each(|item| match item.data {
         ChainType::Merge(merge) => {
             exists_keys.extend(use_keys(&merge));
             config = use_merge(merge, config.to_owned());
-            config = use_filter(config.to_owned(), &valid, enable_filter);
         }
         ChainType::Script(script) => {
             let mut logs = vec![];
@@ -73,7 +66,6 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
             match use_script(script, config.to_owned()) {
                 Ok((res_config, res_logs)) => {
                     exists_keys.extend(use_keys(&res_config));
-                    config = use_filter(res_config, &valid, enable_filter);
                     logs.extend(res_logs);
                 }
                 Err(err) => logs.push(("exception".into(), err.to_string())),
@@ -88,8 +80,6 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
         config.insert(key, value);
     }
 
-    let clash_fields = use_clash_fields();
-
     // 内建脚本最后跑
     if enable_builtin {
         ChainItem::builtin()
@@ -102,7 +92,7 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
                 match item.data {
                     ChainType::Script(script) => match use_script(script, config.to_owned()) {
                         Ok((res_config, _)) => {
-                            config = use_filter(res_config, &clash_fields, enable_filter);
+                            config = res_config;
                         }
                         Err(err) => {
                             log::error!(target: "app", "builtin script error `{err}`");
@@ -113,12 +103,11 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
             });
     }
 
-    config = use_filter(config, &clash_fields, enable_filter);
     config = use_tun(config, enable_tun);
-    config = use_sort(config, enable_filter);
+    config = use_sort(config);
 
     let mut exists_set = HashSet::new();
-    exists_set.extend(exists_keys.into_iter().filter(|s| clash_fields.contains(s)));
+    exists_set.extend(exists_keys.into_iter());
     exists_keys = exists_set.into_iter().collect();
 
     (config, exists_keys, result_map)

+ 4 - 0
src-tauri/src/feat.rs

@@ -162,6 +162,8 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
 
     match {
         let mixed_port = patch.get("mixed-port");
+        let socks_port = patch.get("socks-port");
+        let port = patch.get("port");
         let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
         if mixed_port.is_some() && !enable_random_port {
             let changed = mixed_port.unwrap()
@@ -182,6 +184,8 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
 
         // 激活订阅
         if mixed_port.is_some()
+            || socks_port.is_some()
+            || port.is_some()
             || patch.get("secret").is_some()
             || patch.get("external-controller").is_some()
         {

+ 0 - 123
src/components/setting/mods/clash-field-viewer.tsx

@@ -1,123 +0,0 @@
-import useSWR from "swr";
-import { forwardRef, useImperativeHandle, useState } from "react";
-import { useTranslation } from "react-i18next";
-import { Checkbox, Divider, Stack, Tooltip, Typography } from "@mui/material";
-import { InfoRounded } from "@mui/icons-material";
-import { getRuntimeExists } from "@/services/cmds";
-import {
-  HANDLE_FIELDS,
-  DEFAULT_FIELDS,
-  OTHERS_FIELDS,
-} from "@/utils/clash-fields";
-import { BaseDialog, DialogRef } from "@/components/base";
-import { useProfiles } from "@/hooks/use-profiles";
-import { Notice } from "@/components/base";
-
-const otherFields = [...OTHERS_FIELDS];
-const handleFields = [...HANDLE_FIELDS, ...DEFAULT_FIELDS];
-
-export const ClashFieldViewer = forwardRef<DialogRef>((props, ref) => {
-  const { t } = useTranslation();
-
-  const { profiles = {}, patchProfiles } = useProfiles();
-  const { data: existsKeys = [], mutate: mutateExists } = useSWR(
-    "getRuntimeExists",
-    getRuntimeExists
-  );
-
-  const [open, setOpen] = useState(false);
-  const [selected, setSelected] = useState<string[]>([]);
-
-  useImperativeHandle(ref, () => ({
-    open: () => {
-      mutateExists();
-      setSelected(profiles.valid || []);
-      setOpen(true);
-    },
-    close: () => setOpen(false),
-  }));
-
-  const handleChange = (item: string) => {
-    if (!item) return;
-
-    setSelected((old) =>
-      old.includes(item) ? old.filter((e) => e !== item) : [...old, item]
-    );
-  };
-
-  const handleSave = async () => {
-    setOpen(false);
-
-    const oldSet = new Set(profiles.valid || []);
-    const curSet = new Set(selected);
-    const joinSet = new Set(selected.concat([...oldSet]));
-
-    if (curSet.size === oldSet.size && curSet.size === joinSet.size) return;
-
-    try {
-      await patchProfiles({ valid: [...curSet] });
-      // Notice.success("Refresh clash config", 1000);
-    } catch (err: any) {
-      Notice.error(err?.message || err.toString());
-    }
-  };
-
-  return (
-    <BaseDialog
-      open={open}
-      title={t("Clash Field")}
-      contentSx={{
-        pb: 0,
-        width: 320,
-        height: 300,
-        overflowY: "auto",
-        userSelect: "text",
-      }}
-      okBtn={t("Save")}
-      cancelBtn={t("Back")}
-      onClose={() => setOpen(false)}
-      onCancel={() => setOpen(false)}
-      onOk={handleSave}
-    >
-      {otherFields.map((item) => {
-        const inSelect = selected.includes(item);
-        const inConfig = existsKeys.includes(item);
-
-        return (
-          <Stack key={item} mb={0.5} direction="row" alignItems="center">
-            <Checkbox
-              checked={inSelect}
-              size="small"
-              sx={{ p: 0.5 }}
-              onChange={() => handleChange(item)}
-            />
-            <Typography width="100%">{item}</Typography>
-
-            {!inSelect && inConfig && <WarnIcon />}
-          </Stack>
-        );
-      })}
-
-      <Divider sx={{ my: 1 }}>
-        <Typography color="text.secondary" fontSize={14}>
-          Clash Verge Control Fields
-        </Typography>
-      </Divider>
-
-      {handleFields.map((item) => (
-        <Stack key={item} mb={0.5} direction="row" alignItems="center">
-          <Checkbox defaultChecked disabled size="small" sx={{ p: 0.5 }} />
-          <Typography>{item}</Typography>
-        </Stack>
-      ))}
-    </BaseDialog>
-  );
-});
-
-function WarnIcon() {
-  return (
-    <Tooltip title="The field exists in the config but not enabled.">
-      <InfoRounded color="warning" sx={{ cursor: "pointer", opacity: 0.5 }} />
-    </Tooltip>
-  );
-}

+ 45 - 5
src/components/setting/mods/clash-port-viewer.tsx

@@ -13,26 +13,42 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
   const { verge, patchVerge } = useVerge();
 
   const [open, setOpen] = useState(false);
+  const [mixedPort, setMixedPort] = useState(
+    verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897
+  );
+  const [socksPort, setSocksPort] = useState(
+    verge?.verge_socks_port ?? clashInfo?.socks_port ?? 7898
+  );
   const [port, setPort] = useState(
-    verge?.verge_mixed_port ?? clashInfo?.port ?? 7897
+    verge?.verge_port ?? clashInfo?.port ?? 7899
   );
 
   useImperativeHandle(ref, () => ({
     open: () => {
-      if (verge?.verge_mixed_port) setPort(verge?.verge_mixed_port);
+      if (verge?.verge_mixed_port) setMixedPort(verge?.verge_mixed_port);
+      if (verge?.verge_socks_port) setSocksPort(verge?.verge_socks_port);
+      if (verge?.verge_port) setPort(verge?.verge_port);
       setOpen(true);
     },
     close: () => setOpen(false),
   }));
 
   const onSave = useLockFn(async () => {
-    if (port === verge?.verge_mixed_port) {
+    if (
+      mixedPort === verge?.verge_mixed_port &&
+      socksPort === verge?.verge_socks_port &&
+      port === verge?.verge_port
+    ) {
       setOpen(false);
       return;
     }
     try {
-      await patchInfo({ "mixed-port": port });
-      await patchVerge({ verge_mixed_port: port });
+      await patchInfo({ "mixed-port": mixedPort });
+      await patchInfo({ "socks-port": socksPort });
+      await patchInfo({ port });
+      await patchVerge({ verge_mixed_port: mixedPort });
+      await patchVerge({ verge_socks_port: socksPort });
+      await patchVerge({ verge_port: port });
       setOpen(false);
       Notice.success("Change Clash port successfully!", 1000);
     } catch (err: any) {
@@ -54,6 +70,30 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
       <List>
         <ListItem sx={{ padding: "5px 2px" }}>
           <ListItemText primary="Mixed Port" />
+          <TextField
+            size="small"
+            autoComplete="off"
+            sx={{ width: 135 }}
+            value={mixedPort}
+            onChange={(e) =>
+              setMixedPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
+            }
+          />
+        </ListItem>
+        <ListItem sx={{ padding: "5px 2px" }}>
+          <ListItemText primary="Socks Port" />
+          <TextField
+            size="small"
+            autoComplete="off"
+            sx={{ width: 135 }}
+            value={socksPort}
+            onChange={(e) =>
+              setSocksPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
+            }
+          />
+        </ListItem>
+        <ListItem sx={{ padding: "5px 2px" }}>
+          <ListItemText primary="Http Port" />
           <TextField
             size="small"
             autoComplete="off"

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

@@ -21,7 +21,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
   const [values, setValues] = useState({
     appLogLevel: "info",
     autoCloseConnection: true,
-    enableClashFields: true,
     enableBuiltinEnhanced: true,
     proxyLayoutColumn: 6,
     defaultLatencyTest: "",
@@ -34,7 +33,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
       setValues({
         appLogLevel: verge?.app_log_level ?? "info",
         autoCloseConnection: verge?.auto_close_connection ?? true,
-        enableClashFields: verge?.enable_clash_fields ?? true,
         enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
         proxyLayoutColumn: verge?.proxy_layout_column || 6,
         defaultLatencyTest: verge?.default_latency_test || "",
@@ -49,7 +47,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
       await patchVerge({
         app_log_level: values.appLogLevel,
         auto_close_connection: values.autoCloseConnection,
-        enable_clash_fields: values.enableClashFields,
         enable_builtin_enhanced: values.enableBuiltinEnhanced,
         proxy_layout_column: values.proxyLayoutColumn,
         default_latency_test: values.defaultLatencyTest,
@@ -105,17 +102,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
           />
         </ListItem>
 
-        <ListItem sx={{ padding: "5px 2px" }}>
-          <ListItemText primary={t("Enable Clash Fields Filter")} />
-          <Switch
-            edge="end"
-            checked={values.enableClashFields}
-            onChange={(_, c) =>
-              setValues((v) => ({ ...v, enableClashFields: c }))
-            }
-          />
-        </ListItem>
-
         <ListItem sx={{ padding: "5px 2px" }}>
           <ListItemText primary={t("Enable Builtin Enhanced")} />
           <Switch

+ 1 - 20
src/components/setting/setting-clash.tsx

@@ -15,7 +15,6 @@ import { DialogRef, Notice } from "@/components/base";
 import { useClash } from "@/hooks/use-clash";
 import { GuardState } from "./mods/guard-state";
 import { WebUIViewer } from "./mods/web-ui-viewer";
-import { ClashFieldViewer } from "./mods/clash-field-viewer";
 import { ClashPortViewer } from "./mods/clash-port-viewer";
 import { ControllerViewer } from "./mods/controller-viewer";
 import { SettingList, SettingItem } from "./mods/setting-comp";
@@ -39,11 +38,7 @@ const SettingClash = ({ onError }: Props) => {
 
   const { ipv6, "allow-lan": allowLan, "log-level": logLevel } = clash ?? {};
 
-  const {
-    enable_random_port = false,
-    verge_mixed_port,
-    enable_clash_fields = true,
-  } = verge ?? {};
+  const { enable_random_port = false, verge_mixed_port } = verge ?? {};
 
   const webRef = useRef<DialogRef>(null);
   const fieldRef = useRef<DialogRef>(null);
@@ -70,7 +65,6 @@ const SettingClash = ({ onError }: Props) => {
   return (
     <SettingList title={t("Clash Setting")}>
       <WebUIViewer ref={webRef} />
-      <ClashFieldViewer ref={fieldRef} />
       <ClashPortViewer ref={portRef} />
       <ControllerViewer ref={ctrlRef} />
       <ClashCoreViewer ref={coreRef} />
@@ -176,19 +170,6 @@ const SettingClash = ({ onError }: Props) => {
         </IconButton>
       </SettingItem>
 
-      {enable_clash_fields && (
-        <SettingItem label={t("Clash Field")}>
-          <IconButton
-            color="inherit"
-            size="small"
-            sx={{ my: "2px" }}
-            onClick={() => fieldRef.current?.open()}
-          >
-            <ArrowForward />
-          </IconButton>
-        </SettingItem>
-      )}
-
       <SettingItem
         label={t("Clash Core")}
         extra={

+ 26 - 1
src/hooks/use-clash.ts

@@ -48,11 +48,16 @@ export const useClashInfo = () => {
 
   const patchInfo = async (
     patch: Partial<
-      Pick<IConfigData, "mixed-port" | "external-controller" | "secret">
+      Pick<
+        IConfigData,
+        "port" | "socks-port" | "mixed-port" | "external-controller" | "secret"
+      >
     >
   ) => {
     const hasInfo =
       patch["mixed-port"] != null ||
+      patch["socks-port"] != null ||
+      patch["port"] != null ||
       patch["external-controller"] != null ||
       patch.secret != null;
 
@@ -68,6 +73,26 @@ export const useClashInfo = () => {
       }
     }
 
+    if (patch["socks-port"]) {
+      const port = patch["socks-port"];
+      if (port < 1000) {
+        throw new Error("The port should not < 1000");
+      }
+      if (port > 65536) {
+        throw new Error("The port should not > 65536");
+      }
+    }
+
+    if (patch["port"]) {
+      const port = patch["port"];
+      if (port < 1000) {
+        throw new Error("The port should not < 1000");
+      }
+      if (port > 65536) {
+        throw new Error("The port should not > 65536");
+      }
+    }
+
     await patchClashConfig(patch);
     mutateInfo();
     mutate("getClashConfig");

+ 5 - 2
src/services/types.d.ts

@@ -131,7 +131,9 @@ interface IConnections {
 
 interface IClashInfo {
   // status: string;
-  port?: number; // clash mixed port
+  mixed_port?: number; // clash mixed port
+  socks_port?: number; // clash socks port
+  port?: number; // clash http port
   server?: string; // external-controller
   secret?: string;
 }
@@ -196,6 +198,8 @@ interface IVergeConfig {
   enable_system_proxy?: boolean;
   enable_random_port?: boolean;
   verge_mixed_port?: number;
+  verge_socks_port?: number;
+  verge_port?: number;
   enable_proxy_guard?: boolean;
   proxy_guard_duration?: number;
   system_proxy_bypass?: string;
@@ -215,7 +219,6 @@ interface IVergeConfig {
   };
   auto_close_connection?: boolean;
   default_latency_test?: string;
-  enable_clash_fields?: boolean;
   enable_builtin_enhanced?: boolean;
   auto_log_clean?: 0 | 1 | 2 | 3;
   proxy_layout_column?: number;

+ 0 - 53
src/utils/clash-fields.ts

@@ -1,53 +0,0 @@
-export const HANDLE_FIELDS = [
-  "mode",
-  "port",
-  "socks-port",
-  "mixed-port",
-  "allow-lan",
-  "log-level",
-  "ipv6",
-  "secret",
-  "external-controller",
-];
-
-export const DEFAULT_FIELDS = [
-  "proxies",
-  "proxy-groups",
-  "proxy-providers",
-  "rules",
-  "rule-providers",
-] as const;
-
-export const OTHERS_FIELDS = [
-  "dns",
-  "tun",
-  "ebpf",
-  "hosts",
-  "script",
-  "profile",
-  "payload",
-  "tunnels",
-  "auto-redir",
-  "experimental",
-  "interface-name",
-  "routing-mark",
-  "redir-port",
-  "tproxy-port",
-  "iptables",
-  "external-ui",
-  "bind-address",
-  "authentication",
-  "tls", // meta
-  "sniffer", // meta
-  "geox-url", // meta
-  "listeners", // meta
-  "sub-rules", // meta
-  "geodata-mode", // meta
-  "unified-delay", // meta
-  "tcp-concurrent", // meta
-  "enable-process", // meta
-  "find-process-mode", // meta
-  "skip-auth-prefixes", // meta
-  "external-controller-tls", // meta
-  "global-client-fingerprint", // meta
-] as const;