diff --git a/.editorconfig b/.editorconfig
index 33fc5f06571b787e350d694f1835b9cb0185283b..8e94654d5fce93c74043e0ec06624595bb0675a7 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,3 +5,9 @@ charset = utf-8
 end_of_line = lf
 indent_size = 2
 insert_final_newline = true
+
+[*.rs]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+insert_final_newline = true
diff --git a/src-tauri/build.rs b/src-tauri/build.rs
index 795b9b7c83dbfc6bf454958eef78f93e211703d2..d860e1e6a7cac333c3cc0bc9cb67faf286b07d69 100644
--- a/src-tauri/build.rs
+++ b/src-tauri/build.rs
@@ -1,3 +1,3 @@
 fn main() {
-  tauri_build::build()
+    tauri_build::build()
 }
diff --git a/src-tauri/rustfmt.toml b/src-tauri/rustfmt.toml
index 550a09853f31cdc022275ee3ce02659855ac3c70..11eda8825f2c9d0290de2ad518684dbc9c95177b 100644
--- a/src-tauri/rustfmt.toml
+++ b/src-tauri/rustfmt.toml
@@ -1,6 +1,6 @@
 max_width = 100
 hard_tabs = false
-tab_spaces = 2
+tab_spaces = 4
 newline_style = "Auto"
 use_small_heuristics = "Default"
 reorder_imports = true
diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index 27892d501384c31ac9d95adcf3220c80645bc038..e8ac49f57c710aca5966159d0b0bd09f7ba40f5b 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -1,7 +1,7 @@
 use crate::{
-  core::Core,
-  data::{ClashInfo, Data, PrfItem, PrfOption, Profiles, Verge},
-  utils::{dirs, help},
+    core::Core,
+    data::{ClashInfo, Data, PrfItem, PrfOption, Profiles, Verge},
+    utils::{dirs, help},
 };
 use crate::{log_if_err, ret_err, wrap_err};
 use anyhow::Result;
@@ -14,27 +14,27 @@ type CmdResult<T = ()> = Result<T, String>;
 /// get all profiles from `profiles.yaml`
 #[tauri::command]
 pub fn get_profiles() -> CmdResult<Profiles> {
-  let global = Data::global();
-  let profiles = global.profiles.lock();
-  Ok(profiles.clone())
+    let global = Data::global();
+    let profiles = global.profiles.lock();
+    Ok(profiles.clone())
 }
 
 /// manually exec enhanced profile
 #[tauri::command]
 pub fn enhance_profiles() -> CmdResult {
-  let core = Core::global();
-  wrap_err!(core.activate())
+    let core = Core::global();
+    wrap_err!(core.activate())
 }
 
 /// import the profile from url
 /// and save to `profiles.yaml`
 #[tauri::command]
 pub async fn import_profile(url: String, option: Option<PrfOption>) -> CmdResult {
-  let item = wrap_err!(PrfItem::from_url(&url, None, None, option).await)?;
+    let item = wrap_err!(PrfItem::from_url(&url, None, None, option).await)?;
 
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  wrap_err!(profiles.append_item(item))
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    wrap_err!(profiles.append_item(item))
 }
 
 /// new a profile
@@ -42,166 +42,166 @@ pub async fn import_profile(url: String, option: Option<PrfOption>) -> CmdResult
 /// view the temp profile file by using vscode or other editor
 #[tauri::command]
 pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResult {
-  let item = wrap_err!(PrfItem::from(item, file_data).await)?;
+    let item = wrap_err!(PrfItem::from(item, file_data).await)?;
 
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  wrap_err!(profiles.append_item(item))
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    wrap_err!(profiles.append_item(item))
 }
 
 /// Update the profile
 #[tauri::command]
 pub async fn update_profile(index: String, option: Option<PrfOption>) -> CmdResult {
-  let core = Core::global();
-  wrap_err!(core.update_profile_item(index, option).await)
+    let core = Core::global();
+    wrap_err!(core.update_profile_item(index, option).await)
 }
 
 /// change the current profile
 #[tauri::command]
 pub fn select_profile(index: String) -> CmdResult {
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  wrap_err!(profiles.put_current(index))?;
-  drop(profiles);
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    wrap_err!(profiles.put_current(index))?;
+    drop(profiles);
 
-  let core = Core::global();
-  wrap_err!(core.activate())
+    let core = Core::global();
+    wrap_err!(core.activate())
 }
 
 /// change the profile chain
 #[tauri::command]
 pub fn change_profile_chain(chain: Option<Vec<String>>) -> CmdResult {
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  wrap_err!(profiles.put_chain(chain))?;
-  drop(profiles);
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    wrap_err!(profiles.put_chain(chain))?;
+    drop(profiles);
 
-  let core = Core::global();
-  wrap_err!(core.activate())
+    let core = Core::global();
+    wrap_err!(core.activate())
 }
 
 /// change the profile valid fields
 #[tauri::command]
 pub fn change_profile_valid(valid: Option<Vec<String>>) -> CmdResult {
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  wrap_err!(profiles.put_valid(valid))?;
-  drop(profiles);
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    wrap_err!(profiles.put_valid(valid))?;
+    drop(profiles);
 
-  let core = Core::global();
-  wrap_err!(core.activate())
+    let core = Core::global();
+    wrap_err!(core.activate())
 }
 
 /// delete profile item
 #[tauri::command]
 pub fn delete_profile(index: String) -> CmdResult {
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  if wrap_err!(profiles.delete_item(index))? {
-    drop(profiles);
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    if wrap_err!(profiles.delete_item(index))? {
+        drop(profiles);
 
-    let core = Core::global();
-    log_if_err!(core.activate());
-  }
-  Ok(())
+        let core = Core::global();
+        log_if_err!(core.activate());
+    }
+    Ok(())
 }
 
 /// patch the profile config
 #[tauri::command]
 pub fn patch_profile(index: String, profile: PrfItem) -> CmdResult {
-  let global = Data::global();
-  let mut profiles = global.profiles.lock();
-  wrap_err!(profiles.patch_item(index, profile))?;
-  drop(profiles);
+    let global = Data::global();
+    let mut profiles = global.profiles.lock();
+    wrap_err!(profiles.patch_item(index, profile))?;
+    drop(profiles);
 
-  // update cron task
-  let core = Core::global();
-  let mut timer = core.timer.lock();
-  wrap_err!(timer.refresh())
+    // update cron task
+    let core = Core::global();
+    let mut timer = core.timer.lock();
+    wrap_err!(timer.refresh())
 }
 
 /// run vscode command to edit the profile
 #[tauri::command]
 pub fn view_profile(index: String) -> CmdResult {
-  let global = Data::global();
-  let profiles = global.profiles.lock();
-  let item = wrap_err!(profiles.get_item(&index))?;
+    let global = Data::global();
+    let profiles = global.profiles.lock();
+    let item = wrap_err!(profiles.get_item(&index))?;
 
-  let file = item.file.clone();
-  if file.is_none() {
-    ret_err!("file is null");
-  }
+    let file = item.file.clone();
+    if file.is_none() {
+        ret_err!("file is null");
+    }
 
-  let path = dirs::app_profiles_dir().join(file.unwrap());
-  if !path.exists() {
-    ret_err!("file not found");
-  }
+    let path = dirs::app_profiles_dir().join(file.unwrap());
+    if !path.exists() {
+        ret_err!("file not found");
+    }
 
-  wrap_err!(help::open_file(path))
+    wrap_err!(help::open_file(path))
 }
 
 /// read the profile item file data
 #[tauri::command]
 pub fn read_profile_file(index: String) -> CmdResult<String> {
-  let global = Data::global();
-  let profiles = global.profiles.lock();
-  let item = wrap_err!(profiles.get_item(&index))?;
-  let data = wrap_err!(item.read_file())?;
-  Ok(data)
+    let global = Data::global();
+    let profiles = global.profiles.lock();
+    let item = wrap_err!(profiles.get_item(&index))?;
+    let data = wrap_err!(item.read_file())?;
+    Ok(data)
 }
 
 /// save the profile item file data
 #[tauri::command]
 pub fn save_profile_file(index: String, file_data: Option<String>) -> CmdResult {
-  if file_data.is_none() {
-    return Ok(());
-  }
+    if file_data.is_none() {
+        return Ok(());
+    }
 
-  let global = Data::global();
-  let profiles = global.profiles.lock();
-  let item = wrap_err!(profiles.get_item(&index))?;
-  wrap_err!(item.save_file(file_data.unwrap()))
+    let global = Data::global();
+    let profiles = global.profiles.lock();
+    let item = wrap_err!(profiles.get_item(&index))?;
+    wrap_err!(item.save_file(file_data.unwrap()))
 }
 
 /// get the clash core info from the state
 /// the caller can also get the infomation by clash's api
 #[tauri::command]
 pub fn get_clash_info() -> CmdResult<ClashInfo> {
-  let global = Data::global();
-  let clash = global.clash.lock();
-  Ok(clash.info.clone())
+    let global = Data::global();
+    let clash = global.clash.lock();
+    Ok(clash.info.clone())
 }
 
 /// get the runtime clash config mapping
 #[tauri::command]
 pub fn get_runtime_config() -> CmdResult<Option<Mapping>> {
-  let core = Core::global();
-  let rt = core.runtime.lock();
-  Ok(rt.config.clone())
+    let core = Core::global();
+    let rt = core.runtime.lock();
+    Ok(rt.config.clone())
 }
 
 /// get the runtime clash config yaml string
 #[tauri::command]
 pub fn get_runtime_yaml() -> CmdResult<Option<String>> {
-  let core = Core::global();
-  let rt = core.runtime.lock();
-  Ok(rt.config_yaml.clone())
+    let core = Core::global();
+    let rt = core.runtime.lock();
+    Ok(rt.config_yaml.clone())
 }
 
 /// get the runtime config exists keys
 #[tauri::command]
 pub fn get_runtime_exists() -> CmdResult<Vec<String>> {
-  let core = Core::global();
-  let rt = core.runtime.lock();
-  Ok(rt.exists_keys.clone())
+    let core = Core::global();
+    let rt = core.runtime.lock();
+    Ok(rt.exists_keys.clone())
 }
 
 /// get the runtime enhanced chain log
 #[tauri::command]
 pub fn get_runtime_logs() -> CmdResult<HashMap<String, Vec<(String, String)>>> {
-  let core = Core::global();
-  let rt = core.runtime.lock();
-  Ok(rt.chain_logs.clone())
+    let core = Core::global();
+    let rt = core.runtime.lock();
+    Ok(rt.chain_logs.clone())
 }
 
 /// update the clash core config
@@ -209,153 +209,153 @@ pub fn get_runtime_logs() -> CmdResult<HashMap<String, Vec<(String, String)>>> {
 /// then we should save the latest config
 #[tauri::command]
 pub fn patch_clash_config(payload: Mapping) -> CmdResult {
-  let core = Core::global();
-  wrap_err!(core.patch_clash(payload))
+    let core = Core::global();
+    wrap_err!(core.patch_clash(payload))
 }
 
 #[tauri::command]
 pub fn get_verge_config() -> CmdResult<Verge> {
-  let global = Data::global();
-  let verge = global.verge.lock();
-  Ok(verge.clone())
+    let global = Data::global();
+    let verge = global.verge.lock();
+    Ok(verge.clone())
 }
 
 /// patch the verge config
 /// this command only save the config and not responsible for other things
 #[tauri::command]
 pub fn patch_verge_config(payload: Verge) -> CmdResult {
-  let core = Core::global();
-  wrap_err!(core.patch_verge(payload))
+    let core = Core::global();
+    wrap_err!(core.patch_verge(payload))
 }
 
 #[tauri::command]
 pub fn update_hotkeys(hotkeys: Vec<String>) -> CmdResult {
-  let core = Core::global();
-  let mut hotkey = core.hotkey.lock();
-  wrap_err!(hotkey.update(hotkeys))
+    let core = Core::global();
+    let mut hotkey = core.hotkey.lock();
+    wrap_err!(hotkey.update(hotkeys))
 }
 
 /// change clash core
 #[tauri::command]
 pub fn change_clash_core(clash_core: Option<String>) -> CmdResult {
-  let core = Core::global();
-  wrap_err!(core.change_core(clash_core))
+    let core = Core::global();
+    wrap_err!(core.change_core(clash_core))
 }
 
 /// restart the sidecar
 #[tauri::command]
 pub fn restart_sidecar() -> CmdResult {
-  let core = Core::global();
-  wrap_err!(core.restart_clash())
+    let core = Core::global();
+    wrap_err!(core.restart_clash())
 }
 
 /// kill all sidecars when update app
 #[tauri::command]
 pub fn kill_sidecar() {
-  tauri::api::process::kill_children();
+    tauri::api::process::kill_children();
 }
 
 /// get the system proxy
 #[tauri::command]
 pub fn get_sys_proxy() -> CmdResult<Mapping> {
-  let current = wrap_err!(Sysproxy::get_system_proxy())?;
+    let current = wrap_err!(Sysproxy::get_system_proxy())?;
 
-  let mut map = Mapping::new();
-  map.insert("enable".into(), current.enable.into());
-  map.insert(
-    "server".into(),
-    format!("{}:{}", current.host, current.port).into(),
-  );
-  map.insert("bypass".into(), current.bypass.into());
+    let mut map = Mapping::new();
+    map.insert("enable".into(), current.enable.into());
+    map.insert(
+        "server".into(),
+        format!("{}:{}", current.host, current.port).into(),
+    );
+    map.insert("bypass".into(), current.bypass.into());
 
-  Ok(map)
+    Ok(map)
 }
 
 #[tauri::command]
 pub fn get_clash_logs() -> CmdResult<VecDeque<String>> {
-  let core = Core::global();
-  let service = core.service.lock();
-  Ok(service.get_logs())
+    let core = Core::global();
+    let service = core.service.lock();
+    Ok(service.get_logs())
 }
 
 /// open app config dir
 #[tauri::command]
 pub fn open_app_dir() -> CmdResult<()> {
-  let app_dir = dirs::app_home_dir();
-  wrap_err!(open::that(app_dir))
+    let app_dir = dirs::app_home_dir();
+    wrap_err!(open::that(app_dir))
 }
 
 /// open logs dir
 #[tauri::command]
 pub fn open_logs_dir() -> CmdResult<()> {
-  let log_dir = dirs::app_logs_dir();
-  wrap_err!(open::that(log_dir))
+    let log_dir = dirs::app_logs_dir();
+    wrap_err!(open::that(log_dir))
 }
 
 /// open url
 #[tauri::command]
 pub fn open_web_url(url: String) -> CmdResult<()> {
-  wrap_err!(open::that(url))
+    wrap_err!(open::that(url))
 }
 
 /// service mode
 #[cfg(windows)]
 pub mod service {
-  use super::*;
-  use crate::core::win_service::JsonResponse;
-
-  #[tauri::command]
-  pub async fn start_service() -> CmdResult<()> {
-    wrap_err!(crate::core::Service::start_service().await)
-  }
-
-  #[tauri::command]
-  pub async fn stop_service() -> CmdResult<()> {
-    wrap_err!(crate::core::Service::stop_service().await)
-  }
-
-  #[tauri::command]
-  pub async fn check_service() -> CmdResult<JsonResponse> {
-    // no log
-    match crate::core::Service::check_service().await {
-      Ok(res) => Ok(res),
-      Err(err) => Err(err.to_string()),
+    use super::*;
+    use crate::core::win_service::JsonResponse;
+
+    #[tauri::command]
+    pub async fn start_service() -> CmdResult<()> {
+        wrap_err!(crate::core::Service::start_service().await)
     }
-  }
 
-  #[tauri::command]
-  pub async fn install_service() -> CmdResult<()> {
-    wrap_err!(crate::core::Service::install_service().await)
-  }
+    #[tauri::command]
+    pub async fn stop_service() -> CmdResult<()> {
+        wrap_err!(crate::core::Service::stop_service().await)
+    }
+
+    #[tauri::command]
+    pub async fn check_service() -> CmdResult<JsonResponse> {
+        // no log
+        match crate::core::Service::check_service().await {
+            Ok(res) => Ok(res),
+            Err(err) => Err(err.to_string()),
+        }
+    }
+
+    #[tauri::command]
+    pub async fn install_service() -> CmdResult<()> {
+        wrap_err!(crate::core::Service::install_service().await)
+    }
 
-  #[tauri::command]
-  pub async fn uninstall_service() -> CmdResult<()> {
-    wrap_err!(crate::core::Service::uninstall_service().await)
-  }
+    #[tauri::command]
+    pub async fn uninstall_service() -> CmdResult<()> {
+        wrap_err!(crate::core::Service::uninstall_service().await)
+    }
 }
 
 #[cfg(not(windows))]
 pub mod service {
-  use super::*;
+    use super::*;
 
-  #[tauri::command]
-  pub async fn start_service() -> CmdResult<()> {
-    Ok(())
-  }
-  #[tauri::command]
-  pub async fn stop_service() -> CmdResult<()> {
-    Ok(())
-  }
-  #[tauri::command]
-  pub async fn check_service() -> CmdResult<()> {
-    Ok(())
-  }
-  #[tauri::command]
-  pub async fn install_service() -> CmdResult<()> {
-    Ok(())
-  }
-  #[tauri::command]
-  pub async fn uninstall_service() -> CmdResult<()> {
-    Ok(())
-  }
+    #[tauri::command]
+    pub async fn start_service() -> CmdResult<()> {
+        Ok(())
+    }
+    #[tauri::command]
+    pub async fn stop_service() -> CmdResult<()> {
+        Ok(())
+    }
+    #[tauri::command]
+    pub async fn check_service() -> CmdResult<()> {
+        Ok(())
+    }
+    #[tauri::command]
+    pub async fn install_service() -> CmdResult<()> {
+        Ok(())
+    }
+    #[tauri::command]
+    pub async fn uninstall_service() -> CmdResult<()> {
+        Ok(())
+    }
 }
diff --git a/src-tauri/src/config/field.rs b/src-tauri/src/config/field.rs
index 71054679b1f46e03eafa0e0ce1624a18617e7024..b7f52dead13af64354cf1a1187ef2eaf153aef4c 100644
--- a/src-tauri/src/config/field.rs
+++ b/src-tauri/src/config/field.rs
@@ -1,119 +1,119 @@
 use serde_yaml::{Mapping, Value};
 
 pub const HANDLE_FIELDS: [&str; 9] = [
-  "port",
-  "socks-port",
-  "mixed-port",
-  "mode",
-  "ipv6",
-  "log-level",
-  "allow-lan",
-  "external-controller",
-  "secret",
+    "port",
+    "socks-port",
+    "mixed-port",
+    "mode",
+    "ipv6",
+    "log-level",
+    "allow-lan",
+    "external-controller",
+    "secret",
 ];
 
 pub const DEFAULT_FIELDS: [&str; 5] = [
-  "proxies",
-  "proxy-groups",
-  "rules",
-  "proxy-providers",
-  "rule-providers",
+    "proxies",
+    "proxy-groups",
+    "rules",
+    "proxy-providers",
+    "rule-providers",
 ];
 
 pub const OTHERS_FIELDS: [&str; 21] = [
-  "tun",
-  "dns",
-  "ebpf",
-  "hosts",
-  "script",
-  "profile",
-  "payload",
-  "auto-redir",
-  "experimental",
-  "interface-name",
-  "routing-mark",
-  "redir-port",
-  "tproxy-port",
-  "iptables",
-  "external-ui",
-  "bind-address",
-  "authentication",
-  "sniffer",        // meta
-  "sub-rules",      // meta
-  "geodata-mode",   // meta
-  "tcp-concurrent", // meta
+    "tun",
+    "dns",
+    "ebpf",
+    "hosts",
+    "script",
+    "profile",
+    "payload",
+    "auto-redir",
+    "experimental",
+    "interface-name",
+    "routing-mark",
+    "redir-port",
+    "tproxy-port",
+    "iptables",
+    "external-ui",
+    "bind-address",
+    "authentication",
+    "sniffer",        // meta
+    "sub-rules",      // meta
+    "geodata-mode",   // meta
+    "tcp-concurrent", // meta
 ];
 
 pub fn use_clash_fields() -> Vec<String> {
-  DEFAULT_FIELDS
-    .into_iter()
-    .chain(HANDLE_FIELDS)
-    .chain(OTHERS_FIELDS)
-    .map(|s| s.to_string())
-    .collect()
+    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);
+    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()
+    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>) -> Mapping {
-  let mut ret = Mapping::new();
+    let mut ret = Mapping::new();
 
-  for (key, value) in config.into_iter() {
-    if let Some(key) = key.as_str() {
-      if filter.contains(&key.to_string()) {
-        ret.insert(Value::from(key), value);
-      }
+    for (key, value) in config.into_iter() {
+        if let Some(key) = key.as_str() {
+            if filter.contains(&key.to_string()) {
+                ret.insert(Value::from(key), value);
+            }
+        }
     }
-  }
-  ret
+    ret
 }
 
 pub fn use_lowercase(config: Mapping) -> Mapping {
-  let mut ret = Mapping::new();
+    let mut ret = Mapping::new();
 
-  for (key, value) in config.into_iter() {
-    if let Some(key_str) = key.as_str() {
-      let mut key_str = String::from(key_str);
-      key_str.make_ascii_lowercase();
-      ret.insert(Value::from(key_str), value);
+    for (key, value) in config.into_iter() {
+        if let Some(key_str) = key.as_str() {
+            let mut key_str = String::from(key_str);
+            key_str.make_ascii_lowercase();
+            ret.insert(Value::from(key_str), value);
+        }
     }
-  }
-  ret
+    ret
 }
 
 pub fn use_sort(config: Mapping) -> Mapping {
-  let mut ret = Mapping::new();
+    let mut ret = Mapping::new();
 
-  HANDLE_FIELDS
-    .into_iter()
-    .chain(OTHERS_FIELDS)
-    .chain(DEFAULT_FIELDS)
-    .for_each(|key| {
-      let key = Value::from(key);
-      config.get(&key).map(|value| {
-        ret.insert(key, value.clone());
-      });
-    });
-  ret
+    HANDLE_FIELDS
+        .into_iter()
+        .chain(OTHERS_FIELDS)
+        .chain(DEFAULT_FIELDS)
+        .for_each(|key| {
+            let key = Value::from(key);
+            config.get(&key).map(|value| {
+                ret.insert(key, value.clone());
+            });
+        });
+    ret
 }
 
 pub fn use_keys(config: &Mapping) -> Vec<String> {
-  config
-    .iter()
-    .filter_map(|(key, _)| key.as_str())
-    .map(|s| {
-      let mut s = s.to_string();
-      s.make_ascii_lowercase();
-      return s;
-    })
-    .collect()
+    config
+        .iter()
+        .filter_map(|(key, _)| key.as_str())
+        .map(|s| {
+            let mut s = s.to_string();
+            s.make_ascii_lowercase();
+            return s;
+        })
+        .collect()
 }
diff --git a/src-tauri/src/config/merge.rs b/src-tauri/src/config/merge.rs
index 335d788fdf281e8d20e35bcb035437f35529973c..7f6b89dbdb9b6da7b34ab95ec53db8d3054c2160 100644
--- a/src-tauri/src/config/merge.rs
+++ b/src-tauri/src/config/merge.rs
@@ -3,60 +3,60 @@ use serde_yaml::{self, Mapping, Sequence, Value};
 
 #[allow(unused)]
 const MERGE_FIELDS: [&str; 6] = [
-  "prepend-rules",
-  "append-rules",
-  "prepend-proxies",
-  "append-proxies",
-  "prepend-proxy-groups",
-  "append-proxy-groups",
+    "prepend-rules",
+    "append-rules",
+    "prepend-proxies",
+    "append-proxies",
+    "prepend-proxy-groups",
+    "append-proxy-groups",
 ];
 
 pub fn use_merge(merge: Mapping, mut config: Mapping) -> Mapping {
-  // 直接覆盖原字段
-  use_lowercase(merge.clone())
-    .into_iter()
-    .for_each(|(key, value)| {
-      config.insert(key, value);
-    });
+    // 直接覆盖原字段
+    use_lowercase(merge.clone())
+        .into_iter()
+        .for_each(|(key, value)| {
+            config.insert(key, value);
+        });
 
-  let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string());
-  let merge = use_filter(merge, &merge_list.collect());
+    let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string());
+    let merge = use_filter(merge, &merge_list.collect());
 
-  ["rules", "proxies", "proxy-groups"]
-    .iter()
-    .for_each(|key_str| {
-      let key_val = Value::from(key_str.to_string());
+    ["rules", "proxies", "proxy-groups"]
+        .iter()
+        .for_each(|key_str| {
+            let key_val = Value::from(key_str.to_string());
 
-      let mut list = Sequence::default();
-      list = config.get(&key_val).map_or(list.clone(), |val| {
-        val.as_sequence().map_or(list, |v| v.clone())
-      });
+            let mut list = Sequence::default();
+            list = config.get(&key_val).map_or(list.clone(), |val| {
+                val.as_sequence().map_or(list, |v| v.clone())
+            });
 
-      let pre_key = Value::from(format!("prepend-{key_str}"));
-      let post_key = Value::from(format!("append-{key_str}"));
+            let pre_key = Value::from(format!("prepend-{key_str}"));
+            let post_key = Value::from(format!("append-{key_str}"));
 
-      if let Some(pre_val) = merge.get(&pre_key) {
-        if pre_val.is_sequence() {
-          let mut pre_val = pre_val.as_sequence().unwrap().clone();
-          pre_val.extend(list);
-          list = pre_val;
-        }
-      }
+            if let Some(pre_val) = merge.get(&pre_key) {
+                if pre_val.is_sequence() {
+                    let mut pre_val = pre_val.as_sequence().unwrap().clone();
+                    pre_val.extend(list);
+                    list = pre_val;
+                }
+            }
 
-      if let Some(post_val) = merge.get(&post_key) {
-        if post_val.is_sequence() {
-          list.extend(post_val.as_sequence().unwrap().clone());
-        }
-      }
+            if let Some(post_val) = merge.get(&post_key) {
+                if post_val.is_sequence() {
+                    list.extend(post_val.as_sequence().unwrap().clone());
+                }
+            }
 
-      config.insert(key_val, Value::from(list));
-    });
-  config
+            config.insert(key_val, Value::from(list));
+        });
+    config
 }
 
 #[test]
 fn test_merge() -> anyhow::Result<()> {
-  let merge = r"
+    let merge = r"
     prepend-rules:
       - prepend
       - 1123123
@@ -76,18 +76,18 @@ fn test_merge() -> anyhow::Result<()> {
       enable: true
   ";
 
-  let config = r"
+    let config = r"
     rules:
       - aaaaa
     script1: test
   ";
 
-  let merge = serde_yaml::from_str::<Mapping>(merge)?;
-  let config = serde_yaml::from_str::<Mapping>(config)?;
+    let merge = serde_yaml::from_str::<Mapping>(merge)?;
+    let config = serde_yaml::from_str::<Mapping>(config)?;
 
-  let result = serde_yaml::to_string(&use_merge(merge, config))?;
+    let result = serde_yaml::to_string(&use_merge(merge, config))?;
 
-  println!("{result}");
+    println!("{result}");
 
-  Ok(())
+    Ok(())
 }
diff --git a/src-tauri/src/config/mod.rs b/src-tauri/src/config/mod.rs
index 5bfca85955d32cefb377129d9d5f64da87ea7a05..7020020ca7c786e54d2f7ce6ea780cdc73453e2d 100644
--- a/src-tauri/src/config/mod.rs
+++ b/src-tauri/src/config/mod.rs
@@ -16,54 +16,54 @@ use std::collections::HashSet;
 type ResultLog = Vec<(String, String)>;
 
 pub fn enhance_config(
-  clash_config: Mapping,
-  profile_config: Mapping,
-  chain: Vec<ChainItem>,
-  valid: Vec<String>,
-  tun_mode: bool,
+    clash_config: Mapping,
+    profile_config: Mapping,
+    chain: Vec<ChainItem>,
+    valid: Vec<String>,
+    tun_mode: bool,
 ) -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
-  let mut config = profile_config;
-  let mut result_map = HashMap::new();
-  let mut exists_keys = use_keys(&config);
+    let mut config = profile_config;
+    let mut result_map = HashMap::new();
+    let mut exists_keys = use_keys(&config);
 
-  let valid = use_valid_fields(valid);
+    let valid = use_valid_fields(valid);
 
-  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);
-    }
-    ChainType::Script(script) => {
-      let mut logs = vec![];
-
-      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);
-          logs.extend(res_logs);
+    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);
         }
-        Err(err) => logs.push(("exception".into(), err.to_string())),
-      }
+        ChainType::Script(script) => {
+            let mut logs = vec![];
 
-      result_map.insert(item.uid, logs);
-    }
-  });
+            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);
+                    logs.extend(res_logs);
+                }
+                Err(err) => logs.push(("exception".into(), err.to_string())),
+            }
 
-  config = use_filter(config, &valid);
+            result_map.insert(item.uid, logs);
+        }
+    });
+
+    config = use_filter(config, &valid);
 
-  for (key, value) in clash_config.into_iter() {
-    config.insert(key, value);
-  }
+    for (key, value) in clash_config.into_iter() {
+        config.insert(key, value);
+    }
 
-  let clash_fields = use_clash_fields();
-  config = use_filter(config, &clash_fields);
-  config = use_tun(config, tun_mode);
-  config = use_sort(config);
+    let clash_fields = use_clash_fields();
+    config = use_filter(config, &clash_fields);
+    config = use_tun(config, tun_mode);
+    config = use_sort(config);
 
-  let mut exists_set = HashSet::new();
-  exists_set.extend(exists_keys.into_iter().filter(|s| clash_fields.contains(s)));
-  exists_keys = exists_set.into_iter().collect();
+    let mut exists_set = HashSet::new();
+    exists_set.extend(exists_keys.into_iter().filter(|s| clash_fields.contains(s)));
+    exists_keys = exists_set.into_iter().collect();
 
-  (config, exists_keys, result_map)
+    (config, exists_keys, result_map)
 }
diff --git a/src-tauri/src/config/script.rs b/src-tauri/src/config/script.rs
index bc7f001dbf7452f9e3963f4d6b6d026b4dcec0c8..97b34c2092b4426ac00c3e3cf068eb6eae111ae9 100644
--- a/src-tauri/src/config/script.rs
+++ b/src-tauri/src/config/script.rs
@@ -3,66 +3,66 @@ use anyhow::Result;
 use serde_yaml::Mapping;
 
 pub fn use_script(script: String, config: Mapping) -> Result<(Mapping, Vec<(String, String)>)> {
-  use rquickjs::{Context, Func, Runtime};
-  use std::sync::{Arc, Mutex};
+    use rquickjs::{Context, Func, Runtime};
+    use std::sync::{Arc, Mutex};
 
-  let runtime = Runtime::new().unwrap();
-  let context = Context::full(&runtime).unwrap();
-  let outputs = Arc::new(Mutex::new(vec![]));
+    let runtime = Runtime::new().unwrap();
+    let context = Context::full(&runtime).unwrap();
+    let outputs = Arc::new(Mutex::new(vec![]));
 
-  let copy_outputs = outputs.clone();
-  let result = context.with(|ctx| -> Result<Mapping> {
-    ctx.globals().set(
-      "__verge_log__",
-      Func::from(move |level: String, data: String| {
-        let mut out = copy_outputs.lock().unwrap();
-        out.push((level, data));
-      }),
-    )?;
+    let copy_outputs = outputs.clone();
+    let result = context.with(|ctx| -> Result<Mapping> {
+        ctx.globals().set(
+            "__verge_log__",
+            Func::from(move |level: String, data: String| {
+                let mut out = copy_outputs.lock().unwrap();
+                out.push((level, data));
+            }),
+        )?;
 
-    ctx.eval(
-      r#"var console = Object.freeze({
+        ctx.eval(
+            r#"var console = Object.freeze({
         log(data){__verge_log__("log",JSON.stringify(data))}, 
         info(data){__verge_log__("info",JSON.stringify(data))}, 
         error(data){__verge_log__("error",JSON.stringify(data))},
         debug(data){__verge_log__("debug",JSON.stringify(data))},
       });"#,
-    )?;
+        )?;
 
-    let config = use_lowercase(config.clone());
-    let config_str = serde_json::to_string(&config)?;
+        let config = use_lowercase(config.clone());
+        let config_str = serde_json::to_string(&config)?;
 
-    let code = format!(
-      r#"try{{
+        let code = format!(
+            r#"try{{
         {script};
         JSON.stringify(main({config_str})||'')
       }} catch(err) {{
         `__error_flag__ ${{err.toString()}}`
       }}"#
-    );
-    let result: String = ctx.eval(code.as_str())?;
-    if result.starts_with("__error_flag__") {
-      anyhow::bail!(result[15..].to_owned());
-    }
-    if result == "\"\"" {
-      anyhow::bail!("main function should return object");
-    }
-    return Ok(serde_json::from_str::<Mapping>(result.as_str())?);
-  });
+        );
+        let result: String = ctx.eval(code.as_str())?;
+        if result.starts_with("__error_flag__") {
+            anyhow::bail!(result[15..].to_owned());
+        }
+        if result == "\"\"" {
+            anyhow::bail!("main function should return object");
+        }
+        return Ok(serde_json::from_str::<Mapping>(result.as_str())?);
+    });
 
-  let mut out = outputs.lock().unwrap();
-  match result {
-    Ok(config) => Ok((use_lowercase(config), out.to_vec())),
-    Err(err) => {
-      out.push(("exception".into(), err.to_string()));
-      Ok((config, out.to_vec()))
+    let mut out = outputs.lock().unwrap();
+    match result {
+        Ok(config) => Ok((use_lowercase(config), out.to_vec())),
+        Err(err) => {
+            out.push(("exception".into(), err.to_string()));
+            Ok((config, out.to_vec()))
+        }
     }
-  }
 }
 
 #[test]
 fn test_script() {
-  let script = r#"
+    let script = r#"
     function main(config) {
       if (Array.isArray(config.rules)) {
         config.rules = [...config.rules, "add"];
@@ -73,7 +73,7 @@ fn test_script() {
     }
   "#;
 
-  let config = r#"
+    let config = r#"
     rules:
       - 111
       - 222
@@ -83,12 +83,12 @@ fn test_script() {
       enable: false
   "#;
 
-  let config = serde_yaml::from_str(config).unwrap();
-  let (config, results) = use_script(script.into(), config).unwrap();
+    let config = serde_yaml::from_str(config).unwrap();
+    let (config, results) = use_script(script.into(), config).unwrap();
 
-  let config_str = serde_yaml::to_string(&config).unwrap();
+    let config_str = serde_yaml::to_string(&config).unwrap();
 
-  println!("{config_str}");
+    println!("{config_str}");
 
-  dbg!(results);
+    dbg!(results);
 }
diff --git a/src-tauri/src/config/tun.rs b/src-tauri/src/config/tun.rs
index 8c19f47e8db5f9032ab170635af3d57d58e53011..680d36fda660f121b97be594d2e46b4599dc5667 100644
--- a/src-tauri/src/config/tun.rs
+++ b/src-tauri/src/config/tun.rs
@@ -1,81 +1,81 @@
 use serde_yaml::{Mapping, Value};
 
 macro_rules! revise {
-  ($map: expr, $key: expr, $val: expr) => {
-    let ret_key = Value::String($key.into());
-    $map.insert(ret_key, Value::from($val));
-  };
+    ($map: expr, $key: expr, $val: expr) => {
+        let ret_key = Value::String($key.into());
+        $map.insert(ret_key, Value::from($val));
+    };
 }
 
 // if key not exists then append value
 macro_rules! append {
-  ($map: expr, $key: expr, $val: expr) => {
-    let ret_key = Value::String($key.into());
-    if !$map.contains_key(&ret_key) {
-      $map.insert(ret_key, Value::from($val));
-    }
-  };
+    ($map: expr, $key: expr, $val: expr) => {
+        let ret_key = Value::String($key.into());
+        if !$map.contains_key(&ret_key) {
+            $map.insert(ret_key, Value::from($val));
+        }
+    };
 }
 
 pub fn use_tun(mut config: Mapping, enable: bool) -> Mapping {
-  let tun_key = Value::from("tun");
-  let tun_val = config.get(&tun_key);
+    let tun_key = Value::from("tun");
+    let tun_val = config.get(&tun_key);
 
-  if !enable && tun_val.is_none() {
-    return config;
-  }
+    if !enable && tun_val.is_none() {
+        return config;
+    }
 
-  let mut tun_val = tun_val.map_or(Mapping::new(), |val| {
-    val.as_mapping().cloned().unwrap_or(Mapping::new())
-  });
+    let mut tun_val = tun_val.map_or(Mapping::new(), |val| {
+        val.as_mapping().cloned().unwrap_or(Mapping::new())
+    });
 
-  revise!(tun_val, "enable", enable);
-  if enable {
-    append!(tun_val, "stack", "gvisor");
-    append!(tun_val, "dns-hijack", vec!["198.18.0.2:53"]);
-    append!(tun_val, "auto-route", true);
-    append!(tun_val, "auto-detect-interface", true);
-  }
+    revise!(tun_val, "enable", enable);
+    if enable {
+        append!(tun_val, "stack", "gvisor");
+        append!(tun_val, "dns-hijack", vec!["198.18.0.2:53"]);
+        append!(tun_val, "auto-route", true);
+        append!(tun_val, "auto-detect-interface", true);
+    }
 
-  revise!(config, "tun", tun_val);
+    revise!(config, "tun", tun_val);
 
-  if enable {
-    use_dns_for_tun(config)
-  } else {
-    config
-  }
+    if enable {
+        use_dns_for_tun(config)
+    } else {
+        config
+    }
 }
 
 fn use_dns_for_tun(mut config: Mapping) -> Mapping {
-  let dns_key = Value::from("dns");
-  let dns_val = config.get(&dns_key);
+    let dns_key = Value::from("dns");
+    let dns_val = config.get(&dns_key);
 
-  let mut dns_val = dns_val.map_or(Mapping::new(), |val| {
-    val.as_mapping().cloned().unwrap_or(Mapping::new())
-  });
+    let mut dns_val = dns_val.map_or(Mapping::new(), |val| {
+        val.as_mapping().cloned().unwrap_or(Mapping::new())
+    });
 
-  // 开启tun将同时开启dns
-  revise!(dns_val, "enable", true);
+    // 开启tun将同时开启dns
+    revise!(dns_val, "enable", true);
 
-  append!(dns_val, "enhanced-mode", "fake-ip");
-  append!(dns_val, "fake-ip-range", "198.18.0.1/16");
-  append!(
-    dns_val,
-    "nameserver",
-    vec!["114.114.114.114", "223.5.5.5", "8.8.8.8"]
-  );
-  append!(dns_val, "fallback", vec![] as Vec<&str>);
+    append!(dns_val, "enhanced-mode", "fake-ip");
+    append!(dns_val, "fake-ip-range", "198.18.0.1/16");
+    append!(
+        dns_val,
+        "nameserver",
+        vec!["114.114.114.114", "223.5.5.5", "8.8.8.8"]
+    );
+    append!(dns_val, "fallback", vec![] as Vec<&str>);
 
-  #[cfg(target_os = "windows")]
-  append!(
-    dns_val,
-    "fake-ip-filter",
-    vec![
-      "dns.msftncsi.com",
-      "www.msftncsi.com",
-      "www.msftconnecttest.com"
-    ]
-  );
-  revise!(config, "dns", dns_val);
-  config
+    #[cfg(target_os = "windows")]
+    append!(
+        dns_val,
+        "fake-ip-filter",
+        vec![
+            "dns.msftncsi.com",
+            "www.msftncsi.com",
+            "www.msftconnecttest.com"
+        ]
+    );
+    revise!(config, "dns", dns_val);
+    config
 }
diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs
index f734536938c060c73bb4673d2c1c967ab8e40f74..dd04a48e2aeec739bc6325f683d64c712c259791 100644
--- a/src-tauri/src/core/handle.rs
+++ b/src-tauri/src/core/handle.rs
@@ -5,62 +5,61 @@ use tauri::{AppHandle, Manager, Window};
 
 #[derive(Debug, Default, Clone)]
 pub struct Handle {
-  pub app_handle: Option<AppHandle>,
+    pub app_handle: Option<AppHandle>,
 }
 
 impl Handle {
-  pub fn set_inner(&mut self, app_handle: AppHandle) {
-    self.app_handle = Some(app_handle);
-  }
+    pub fn set_inner(&mut self, app_handle: AppHandle) {
+        self.app_handle = Some(app_handle);
+    }
 
-  pub fn get_window(&self) -> Option<Window> {
-    self
-      .app_handle
-      .as_ref()
-      .map_or(None, |a| a.get_window("main"))
-  }
+    pub fn get_window(&self) -> Option<Window> {
+        self.app_handle
+            .as_ref()
+            .map_or(None, |a| a.get_window("main"))
+    }
 
-  pub fn refresh_clash(&self) {
-    if let Some(window) = self.get_window() {
-      log_if_err!(window.emit("verge://refresh-clash-config", "yes"));
+    pub fn refresh_clash(&self) {
+        if let Some(window) = self.get_window() {
+            log_if_err!(window.emit("verge://refresh-clash-config", "yes"));
+        }
     }
-  }
 
-  pub fn refresh_verge(&self) {
-    if let Some(window) = self.get_window() {
-      log_if_err!(window.emit("verge://refresh-verge-config", "yes"));
+    pub fn refresh_verge(&self) {
+        if let Some(window) = self.get_window() {
+            log_if_err!(window.emit("verge://refresh-verge-config", "yes"));
+        }
     }
-  }
 
-  #[allow(unused)]
-  pub fn refresh_profiles(&self) {
-    if let Some(window) = self.get_window() {
-      log_if_err!(window.emit("verge://refresh-profiles-config", "yes"));
+    #[allow(unused)]
+    pub fn refresh_profiles(&self) {
+        if let Some(window) = self.get_window() {
+            log_if_err!(window.emit("verge://refresh-profiles-config", "yes"));
+        }
     }
-  }
 
-  pub fn notice_message(&self, status: String, msg: String) {
-    if let Some(window) = self.get_window() {
-      log_if_err!(window.emit("verge://notice-message", (status, msg)));
+    pub fn notice_message(&self, status: String, msg: String) {
+        if let Some(window) = self.get_window() {
+            log_if_err!(window.emit("verge://notice-message", (status, msg)));
+        }
     }
-  }
 
-  pub fn update_systray(&self) -> Result<()> {
-    if self.app_handle.is_none() {
-      bail!("update_systray unhandle error");
+    pub fn update_systray(&self) -> Result<()> {
+        if self.app_handle.is_none() {
+            bail!("update_systray unhandle error");
+        }
+        let app_handle = self.app_handle.as_ref().unwrap();
+        Tray::update_systray(app_handle)?;
+        Ok(())
     }
-    let app_handle = self.app_handle.as_ref().unwrap();
-    Tray::update_systray(app_handle)?;
-    Ok(())
-  }
 
-  /// update the system tray state
-  pub fn update_systray_part(&self) -> Result<()> {
-    if self.app_handle.is_none() {
-      bail!("update_systray unhandle error");
+    /// update the system tray state
+    pub fn update_systray_part(&self) -> Result<()> {
+        if self.app_handle.is_none() {
+            bail!("update_systray unhandle error");
+        }
+        let app_handle = self.app_handle.as_ref().unwrap();
+        Tray::update_part(app_handle)?;
+        Ok(())
     }
-    let app_handle = self.app_handle.as_ref().unwrap();
-    Tray::update_part(app_handle)?;
-    Ok(())
-  }
 }
diff --git a/src-tauri/src/core/hotkey.rs b/src-tauri/src/core/hotkey.rs
index 744674623361cc6e85da8e6a943a68277b16bbd7..4ce4847e6834d4f8522d3f55d1213e3761bda42b 100644
--- a/src-tauri/src/core/hotkey.rs
+++ b/src-tauri/src/core/hotkey.rs
@@ -4,150 +4,150 @@ use std::collections::HashMap;
 use tauri::{AppHandle, GlobalShortcutManager};
 
 pub struct Hotkey {
-  current: Vec<String>, // 保存当前的热键设置
-  manager: Option<AppHandle>,
+    current: Vec<String>, // 保存当前的热键设置
+    manager: Option<AppHandle>,
 }
 
 impl Hotkey {
-  pub fn new() -> Hotkey {
-    Hotkey {
-      current: Vec::new(),
-      manager: None,
+    pub fn new() -> Hotkey {
+        Hotkey {
+            current: Vec::new(),
+            manager: None,
+        }
     }
-  }
-
-  pub fn init(&mut self, app_handle: AppHandle) -> Result<()> {
-    self.manager = Some(app_handle);
-    let data = Data::global();
-    let verge = data.verge.lock();
-
-    if let Some(hotkeys) = verge.hotkeys.as_ref() {
-      for hotkey in hotkeys.iter() {
-        let mut iter = hotkey.split(',');
-        let func = iter.next();
-        let key = iter.next();
-
-        if func.is_some() && key.is_some() {
-          log_if_err!(self.register(key.unwrap(), func.unwrap()));
-        } else {
-          log::error!(target: "app", "invalid hotkey \"{}\":\"{}\"", key.unwrap_or("None"), func.unwrap_or("None"));
+
+    pub fn init(&mut self, app_handle: AppHandle) -> Result<()> {
+        self.manager = Some(app_handle);
+        let data = Data::global();
+        let verge = data.verge.lock();
+
+        if let Some(hotkeys) = verge.hotkeys.as_ref() {
+            for hotkey in hotkeys.iter() {
+                let mut iter = hotkey.split(',');
+                let func = iter.next();
+                let key = iter.next();
+
+                if func.is_some() && key.is_some() {
+                    log_if_err!(self.register(key.unwrap(), func.unwrap()));
+                } else {
+                    log::error!(target: "app", "invalid hotkey \"{}\":\"{}\"", key.unwrap_or("None"), func.unwrap_or("None"));
+                }
+            }
+            self.current = hotkeys.clone();
         }
-      }
-      self.current = hotkeys.clone();
+
+        Ok(())
     }
 
-    Ok(())
-  }
+    fn get_manager(&self) -> Result<impl GlobalShortcutManager> {
+        if self.manager.is_none() {
+            bail!("failed to get hotkey manager");
+        }
+        Ok(self.manager.as_ref().unwrap().global_shortcut_manager())
+    }
+
+    fn register(&mut self, hotkey: &str, func: &str) -> Result<()> {
+        let mut manager = self.get_manager()?;
+
+        if manager.is_registered(hotkey)? {
+            manager.unregister(hotkey)?;
+        }
+
+        let f = match func.trim() {
+            "clash_mode_rule" => || feat::change_clash_mode("rule"),
+            "clash_mode_global" => || feat::change_clash_mode("global"),
+            "clash_mode_direct" => || feat::change_clash_mode("direct"),
+            "clash_mode_script" => || feat::change_clash_mode("script"),
+            "toggle_system_proxy" => || feat::toggle_system_proxy(),
+            "enable_system_proxy" => || feat::enable_system_proxy(),
+            "disable_system_proxy" => || feat::disable_system_proxy(),
+            "toggle_tun_mode" => || feat::toggle_tun_mode(),
+            "enable_tun_mode" => || feat::enable_tun_mode(),
+            "disable_tun_mode" => || feat::disable_tun_mode(),
+
+            _ => bail!("invalid function \"{func}\""),
+        };
+
+        manager.register(hotkey, f)?;
+        log::info!(target: "app", "register hotkey {hotkey} {func}");
+        Ok(())
+    }
 
-  fn get_manager(&self) -> Result<impl GlobalShortcutManager> {
-    if self.manager.is_none() {
-      bail!("failed to get hotkey manager");
+    fn unregister(&mut self, hotkey: &str) -> Result<()> {
+        self.get_manager()?.unregister(&hotkey)?;
+        log::info!(target: "app", "unregister hotkey {hotkey}");
+        Ok(())
     }
-    Ok(self.manager.as_ref().unwrap().global_shortcut_manager())
-  }
 
-  fn register(&mut self, hotkey: &str, func: &str) -> Result<()> {
-    let mut manager = self.get_manager()?;
+    pub fn update(&mut self, new_hotkeys: Vec<String>) -> Result<()> {
+        let current = self.current.to_owned();
+        let old_map = Self::get_map_from_vec(&current);
+        let new_map = Self::get_map_from_vec(&new_hotkeys);
+
+        let (del, add) = Self::get_diff(old_map, new_map);
+
+        del.iter().for_each(|key| {
+            let _ = self.unregister(key);
+        });
 
-    if manager.is_registered(hotkey)? {
-      manager.unregister(hotkey)?;
+        add.iter().for_each(|(key, func)| {
+            log_if_err!(self.register(key, func));
+        });
+
+        self.current = new_hotkeys;
+        Ok(())
     }
 
-    let f = match func.trim() {
-      "clash_mode_rule" => || feat::change_clash_mode("rule"),
-      "clash_mode_global" => || feat::change_clash_mode("global"),
-      "clash_mode_direct" => || feat::change_clash_mode("direct"),
-      "clash_mode_script" => || feat::change_clash_mode("script"),
-      "toggle_system_proxy" => || feat::toggle_system_proxy(),
-      "enable_system_proxy" => || feat::enable_system_proxy(),
-      "disable_system_proxy" => || feat::disable_system_proxy(),
-      "toggle_tun_mode" => || feat::toggle_tun_mode(),
-      "enable_tun_mode" => || feat::enable_tun_mode(),
-      "disable_tun_mode" => || feat::disable_tun_mode(),
-
-      _ => bail!("invalid function \"{func}\""),
-    };
-
-    manager.register(hotkey, f)?;
-    log::info!(target: "app", "register hotkey {hotkey} {func}");
-    Ok(())
-  }
-
-  fn unregister(&mut self, hotkey: &str) -> Result<()> {
-    self.get_manager()?.unregister(&hotkey)?;
-    log::info!(target: "app", "unregister hotkey {hotkey}");
-    Ok(())
-  }
-
-  pub fn update(&mut self, new_hotkeys: Vec<String>) -> Result<()> {
-    let current = self.current.to_owned();
-    let old_map = Self::get_map_from_vec(&current);
-    let new_map = Self::get_map_from_vec(&new_hotkeys);
-
-    let (del, add) = Self::get_diff(old_map, new_map);
-
-    del.iter().for_each(|key| {
-      let _ = self.unregister(key);
-    });
-
-    add.iter().for_each(|(key, func)| {
-      log_if_err!(self.register(key, func));
-    });
-
-    self.current = new_hotkeys;
-    Ok(())
-  }
-
-  fn get_map_from_vec<'a>(hotkeys: &'a Vec<String>) -> HashMap<&'a str, &'a str> {
-    let mut map = HashMap::new();
-
-    hotkeys.iter().for_each(|hotkey| {
-      let mut iter = hotkey.split(',');
-      let func = iter.next();
-      let key = iter.next();
-
-      if func.is_some() && key.is_some() {
-        let func = func.unwrap().trim();
-        let key = key.unwrap().trim();
-        map.insert(key, func);
-      }
-    });
-    map
-  }
-
-  fn get_diff<'a>(
-    old_map: HashMap<&'a str, &'a str>,
-    new_map: HashMap<&'a str, &'a str>,
-  ) -> (Vec<&'a str>, Vec<(&'a str, &'a str)>) {
-    let mut del_list = vec![];
-    let mut add_list = vec![];
-
-    old_map.iter().for_each(|(&key, func)| {
-      match new_map.get(key) {
-        Some(new_func) => {
-          if new_func != func {
-            del_list.push(key);
-            add_list.push((key, *new_func));
-          }
-        }
-        None => del_list.push(key),
-      };
-    });
-
-    new_map.iter().for_each(|(&key, &func)| {
-      if old_map.get(key).is_none() {
-        add_list.push((key, func));
-      }
-    });
-
-    (del_list, add_list)
-  }
+    fn get_map_from_vec<'a>(hotkeys: &'a Vec<String>) -> HashMap<&'a str, &'a str> {
+        let mut map = HashMap::new();
+
+        hotkeys.iter().for_each(|hotkey| {
+            let mut iter = hotkey.split(',');
+            let func = iter.next();
+            let key = iter.next();
+
+            if func.is_some() && key.is_some() {
+                let func = func.unwrap().trim();
+                let key = key.unwrap().trim();
+                map.insert(key, func);
+            }
+        });
+        map
+    }
+
+    fn get_diff<'a>(
+        old_map: HashMap<&'a str, &'a str>,
+        new_map: HashMap<&'a str, &'a str>,
+    ) -> (Vec<&'a str>, Vec<(&'a str, &'a str)>) {
+        let mut del_list = vec![];
+        let mut add_list = vec![];
+
+        old_map.iter().for_each(|(&key, func)| {
+            match new_map.get(key) {
+                Some(new_func) => {
+                    if new_func != func {
+                        del_list.push(key);
+                        add_list.push((key, *new_func));
+                    }
+                }
+                None => del_list.push(key),
+            };
+        });
+
+        new_map.iter().for_each(|(&key, &func)| {
+            if old_map.get(key).is_none() {
+                add_list.push((key, func));
+            }
+        });
+
+        (del_list, add_list)
+    }
 }
 
 impl Drop for Hotkey {
-  fn drop(&mut self) {
-    if let Ok(mut manager) = self.get_manager() {
-      let _ = manager.unregister_all();
+    fn drop(&mut self) {
+        if let Ok(mut manager) = self.get_manager() {
+            let _ = manager.unregister_all();
+        }
     }
-  }
 }
diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs
index 4cc30ac469d7368245367750ce21b473d0d4ef4d..c91c60996d79cd5f136499e9ace5c6e4819b06e0 100644
--- a/src-tauri/src/core/mod.rs
+++ b/src-tauri/src/core/mod.rs
@@ -22,328 +22,328 @@ pub use self::service::*;
 
 #[derive(Clone)]
 pub struct Core {
-  pub service: Arc<Mutex<Service>>,
-  pub sysopt: Arc<Mutex<Sysopt>>,
-  pub timer: Arc<Mutex<Timer>>,
-  pub hotkey: Arc<Mutex<Hotkey>>,
-  pub runtime: Arc<Mutex<RuntimeResult>>,
-  pub handle: Arc<Mutex<Handle>>,
+    pub service: Arc<Mutex<Service>>,
+    pub sysopt: Arc<Mutex<Sysopt>>,
+    pub timer: Arc<Mutex<Timer>>,
+    pub hotkey: Arc<Mutex<Hotkey>>,
+    pub runtime: Arc<Mutex<RuntimeResult>>,
+    pub handle: Arc<Mutex<Handle>>,
 }
 
 impl Core {
-  pub fn global() -> &'static Core {
-    static CORE: OnceCell<Core> = OnceCell::new();
-
-    CORE.get_or_init(|| Core {
-      service: Arc::new(Mutex::new(Service::new())),
-      sysopt: Arc::new(Mutex::new(Sysopt::new())),
-      timer: Arc::new(Mutex::new(Timer::new())),
-      hotkey: Arc::new(Mutex::new(Hotkey::new())),
-      runtime: Arc::new(Mutex::new(RuntimeResult::default())),
-      handle: Arc::new(Mutex::new(Handle::default())),
-    })
-  }
-
-  /// initialize the core state
-  pub fn init(&self, app_handle: tauri::AppHandle) {
-    // kill old clash process
-    Service::kill_old_clash();
-
-    let mut handle = self.handle.lock();
-    handle.set_inner(app_handle.clone());
-    drop(handle);
-
-    let mut service = self.service.lock();
-    log_if_err!(service.start());
-    drop(service);
-
-    log_if_err!(self.activate());
-
-    let mut sysopt = self.sysopt.lock();
-    log_if_err!(sysopt.init_launch());
-    log_if_err!(sysopt.init_sysproxy());
-    drop(sysopt);
-
-    let handle = self.handle.lock();
-    log_if_err!(handle.update_systray_part());
-    drop(handle);
-
-    let mut hotkey = self.hotkey.lock();
-    log_if_err!(hotkey.init(app_handle));
-    drop(hotkey);
-
-    // timer initialize
-    let mut timer = self.timer.lock();
-    log_if_err!(timer.restore());
-  }
-
-  /// restart the clash sidecar
-  pub fn restart_clash(&self) -> Result<()> {
-    let mut service = self.service.lock();
-    service.restart()?;
-    drop(service);
-    self.activate()
-  }
-
-  /// change the clash core
-  pub fn change_core(&self, clash_core: Option<String>) -> Result<()> {
-    let clash_core = clash_core.unwrap_or("clash".into());
-
-    if &clash_core != "clash" && &clash_core != "clash-meta" {
-      bail!("invalid clash core name \"{clash_core}\"");
+    pub fn global() -> &'static Core {
+        static CORE: OnceCell<Core> = OnceCell::new();
+
+        CORE.get_or_init(|| Core {
+            service: Arc::new(Mutex::new(Service::new())),
+            sysopt: Arc::new(Mutex::new(Sysopt::new())),
+            timer: Arc::new(Mutex::new(Timer::new())),
+            hotkey: Arc::new(Mutex::new(Hotkey::new())),
+            runtime: Arc::new(Mutex::new(RuntimeResult::default())),
+            handle: Arc::new(Mutex::new(Handle::default())),
+        })
     }
 
-    let global = Data::global();
-    let mut verge = global.verge.lock();
-    verge.patch_config(Verge {
-      clash_core: Some(clash_core.clone()),
-      ..Verge::default()
-    })?;
-    drop(verge);
-
-    let mut service = self.service.lock();
-    service.clear_logs();
-    service.restart()?;
-    drop(service);
-
-    self.activate()
-  }
-
-  /// Patch Clash
-  /// handle the clash config changed
-  pub fn patch_clash(&self, patch: Mapping) -> Result<()> {
-    let patch_cloned = patch.clone();
-    let clash_mode = patch.get("mode");
-    let mixed_port = patch.get("mixed-port");
-    let external = patch.get("external-controller");
-    let secret = patch.get("secret");
-
-    let valid_port = {
-      let global = Data::global();
-      let mut clash = global.clash.lock();
-      clash.patch_config(patch_cloned)?;
-      clash.info.port.is_some()
-    };
-
-    // todo: port check
-    if (mixed_port.is_some() && valid_port) || external.is_some() || secret.is_some() {
-      let mut service = self.service.lock();
-      service.restart()?;
-      drop(service);
-
-      self.activate()?;
-
-      let mut sysopt = self.sysopt.lock();
-      sysopt.init_sysproxy()?;
-    }
+    /// initialize the core state
+    pub fn init(&self, app_handle: tauri::AppHandle) {
+        // kill old clash process
+        Service::kill_old_clash();
+
+        let mut handle = self.handle.lock();
+        handle.set_inner(app_handle.clone());
+        drop(handle);
+
+        let mut service = self.service.lock();
+        log_if_err!(service.start());
+        drop(service);
+
+        log_if_err!(self.activate());
+
+        let mut sysopt = self.sysopt.lock();
+        log_if_err!(sysopt.init_launch());
+        log_if_err!(sysopt.init_sysproxy());
+        drop(sysopt);
 
-    if clash_mode.is_some() {
-      let handle = self.handle.lock();
-      handle.update_systray_part()?;
+        let handle = self.handle.lock();
+        log_if_err!(handle.update_systray_part());
+        drop(handle);
+
+        let mut hotkey = self.hotkey.lock();
+        log_if_err!(hotkey.init(app_handle));
+        drop(hotkey);
+
+        // timer initialize
+        let mut timer = self.timer.lock();
+        log_if_err!(timer.restore());
     }
 
-    Ok(())
-  }
-
-  /// Patch Verge
-  pub fn patch_verge(&self, patch: Verge) -> Result<()> {
-    // save the patch
-    let global = Data::global();
-    let mut verge = global.verge.lock();
-    verge.patch_config(patch.clone())?;
-    drop(verge);
-
-    let tun_mode = patch.enable_tun_mode;
-    let auto_launch = patch.enable_auto_launch;
-    let system_proxy = patch.enable_system_proxy;
-    let proxy_bypass = patch.system_proxy_bypass;
-    let proxy_guard = patch.enable_proxy_guard;
-    let language = patch.language;
-
-    #[cfg(target_os = "windows")]
-    {
-      let service_mode = patch.enable_service_mode;
-
-      // 重启服务
-      if service_mode.is_some() {
+    /// restart the clash sidecar
+    pub fn restart_clash(&self) -> Result<()> {
         let mut service = self.service.lock();
         service.restart()?;
         drop(service);
-      }
+        self.activate()
+    }
 
-      if tun_mode.is_some() && *tun_mode.as_ref().unwrap_or(&false) {
-        let wintun_dll = crate::utils::dirs::app_home_dir().join("wintun.dll");
-        if !wintun_dll.exists() {
-          bail!("failed to enable TUN for missing `wintun.dll`");
+    /// change the clash core
+    pub fn change_core(&self, clash_core: Option<String>) -> Result<()> {
+        let clash_core = clash_core.unwrap_or("clash".into());
+
+        if &clash_core != "clash" && &clash_core != "clash-meta" {
+            bail!("invalid clash core name \"{clash_core}\"");
         }
-      }
 
-      if service_mode.is_some() || tun_mode.is_some() {
-        self.activate()?;
-      }
-    }
+        let global = Data::global();
+        let mut verge = global.verge.lock();
+        verge.patch_config(Verge {
+            clash_core: Some(clash_core.clone()),
+            ..Verge::default()
+        })?;
+        drop(verge);
+
+        let mut service = self.service.lock();
+        service.clear_logs();
+        service.restart()?;
+        drop(service);
 
-    #[cfg(not(target_os = "windows"))]
-    if tun_mode.is_some() {
-      self.activate()?;
+        self.activate()
     }
 
-    let mut sysopt = self.sysopt.lock();
+    /// Patch Clash
+    /// handle the clash config changed
+    pub fn patch_clash(&self, patch: Mapping) -> Result<()> {
+        let patch_cloned = patch.clone();
+        let clash_mode = patch.get("mode");
+        let mixed_port = patch.get("mixed-port");
+        let external = patch.get("external-controller");
+        let secret = patch.get("secret");
+
+        let valid_port = {
+            let global = Data::global();
+            let mut clash = global.clash.lock();
+            clash.patch_config(patch_cloned)?;
+            clash.info.port.is_some()
+        };
+
+        // todo: port check
+        if (mixed_port.is_some() && valid_port) || external.is_some() || secret.is_some() {
+            let mut service = self.service.lock();
+            service.restart()?;
+            drop(service);
 
-    if auto_launch.is_some() {
-      sysopt.update_launch()?;
-    }
-    if system_proxy.is_some() || proxy_bypass.is_some() {
-      sysopt.update_sysproxy()?;
-      sysopt.guard_proxy();
+            self.activate()?;
+
+            let mut sysopt = self.sysopt.lock();
+            sysopt.init_sysproxy()?;
+        }
+
+        if clash_mode.is_some() {
+            let handle = self.handle.lock();
+            handle.update_systray_part()?;
+        }
+
+        Ok(())
     }
-    if proxy_guard.unwrap_or(false) {
-      sysopt.guard_proxy();
+
+    /// Patch Verge
+    pub fn patch_verge(&self, patch: Verge) -> Result<()> {
+        // save the patch
+        let global = Data::global();
+        let mut verge = global.verge.lock();
+        verge.patch_config(patch.clone())?;
+        drop(verge);
+
+        let tun_mode = patch.enable_tun_mode;
+        let auto_launch = patch.enable_auto_launch;
+        let system_proxy = patch.enable_system_proxy;
+        let proxy_bypass = patch.system_proxy_bypass;
+        let proxy_guard = patch.enable_proxy_guard;
+        let language = patch.language;
+
+        #[cfg(target_os = "windows")]
+        {
+            let service_mode = patch.enable_service_mode;
+
+            // 重启服务
+            if service_mode.is_some() {
+                let mut service = self.service.lock();
+                service.restart()?;
+                drop(service);
+            }
+
+            if tun_mode.is_some() && *tun_mode.as_ref().unwrap_or(&false) {
+                let wintun_dll = crate::utils::dirs::app_home_dir().join("wintun.dll");
+                if !wintun_dll.exists() {
+                    bail!("failed to enable TUN for missing `wintun.dll`");
+                }
+            }
+
+            if service_mode.is_some() || tun_mode.is_some() {
+                self.activate()?;
+            }
+        }
+
+        #[cfg(not(target_os = "windows"))]
+        if tun_mode.is_some() {
+            self.activate()?;
+        }
+
+        let mut sysopt = self.sysopt.lock();
+
+        if auto_launch.is_some() {
+            sysopt.update_launch()?;
+        }
+        if system_proxy.is_some() || proxy_bypass.is_some() {
+            sysopt.update_sysproxy()?;
+            sysopt.guard_proxy();
+        }
+        if proxy_guard.unwrap_or(false) {
+            sysopt.guard_proxy();
+        }
+
+        // æ›´æ–°tray
+        if language.is_some() {
+            let handle = self.handle.lock();
+            handle.update_systray()?;
+        } else if system_proxy.is_some() || tun_mode.is_some() {
+            let handle = self.handle.lock();
+            handle.update_systray_part()?;
+        }
+
+        if patch.hotkeys.is_some() {
+            let mut hotkey = self.hotkey.lock();
+            hotkey.update(patch.hotkeys.unwrap())?;
+        }
+
+        Ok(())
     }
 
-    // æ›´æ–°tray
-    if language.is_some() {
-      let handle = self.handle.lock();
-      handle.update_systray()?;
-    } else if system_proxy.is_some() || tun_mode.is_some() {
-      let handle = self.handle.lock();
-      handle.update_systray_part()?;
+    // update rule/global/direct/script mode
+    pub fn update_mode(&self, mode: &str) -> Result<()> {
+        // save config to file
+        let info = {
+            let global = Data::global();
+            let mut clash = global.clash.lock();
+            clash.config.insert(Value::from("mode"), Value::from(mode));
+            clash.save_config()?;
+            clash.info.clone()
+        };
+
+        let mut mapping = Mapping::new();
+        mapping.insert(Value::from("mode"), Value::from(mode));
+
+        let handle = self.handle.clone();
+
+        tauri::async_runtime::spawn(async move {
+            log_if_err!(Service::patch_config(info, mapping.to_owned()).await);
+
+            // update tray
+            let handle = handle.lock();
+            handle.refresh_clash();
+            log_if_err!(handle.update_systray_part());
+        });
+
+        Ok(())
     }
 
-    if patch.hotkeys.is_some() {
-      let mut hotkey = self.hotkey.lock();
-      hotkey.update(patch.hotkeys.unwrap())?;
+    /// activate the profile
+    /// auto activate enhanced profile
+    /// 触发clash配置更新
+    pub fn activate(&self) -> Result<()> {
+        let global = Data::global();
+
+        let verge = global.verge.lock();
+        let clash = global.clash.lock();
+        let profiles = global.profiles.lock();
+
+        let tun_mode = verge.enable_tun_mode.clone().unwrap_or(false);
+        let profile_activate = profiles.gen_activate()?;
+
+        let clash_config = clash.config.clone();
+        let clash_info = clash.info.clone();
+
+        drop(clash);
+        drop(verge);
+        drop(profiles);
+
+        let (config, exists_keys, logs) = enhance_config(
+            clash_config,
+            profile_activate.current,
+            profile_activate.chain,
+            profile_activate.valid,
+            tun_mode,
+        );
+
+        let mut runtime = self.runtime.lock();
+        *runtime = RuntimeResult {
+            config: Some(config.clone()),
+            config_yaml: Some(serde_yaml::to_string(&config).unwrap_or("".into())),
+            exists_keys,
+            chain_logs: logs,
+        };
+        drop(runtime);
+
+        let mut service = self.service.lock();
+        service.check_start()?;
+        drop(service);
+
+        let handle = self.handle.clone();
+        tauri::async_runtime::spawn(async move {
+            match Service::set_config(clash_info, config).await {
+                Ok(_) => {
+                    let handle = handle.lock();
+                    handle.refresh_clash();
+                    handle.notice_message("set_config::ok".into(), "ok".into());
+                }
+                Err(err) => {
+                    let handle = handle.lock();
+                    handle.notice_message("set_config::error".into(), format!("{err}"));
+                    log::error!(target: "app", "{err}")
+                }
+            }
+        });
+
+        Ok(())
     }
 
-    Ok(())
-  }
-
-  // update rule/global/direct/script mode
-  pub fn update_mode(&self, mode: &str) -> Result<()> {
-    // save config to file
-    let info = {
-      let global = Data::global();
-      let mut clash = global.clash.lock();
-      clash.config.insert(Value::from("mode"), Value::from(mode));
-      clash.save_config()?;
-      clash.info.clone()
-    };
-
-    let mut mapping = Mapping::new();
-    mapping.insert(Value::from("mode"), Value::from(mode));
-
-    let handle = self.handle.clone();
-
-    tauri::async_runtime::spawn(async move {
-      log_if_err!(Service::patch_config(info, mapping.to_owned()).await);
-
-      // update tray
-      let handle = handle.lock();
-      handle.refresh_clash();
-      log_if_err!(handle.update_systray_part());
-    });
-
-    Ok(())
-  }
-
-  /// activate the profile
-  /// auto activate enhanced profile
-  /// 触发clash配置更新
-  pub fn activate(&self) -> Result<()> {
-    let global = Data::global();
-
-    let verge = global.verge.lock();
-    let clash = global.clash.lock();
-    let profiles = global.profiles.lock();
-
-    let tun_mode = verge.enable_tun_mode.clone().unwrap_or(false);
-    let profile_activate = profiles.gen_activate()?;
-
-    let clash_config = clash.config.clone();
-    let clash_info = clash.info.clone();
-
-    drop(clash);
-    drop(verge);
-    drop(profiles);
-
-    let (config, exists_keys, logs) = enhance_config(
-      clash_config,
-      profile_activate.current,
-      profile_activate.chain,
-      profile_activate.valid,
-      tun_mode,
-    );
-
-    let mut runtime = self.runtime.lock();
-    *runtime = RuntimeResult {
-      config: Some(config.clone()),
-      config_yaml: Some(serde_yaml::to_string(&config).unwrap_or("".into())),
-      exists_keys,
-      chain_logs: logs,
-    };
-    drop(runtime);
-
-    let mut service = self.service.lock();
-    service.check_start()?;
-    drop(service);
-
-    let handle = self.handle.clone();
-    tauri::async_runtime::spawn(async move {
-      match Service::set_config(clash_info, config).await {
-        Ok(_) => {
-          let handle = handle.lock();
-          handle.refresh_clash();
-          handle.notice_message("set_config::ok".into(), "ok".into());
-        }
-        Err(err) => {
-          let handle = handle.lock();
-          handle.notice_message("set_config::error".into(), format!("{err}"));
-          log::error!(target: "app", "{err}")
-        }
-      }
-    });
-
-    Ok(())
-  }
-
-  /// Static function
-  /// update profile item
-  pub async fn update_profile_item(&self, uid: String, option: Option<PrfOption>) -> Result<()> {
-    let global = Data::global();
-
-    let (url, opt) = {
-      let profiles = global.profiles.lock();
-      let item = profiles.get_item(&uid)?;
-
-      if let Some(typ) = item.itype.as_ref() {
-        // maybe only valid for `local` profile
-        if *typ != "remote" {
-          // reactivate the config
-          if Some(uid) == profiles.get_current() {
+    /// Static function
+    /// update profile item
+    pub async fn update_profile_item(&self, uid: String, option: Option<PrfOption>) -> Result<()> {
+        let global = Data::global();
+
+        let (url, opt) = {
+            let profiles = global.profiles.lock();
+            let item = profiles.get_item(&uid)?;
+
+            if let Some(typ) = item.itype.as_ref() {
+                // maybe only valid for `local` profile
+                if *typ != "remote" {
+                    // reactivate the config
+                    if Some(uid) == profiles.get_current() {
+                        drop(profiles);
+                        self.activate()?;
+                    }
+                    return Ok(());
+                }
+            }
+            if item.url.is_none() {
+                bail!("failed to get the profile item url");
+            }
+            (item.url.clone().unwrap(), item.option.clone())
+        };
+
+        let merged_opt = PrfOption::merge(opt, option);
+        let item = PrfItem::from_url(&url, None, None, merged_opt).await?;
+
+        let mut profiles = global.profiles.lock();
+        profiles.update_item(uid.clone(), item)?;
+
+        // reactivate the profile
+        if Some(uid) == profiles.get_current() {
             drop(profiles);
             self.activate()?;
-          }
-          return Ok(());
         }
-      }
-      if item.url.is_none() {
-        bail!("failed to get the profile item url");
-      }
-      (item.url.clone().unwrap(), item.option.clone())
-    };
-
-    let merged_opt = PrfOption::merge(opt, option);
-    let item = PrfItem::from_url(&url, None, None, merged_opt).await?;
-
-    let mut profiles = global.profiles.lock();
-    profiles.update_item(uid.clone(), item)?;
-
-    // reactivate the profile
-    if Some(uid) == profiles.get_current() {
-      drop(profiles);
-      self.activate()?;
-    }
 
-    Ok(())
-  }
+        Ok(())
+    }
 }
diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs
index 8cc2ed7eabc3a8f2e28028db1f8f4abc11880290..21fb7ed0fb0909230f0fed04c2ce1f6cb5a8e8f6 100644
--- a/src-tauri/src/core/service.rs
+++ b/src-tauri/src/core/service.rs
@@ -9,8 +9,8 @@ use std::fs;
 use std::io::Write;
 use std::sync::Arc;
 use std::{
-  collections::{HashMap, VecDeque},
-  time::Duration,
+    collections::{HashMap, VecDeque},
+    time::Duration,
 };
 use tauri::api::process::{Command, CommandChild, CommandEvent};
 use tokio::time::sleep;
@@ -19,209 +19,209 @@ const LOGS_QUEUE_LEN: usize = 100;
 
 #[derive(Debug)]
 pub struct Service {
-  sidecar: Option<CommandChild>,
+    sidecar: Option<CommandChild>,
 
-  logs: Arc<RwLock<VecDeque<String>>>,
+    logs: Arc<RwLock<VecDeque<String>>>,
 
-  #[allow(unused)]
-  use_service_mode: bool,
+    #[allow(unused)]
+    use_service_mode: bool,
 }
 
 impl Service {
-  pub fn new() -> Service {
-    let queue = VecDeque::with_capacity(LOGS_QUEUE_LEN + 10);
+    pub fn new() -> Service {
+        let queue = VecDeque::with_capacity(LOGS_QUEUE_LEN + 10);
 
-    Service {
-      sidecar: None,
-      logs: Arc::new(RwLock::new(queue)),
-      use_service_mode: false,
+        Service {
+            sidecar: None,
+            logs: Arc::new(RwLock::new(queue)),
+            use_service_mode: false,
+        }
     }
-  }
-
-  pub fn start(&mut self) -> Result<()> {
-    #[cfg(not(target_os = "windows"))]
-    self.start_clash_by_sidecar()?;
-
-    #[cfg(target_os = "windows")]
-    {
-      let enable = {
-        let data = Data::global();
-        let verge = data.verge.lock();
-        verge.enable_service_mode.clone().unwrap_or(false)
-      };
 
-      self.use_service_mode = enable;
+    pub fn start(&mut self) -> Result<()> {
+        #[cfg(not(target_os = "windows"))]
+        self.start_clash_by_sidecar()?;
+
+        #[cfg(target_os = "windows")]
+        {
+            let enable = {
+                let data = Data::global();
+                let verge = data.verge.lock();
+                verge.enable_service_mode.clone().unwrap_or(false)
+            };
 
-      if !enable {
-        return self.start_clash_by_sidecar();
-      }
+            self.use_service_mode = enable;
 
-      tauri::async_runtime::spawn(async move {
-        match Self::check_service().await {
-          Ok(status) => {
-            // 未启动clash
-            if status.code != 0 {
-              log_if_err!(Self::start_clash_by_service().await);
+            if !enable {
+                return self.start_clash_by_sidecar();
             }
-          }
-          Err(err) => log::error!(target: "app", "{err}"),
+
+            tauri::async_runtime::spawn(async move {
+                match Self::check_service().await {
+                    Ok(status) => {
+                        // 未启动clash
+                        if status.code != 0 {
+                            log_if_err!(Self::start_clash_by_service().await);
+                        }
+                    }
+                    Err(err) => log::error!(target: "app", "{err}"),
+                }
+            });
         }
-      });
+
+        Ok(())
     }
 
-    Ok(())
-  }
+    pub fn stop(&mut self) -> Result<()> {
+        #[cfg(not(target_os = "windows"))]
+        self.stop_clash_by_sidecar()?;
 
-  pub fn stop(&mut self) -> Result<()> {
-    #[cfg(not(target_os = "windows"))]
-    self.stop_clash_by_sidecar()?;
+        #[cfg(target_os = "windows")]
+        {
+            let _ = self.stop_clash_by_sidecar();
 
-    #[cfg(target_os = "windows")]
-    {
-      let _ = self.stop_clash_by_sidecar();
+            if self.use_service_mode {
+                tauri::async_runtime::block_on(async move {
+                    log_if_err!(Self::stop_clash_by_service().await);
+                });
+            }
+        }
 
-      if self.use_service_mode {
-        tauri::async_runtime::block_on(async move {
-          log_if_err!(Self::stop_clash_by_service().await);
-        });
-      }
+        Ok(())
     }
 
-    Ok(())
-  }
-
-  pub fn restart(&mut self) -> Result<()> {
-    self.stop()?;
-    self.start()
-  }
-
-  pub fn get_logs(&self) -> VecDeque<String> {
-    self.logs.read().clone()
-  }
-
-  #[allow(unused)]
-  pub fn set_logs(&self, text: String) {
-    let mut logs = self.logs.write();
-    if logs.len() > LOGS_QUEUE_LEN {
-      (*logs).pop_front();
+    pub fn restart(&mut self) -> Result<()> {
+        self.stop()?;
+        self.start()
     }
-    (*logs).push_back(text);
-  }
-
-  pub fn clear_logs(&self) {
-    let mut logs = self.logs.write();
-    (*logs).clear();
-  }
-
-  /// start the clash sidecar
-  fn start_clash_by_sidecar(&mut self) -> Result<()> {
-    if self.sidecar.is_some() {
-      let sidecar = self.sidecar.take().unwrap();
-      let _ = sidecar.kill();
+
+    pub fn get_logs(&self) -> VecDeque<String> {
+        self.logs.read().clone()
     }
 
-    let clash_core: String = {
-      let global = Data::global();
-      let verge = global.verge.lock();
-      verge.clash_core.clone().unwrap_or("clash".into())
-    };
-
-    let app_dir = dirs::app_home_dir();
-    let app_dir = app_dir.as_os_str().to_str().unwrap();
-
-    // fix #212
-    let args = match clash_core.as_str() {
-      "clash-meta" => vec!["-m", "-d", app_dir],
-      _ => vec!["-d", app_dir],
-    };
-
-    let cmd = Command::new_sidecar(clash_core)?;
-
-    let (mut rx, cmd_child) = cmd.args(args).spawn()?;
-
-    // 将pid写入文件中
-    let pid = cmd_child.pid();
-    log_if_err!(|| -> Result<()> {
-      let path = dirs::clash_pid_path();
-      fs::File::create(path)?.write(format!("{pid}").as_bytes())?;
-      Ok(())
-    }());
-
-    self.sidecar = Some(cmd_child);
-
-    // clash log
-    let logs = self.logs.clone();
-    tauri::async_runtime::spawn(async move {
-      let write_log = |text: String| {
-        let mut logs = logs.write();
-        if logs.len() >= LOGS_QUEUE_LEN {
-          (*logs).pop_front();
+    #[allow(unused)]
+    pub fn set_logs(&self, text: String) {
+        let mut logs = self.logs.write();
+        if logs.len() > LOGS_QUEUE_LEN {
+            (*logs).pop_front();
         }
         (*logs).push_back(text);
-      };
+    }
+
+    pub fn clear_logs(&self) {
+        let mut logs = self.logs.write();
+        (*logs).clear();
+    }
 
-      while let Some(event) = rx.recv().await {
-        match event {
-          CommandEvent::Stdout(line) => {
-            let can_short = line.starts_with("time=") && line.len() > 33;
-            let stdout = if can_short { &line[33..] } else { &line };
-            log::info!(target: "app" ,"[clash]: {}", stdout);
-            write_log(line);
-          }
-          CommandEvent::Stderr(err) => {
-            log::error!(target: "app" ,"[clash error]: {}", err);
-            write_log(err);
-          }
-          CommandEvent::Error(err) => log::error!(target: "app" ,"{err}"),
-          CommandEvent::Terminated(_) => break,
-          _ => {}
+    /// start the clash sidecar
+    fn start_clash_by_sidecar(&mut self) -> Result<()> {
+        if self.sidecar.is_some() {
+            let sidecar = self.sidecar.take().unwrap();
+            let _ = sidecar.kill();
         }
-      }
-    });
 
-    Ok(())
-  }
+        let clash_core: String = {
+            let global = Data::global();
+            let verge = global.verge.lock();
+            verge.clash_core.clone().unwrap_or("clash".into())
+        };
+
+        let app_dir = dirs::app_home_dir();
+        let app_dir = app_dir.as_os_str().to_str().unwrap();
+
+        // fix #212
+        let args = match clash_core.as_str() {
+            "clash-meta" => vec!["-m", "-d", app_dir],
+            _ => vec!["-d", app_dir],
+        };
+
+        let cmd = Command::new_sidecar(clash_core)?;
+
+        let (mut rx, cmd_child) = cmd.args(args).spawn()?;
+
+        // 将pid写入文件中
+        let pid = cmd_child.pid();
+        log_if_err!(|| -> Result<()> {
+            let path = dirs::clash_pid_path();
+            fs::File::create(path)?.write(format!("{pid}").as_bytes())?;
+            Ok(())
+        }());
+
+        self.sidecar = Some(cmd_child);
+
+        // clash log
+        let logs = self.logs.clone();
+        tauri::async_runtime::spawn(async move {
+            let write_log = |text: String| {
+                let mut logs = logs.write();
+                if logs.len() >= LOGS_QUEUE_LEN {
+                    (*logs).pop_front();
+                }
+                (*logs).push_back(text);
+            };
+
+            while let Some(event) = rx.recv().await {
+                match event {
+                    CommandEvent::Stdout(line) => {
+                        let can_short = line.starts_with("time=") && line.len() > 33;
+                        let stdout = if can_short { &line[33..] } else { &line };
+                        log::info!(target: "app" ,"[clash]: {}", stdout);
+                        write_log(line);
+                    }
+                    CommandEvent::Stderr(err) => {
+                        log::error!(target: "app" ,"[clash error]: {}", err);
+                        write_log(err);
+                    }
+                    CommandEvent::Error(err) => log::error!(target: "app" ,"{err}"),
+                    CommandEvent::Terminated(_) => break,
+                    _ => {}
+                }
+            }
+        });
 
-  /// stop the clash sidecar
-  fn stop_clash_by_sidecar(&mut self) -> Result<()> {
-    if let Some(sidecar) = self.sidecar.take() {
-      sidecar.kill()?;
-    }
-    Ok(())
-  }
-
-  pub fn check_start(&mut self) -> Result<()> {
-    #[cfg(target_os = "windows")]
-    {
-      let global = Data::global();
-      let verge = global.verge.lock();
-      let service_mode = verge.enable_service_mode.unwrap_or(false);
-
-      if !service_mode && self.sidecar.is_none() {
-        self.start()?;
-      }
+        Ok(())
     }
 
-    #[cfg(not(target_os = "windows"))]
-    if self.sidecar.is_none() {
-      self.start()?;
+    /// stop the clash sidecar
+    fn stop_clash_by_sidecar(&mut self) -> Result<()> {
+        if let Some(sidecar) = self.sidecar.take() {
+            sidecar.kill()?;
+        }
+        Ok(())
     }
 
-    Ok(())
-  }
+    pub fn check_start(&mut self) -> Result<()> {
+        #[cfg(target_os = "windows")]
+        {
+            let global = Data::global();
+            let verge = global.verge.lock();
+            let service_mode = verge.enable_service_mode.unwrap_or(false);
+
+            if !service_mode && self.sidecar.is_none() {
+                self.start()?;
+            }
+        }
+
+        #[cfg(not(target_os = "windows"))]
+        if self.sidecar.is_none() {
+            self.start()?;
+        }
+
+        Ok(())
+    }
 
-  /// update clash config
-  /// using PUT methods
-  pub async fn set_config(info: ClashInfo, config: Mapping) -> Result<()> {
-    let temp_path = dirs::profiles_temp_path();
-    config::save_yaml(temp_path.clone(), &config, Some("# Clash Verge Temp File"))?;
+    /// update clash config
+    /// using PUT methods
+    pub async fn set_config(info: ClashInfo, config: Mapping) -> Result<()> {
+        let temp_path = dirs::profiles_temp_path();
+        config::save_yaml(temp_path.clone(), &config, Some("# Clash Verge Temp File"))?;
 
-    let (server, headers) = Self::clash_client_info(info)?;
+        let (server, headers) = Self::clash_client_info(info)?;
 
-    let mut data = HashMap::new();
-    data.insert("path", temp_path.as_os_str().to_str().unwrap());
+        let mut data = HashMap::new();
+        data.insert("path", temp_path.as_os_str().to_str().unwrap());
 
-    macro_rules! report_err {
+        macro_rules! report_err {
       ($i: expr, $e: expr) => {
         match $i {
           4 => bail!($e),
@@ -230,306 +230,308 @@ impl Service {
       };
     }
 
-    // retry 5 times
-    for i in 0..5 {
-      let headers = headers.clone();
-      match reqwest::ClientBuilder::new().no_proxy().build() {
-        Ok(client) => {
-          let builder = client.put(&server).headers(headers).json(&data);
-          match builder.send().await {
-            Ok(resp) => match resp.status().as_u16() {
-              204 => break,
-              // 配置有问题不重试
-              400 => bail!("failed to update clash config with status 400"),
-              status @ _ => report_err!(i, "failed to activate clash with status \"{status}\""),
-            },
-            Err(err) => report_err!(i, "{err}"),
-          }
+        // retry 5 times
+        for i in 0..5 {
+            let headers = headers.clone();
+            match reqwest::ClientBuilder::new().no_proxy().build() {
+                Ok(client) => {
+                    let builder = client.put(&server).headers(headers).json(&data);
+                    match builder.send().await {
+                        Ok(resp) => match resp.status().as_u16() {
+                            204 => break,
+                            // 配置有问题不重试
+                            400 => bail!("failed to update clash config with status 400"),
+                            status @ _ => {
+                                report_err!(i, "failed to activate clash with status \"{status}\"")
+                            }
+                        },
+                        Err(err) => report_err!(i, "{err}"),
+                    }
+                }
+                Err(err) => report_err!(i, "{err}"),
+            }
+            sleep(Duration::from_millis(500)).await;
         }
-        Err(err) => report_err!(i, "{err}"),
-      }
-      sleep(Duration::from_millis(500)).await;
+
+        Ok(())
     }
 
-    Ok(())
-  }
-
-  /// patch clash config
-  pub async fn patch_config(info: ClashInfo, config: Mapping) -> Result<()> {
-    let (server, headers) = Self::clash_client_info(info)?;
-
-    let client = reqwest::ClientBuilder::new().no_proxy().build()?;
-    let builder = client.patch(&server).headers(headers.clone()).json(&config);
-    builder.send().await?;
-    Ok(())
-  }
-
-  /// get clash client url and headers from clash info
-  fn clash_client_info(info: ClashInfo) -> Result<(String, HeaderMap)> {
-    if info.server.is_none() {
-      let status = &info.status;
-      if info.port.is_none() {
-        bail!("failed to parse config.yaml file with status {status}");
-      } else {
-        bail!("failed to parse the server with status {status}");
-      }
+    /// patch clash config
+    pub async fn patch_config(info: ClashInfo, config: Mapping) -> Result<()> {
+        let (server, headers) = Self::clash_client_info(info)?;
+
+        let client = reqwest::ClientBuilder::new().no_proxy().build()?;
+        let builder = client.patch(&server).headers(headers.clone()).json(&config);
+        builder.send().await?;
+        Ok(())
     }
 
-    let server = info.server.unwrap();
-    let server = format!("http://{server}/configs");
+    /// get clash client url and headers from clash info
+    fn clash_client_info(info: ClashInfo) -> Result<(String, HeaderMap)> {
+        if info.server.is_none() {
+            let status = &info.status;
+            if info.port.is_none() {
+                bail!("failed to parse config.yaml file with status {status}");
+            } else {
+                bail!("failed to parse the server with status {status}");
+            }
+        }
 
-    let mut headers = HeaderMap::new();
-    headers.insert("Content-Type", "application/json".parse().unwrap());
+        let server = info.server.unwrap();
+        let server = format!("http://{server}/configs");
 
-    if let Some(secret) = info.secret.as_ref() {
-      let secret = format!("Bearer {}", secret.clone()).parse().unwrap();
-      headers.insert("Authorization", secret);
-    }
+        let mut headers = HeaderMap::new();
+        headers.insert("Content-Type", "application/json".parse().unwrap());
 
-    Ok((server, headers))
-  }
+        if let Some(secret) = info.secret.as_ref() {
+            let secret = format!("Bearer {}", secret.clone()).parse().unwrap();
+            headers.insert("Authorization", secret);
+        }
+
+        Ok((server, headers))
+    }
 
-  /// kill old clash process
-  pub fn kill_old_clash() {
-    use sysinfo::{Pid, PidExt, ProcessExt, System, SystemExt};
+    /// kill old clash process
+    pub fn kill_old_clash() {
+        use sysinfo::{Pid, PidExt, ProcessExt, System, SystemExt};
 
-    if let Ok(pid) = fs::read(dirs::clash_pid_path()) {
-      if let Ok(pid) = String::from_utf8_lossy(&pid).parse() {
-        let mut system = System::new();
-        system.refresh_all();
+        if let Ok(pid) = fs::read(dirs::clash_pid_path()) {
+            if let Ok(pid) = String::from_utf8_lossy(&pid).parse() {
+                let mut system = System::new();
+                system.refresh_all();
 
-        let proc = system.process(Pid::from_u32(pid));
-        if let Some(proc) = proc {
-          proc.kill();
+                let proc = system.process(Pid::from_u32(pid));
+                if let Some(proc) = proc {
+                    proc.kill();
+                }
+            }
         }
-      }
     }
-  }
 }
 
 impl Drop for Service {
-  fn drop(&mut self) {
-    log_if_err!(self.stop());
-  }
+    fn drop(&mut self) {
+        log_if_err!(self.stop());
+    }
 }
 
 /// ### Service Mode
 ///
 #[cfg(target_os = "windows")]
 pub mod win_service {
-  use super::*;
-  use anyhow::Context;
-  use deelevate::{PrivilegeLevel, Token};
-  use runas::Command as RunasCommand;
-  use serde::{Deserialize, Serialize};
-  use std::os::windows::process::CommandExt;
-  use std::{env::current_exe, process::Command as StdCommand};
-
-  const SERVICE_NAME: &str = "clash_verge_service";
-
-  const SERVICE_URL: &str = "http://127.0.0.1:33211";
-
-  #[derive(Debug, Deserialize, Serialize, Clone)]
-  pub struct ResponseBody {
-    pub bin_path: String,
-    pub config_dir: String,
-    pub log_file: String,
-  }
-
-  #[derive(Debug, Deserialize, Serialize, Clone)]
-  pub struct JsonResponse {
-    pub code: u64,
-    pub msg: String,
-    pub data: Option<ResponseBody>,
-  }
-
-  impl Service {
-    /// Install the Clash Verge Service
-    /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
-    pub async fn install_service() -> Result<()> {
-      let binary_path = dirs::service_path();
-      let install_path = binary_path.with_file_name("install-service.exe");
-
-      if !install_path.exists() {
-        bail!("installer exe not found");
-      }
-
-      let token = Token::with_current_process()?;
-      let level = token.privilege_level()?;
-
-      let status = match level {
-        PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).status()?,
-        _ => StdCommand::new(install_path)
-          .creation_flags(0x08000000)
-          .status()?,
-      };
-
-      if !status.success() {
-        bail!(
-          "failed to install service with status {}",
-          status.code().unwrap()
-        );
-      }
+    use super::*;
+    use anyhow::Context;
+    use deelevate::{PrivilegeLevel, Token};
+    use runas::Command as RunasCommand;
+    use serde::{Deserialize, Serialize};
+    use std::os::windows::process::CommandExt;
+    use std::{env::current_exe, process::Command as StdCommand};
+
+    const SERVICE_NAME: &str = "clash_verge_service";
+
+    const SERVICE_URL: &str = "http://127.0.0.1:33211";
+
+    #[derive(Debug, Deserialize, Serialize, Clone)]
+    pub struct ResponseBody {
+        pub bin_path: String,
+        pub config_dir: String,
+        pub log_file: String,
+    }
 
-      Ok(())
+    #[derive(Debug, Deserialize, Serialize, Clone)]
+    pub struct JsonResponse {
+        pub code: u64,
+        pub msg: String,
+        pub data: Option<ResponseBody>,
     }
 
-    /// Uninstall the Clash Verge Service
-    /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
-    pub async fn uninstall_service() -> Result<()> {
-      let binary_path = dirs::service_path();
-      let uninstall_path = binary_path.with_file_name("uninstall-service.exe");
+    impl Service {
+        /// Install the Clash Verge Service
+        /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
+        pub async fn install_service() -> Result<()> {
+            let binary_path = dirs::service_path();
+            let install_path = binary_path.with_file_name("install-service.exe");
 
-      if !uninstall_path.exists() {
-        bail!("uninstaller exe not found");
-      }
+            if !install_path.exists() {
+                bail!("installer exe not found");
+            }
 
-      let token = Token::with_current_process()?;
-      let level = token.privilege_level()?;
+            let token = Token::with_current_process()?;
+            let level = token.privilege_level()?;
+
+            let status = match level {
+                PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).status()?,
+                _ => StdCommand::new(install_path)
+                    .creation_flags(0x08000000)
+                    .status()?,
+            };
+
+            if !status.success() {
+                bail!(
+                    "failed to install service with status {}",
+                    status.code().unwrap()
+                );
+            }
 
-      let status = match level {
-        PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).status()?,
-        _ => StdCommand::new(uninstall_path)
-          .creation_flags(0x08000000)
-          .status()?,
-      };
+            Ok(())
+        }
 
-      if !status.success() {
-        bail!(
-          "failed to uninstall service with status {}",
-          status.code().unwrap()
-        );
-      }
+        /// Uninstall the Clash Verge Service
+        /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
+        pub async fn uninstall_service() -> Result<()> {
+            let binary_path = dirs::service_path();
+            let uninstall_path = binary_path.with_file_name("uninstall-service.exe");
 
-      Ok(())
-    }
+            if !uninstall_path.exists() {
+                bail!("uninstaller exe not found");
+            }
 
-    /// [deprecated]
-    /// start service
-    /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
-    pub async fn start_service() -> Result<()> {
-      let token = Token::with_current_process()?;
-      let level = token.privilege_level()?;
+            let token = Token::with_current_process()?;
+            let level = token.privilege_level()?;
+
+            let status = match level {
+                PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).status()?,
+                _ => StdCommand::new(uninstall_path)
+                    .creation_flags(0x08000000)
+                    .status()?,
+            };
+
+            if !status.success() {
+                bail!(
+                    "failed to uninstall service with status {}",
+                    status.code().unwrap()
+                );
+            }
 
-      let args = ["start", SERVICE_NAME];
+            Ok(())
+        }
 
-      let status = match level {
-        PrivilegeLevel::NotPrivileged => RunasCommand::new("sc").args(&args).status()?,
-        _ => StdCommand::new("sc").args(&args).status()?,
-      };
+        /// [deprecated]
+        /// start service
+        /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
+        pub async fn start_service() -> Result<()> {
+            let token = Token::with_current_process()?;
+            let level = token.privilege_level()?;
+
+            let args = ["start", SERVICE_NAME];
+
+            let status = match level {
+                PrivilegeLevel::NotPrivileged => RunasCommand::new("sc").args(&args).status()?,
+                _ => StdCommand::new("sc").args(&args).status()?,
+            };
+
+            match status.success() {
+                true => Ok(()),
+                false => bail!(
+                    "failed to start service with status {}",
+                    status.code().unwrap()
+                ),
+            }
+        }
 
-      match status.success() {
-        true => Ok(()),
-        false => bail!(
-          "failed to start service with status {}",
-          status.code().unwrap()
-        ),
-      }
-    }
+        /// stop service
+        pub async fn stop_service() -> Result<()> {
+            let url = format!("{SERVICE_URL}/stop_service");
+            let res = reqwest::ClientBuilder::new()
+                .no_proxy()
+                .build()?
+                .post(url)
+                .send()
+                .await?
+                .json::<JsonResponse>()
+                .await
+                .context("failed to connect to the Clash Verge Service")?;
+
+            if res.code != 0 {
+                bail!(res.msg);
+            }
 
-    /// stop service
-    pub async fn stop_service() -> Result<()> {
-      let url = format!("{SERVICE_URL}/stop_service");
-      let res = reqwest::ClientBuilder::new()
-        .no_proxy()
-        .build()?
-        .post(url)
-        .send()
-        .await?
-        .json::<JsonResponse>()
-        .await
-        .context("failed to connect to the Clash Verge Service")?;
-
-      if res.code != 0 {
-        bail!(res.msg);
-      }
-
-      Ok(())
-    }
+            Ok(())
+        }
 
-    /// check the windows service status
-    pub async fn check_service() -> Result<JsonResponse> {
-      let url = format!("{SERVICE_URL}/get_clash");
-      let response = reqwest::ClientBuilder::new()
-        .no_proxy()
-        .build()?
-        .get(url)
-        .send()
-        .await?
-        .json::<JsonResponse>()
-        .await
-        .context("failed to connect to the Clash Verge Service")?;
-
-      Ok(response)
-    }
+        /// check the windows service status
+        pub async fn check_service() -> Result<JsonResponse> {
+            let url = format!("{SERVICE_URL}/get_clash");
+            let response = reqwest::ClientBuilder::new()
+                .no_proxy()
+                .build()?
+                .get(url)
+                .send()
+                .await?
+                .json::<JsonResponse>()
+                .await
+                .context("failed to connect to the Clash Verge Service")?;
+
+            Ok(response)
+        }
 
-    /// start the clash by service
-    pub(super) async fn start_clash_by_service() -> Result<()> {
-      let status = Self::check_service().await?;
+        /// start the clash by service
+        pub(super) async fn start_clash_by_service() -> Result<()> {
+            let status = Self::check_service().await?;
 
-      if status.code == 0 {
-        Self::stop_clash_by_service().await?;
-        sleep(Duration::from_secs(1)).await;
-      }
+            if status.code == 0 {
+                Self::stop_clash_by_service().await?;
+                sleep(Duration::from_secs(1)).await;
+            }
 
-      let clash_core = {
-        let global = Data::global();
-        let verge = global.verge.lock();
-        verge.clash_core.clone().unwrap_or("clash".into())
-      };
+            let clash_core = {
+                let global = Data::global();
+                let verge = global.verge.lock();
+                verge.clash_core.clone().unwrap_or("clash".into())
+            };
+
+            let clash_bin = format!("{clash_core}.exe");
+            let bin_path = current_exe().unwrap().with_file_name(clash_bin);
+            let bin_path = bin_path.as_os_str().to_str().unwrap();
+
+            let config_dir = dirs::app_home_dir();
+            let config_dir = config_dir.as_os_str().to_str().unwrap();
+
+            let log_path = dirs::service_log_file();
+            let log_path = log_path.as_os_str().to_str().unwrap();
+
+            let mut map = HashMap::new();
+            map.insert("bin_path", bin_path);
+            map.insert("config_dir", config_dir);
+            map.insert("log_file", log_path);
+
+            let url = format!("{SERVICE_URL}/start_clash");
+            let res = reqwest::ClientBuilder::new()
+                .no_proxy()
+                .build()?
+                .post(url)
+                .json(&map)
+                .send()
+                .await?
+                .json::<JsonResponse>()
+                .await
+                .context("failed to connect to the Clash Verge Service")?;
+
+            if res.code != 0 {
+                bail!(res.msg);
+            }
 
-      let clash_bin = format!("{clash_core}.exe");
-      let bin_path = current_exe().unwrap().with_file_name(clash_bin);
-      let bin_path = bin_path.as_os_str().to_str().unwrap();
-
-      let config_dir = dirs::app_home_dir();
-      let config_dir = config_dir.as_os_str().to_str().unwrap();
-
-      let log_path = dirs::service_log_file();
-      let log_path = log_path.as_os_str().to_str().unwrap();
-
-      let mut map = HashMap::new();
-      map.insert("bin_path", bin_path);
-      map.insert("config_dir", config_dir);
-      map.insert("log_file", log_path);
-
-      let url = format!("{SERVICE_URL}/start_clash");
-      let res = reqwest::ClientBuilder::new()
-        .no_proxy()
-        .build()?
-        .post(url)
-        .json(&map)
-        .send()
-        .await?
-        .json::<JsonResponse>()
-        .await
-        .context("failed to connect to the Clash Verge Service")?;
-
-      if res.code != 0 {
-        bail!(res.msg);
-      }
-
-      Ok(())
-    }
+            Ok(())
+        }
+
+        /// stop the clash by service
+        pub(super) async fn stop_clash_by_service() -> Result<()> {
+            let url = format!("{SERVICE_URL}/stop_clash");
+            let res = reqwest::ClientBuilder::new()
+                .no_proxy()
+                .build()?
+                .post(url)
+                .send()
+                .await?
+                .json::<JsonResponse>()
+                .await
+                .context("failed to connect to the Clash Verge Service")?;
+
+            if res.code != 0 {
+                bail!(res.msg);
+            }
 
-    /// stop the clash by service
-    pub(super) async fn stop_clash_by_service() -> Result<()> {
-      let url = format!("{SERVICE_URL}/stop_clash");
-      let res = reqwest::ClientBuilder::new()
-        .no_proxy()
-        .build()?
-        .post(url)
-        .send()
-        .await?
-        .json::<JsonResponse>()
-        .await
-        .context("failed to connect to the Clash Verge Service")?;
-
-      if res.code != 0 {
-        bail!(res.msg);
-      }
-
-      Ok(())
+            Ok(())
+        }
     }
-  }
 }
diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs
index d2a5e4f6125fa233ee4f1d71d5d13624ed6885d7..53bf9394da4761b3378c5bf0e53e75319dc8af34 100644
--- a/src-tauri/src/core/sysopt.rs
+++ b/src-tauri/src/core/sysopt.rs
@@ -6,18 +6,18 @@ use sysproxy::Sysproxy;
 use tauri::{async_runtime::Mutex, utils::platform::current_exe};
 
 pub struct Sysopt {
-  /// current system proxy setting
-  cur_sysproxy: Option<Sysproxy>,
+    /// current system proxy setting
+    cur_sysproxy: Option<Sysproxy>,
 
-  /// record the original system proxy
-  /// recover it when exit
-  old_sysproxy: Option<Sysproxy>,
+    /// record the original system proxy
+    /// recover it when exit
+    old_sysproxy: Option<Sysproxy>,
 
-  /// helps to auto launch the app
-  auto_launch: Option<AutoLaunch>,
+    /// helps to auto launch the app
+    auto_launch: Option<AutoLaunch>,
 
-  /// record whether the guard async is running or not
-  guard_state: Arc<Mutex<bool>>,
+    /// record whether the guard async is running or not
+    guard_state: Arc<Mutex<bool>>,
 }
 
 #[cfg(target_os = "windows")]
@@ -28,258 +28,258 @@ static DEFAULT_BYPASS: &str = "localhost,127.0.0.1/8,::1";
 static DEFAULT_BYPASS: &str = "127.0.0.1,localhost,<local>";
 
 impl Sysopt {
-  pub fn new() -> Sysopt {
-    Sysopt {
-      cur_sysproxy: None,
-      old_sysproxy: None,
-      auto_launch: None,
-      guard_state: Arc::new(Mutex::new(false)),
+    pub fn new() -> Sysopt {
+        Sysopt {
+            cur_sysproxy: None,
+            old_sysproxy: None,
+            auto_launch: None,
+            guard_state: Arc::new(Mutex::new(false)),
+        }
     }
-  }
-
-  /// init the sysproxy
-  pub fn init_sysproxy(&mut self) -> Result<()> {
-    let data = Data::global();
-    let clash = data.clash.lock();
-    let port = clash.info.port.clone();
 
-    if port.is_none() {
-      bail!("clash port is none");
-    }
+    /// init the sysproxy
+    pub fn init_sysproxy(&mut self) -> Result<()> {
+        let data = Data::global();
+        let clash = data.clash.lock();
+        let port = clash.info.port.clone();
 
-    let verge = data.verge.lock();
+        if port.is_none() {
+            bail!("clash port is none");
+        }
 
-    let enable = verge.enable_system_proxy.clone().unwrap_or(false);
-    let bypass = verge.system_proxy_bypass.clone();
-    let bypass = bypass.unwrap_or(DEFAULT_BYPASS.into());
+        let verge = data.verge.lock();
 
-    let port = port.unwrap().parse::<u16>()?;
-    let host = String::from("127.0.0.1");
+        let enable = verge.enable_system_proxy.clone().unwrap_or(false);
+        let bypass = verge.system_proxy_bypass.clone();
+        let bypass = bypass.unwrap_or(DEFAULT_BYPASS.into());
 
-    self.cur_sysproxy = Some(Sysproxy {
-      enable,
-      host,
-      port,
-      bypass,
-    });
+        let port = port.unwrap().parse::<u16>()?;
+        let host = String::from("127.0.0.1");
 
-    if enable {
-      self.old_sysproxy = Sysproxy::get_system_proxy().map_or(None, |p| Some(p));
-      self.cur_sysproxy.as_ref().unwrap().set_system_proxy()?;
-    }
+        self.cur_sysproxy = Some(Sysproxy {
+            enable,
+            host,
+            port,
+            bypass,
+        });
 
-    // run the system proxy guard
-    self.guard_proxy();
-    Ok(())
-  }
+        if enable {
+            self.old_sysproxy = Sysproxy::get_system_proxy().map_or(None, |p| Some(p));
+            self.cur_sysproxy.as_ref().unwrap().set_system_proxy()?;
+        }
 
-  /// update the system proxy
-  pub fn update_sysproxy(&mut self) -> Result<()> {
-    if self.cur_sysproxy.is_none() || self.old_sysproxy.is_none() {
-      return self.init_sysproxy();
+        // run the system proxy guard
+        self.guard_proxy();
+        Ok(())
     }
 
-    let data = Data::global();
-    let verge = data.verge.lock();
-
-    let enable = verge.enable_system_proxy.clone().unwrap_or(false);
-    let bypass = verge.system_proxy_bypass.clone();
-    let bypass = bypass.unwrap_or(DEFAULT_BYPASS.into());
-
-    let mut sysproxy = self.cur_sysproxy.take().unwrap();
-
-    sysproxy.enable = enable;
-    sysproxy.bypass = bypass;
-
-    self.cur_sysproxy = Some(sysproxy);
-    self.cur_sysproxy.as_ref().unwrap().set_system_proxy()?;
-
-    Ok(())
-  }
-
-  /// reset the sysproxy
-  pub fn reset_sysproxy(&mut self) -> Result<()> {
-    let cur = self.cur_sysproxy.take();
-
-    if let Some(mut old) = self.old_sysproxy.take() {
-      // 如果原代理和当前代理 端口一致,就disable关闭,否则就恢复原代理设置
-      // 当前没有设置代理的时候,不确定旧设置是否和当前一致,全关了
-      let port_same = cur.map_or(true, |cur| old.port == cur.port);
+    /// update the system proxy
+    pub fn update_sysproxy(&mut self) -> Result<()> {
+        if self.cur_sysproxy.is_none() || self.old_sysproxy.is_none() {
+            return self.init_sysproxy();
+        }
 
-      if old.enable && port_same {
-        old.enable = false;
-        log::info!(target: "app", "reset proxy by disabling the original proxy");
-      } else {
-        log::info!(target: "app", "reset proxy to the original proxy");
-      }
+        let data = Data::global();
+        let verge = data.verge.lock();
 
-      old.set_system_proxy()?;
-    } else if let Some(mut cur @ Sysproxy { enable: true, .. }) = cur {
-      // 没有原代理,就按现在的代理设置disable即可
-      log::info!(target: "app", "reset proxy by disabling the current proxy");
-      cur.enable = false;
-      cur.set_system_proxy()?;
-    } else {
-      log::info!(target: "app", "reset proxy with no action");
-    }
+        let enable = verge.enable_system_proxy.clone().unwrap_or(false);
+        let bypass = verge.system_proxy_bypass.clone();
+        let bypass = bypass.unwrap_or(DEFAULT_BYPASS.into());
 
-    Ok(())
-  }
-
-  /// init the auto launch
-  pub fn init_launch(&mut self) -> Result<()> {
-    let data = Data::global();
-    let verge = data.verge.lock();
-    let enable = verge.enable_auto_launch.clone().unwrap_or(false);
-
-    let app_exe = current_exe()?;
-    let app_exe = dunce::canonicalize(app_exe)?;
-    let app_name = app_exe
-      .file_stem()
-      .and_then(|f| f.to_str())
-      .ok_or(anyhow!("failed to get file stem"))?;
-
-    let app_path = app_exe
-      .as_os_str()
-      .to_str()
-      .ok_or(anyhow!("failed to get app_path"))?
-      .to_string();
-
-    // fix issue #26
-    #[cfg(target_os = "windows")]
-    let app_path = format!("\"{app_path}\"");
-
-    // use the /Applications/Clash Verge.app path
-    #[cfg(target_os = "macos")]
-    let app_path = (|| -> Option<String> {
-      let path = std::path::PathBuf::from(&app_path);
-      let path = path.parent()?.parent()?.parent()?;
-      let extension = path.extension()?.to_str()?;
-      match extension == "app" {
-        true => Some(path.as_os_str().to_str()?.to_string()),
-        false => None,
-      }
-    })()
-    .unwrap_or(app_path);
-
-    let auto = AutoLaunchBuilder::new()
-      .set_app_name(app_name)
-      .set_app_path(&app_path)
-      .build()?;
-
-    self.auto_launch = Some(auto);
-
-    // 避免在开发时将自启动关了
-    #[cfg(feature = "verge-dev")]
-    if !enable {
-      return Ok(());
-    }
+        let mut sysproxy = self.cur_sysproxy.take().unwrap();
 
-    let auto = self.auto_launch.as_ref().unwrap();
+        sysproxy.enable = enable;
+        sysproxy.bypass = bypass;
 
-    // macos每次启动都更新登录项,避免重复设置登录项
-    #[cfg(target_os = "macos")]
-    {
-      let _ = auto.disable();
-      if enable {
-        auto.enable()?;
-      }
-    }
+        self.cur_sysproxy = Some(sysproxy);
+        self.cur_sysproxy.as_ref().unwrap().set_system_proxy()?;
 
-    #[cfg(not(target_os = "macos"))]
-    {
-      match enable {
-        true => auto.enable()?,
-        false => auto.disable()?,
-      };
+        Ok(())
     }
 
-    Ok(())
-  }
+    /// reset the sysproxy
+    pub fn reset_sysproxy(&mut self) -> Result<()> {
+        let cur = self.cur_sysproxy.take();
+
+        if let Some(mut old) = self.old_sysproxy.take() {
+            // 如果原代理和当前代理 端口一致,就disable关闭,否则就恢复原代理设置
+            // 当前没有设置代理的时候,不确定旧设置是否和当前一致,全关了
+            let port_same = cur.map_or(true, |cur| old.port == cur.port);
+
+            if old.enable && port_same {
+                old.enable = false;
+                log::info!(target: "app", "reset proxy by disabling the original proxy");
+            } else {
+                log::info!(target: "app", "reset proxy to the original proxy");
+            }
+
+            old.set_system_proxy()?;
+        } else if let Some(mut cur @ Sysproxy { enable: true, .. }) = cur {
+            // 没有原代理,就按现在的代理设置disable即可
+            log::info!(target: "app", "reset proxy by disabling the current proxy");
+            cur.enable = false;
+            cur.set_system_proxy()?;
+        } else {
+            log::info!(target: "app", "reset proxy with no action");
+        }
 
-  /// update the startup
-  pub fn update_launch(&mut self) -> Result<()> {
-    if self.auto_launch.is_none() {
-      return self.init_launch();
+        Ok(())
     }
 
-    let data = Data::global();
-    let verge = data.verge.lock();
-    let enable = verge.enable_auto_launch.clone().unwrap_or(false);
-
-    let auto_launch = self.auto_launch.as_ref().unwrap();
-
-    match enable {
-      true => auto_launch.enable()?,
-      false => crate::log_if_err!(auto_launch.disable()), // 忽略关闭的错误
-    };
-
-    Ok(())
-  }
-
-  /// launch a system proxy guard
-  /// read config from file directly
-  pub fn guard_proxy(&self) {
-    use tokio::time::{sleep, Duration};
-
-    let guard_state = self.guard_state.clone();
-
-    tauri::async_runtime::spawn(async move {
-      // if it is running, exit
-      let mut state = guard_state.lock().await;
-      if *state {
-        return;
-      }
-      *state = true;
-      drop(state);
+    /// init the auto launch
+    pub fn init_launch(&mut self) -> Result<()> {
+        let data = Data::global();
+        let verge = data.verge.lock();
+        let enable = verge.enable_auto_launch.clone().unwrap_or(false);
+
+        let app_exe = current_exe()?;
+        let app_exe = dunce::canonicalize(app_exe)?;
+        let app_name = app_exe
+            .file_stem()
+            .and_then(|f| f.to_str())
+            .ok_or(anyhow!("failed to get file stem"))?;
+
+        let app_path = app_exe
+            .as_os_str()
+            .to_str()
+            .ok_or(anyhow!("failed to get app_path"))?
+            .to_string();
+
+        // fix issue #26
+        #[cfg(target_os = "windows")]
+        let app_path = format!("\"{app_path}\"");
+
+        // use the /Applications/Clash Verge.app path
+        #[cfg(target_os = "macos")]
+        let app_path = (|| -> Option<String> {
+            let path = std::path::PathBuf::from(&app_path);
+            let path = path.parent()?.parent()?.parent()?;
+            let extension = path.extension()?.to_str()?;
+            match extension == "app" {
+                true => Some(path.as_os_str().to_str()?.to_string()),
+                false => None,
+            }
+        })()
+        .unwrap_or(app_path);
+
+        let auto = AutoLaunchBuilder::new()
+            .set_app_name(app_name)
+            .set_app_path(&app_path)
+            .build()?;
+
+        self.auto_launch = Some(auto);
+
+        // 避免在开发时将自启动关了
+        #[cfg(feature = "verge-dev")]
+        if !enable {
+            return Ok(());
+        }
 
-      // default duration is 10s
-      let mut wait_secs = 10u64;
+        let auto = self.auto_launch.as_ref().unwrap();
 
-      loop {
-        sleep(Duration::from_secs(wait_secs)).await;
+        // macos每次启动都更新登录项,避免重复设置登录项
+        #[cfg(target_os = "macos")]
+        {
+            let _ = auto.disable();
+            if enable {
+                auto.enable()?;
+            }
+        }
 
-        let global = Data::global();
-        let verge = global.verge.lock();
+        #[cfg(not(target_os = "macos"))]
+        {
+            match enable {
+                true => auto.enable()?,
+                false => auto.disable()?,
+            };
+        }
 
-        let enable = verge.enable_system_proxy.clone().unwrap_or(false);
-        let guard = verge.enable_proxy_guard.clone().unwrap_or(false);
-        let guard_duration = verge.proxy_guard_duration.clone().unwrap_or(10);
-        let bypass = verge.system_proxy_bypass.clone();
-        drop(verge);
+        Ok(())
+    }
 
-        // stop loop
-        if !enable || !guard {
-          break;
+    /// update the startup
+    pub fn update_launch(&mut self) -> Result<()> {
+        if self.auto_launch.is_none() {
+            return self.init_launch();
         }
 
-        // update duration
-        wait_secs = guard_duration;
+        let data = Data::global();
+        let verge = data.verge.lock();
+        let enable = verge.enable_auto_launch.clone().unwrap_or(false);
 
-        let clash = global.clash.lock();
-        let port = clash.info.port.clone();
-        let port = port.unwrap_or("".into()).parse::<u16>();
-        drop(clash);
-
-        log::debug!(target: "app", "try to guard the system proxy");
-
-        match port {
-          Ok(port) => {
-            let sysproxy = Sysproxy {
-              enable: true,
-              host: "127.0.0.1".into(),
-              port,
-              bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()),
-            };
+        let auto_launch = self.auto_launch.as_ref().unwrap();
 
-            log_if_err!(sysproxy.set_system_proxy());
-          }
-          Err(_) => log::error!(target: "app", "failed to parse clash port"),
-        }
-      }
+        match enable {
+            true => auto_launch.enable()?,
+            false => crate::log_if_err!(auto_launch.disable()), // 忽略关闭的错误
+        };
 
-      let mut state = guard_state.lock().await;
-      *state = false;
-    });
-  }
+        Ok(())
+    }
+
+    /// launch a system proxy guard
+    /// read config from file directly
+    pub fn guard_proxy(&self) {
+        use tokio::time::{sleep, Duration};
+
+        let guard_state = self.guard_state.clone();
+
+        tauri::async_runtime::spawn(async move {
+            // if it is running, exit
+            let mut state = guard_state.lock().await;
+            if *state {
+                return;
+            }
+            *state = true;
+            drop(state);
+
+            // default duration is 10s
+            let mut wait_secs = 10u64;
+
+            loop {
+                sleep(Duration::from_secs(wait_secs)).await;
+
+                let global = Data::global();
+                let verge = global.verge.lock();
+
+                let enable = verge.enable_system_proxy.clone().unwrap_or(false);
+                let guard = verge.enable_proxy_guard.clone().unwrap_or(false);
+                let guard_duration = verge.proxy_guard_duration.clone().unwrap_or(10);
+                let bypass = verge.system_proxy_bypass.clone();
+                drop(verge);
+
+                // stop loop
+                if !enable || !guard {
+                    break;
+                }
+
+                // update duration
+                wait_secs = guard_duration;
+
+                let clash = global.clash.lock();
+                let port = clash.info.port.clone();
+                let port = port.unwrap_or("".into()).parse::<u16>();
+                drop(clash);
+
+                log::debug!(target: "app", "try to guard the system proxy");
+
+                match port {
+                    Ok(port) => {
+                        let sysproxy = Sysproxy {
+                            enable: true,
+                            host: "127.0.0.1".into(),
+                            port,
+                            bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()),
+                        };
+
+                        log_if_err!(sysproxy.set_system_proxy());
+                    }
+                    Err(_) => log::error!(target: "app", "failed to parse clash port"),
+                }
+            }
+
+            let mut state = guard_state.lock().await;
+            *state = false;
+        });
+    }
 }
diff --git a/src-tauri/src/core/timer.rs b/src-tauri/src/core/timer.rs
index 3728b763817f19b12765fe45e4d241977545737c..4d9ccba7e1b7e2989255c8d30eba2d917bfdebfb 100644
--- a/src-tauri/src/core/timer.rs
+++ b/src-tauri/src/core/timer.rs
@@ -8,165 +8,165 @@ use std::collections::HashMap;
 type TaskID = u64;
 
 pub struct Timer {
-  /// cron manager
-  delay_timer: DelayTimer,
+    /// cron manager
+    delay_timer: DelayTimer,
 
-  /// save the current state
-  timer_map: HashMap<String, (TaskID, u64)>,
+    /// save the current state
+    timer_map: HashMap<String, (TaskID, u64)>,
 
-  /// increment id
-  timer_count: TaskID,
+    /// increment id
+    timer_count: TaskID,
 }
 
 impl Timer {
-  pub fn new() -> Self {
-    Timer {
-      delay_timer: DelayTimerBuilder::default().build(),
-      timer_map: HashMap::new(),
-      timer_count: 1,
-    }
-  }
-
-  /// Correctly update all cron tasks
-  pub fn refresh(&mut self) -> Result<()> {
-    let diff_map = self.gen_diff();
-
-    for (uid, diff) in diff_map.into_iter() {
-      match diff {
-        DiffFlag::Del(tid) => {
-          let _ = self.timer_map.remove(&uid);
-          log_if_err!(self.delay_timer.remove_task(tid));
-        }
-        DiffFlag::Add(tid, val) => {
-          let _ = self.timer_map.insert(uid.clone(), (tid, val));
-          log_if_err!(self.add_task(uid, tid, val));
+    pub fn new() -> Self {
+        Timer {
+            delay_timer: DelayTimerBuilder::default().build(),
+            timer_map: HashMap::new(),
+            timer_count: 1,
         }
-        DiffFlag::Mod(tid, val) => {
-          let _ = self.timer_map.insert(uid.clone(), (tid, val));
-          log_if_err!(self.delay_timer.remove_task(tid));
-          log_if_err!(self.add_task(uid, tid, val));
-        }
-      }
     }
 
-    Ok(())
-  }
-
-  /// restore timer
-  pub fn restore(&mut self) -> Result<()> {
-    self.refresh()?;
-
-    let cur_timestamp = get_now(); // seconds
-
-    let global = Data::global();
-    let profiles = global.profiles.lock();
-
-    profiles
-      .get_items()
-      .unwrap_or(&vec![])
-      .iter()
-      .filter(|item| item.uid.is_some() && item.updated.is_some() && item.option.is_some())
-      .filter(|item| {
-        // mins to seconds
-        let interval = item.option.as_ref().unwrap().update_interval.unwrap_or(0) as usize * 60;
-        let updated = item.updated.unwrap();
-        return interval > 0 && cur_timestamp - updated >= interval;
-      })
-      .for_each(|item| {
-        let uid = item.uid.as_ref().unwrap();
-        if let Some((task_id, _)) = self.timer_map.get(uid) {
-          log_if_err!(self.delay_timer.advance_task(*task_id));
+    /// Correctly update all cron tasks
+    pub fn refresh(&mut self) -> Result<()> {
+        let diff_map = self.gen_diff();
+
+        for (uid, diff) in diff_map.into_iter() {
+            match diff {
+                DiffFlag::Del(tid) => {
+                    let _ = self.timer_map.remove(&uid);
+                    log_if_err!(self.delay_timer.remove_task(tid));
+                }
+                DiffFlag::Add(tid, val) => {
+                    let _ = self.timer_map.insert(uid.clone(), (tid, val));
+                    log_if_err!(self.add_task(uid, tid, val));
+                }
+                DiffFlag::Mod(tid, val) => {
+                    let _ = self.timer_map.insert(uid.clone(), (tid, val));
+                    log_if_err!(self.delay_timer.remove_task(tid));
+                    log_if_err!(self.add_task(uid, tid, val));
+                }
+            }
         }
-      });
 
-    Ok(())
-  }
+        Ok(())
+    }
 
-  /// generate a uid -> update_interval map
-  fn gen_map(&self) -> HashMap<String, u64> {
-    let global = Data::global();
-    let profiles = global.profiles.lock();
+    /// restore timer
+    pub fn restore(&mut self) -> Result<()> {
+        self.refresh()?;
+
+        let cur_timestamp = get_now(); // seconds
+
+        let global = Data::global();
+        let profiles = global.profiles.lock();
+
+        profiles
+            .get_items()
+            .unwrap_or(&vec![])
+            .iter()
+            .filter(|item| item.uid.is_some() && item.updated.is_some() && item.option.is_some())
+            .filter(|item| {
+                // mins to seconds
+                let interval =
+                    item.option.as_ref().unwrap().update_interval.unwrap_or(0) as usize * 60;
+                let updated = item.updated.unwrap();
+                return interval > 0 && cur_timestamp - updated >= interval;
+            })
+            .for_each(|item| {
+                let uid = item.uid.as_ref().unwrap();
+                if let Some((task_id, _)) = self.timer_map.get(uid) {
+                    log_if_err!(self.delay_timer.advance_task(*task_id));
+                }
+            });
+
+        Ok(())
+    }
 
-    let mut new_map = HashMap::new();
+    /// generate a uid -> update_interval map
+    fn gen_map(&self) -> HashMap<String, u64> {
+        let global = Data::global();
+        let profiles = global.profiles.lock();
 
-    if let Some(items) = profiles.get_items() {
-      for item in items.iter() {
-        if item.option.is_some() {
-          let option = item.option.as_ref().unwrap();
-          let interval = option.update_interval.unwrap_or(0);
+        let mut new_map = HashMap::new();
 
-          if interval > 0 {
-            new_map.insert(item.uid.clone().unwrap(), interval);
-          }
+        if let Some(items) = profiles.get_items() {
+            for item in items.iter() {
+                if item.option.is_some() {
+                    let option = item.option.as_ref().unwrap();
+                    let interval = option.update_interval.unwrap_or(0);
+
+                    if interval > 0 {
+                        new_map.insert(item.uid.clone().unwrap(), interval);
+                    }
+                }
+            }
         }
-      }
-    }
 
-    new_map
-  }
+        new_map
+    }
 
-  /// generate the diff map for refresh
-  fn gen_diff(&mut self) -> HashMap<String, DiffFlag> {
-    let mut diff_map = HashMap::new();
+    /// generate the diff map for refresh
+    fn gen_diff(&mut self) -> HashMap<String, DiffFlag> {
+        let mut diff_map = HashMap::new();
 
-    let new_map = self.gen_map();
-    let cur_map = &self.timer_map;
+        let new_map = self.gen_map();
+        let cur_map = &self.timer_map;
 
-    cur_map.iter().for_each(|(uid, (tid, val))| {
-      let new_val = new_map.get(uid).unwrap_or(&0);
+        cur_map.iter().for_each(|(uid, (tid, val))| {
+            let new_val = new_map.get(uid).unwrap_or(&0);
 
-      if *new_val == 0 {
-        diff_map.insert(uid.clone(), DiffFlag::Del(*tid));
-      } else if new_val != val {
-        diff_map.insert(uid.clone(), DiffFlag::Mod(*tid, *new_val));
-      }
-    });
+            if *new_val == 0 {
+                diff_map.insert(uid.clone(), DiffFlag::Del(*tid));
+            } else if new_val != val {
+                diff_map.insert(uid.clone(), DiffFlag::Mod(*tid, *new_val));
+            }
+        });
 
-    let mut count = self.timer_count;
+        let mut count = self.timer_count;
 
-    new_map.iter().for_each(|(uid, val)| {
-      if cur_map.get(uid).is_none() {
-        diff_map.insert(uid.clone(), DiffFlag::Add(count, *val));
+        new_map.iter().for_each(|(uid, val)| {
+            if cur_map.get(uid).is_none() {
+                diff_map.insert(uid.clone(), DiffFlag::Add(count, *val));
 
-        count += 1;
-      }
-    });
+                count += 1;
+            }
+        });
 
-    self.timer_count = count;
+        self.timer_count = count;
 
-    diff_map
-  }
+        diff_map
+    }
 
-  /// add a cron task
-  fn add_task(&self, uid: String, tid: TaskID, minutes: u64) -> Result<()> {
-    let core = Core::global();
+    /// add a cron task
+    fn add_task(&self, uid: String, tid: TaskID, minutes: u64) -> Result<()> {
+        let core = Core::global();
 
-    let task = TaskBuilder::default()
-      .set_task_id(tid)
-      .set_maximum_parallel_runnable_num(1)
-      .set_frequency_repeated_by_minutes(minutes)
-      // .set_frequency_repeated_by_seconds(minutes) // for test
-      .spawn_async_routine(move || Self::async_task(core.to_owned(), uid.to_owned()))
-      .context("failed to create timer task")?;
+        let task = TaskBuilder::default()
+            .set_task_id(tid)
+            .set_maximum_parallel_runnable_num(1)
+            .set_frequency_repeated_by_minutes(minutes)
+            // .set_frequency_repeated_by_seconds(minutes) // for test
+            .spawn_async_routine(move || Self::async_task(core.to_owned(), uid.to_owned()))
+            .context("failed to create timer task")?;
 
-    self
-      .delay_timer
-      .add_task(task)
-      .context("failed to add timer task")?;
+        self.delay_timer
+            .add_task(task)
+            .context("failed to add timer task")?;
 
-    Ok(())
-  }
+        Ok(())
+    }
 
-  /// the task runner
-  async fn async_task(core: Core, uid: String) {
-    log::info!(target: "app", "running timer task `{uid}`");
-    log_if_err!(core.update_profile_item(uid, None).await);
-  }
+    /// the task runner
+    async fn async_task(core: Core, uid: String) {
+        log::info!(target: "app", "running timer task `{uid}`");
+        log_if_err!(core.update_profile_item(uid, None).await);
+    }
 }
 
 #[derive(Debug)]
 enum DiffFlag {
-  Del(TaskID),
-  Add(TaskID, u64),
-  Mod(TaskID, u64),
+    Del(TaskID),
+    Add(TaskID, u64),
+    Mod(TaskID, u64),
 }
diff --git a/src-tauri/src/core/tray.rs b/src-tauri/src/core/tray.rs
index 6b3fb9966a81bf702bdda0fbefe2db6f0a610784..a65c45724e36c222291ad1819282f8eea3595633 100644
--- a/src-tauri/src/core/tray.rs
+++ b/src-tauri/src/core/tray.rs
@@ -1,124 +1,130 @@
 use crate::{data::Data, feat, utils::resolve};
 use anyhow::{Ok, Result};
 use tauri::{
-  api, AppHandle, CustomMenuItem, Manager, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
-  SystemTraySubmenu,
+    api, AppHandle, CustomMenuItem, Manager, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
+    SystemTraySubmenu,
 };
 
 pub struct Tray {}
 
 impl Tray {
-  pub fn tray_menu(app_handle: &AppHandle) -> SystemTrayMenu {
-    let data = Data::global();
-    let zh = {
-      let verge = data.verge.lock();
-      verge.language == Some("zh".into())
-    };
+    pub fn tray_menu(app_handle: &AppHandle) -> SystemTrayMenu {
+        let data = Data::global();
+        let zh = {
+            let verge = data.verge.lock();
+            verge.language == Some("zh".into())
+        };
 
-    let version = app_handle.package_info().version.to_string();
+        let version = app_handle.package_info().version.to_string();
 
-    if zh {
-      SystemTrayMenu::new()
-        .add_item(CustomMenuItem::new("open_window", "打开面板"))
-        .add_native_item(SystemTrayMenuItem::Separator)
-        .add_item(CustomMenuItem::new("rule_mode", "规则模式"))
-        .add_item(CustomMenuItem::new("global_mode", "全局模式"))
-        .add_item(CustomMenuItem::new("direct_mode", "直连模式"))
-        .add_item(CustomMenuItem::new("script_mode", "脚本模式"))
-        .add_native_item(SystemTrayMenuItem::Separator)
-        .add_item(CustomMenuItem::new("system_proxy", "系统代理"))
-        .add_item(CustomMenuItem::new("tun_mode", "TUN 模式"))
-        .add_submenu(SystemTraySubmenu::new(
-          "更多",
-          SystemTrayMenu::new()
-            .add_item(CustomMenuItem::new("restart_clash", "重启 Clash"))
-            .add_item(CustomMenuItem::new("restart_app", "重启应用"))
-            .add_item(CustomMenuItem::new("app_version", format!("Version {version}")).disabled()),
-        ))
-        .add_native_item(SystemTrayMenuItem::Separator)
-        .add_item(CustomMenuItem::new("quit", "退出").accelerator("CmdOrControl+Q"))
-    } else {
-      SystemTrayMenu::new()
-        .add_item(CustomMenuItem::new("open_window", "Dashboard"))
-        .add_native_item(SystemTrayMenuItem::Separator)
-        .add_item(CustomMenuItem::new("rule_mode", "Rule Mode"))
-        .add_item(CustomMenuItem::new("global_mode", "Global Mode"))
-        .add_item(CustomMenuItem::new("direct_mode", "Direct Mode"))
-        .add_item(CustomMenuItem::new("script_mode", "Script Mode"))
-        .add_native_item(SystemTrayMenuItem::Separator)
-        .add_item(CustomMenuItem::new("system_proxy", "System Proxy"))
-        .add_item(CustomMenuItem::new("tun_mode", "Tun Mode"))
-        .add_submenu(SystemTraySubmenu::new(
-          "More",
-          SystemTrayMenu::new()
-            .add_item(CustomMenuItem::new("restart_clash", "Restart Clash"))
-            .add_item(CustomMenuItem::new("restart_app", "Restart App"))
-            .add_item(CustomMenuItem::new("app_version", format!("Version {version}")).disabled()),
-        ))
-        .add_native_item(SystemTrayMenuItem::Separator)
-        .add_item(CustomMenuItem::new("quit", "Quit").accelerator("CmdOrControl+Q"))
+        if zh {
+            SystemTrayMenu::new()
+                .add_item(CustomMenuItem::new("open_window", "打开面板"))
+                .add_native_item(SystemTrayMenuItem::Separator)
+                .add_item(CustomMenuItem::new("rule_mode", "规则模式"))
+                .add_item(CustomMenuItem::new("global_mode", "全局模式"))
+                .add_item(CustomMenuItem::new("direct_mode", "直连模式"))
+                .add_item(CustomMenuItem::new("script_mode", "脚本模式"))
+                .add_native_item(SystemTrayMenuItem::Separator)
+                .add_item(CustomMenuItem::new("system_proxy", "系统代理"))
+                .add_item(CustomMenuItem::new("tun_mode", "TUN 模式"))
+                .add_submenu(SystemTraySubmenu::new(
+                    "更多",
+                    SystemTrayMenu::new()
+                        .add_item(CustomMenuItem::new("restart_clash", "重启 Clash"))
+                        .add_item(CustomMenuItem::new("restart_app", "重启应用"))
+                        .add_item(
+                            CustomMenuItem::new("app_version", format!("Version {version}"))
+                                .disabled(),
+                        ),
+                ))
+                .add_native_item(SystemTrayMenuItem::Separator)
+                .add_item(CustomMenuItem::new("quit", "退出").accelerator("CmdOrControl+Q"))
+        } else {
+            SystemTrayMenu::new()
+                .add_item(CustomMenuItem::new("open_window", "Dashboard"))
+                .add_native_item(SystemTrayMenuItem::Separator)
+                .add_item(CustomMenuItem::new("rule_mode", "Rule Mode"))
+                .add_item(CustomMenuItem::new("global_mode", "Global Mode"))
+                .add_item(CustomMenuItem::new("direct_mode", "Direct Mode"))
+                .add_item(CustomMenuItem::new("script_mode", "Script Mode"))
+                .add_native_item(SystemTrayMenuItem::Separator)
+                .add_item(CustomMenuItem::new("system_proxy", "System Proxy"))
+                .add_item(CustomMenuItem::new("tun_mode", "Tun Mode"))
+                .add_submenu(SystemTraySubmenu::new(
+                    "More",
+                    SystemTrayMenu::new()
+                        .add_item(CustomMenuItem::new("restart_clash", "Restart Clash"))
+                        .add_item(CustomMenuItem::new("restart_app", "Restart App"))
+                        .add_item(
+                            CustomMenuItem::new("app_version", format!("Version {version}"))
+                                .disabled(),
+                        ),
+                ))
+                .add_native_item(SystemTrayMenuItem::Separator)
+                .add_item(CustomMenuItem::new("quit", "Quit").accelerator("CmdOrControl+Q"))
+        }
     }
-  }
 
-  pub fn update_systray(app_handle: &AppHandle) -> Result<()> {
-    app_handle
-      .tray_handle()
-      .set_menu(Tray::tray_menu(app_handle))?;
-    Tray::update_part(app_handle)?;
-    Ok(())
-  }
+    pub fn update_systray(app_handle: &AppHandle) -> Result<()> {
+        app_handle
+            .tray_handle()
+            .set_menu(Tray::tray_menu(app_handle))?;
+        Tray::update_part(app_handle)?;
+        Ok(())
+    }
 
-  pub fn update_part(app_handle: &AppHandle) -> Result<()> {
-    let global = Data::global();
-    let clash = global.clash.lock();
-    let mode = clash
-      .config
-      .get(&serde_yaml::Value::from("mode"))
-      .map(|val| val.as_str().unwrap_or("rule"))
-      .unwrap_or("rule");
+    pub fn update_part(app_handle: &AppHandle) -> Result<()> {
+        let global = Data::global();
+        let clash = global.clash.lock();
+        let mode = clash
+            .config
+            .get(&serde_yaml::Value::from("mode"))
+            .map(|val| val.as_str().unwrap_or("rule"))
+            .unwrap_or("rule");
 
-    let tray = app_handle.tray_handle();
+        let tray = app_handle.tray_handle();
 
-    let _ = tray.get_item("rule_mode").set_selected(mode == "rule");
-    let _ = tray.get_item("global_mode").set_selected(mode == "global");
-    let _ = tray.get_item("direct_mode").set_selected(mode == "direct");
-    let _ = tray.get_item("script_mode").set_selected(mode == "script");
+        let _ = tray.get_item("rule_mode").set_selected(mode == "rule");
+        let _ = tray.get_item("global_mode").set_selected(mode == "global");
+        let _ = tray.get_item("direct_mode").set_selected(mode == "direct");
+        let _ = tray.get_item("script_mode").set_selected(mode == "script");
 
-    let verge = global.verge.lock();
-    let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
-    let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false);
+        let verge = global.verge.lock();
+        let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
+        let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false);
 
-    let _ = tray.get_item("system_proxy").set_selected(*system_proxy);
-    let _ = tray.get_item("tun_mode").set_selected(*tun_mode);
+        let _ = tray.get_item("system_proxy").set_selected(*system_proxy);
+        let _ = tray.get_item("tun_mode").set_selected(*tun_mode);
 
-    Ok(())
-  }
+        Ok(())
+    }
 
-  pub fn on_system_tray_event(app_handle: &AppHandle, event: SystemTrayEvent) {
-    match event {
-      SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
-        mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => {
-          let mode = &mode[0..mode.len() - 5];
-          feat::change_clash_mode(mode);
-        }
+    pub fn on_system_tray_event(app_handle: &AppHandle, event: SystemTrayEvent) {
+        match event {
+            SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
+                mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => {
+                    let mode = &mode[0..mode.len() - 5];
+                    feat::change_clash_mode(mode);
+                }
 
-        "open_window" => resolve::create_window(app_handle),
-        "system_proxy" => feat::toggle_system_proxy(),
-        "tun_mode" => feat::toggle_tun_mode(),
-        "restart_clash" => feat::restart_clash_core(),
-        "restart_app" => api::process::restart(&app_handle.env()),
-        "quit" => {
-          resolve::resolve_reset();
-          api::process::kill_children();
-          app_handle.exit(0);
+                "open_window" => resolve::create_window(app_handle),
+                "system_proxy" => feat::toggle_system_proxy(),
+                "tun_mode" => feat::toggle_tun_mode(),
+                "restart_clash" => feat::restart_clash_core(),
+                "restart_app" => api::process::restart(&app_handle.env()),
+                "quit" => {
+                    resolve::resolve_reset();
+                    api::process::kill_children();
+                    app_handle.exit(0);
+                }
+                _ => {}
+            },
+            #[cfg(target_os = "windows")]
+            SystemTrayEvent::LeftClick { .. } => {
+                resolve::create_window(app_handle);
+            }
+            _ => {}
         }
-        _ => {}
-      },
-      #[cfg(target_os = "windows")]
-      SystemTrayEvent::LeftClick { .. } => {
-        resolve::create_window(app_handle);
-      }
-      _ => {}
     }
-  }
 }
diff --git a/src-tauri/src/data/clash.rs b/src-tauri/src/data/clash.rs
index 56bbff37b557d088383847662064a81045bcc661..73ecd35381c77912e8cd138a9ee2e722159ad7c2 100644
--- a/src-tauri/src/data/clash.rs
+++ b/src-tauri/src/data/clash.rs
@@ -5,163 +5,163 @@ use serde_yaml::{Mapping, Value};
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct ClashInfo {
-  /// clash sidecar status
-  pub status: String,
+    /// clash sidecar status
+    pub status: String,
 
-  /// clash core port
-  pub port: Option<String>,
+    /// clash core port
+    pub port: Option<String>,
 
-  /// same as `external-controller`
-  pub server: Option<String>,
+    /// same as `external-controller`
+    pub server: Option<String>,
 
-  /// clash secret
-  pub secret: Option<String>,
+    /// clash secret
+    pub secret: Option<String>,
 }
 
 impl ClashInfo {
-  /// parse the clash's config.yaml
-  /// get some information
-  pub fn from(config: &Mapping) -> ClashInfo {
-    let key_port_1 = Value::from("mixed-port");
-    let key_port_2 = Value::from("port");
-    let key_server = Value::from("external-controller");
-    let key_secret = Value::from("secret");
-
-    let mut status: u32 = 0;
-
-    let port = match config.get(&key_port_1) {
-      Some(value) => match value {
-        Value::String(val_str) => Some(val_str.clone()),
-        Value::Number(val_num) => Some(val_num.to_string()),
-        _ => {
-          status |= 0b1;
-          None
+    /// parse the clash's config.yaml
+    /// get some information
+    pub fn from(config: &Mapping) -> ClashInfo {
+        let key_port_1 = Value::from("mixed-port");
+        let key_port_2 = Value::from("port");
+        let key_server = Value::from("external-controller");
+        let key_secret = Value::from("secret");
+
+        let mut status: u32 = 0;
+
+        let port = match config.get(&key_port_1) {
+            Some(value) => match value {
+                Value::String(val_str) => Some(val_str.clone()),
+                Value::Number(val_num) => Some(val_num.to_string()),
+                _ => {
+                    status |= 0b1;
+                    None
+                }
+            },
+            _ => {
+                status |= 0b10;
+                None
+            }
+        };
+        let port = match port {
+            Some(_) => port,
+            None => match config.get(&key_port_2) {
+                Some(value) => match value {
+                    Value::String(val_str) => Some(val_str.clone()),
+                    Value::Number(val_num) => Some(val_num.to_string()),
+                    _ => {
+                        status |= 0b100;
+                        None
+                    }
+                },
+                _ => {
+                    status |= 0b1000;
+                    None
+                }
+            },
+        };
+
+        // `external-controller` could be
+        // "127.0.0.1:9090" or ":9090"
+        let server = match config.get(&key_server) {
+            Some(value) => match value.as_str() {
+                Some(val_str) => {
+                    if val_str.starts_with(":") {
+                        Some(format!("127.0.0.1{val_str}"))
+                    } else if val_str.starts_with("0.0.0.0:") {
+                        Some(format!("127.0.0.1:{}", &val_str[8..]))
+                    } else if val_str.starts_with("[::]:") {
+                        Some(format!("127.0.0.1:{}", &val_str[5..]))
+                    } else {
+                        Some(val_str.into())
+                    }
+                }
+                None => {
+                    status |= 0b10000;
+                    None
+                }
+            },
+            None => {
+                status |= 0b100000;
+                None
+            }
+        };
+
+        let secret = match config.get(&key_secret) {
+            Some(value) => match value {
+                Value::String(val_str) => Some(val_str.clone()),
+                Value::Bool(val_bool) => Some(val_bool.to_string()),
+                Value::Number(val_num) => Some(val_num.to_string()),
+                _ => None,
+            },
+            _ => None,
+        };
+
+        ClashInfo {
+            status: format!("{status}"),
+            port,
+            server,
+            secret,
         }
-      },
-      _ => {
-        status |= 0b10;
-        None
-      }
-    };
-    let port = match port {
-      Some(_) => port,
-      None => match config.get(&key_port_2) {
-        Some(value) => match value {
-          Value::String(val_str) => Some(val_str.clone()),
-          Value::Number(val_num) => Some(val_num.to_string()),
-          _ => {
-            status |= 0b100;
-            None
-          }
-        },
-        _ => {
-          status |= 0b1000;
-          None
-        }
-      },
-    };
-
-    // `external-controller` could be
-    // "127.0.0.1:9090" or ":9090"
-    let server = match config.get(&key_server) {
-      Some(value) => match value.as_str() {
-        Some(val_str) => {
-          if val_str.starts_with(":") {
-            Some(format!("127.0.0.1{val_str}"))
-          } else if val_str.starts_with("0.0.0.0:") {
-            Some(format!("127.0.0.1:{}", &val_str[8..]))
-          } else if val_str.starts_with("[::]:") {
-            Some(format!("127.0.0.1:{}", &val_str[5..]))
-          } else {
-            Some(val_str.into())
-          }
-        }
-        None => {
-          status |= 0b10000;
-          None
-        }
-      },
-      None => {
-        status |= 0b100000;
-        None
-      }
-    };
-
-    let secret = match config.get(&key_secret) {
-      Some(value) => match value {
-        Value::String(val_str) => Some(val_str.clone()),
-        Value::Bool(val_bool) => Some(val_bool.to_string()),
-        Value::Number(val_num) => Some(val_num.to_string()),
-        _ => None,
-      },
-      _ => None,
-    };
-
-    ClashInfo {
-      status: format!("{status}"),
-      port,
-      server,
-      secret,
     }
-  }
 }
 
 #[derive(Debug)]
 pub struct Clash {
-  /// maintain the clash config
-  pub config: Mapping,
+    /// maintain the clash config
+    pub config: Mapping,
 
-  /// some info
-  pub info: ClashInfo,
+    /// some info
+    pub info: ClashInfo,
 }
 
 impl Clash {
-  pub fn new() -> Clash {
-    let config = Clash::read_config();
-    let info = ClashInfo::from(&config);
-
-    Clash { config, info }
-  }
-
-  /// get clash config
-  pub fn read_config() -> Mapping {
-    config::read_merge_mapping(dirs::clash_path())
-  }
-
-  /// save the clash config
-  pub fn save_config(&self) -> Result<()> {
-    config::save_yaml(
-      dirs::clash_path(),
-      &self.config,
-      Some("# Default Config For Clash Core\n\n"),
-    )
-  }
-
-  /// patch update the clash config
-  /// if the port is changed then return true
-  pub fn patch_config(&mut self, patch: Mapping) -> Result<()> {
-    let port_key = Value::from("mixed-port");
-    let server_key = Value::from("external-controller");
-    let secret_key = Value::from("secret");
-
-    let change_info = patch.contains_key(&port_key)
-      || patch.contains_key(&server_key)
-      || patch.contains_key(&secret_key);
-
-    for (key, value) in patch.into_iter() {
-      self.config.insert(key, value);
+    pub fn new() -> Clash {
+        let config = Clash::read_config();
+        let info = ClashInfo::from(&config);
+
+        Clash { config, info }
     }
 
-    if change_info {
-      self.info = ClashInfo::from(&self.config);
+    /// get clash config
+    pub fn read_config() -> Mapping {
+        config::read_merge_mapping(dirs::clash_path())
     }
 
-    self.save_config()
-  }
+    /// save the clash config
+    pub fn save_config(&self) -> Result<()> {
+        config::save_yaml(
+            dirs::clash_path(),
+            &self.config,
+            Some("# Default Config For Clash Core\n\n"),
+        )
+    }
+
+    /// patch update the clash config
+    /// if the port is changed then return true
+    pub fn patch_config(&mut self, patch: Mapping) -> Result<()> {
+        let port_key = Value::from("mixed-port");
+        let server_key = Value::from("external-controller");
+        let secret_key = Value::from("secret");
+
+        let change_info = patch.contains_key(&port_key)
+            || patch.contains_key(&server_key)
+            || patch.contains_key(&secret_key);
+
+        for (key, value) in patch.into_iter() {
+            self.config.insert(key, value);
+        }
+
+        if change_info {
+            self.info = ClashInfo::from(&self.config);
+        }
+
+        self.save_config()
+    }
 }
 
 impl Default for Clash {
-  fn default() -> Self {
-    Clash::new()
-  }
+    fn default() -> Self {
+        Clash::new()
+    }
 }
diff --git a/src-tauri/src/data/mod.rs b/src-tauri/src/data/mod.rs
index 3ba67813069467795e786fe5318e9aa4f4fa00e2..eb6a406433242d3e6f06a485c2286ece68451439 100644
--- a/src-tauri/src/data/mod.rs
+++ b/src-tauri/src/data/mod.rs
@@ -14,19 +14,19 @@ use std::sync::Arc;
 
 #[derive(Debug, Clone)]
 pub struct Data {
-  pub clash: Arc<Mutex<Clash>>,
-  pub verge: Arc<Mutex<Verge>>,
-  pub profiles: Arc<Mutex<Profiles>>,
+    pub clash: Arc<Mutex<Clash>>,
+    pub verge: Arc<Mutex<Verge>>,
+    pub profiles: Arc<Mutex<Profiles>>,
 }
 
 impl Data {
-  pub fn global() -> &'static Data {
-    static DATA: OnceCell<Data> = OnceCell::new();
+    pub fn global() -> &'static Data {
+        static DATA: OnceCell<Data> = OnceCell::new();
 
-    DATA.get_or_init(|| Data {
-      clash: Arc::new(Mutex::new(Clash::new())),
-      verge: Arc::new(Mutex::new(Verge::new())),
-      profiles: Arc::new(Mutex::new(Profiles::new())),
-    })
-  }
+        DATA.get_or_init(|| Data {
+            clash: Arc::new(Mutex::new(Clash::new())),
+            verge: Arc::new(Mutex::new(Verge::new())),
+            profiles: Arc::new(Mutex::new(Profiles::new())),
+        })
+    }
 }
diff --git a/src-tauri/src/data/prfitem.rs b/src-tauri/src/data/prfitem.rs
index ea2dd11b20dc721e317bac99fde62739a51d864f..90b08f36045e1df6c8d041b8e67aa40512440243 100644
--- a/src-tauri/src/data/prfitem.rs
+++ b/src-tauri/src/data/prfitem.rs
@@ -8,399 +8,399 @@ use sysproxy::Sysproxy;
 
 #[derive(Debug, Clone, Deserialize, Serialize)]
 pub struct PrfItem {
-  pub uid: Option<String>,
+    pub uid: Option<String>,
 
-  /// profile item type
-  /// enum value: remote | local | script | merge
-  #[serde(rename = "type")]
-  pub itype: Option<String>,
+    /// profile item type
+    /// enum value: remote | local | script | merge
+    #[serde(rename = "type")]
+    pub itype: Option<String>,
 
-  /// profile name
-  pub name: Option<String>,
+    /// profile name
+    pub name: Option<String>,
 
-  /// profile file
-  pub file: Option<String>,
+    /// profile file
+    pub file: Option<String>,
 
-  /// profile description
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub desc: Option<String>,
+    /// profile description
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub desc: Option<String>,
 
-  /// source url
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub url: Option<String>,
+    /// source url
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub url: Option<String>,
 
-  /// selected infomation
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub selected: Option<Vec<PrfSelected>>,
+    /// selected infomation
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub selected: Option<Vec<PrfSelected>>,
 
-  /// subscription user info
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub extra: Option<PrfExtra>,
+    /// subscription user info
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub extra: Option<PrfExtra>,
 
-  /// updated time
-  pub updated: Option<usize>,
+    /// updated time
+    pub updated: Option<usize>,
 
-  /// some options of the item
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub option: Option<PrfOption>,
+    /// some options of the item
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub option: Option<PrfOption>,
 
-  /// the file data
-  #[serde(skip)]
-  pub file_data: Option<String>,
+    /// the file data
+    #[serde(skip)]
+    pub file_data: Option<String>,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct PrfSelected {
-  pub name: Option<String>,
-  pub now: Option<String>,
+    pub name: Option<String>,
+    pub now: Option<String>,
 }
 
 #[derive(Default, Debug, Clone, Copy, Deserialize, Serialize)]
 pub struct PrfExtra {
-  pub upload: usize,
-  pub download: usize,
-  pub total: usize,
-  pub expire: usize,
+    pub upload: usize,
+    pub download: usize,
+    pub total: usize,
+    pub expire: usize,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
 pub struct PrfOption {
-  /// for `remote` profile's http request
-  /// see issue #13
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub user_agent: Option<String>,
-
-  /// for `remote` profile
-  /// use system proxy
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub with_proxy: Option<bool>,
-
-  /// for `remote` profile
-  /// use self proxy
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub self_proxy: Option<bool>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub update_interval: Option<u64>,
+    /// for `remote` profile's http request
+    /// see issue #13
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub user_agent: Option<String>,
+
+    /// for `remote` profile
+    /// use system proxy
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub with_proxy: Option<bool>,
+
+    /// for `remote` profile
+    /// use self proxy
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub self_proxy: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub update_interval: Option<u64>,
 }
 
 impl PrfOption {
-  pub fn merge(one: Option<Self>, other: Option<Self>) -> Option<Self> {
-    match (one, other) {
-      (Some(mut a), Some(b)) => {
-        a.user_agent = b.user_agent.or(a.user_agent);
-        a.with_proxy = b.with_proxy.or(a.with_proxy);
-        a.self_proxy = b.self_proxy.or(a.self_proxy);
-        a.update_interval = b.update_interval.or(a.update_interval);
-        Some(a)
-      }
-      t @ _ => t.0.or(t.1),
+    pub fn merge(one: Option<Self>, other: Option<Self>) -> Option<Self> {
+        match (one, other) {
+            (Some(mut a), Some(b)) => {
+                a.user_agent = b.user_agent.or(a.user_agent);
+                a.with_proxy = b.with_proxy.or(a.with_proxy);
+                a.self_proxy = b.self_proxy.or(a.self_proxy);
+                a.update_interval = b.update_interval.or(a.update_interval);
+                Some(a)
+            }
+            t @ _ => t.0.or(t.1),
+        }
     }
-  }
 }
 
 impl Default for PrfItem {
-  fn default() -> Self {
-    PrfItem {
-      uid: None,
-      itype: None,
-      name: None,
-      desc: None,
-      file: None,
-      url: None,
-      selected: None,
-      extra: None,
-      updated: None,
-      option: None,
-      file_data: None,
+    fn default() -> Self {
+        PrfItem {
+            uid: None,
+            itype: None,
+            name: None,
+            desc: None,
+            file: None,
+            url: None,
+            selected: None,
+            extra: None,
+            updated: None,
+            option: None,
+            file_data: None,
+        }
     }
-  }
 }
 
 impl PrfItem {
-  /// From partial item
-  /// must contain `itype`
-  pub async fn from(item: PrfItem, file_data: Option<String>) -> Result<PrfItem> {
-    if item.itype.is_none() {
-      bail!("type should not be null");
-    }
+    /// From partial item
+    /// must contain `itype`
+    pub async fn from(item: PrfItem, file_data: Option<String>) -> Result<PrfItem> {
+        if item.itype.is_none() {
+            bail!("type should not be null");
+        }
 
-    match item.itype.unwrap().as_str() {
-      "remote" => {
-        if item.url.is_none() {
-          bail!("url should not be null");
+        match item.itype.unwrap().as_str() {
+            "remote" => {
+                if item.url.is_none() {
+                    bail!("url should not be null");
+                }
+                let url = item.url.as_ref().unwrap().as_str();
+                let name = item.name;
+                let desc = item.desc;
+                PrfItem::from_url(url, name, desc, item.option).await
+            }
+            "local" => {
+                let name = item.name.unwrap_or("Local File".into());
+                let desc = item.desc.unwrap_or("".into());
+                PrfItem::from_local(name, desc, file_data)
+            }
+            "merge" => {
+                let name = item.name.unwrap_or("Merge".into());
+                let desc = item.desc.unwrap_or("".into());
+                PrfItem::from_merge(name, desc)
+            }
+            "script" => {
+                let name = item.name.unwrap_or("Script".into());
+                let desc = item.desc.unwrap_or("".into());
+                PrfItem::from_script(name, desc)
+            }
+            typ @ _ => bail!("invalid profile item type \"{typ}\""),
         }
-        let url = item.url.as_ref().unwrap().as_str();
-        let name = item.name;
-        let desc = item.desc;
-        PrfItem::from_url(url, name, desc, item.option).await
-      }
-      "local" => {
-        let name = item.name.unwrap_or("Local File".into());
-        let desc = item.desc.unwrap_or("".into());
-        PrfItem::from_local(name, desc, file_data)
-      }
-      "merge" => {
-        let name = item.name.unwrap_or("Merge".into());
-        let desc = item.desc.unwrap_or("".into());
-        PrfItem::from_merge(name, desc)
-      }
-      "script" => {
-        let name = item.name.unwrap_or("Script".into());
-        let desc = item.desc.unwrap_or("".into());
-        PrfItem::from_script(name, desc)
-      }
-      typ @ _ => bail!("invalid profile item type \"{typ}\""),
     }
-  }
-
-  /// ## Local type
-  /// create a new item from name/desc
-  pub fn from_local(name: String, desc: String, file_data: Option<String>) -> Result<PrfItem> {
-    let uid = help::get_uid("l");
-    let file = format!("{uid}.yaml");
-
-    Ok(PrfItem {
-      uid: Some(uid),
-      itype: Some("local".into()),
-      name: Some(name),
-      desc: Some(desc),
-      file: Some(file),
-      url: None,
-      selected: None,
-      extra: None,
-      option: None,
-      updated: Some(help::get_now()),
-      file_data: Some(file_data.unwrap_or(tmpl::ITEM_LOCAL.into())),
-    })
-  }
-
-  /// ## Remote type
-  /// create a new item from url
-  pub async fn from_url(
-    url: &str,
-    name: Option<String>,
-    desc: Option<String>,
-    option: Option<PrfOption>,
-  ) -> Result<PrfItem> {
-    let opt_ref = option.as_ref();
-    let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false));
-    let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false));
-    let user_agent = opt_ref.map_or(None, |o| o.user_agent.clone());
-
-    let mut builder = reqwest::ClientBuilder::new().no_proxy();
-
-    // 使用软件自己的代理
-    if self_proxy {
-      let data = super::Data::global();
-      let port = data.clash.lock().info.port.clone();
-      let port = port.ok_or(anyhow::anyhow!("failed to get clash info port"))?;
-      let proxy_scheme = format!("http://127.0.0.1:{port}");
-
-      if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
-        builder = builder.proxy(proxy);
-      }
-      if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
-        builder = builder.proxy(proxy);
-      }
-      if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
-        builder = builder.proxy(proxy);
-      }
+
+    /// ## Local type
+    /// create a new item from name/desc
+    pub fn from_local(name: String, desc: String, file_data: Option<String>) -> Result<PrfItem> {
+        let uid = help::get_uid("l");
+        let file = format!("{uid}.yaml");
+
+        Ok(PrfItem {
+            uid: Some(uid),
+            itype: Some("local".into()),
+            name: Some(name),
+            desc: Some(desc),
+            file: Some(file),
+            url: None,
+            selected: None,
+            extra: None,
+            option: None,
+            updated: Some(help::get_now()),
+            file_data: Some(file_data.unwrap_or(tmpl::ITEM_LOCAL.into())),
+        })
     }
-    // 使用系统代理
-    else if with_proxy {
-      match Sysproxy::get_system_proxy() {
-        Ok(p @ Sysproxy { enable: true, .. }) => {
-          let proxy_scheme = format!("http://{}:{}", p.host, p.port);
-
-          if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
-            builder = builder.proxy(proxy);
-          }
-          if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
-            builder = builder.proxy(proxy);
-          }
-          if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
-            builder = builder.proxy(proxy);
-          }
+
+    /// ## Remote type
+    /// create a new item from url
+    pub async fn from_url(
+        url: &str,
+        name: Option<String>,
+        desc: Option<String>,
+        option: Option<PrfOption>,
+    ) -> Result<PrfItem> {
+        let opt_ref = option.as_ref();
+        let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false));
+        let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false));
+        let user_agent = opt_ref.map_or(None, |o| o.user_agent.clone());
+
+        let mut builder = reqwest::ClientBuilder::new().no_proxy();
+
+        // 使用软件自己的代理
+        if self_proxy {
+            let data = super::Data::global();
+            let port = data.clash.lock().info.port.clone();
+            let port = port.ok_or(anyhow::anyhow!("failed to get clash info port"))?;
+            let proxy_scheme = format!("http://127.0.0.1:{port}");
+
+            if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
+                builder = builder.proxy(proxy);
+            }
+            if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
+                builder = builder.proxy(proxy);
+            }
+            if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
+                builder = builder.proxy(proxy);
+            }
+        }
+        // 使用系统代理
+        else if with_proxy {
+            match Sysproxy::get_system_proxy() {
+                Ok(p @ Sysproxy { enable: true, .. }) => {
+                    let proxy_scheme = format!("http://{}:{}", p.host, p.port);
+
+                    if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
+                        builder = builder.proxy(proxy);
+                    }
+                    if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
+                        builder = builder.proxy(proxy);
+                    }
+                    if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
+                        builder = builder.proxy(proxy);
+                    }
+                }
+                _ => {}
+            };
         }
-        _ => {}
-      };
-    }
 
-    let version = unsafe { dirs::APP_VERSION };
-    let version = format!("clash-verge/{version}");
-    builder = builder.user_agent(user_agent.unwrap_or(version));
+        let version = unsafe { dirs::APP_VERSION };
+        let version = format!("clash-verge/{version}");
+        builder = builder.user_agent(user_agent.unwrap_or(version));
 
-    let resp = builder.build()?.get(url).send().await?;
+        let resp = builder.build()?.get(url).send().await?;
 
-    let status_code = resp.status();
-    if !StatusCode::is_success(&status_code) {
-      bail!("failed to fetch remote profile with status {status_code}")
-    }
+        let status_code = resp.status();
+        if !StatusCode::is_success(&status_code) {
+            bail!("failed to fetch remote profile with status {status_code}")
+        }
 
-    let header = resp.headers();
+        let header = resp.headers();
+
+        // parse the Subscription UserInfo
+        let extra = match header.get("Subscription-Userinfo") {
+            Some(value) => {
+                let sub_info = value.to_str().unwrap_or("");
+
+                Some(PrfExtra {
+                    upload: help::parse_str(sub_info, "upload=").unwrap_or(0),
+                    download: help::parse_str(sub_info, "download=").unwrap_or(0),
+                    total: help::parse_str(sub_info, "total=").unwrap_or(0),
+                    expire: help::parse_str(sub_info, "expire=").unwrap_or(0),
+                })
+            }
+            None => None,
+        };
+
+        // parse the Content-Disposition
+        let filename = match header.get("Content-Disposition") {
+            Some(value) => {
+                let filename = value.to_str().unwrap_or("");
+                help::parse_str::<String>(filename, "filename=")
+            }
+            None => None,
+        };
+
+        // parse the profile-update-interval
+        let option = match header.get("profile-update-interval") {
+            Some(value) => match value.to_str().unwrap_or("").parse::<u64>() {
+                Ok(val) => Some(PrfOption {
+                    update_interval: Some(val * 60), // hour -> min
+                    ..PrfOption::default()
+                }),
+                Err(_) => None,
+            },
+            None => None,
+        };
+
+        let uid = help::get_uid("r");
+        let file = format!("{uid}.yaml");
+        let name = name.unwrap_or(filename.unwrap_or("Remote File".into()));
+        let data = resp.text_with_charset("utf-8").await?;
+
+        // check the data whether the valid yaml format
+        let yaml = serde_yaml::from_str::<Mapping>(&data) //
+            .context("the remote profile data is invalid yaml")?;
+
+        if !yaml.contains_key("proxies") && !yaml.contains_key("proxy-providers") {
+            bail!("profile does not contain `proxies` or `proxy-providers`");
+        }
 
-    // parse the Subscription UserInfo
-    let extra = match header.get("Subscription-Userinfo") {
-      Some(value) => {
-        let sub_info = value.to_str().unwrap_or("");
+        Ok(PrfItem {
+            uid: Some(uid),
+            itype: Some("remote".into()),
+            name: Some(name),
+            desc,
+            file: Some(file),
+            url: Some(url.into()),
+            selected: None,
+            extra,
+            option,
+            updated: Some(help::get_now()),
+            file_data: Some(data),
+        })
+    }
 
-        Some(PrfExtra {
-          upload: help::parse_str(sub_info, "upload=").unwrap_or(0),
-          download: help::parse_str(sub_info, "download=").unwrap_or(0),
-          total: help::parse_str(sub_info, "total=").unwrap_or(0),
-          expire: help::parse_str(sub_info, "expire=").unwrap_or(0),
+    /// ## Merge type (enhance)
+    /// create the enhanced item by using `merge` rule
+    pub fn from_merge(name: String, desc: String) -> Result<PrfItem> {
+        let uid = help::get_uid("m");
+        let file = format!("{uid}.yaml");
+
+        Ok(PrfItem {
+            uid: Some(uid),
+            itype: Some("merge".into()),
+            name: Some(name),
+            desc: Some(desc),
+            file: Some(file),
+            url: None,
+            selected: None,
+            extra: None,
+            option: None,
+            updated: Some(help::get_now()),
+            file_data: Some(tmpl::ITEM_MERGE.into()),
         })
-      }
-      None => None,
-    };
-
-    // parse the Content-Disposition
-    let filename = match header.get("Content-Disposition") {
-      Some(value) => {
-        let filename = value.to_str().unwrap_or("");
-        help::parse_str::<String>(filename, "filename=")
-      }
-      None => None,
-    };
-
-    // parse the profile-update-interval
-    let option = match header.get("profile-update-interval") {
-      Some(value) => match value.to_str().unwrap_or("").parse::<u64>() {
-        Ok(val) => Some(PrfOption {
-          update_interval: Some(val * 60), // hour -> min
-          ..PrfOption::default()
-        }),
-        Err(_) => None,
-      },
-      None => None,
-    };
-
-    let uid = help::get_uid("r");
-    let file = format!("{uid}.yaml");
-    let name = name.unwrap_or(filename.unwrap_or("Remote File".into()));
-    let data = resp.text_with_charset("utf-8").await?;
-
-    // check the data whether the valid yaml format
-    let yaml = serde_yaml::from_str::<Mapping>(&data) //
-      .context("the remote profile data is invalid yaml")?;
-
-    if !yaml.contains_key("proxies") && !yaml.contains_key("proxy-providers") {
-      bail!("profile does not contain `proxies` or `proxy-providers`");
     }
 
-    Ok(PrfItem {
-      uid: Some(uid),
-      itype: Some("remote".into()),
-      name: Some(name),
-      desc,
-      file: Some(file),
-      url: Some(url.into()),
-      selected: None,
-      extra,
-      option,
-      updated: Some(help::get_now()),
-      file_data: Some(data),
-    })
-  }
-
-  /// ## Merge type (enhance)
-  /// create the enhanced item by using `merge` rule
-  pub fn from_merge(name: String, desc: String) -> Result<PrfItem> {
-    let uid = help::get_uid("m");
-    let file = format!("{uid}.yaml");
-
-    Ok(PrfItem {
-      uid: Some(uid),
-      itype: Some("merge".into()),
-      name: Some(name),
-      desc: Some(desc),
-      file: Some(file),
-      url: None,
-      selected: None,
-      extra: None,
-      option: None,
-      updated: Some(help::get_now()),
-      file_data: Some(tmpl::ITEM_MERGE.into()),
-    })
-  }
-
-  /// ## Script type (enhance)
-  /// create the enhanced item by using javascript(browserjs)
-  pub fn from_script(name: String, desc: String) -> Result<PrfItem> {
-    let uid = help::get_uid("s");
-    let file = format!("{uid}.js"); // js ext
-
-    Ok(PrfItem {
-      uid: Some(uid),
-      itype: Some("script".into()),
-      name: Some(name),
-      desc: Some(desc),
-      file: Some(file),
-      url: None,
-      selected: None,
-      extra: None,
-      option: None,
-      updated: Some(help::get_now()),
-      file_data: Some(tmpl::ITEM_SCRIPT.into()),
-    })
-  }
-
-  /// get the file data
-  pub fn read_file(&self) -> Result<String> {
-    if self.file.is_none() {
-      bail!("could not find the file");
+    /// ## Script type (enhance)
+    /// create the enhanced item by using javascript(browserjs)
+    pub fn from_script(name: String, desc: String) -> Result<PrfItem> {
+        let uid = help::get_uid("s");
+        let file = format!("{uid}.js"); // js ext
+
+        Ok(PrfItem {
+            uid: Some(uid),
+            itype: Some("script".into()),
+            name: Some(name),
+            desc: Some(desc),
+            file: Some(file),
+            url: None,
+            selected: None,
+            extra: None,
+            option: None,
+            updated: Some(help::get_now()),
+            file_data: Some(tmpl::ITEM_SCRIPT.into()),
+        })
     }
 
-    let file = self.file.clone().unwrap();
-    let path = dirs::app_profiles_dir().join(file);
-    fs::read_to_string(path).context("failed to read the file")
-  }
+    /// get the file data
+    pub fn read_file(&self) -> Result<String> {
+        if self.file.is_none() {
+            bail!("could not find the file");
+        }
 
-  /// save the file data
-  pub fn save_file(&self, data: String) -> Result<()> {
-    if self.file.is_none() {
-      bail!("could not find the file");
+        let file = self.file.clone().unwrap();
+        let path = dirs::app_profiles_dir().join(file);
+        fs::read_to_string(path).context("failed to read the file")
     }
 
-    let file = self.file.clone().unwrap();
-    let path = dirs::app_profiles_dir().join(file);
-    fs::write(path, data.as_bytes()).context("failed to save the file")
-  }
-
-  /// get the data for enhanced mode
-  pub fn to_enhance(&self) -> Option<ChainItem> {
-    let itype = self.itype.as_ref()?.as_str();
-    let file = self.file.clone()?;
-    let uid = self.uid.clone().unwrap_or("".into());
-    let path = dirs::app_profiles_dir().join(file);
+    /// save the file data
+    pub fn save_file(&self, data: String) -> Result<()> {
+        if self.file.is_none() {
+            bail!("could not find the file");
+        }
 
-    if !path.exists() {
-      return None;
+        let file = self.file.clone().unwrap();
+        let path = dirs::app_profiles_dir().join(file);
+        fs::write(path, data.as_bytes()).context("failed to save the file")
     }
 
-    match itype {
-      "script" => Some(ChainItem {
-        uid,
-        data: ChainType::Script(fs::read_to_string(path).unwrap_or("".into())),
-      }),
-      "merge" => Some(ChainItem {
-        uid,
-        data: ChainType::Merge(config::read_merge_mapping(path)),
-      }),
-      _ => None,
+    /// get the data for enhanced mode
+    pub fn to_enhance(&self) -> Option<ChainItem> {
+        let itype = self.itype.as_ref()?.as_str();
+        let file = self.file.clone()?;
+        let uid = self.uid.clone().unwrap_or("".into());
+        let path = dirs::app_profiles_dir().join(file);
+
+        if !path.exists() {
+            return None;
+        }
+
+        match itype {
+            "script" => Some(ChainItem {
+                uid,
+                data: ChainType::Script(fs::read_to_string(path).unwrap_or("".into())),
+            }),
+            "merge" => Some(ChainItem {
+                uid,
+                data: ChainType::Merge(config::read_merge_mapping(path)),
+            }),
+            _ => None,
+        }
     }
-  }
 }
 
 #[derive(Debug, Clone)]
 pub struct ChainItem {
-  pub uid: String,
-  pub data: ChainType,
+    pub uid: String,
+    pub data: ChainType,
 }
 
 #[derive(Debug, Clone)]
 pub enum ChainType {
-  Merge(Mapping),
-  Script(String),
+    Merge(Mapping),
+    Script(String),
 }
diff --git a/src-tauri/src/data/profiles.rs b/src-tauri/src/data/profiles.rs
index 09ac55778a4afaf0ef496ecddbf0bd655db6dd0f..6272cd8ccedc0a4b37390b7917296693e92cba10 100644
--- a/src-tauri/src/data/profiles.rs
+++ b/src-tauri/src/data/profiles.rs
@@ -14,315 +14,316 @@ use std::{fs, io::Write};
 ///
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct Profiles {
-  /// same as PrfConfig.current
-  current: Option<String>,
+    /// same as PrfConfig.current
+    current: Option<String>,
 
-  /// same as PrfConfig.chain
-  chain: Option<Vec<String>>,
+    /// same as PrfConfig.chain
+    chain: Option<Vec<String>>,
 
-  /// record valid fields for clash
-  valid: Option<Vec<String>>,
+    /// record valid fields for clash
+    valid: Option<Vec<String>>,
 
-  /// profile list
-  items: Option<Vec<PrfItem>>,
+    /// profile list
+    items: Option<Vec<PrfItem>>,
 }
 
 macro_rules! patch {
-  ($lv: expr, $rv: expr, $key: tt) => {
-    if ($rv.$key).is_some() {
-      $lv.$key = $rv.$key;
-    }
-  };
+    ($lv: expr, $rv: expr, $key: tt) => {
+        if ($rv.$key).is_some() {
+            $lv.$key = $rv.$key;
+        }
+    };
 }
 
 impl Profiles {
-  pub fn new() -> Self {
-    Profiles::read_file()
-  }
-
-  /// read the config from the file
-  pub fn read_file() -> Self {
-    let mut profiles = config::read_yaml::<Self>(dirs::profiles_path());
-
-    if profiles.items.is_none() {
-      profiles.items = Some(vec![]);
+    pub fn new() -> Self {
+        Profiles::read_file()
     }
 
-    // compatiable with the old old old version
-    profiles.items.as_mut().map(|items| {
-      for mut item in items.iter_mut() {
-        if item.uid.is_none() {
-          item.uid = Some(help::get_uid("d"));
+    /// read the config from the file
+    pub fn read_file() -> Self {
+        let mut profiles = config::read_yaml::<Self>(dirs::profiles_path());
+
+        if profiles.items.is_none() {
+            profiles.items = Some(vec![]);
         }
-      }
-    });
-
-    profiles
-  }
-
-  /// save the config to the file
-  pub fn save_file(&self) -> Result<()> {
-    config::save_yaml(
-      dirs::profiles_path(),
-      self,
-      Some("# Profiles Config for Clash Verge\n\n"),
-    )
-  }
-
-  /// get the current uid
-  pub fn get_current(&self) -> Option<String> {
-    self.current.clone()
-  }
-
-  /// only change the main to the target id
-  pub fn put_current(&mut self, uid: String) -> Result<()> {
-    if self.items.is_none() {
-      self.items = Some(vec![]);
+
+        // compatiable with the old old old version
+        profiles.items.as_mut().map(|items| {
+            for mut item in items.iter_mut() {
+                if item.uid.is_none() {
+                    item.uid = Some(help::get_uid("d"));
+                }
+            }
+        });
+
+        profiles
     }
 
-    let items = self.items.as_ref().unwrap();
-    let some_uid = Some(uid.clone());
+    /// save the config to the file
+    pub fn save_file(&self) -> Result<()> {
+        config::save_yaml(
+            dirs::profiles_path(),
+            self,
+            Some("# Profiles Config for Clash Verge\n\n"),
+        )
+    }
 
-    if items.iter().find(|&each| each.uid == some_uid).is_some() {
-      self.current = some_uid;
-      return self.save_file();
+    /// get the current uid
+    pub fn get_current(&self) -> Option<String> {
+        self.current.clone()
     }
 
-    bail!("invalid uid \"{uid}\"");
-  }
-
-  /// just change the `chain`
-  pub fn put_chain(&mut self, chain: Option<Vec<String>>) -> Result<()> {
-    self.chain = chain;
-    self.save_file()
-  }
-
-  /// just change the `field`
-  pub fn put_valid(&mut self, valid: Option<Vec<String>>) -> Result<()> {
-    self.valid = valid;
-    self.save_file()
-  }
-
-  /// get items ref
-  pub fn get_items(&self) -> Option<&Vec<PrfItem>> {
-    self.items.as_ref()
-  }
-
-  /// find the item by the uid
-  pub fn get_item(&self, uid: &String) -> Result<&PrfItem> {
-    if self.items.is_some() {
-      let items = self.items.as_ref().unwrap();
-      let some_uid = Some(uid.clone());
-
-      for each in items.iter() {
-        if each.uid == some_uid {
-          return Ok(each);
+    /// only change the main to the target id
+    pub fn put_current(&mut self, uid: String) -> Result<()> {
+        if self.items.is_none() {
+            self.items = Some(vec![]);
         }
-      }
-    }
 
-    bail!("failed to get the profile item \"uid:{uid}\"");
-  }
+        let items = self.items.as_ref().unwrap();
+        let some_uid = Some(uid.clone());
+
+        if items.iter().find(|&each| each.uid == some_uid).is_some() {
+            self.current = some_uid;
+            return self.save_file();
+        }
 
-  /// append new item
-  /// if the file_data is some
-  /// then should save the data to file
-  pub fn append_item(&mut self, mut item: PrfItem) -> Result<()> {
-    if item.uid.is_none() {
-      bail!("the uid should not be null");
+        bail!("invalid uid \"{uid}\"");
     }
 
-    // save the file data
-    // move the field value after save
-    if let Some(file_data) = item.file_data.take() {
-      if item.file.is_none() {
-        bail!("the file should not be null");
-      }
+    /// just change the `chain`
+    pub fn put_chain(&mut self, chain: Option<Vec<String>>) -> Result<()> {
+        self.chain = chain;
+        self.save_file()
+    }
 
-      let file = item.file.clone().unwrap();
-      let path = dirs::app_profiles_dir().join(&file);
+    /// just change the `field`
+    pub fn put_valid(&mut self, valid: Option<Vec<String>>) -> Result<()> {
+        self.valid = valid;
+        self.save_file()
+    }
 
-      fs::File::create(path)
-        .context(format!("failed to create file \"{}\"", file))?
-        .write(file_data.as_bytes())
-        .context(format!("failed to write to file \"{}\"", file))?;
+    /// get items ref
+    pub fn get_items(&self) -> Option<&Vec<PrfItem>> {
+        self.items.as_ref()
     }
 
-    if self.items.is_none() {
-      self.items = Some(vec![]);
+    /// find the item by the uid
+    pub fn get_item(&self, uid: &String) -> Result<&PrfItem> {
+        if self.items.is_some() {
+            let items = self.items.as_ref().unwrap();
+            let some_uid = Some(uid.clone());
+
+            for each in items.iter() {
+                if each.uid == some_uid {
+                    return Ok(each);
+                }
+            }
+        }
+
+        bail!("failed to get the profile item \"uid:{uid}\"");
     }
 
-    self.items.as_mut().map(|items| items.push(item));
-    self.save_file()
-  }
-
-  /// update the item value
-  pub fn patch_item(&mut self, uid: String, item: PrfItem) -> Result<()> {
-    let mut items = self.items.take().unwrap_or(vec![]);
-
-    for mut each in items.iter_mut() {
-      if each.uid == Some(uid.clone()) {
-        patch!(each, item, itype);
-        patch!(each, item, name);
-        patch!(each, item, desc);
-        patch!(each, item, file);
-        patch!(each, item, url);
-        patch!(each, item, selected);
-        patch!(each, item, extra);
-        patch!(each, item, updated);
-        patch!(each, item, option);
+    /// append new item
+    /// if the file_data is some
+    /// then should save the data to file
+    pub fn append_item(&mut self, mut item: PrfItem) -> Result<()> {
+        if item.uid.is_none() {
+            bail!("the uid should not be null");
+        }
+
+        // save the file data
+        // move the field value after save
+        if let Some(file_data) = item.file_data.take() {
+            if item.file.is_none() {
+                bail!("the file should not be null");
+            }
 
-        self.items = Some(items);
-        return self.save_file();
-      }
+            let file = item.file.clone().unwrap();
+            let path = dirs::app_profiles_dir().join(&file);
+
+            fs::File::create(path)
+                .context(format!("failed to create file \"{}\"", file))?
+                .write(file_data.as_bytes())
+                .context(format!("failed to write to file \"{}\"", file))?;
+        }
+
+        if self.items.is_none() {
+            self.items = Some(vec![]);
+        }
+
+        self.items.as_mut().map(|items| items.push(item));
+        self.save_file()
     }
 
-    self.items = Some(items);
-    bail!("failed to find the profile item \"uid:{uid}\"")
-  }
+    /// update the item value
+    pub fn patch_item(&mut self, uid: String, item: PrfItem) -> Result<()> {
+        let mut items = self.items.take().unwrap_or(vec![]);
+
+        for mut each in items.iter_mut() {
+            if each.uid == Some(uid.clone()) {
+                patch!(each, item, itype);
+                patch!(each, item, name);
+                patch!(each, item, desc);
+                patch!(each, item, file);
+                patch!(each, item, url);
+                patch!(each, item, selected);
+                patch!(each, item, extra);
+                patch!(each, item, updated);
+                patch!(each, item, option);
+
+                self.items = Some(items);
+                return self.save_file();
+            }
+        }
 
-  /// be used to update the remote item
-  /// only patch `updated` `extra` `file_data`
-  pub fn update_item(&mut self, uid: String, mut item: PrfItem) -> Result<()> {
-    if self.items.is_none() {
-      self.items = Some(vec![]);
+        self.items = Some(items);
+        bail!("failed to find the profile item \"uid:{uid}\"")
     }
 
-    // find the item
-    let _ = self.get_item(&uid)?;
+    /// be used to update the remote item
+    /// only patch `updated` `extra` `file_data`
+    pub fn update_item(&mut self, uid: String, mut item: PrfItem) -> Result<()> {
+        if self.items.is_none() {
+            self.items = Some(vec![]);
+        }
 
-    if let Some(items) = self.items.as_mut() {
-      let some_uid = Some(uid.clone());
+        // find the item
+        let _ = self.get_item(&uid)?;
 
-      for mut each in items.iter_mut() {
-        if each.uid == some_uid {
-          each.extra = item.extra;
-          each.updated = item.updated;
+        if let Some(items) = self.items.as_mut() {
+            let some_uid = Some(uid.clone());
 
-          // save the file data
-          // move the field value after save
-          if let Some(file_data) = item.file_data.take() {
-            let file = each.file.take();
-            let file = file.unwrap_or(item.file.take().unwrap_or(format!("{}.yaml", &uid)));
+            for mut each in items.iter_mut() {
+                if each.uid == some_uid {
+                    each.extra = item.extra;
+                    each.updated = item.updated;
 
-            // the file must exists
-            each.file = Some(file.clone());
+                    // save the file data
+                    // move the field value after save
+                    if let Some(file_data) = item.file_data.take() {
+                        let file = each.file.take();
+                        let file =
+                            file.unwrap_or(item.file.take().unwrap_or(format!("{}.yaml", &uid)));
 
-            let path = dirs::app_profiles_dir().join(&file);
+                        // the file must exists
+                        each.file = Some(file.clone());
 
-            fs::File::create(path)
-              .context(format!("failed to create file \"{}\"", file))?
-              .write(file_data.as_bytes())
-              .context(format!("failed to write to file \"{}\"", file))?;
-          }
+                        let path = dirs::app_profiles_dir().join(&file);
 
-          break;
+                        fs::File::create(path)
+                            .context(format!("failed to create file \"{}\"", file))?
+                            .write(file_data.as_bytes())
+                            .context(format!("failed to write to file \"{}\"", file))?;
+                    }
+
+                    break;
+                }
+            }
         }
-      }
+
+        self.save_file()
     }
 
-    self.save_file()
-  }
+    /// delete item
+    /// if delete the current then return true
+    pub fn delete_item(&mut self, uid: String) -> Result<bool> {
+        let current = self.current.as_ref().unwrap_or(&uid);
+        let current = current.clone();
+
+        let mut items = self.items.take().unwrap_or(vec![]);
+        let mut index = None;
+
+        // get the index
+        for i in 0..items.len() {
+            if items[i].uid == Some(uid.clone()) {
+                index = Some(i);
+                break;
+            }
+        }
 
-  /// delete item
-  /// if delete the current then return true
-  pub fn delete_item(&mut self, uid: String) -> Result<bool> {
-    let current = self.current.as_ref().unwrap_or(&uid);
-    let current = current.clone();
+        if let Some(index) = index {
+            items.remove(index).file.map(|file| {
+                let path = dirs::app_profiles_dir().join(file);
+                if path.exists() {
+                    let _ = fs::remove_file(path);
+                }
+            });
+        }
 
-    let mut items = self.items.take().unwrap_or(vec![]);
-    let mut index = None;
+        // delete the original uid
+        if current == uid {
+            self.current = match items.len() > 0 {
+                true => items[0].uid.clone(),
+                false => None,
+            };
+        }
 
-    // get the index
-    for i in 0..items.len() {
-      if items[i].uid == Some(uid.clone()) {
-        index = Some(i);
-        break;
-      }
+        self.items = Some(items);
+        self.save_file()?;
+        Ok(current == uid)
     }
 
-    if let Some(index) = index {
-      items.remove(index).file.map(|file| {
-        let path = dirs::app_profiles_dir().join(file);
-        if path.exists() {
-          let _ = fs::remove_file(path);
-        }
-      });
-    }
+    /// generate the current Mapping data
+    fn gen_current(&self) -> Result<Mapping> {
+        let config = Mapping::new();
 
-    // delete the original uid
-    if current == uid {
-      self.current = match items.len() > 0 {
-        true => items[0].uid.clone(),
-        false => None,
-      };
-    }
+        if self.current.is_none() || self.items.is_none() {
+            return Ok(config);
+        }
 
-    self.items = Some(items);
-    self.save_file()?;
-    Ok(current == uid)
-  }
+        let current = self.current.clone().unwrap();
+        for item in self.items.as_ref().unwrap().iter() {
+            if item.uid == Some(current.clone()) {
+                let file_path = match item.file.clone() {
+                    Some(file) => dirs::app_profiles_dir().join(file),
+                    None => bail!("failed to get the file field"),
+                };
 
-  /// generate the current Mapping data
-  fn gen_current(&self) -> Result<Mapping> {
-    let config = Mapping::new();
+                if !file_path.exists() {
+                    bail!("failed to read the file \"{}\"", file_path.display());
+                }
 
-    if self.current.is_none() || self.items.is_none() {
-      return Ok(config);
+                return Ok(config::read_merge_mapping(file_path.clone()));
+            }
+        }
+        bail!("failed to find current profile \"uid:{current}\"");
     }
 
-    let current = self.current.clone().unwrap();
-    for item in self.items.as_ref().unwrap().iter() {
-      if item.uid == Some(current.clone()) {
-        let file_path = match item.file.clone() {
-          Some(file) => dirs::app_profiles_dir().join(file),
-          None => bail!("failed to get the file field"),
+    /// generate the data for activate clash config
+    pub fn gen_activate(&self) -> Result<PrfActivate> {
+        let current = self.gen_current()?;
+        let chain = match self.chain.as_ref() {
+            Some(chain) => chain
+                .iter()
+                .filter_map(|uid| self.get_item(uid).ok())
+                .filter_map(|item| item.to_enhance())
+                .collect::<Vec<ChainItem>>(),
+            None => vec![],
         };
+        let valid = self.valid.clone().unwrap_or(vec![]);
 
-        if !file_path.exists() {
-          bail!("failed to read the file \"{}\"", file_path.display());
-        }
-
-        return Ok(config::read_merge_mapping(file_path.clone()));
-      }
+        Ok(PrfActivate {
+            current,
+            chain,
+            valid,
+        })
     }
-    bail!("failed to find current profile \"uid:{current}\"");
-  }
-
-  /// generate the data for activate clash config
-  pub fn gen_activate(&self) -> Result<PrfActivate> {
-    let current = self.gen_current()?;
-    let chain = match self.chain.as_ref() {
-      Some(chain) => chain
-        .iter()
-        .filter_map(|uid| self.get_item(uid).ok())
-        .filter_map(|item| item.to_enhance())
-        .collect::<Vec<ChainItem>>(),
-      None => vec![],
-    };
-    let valid = self.valid.clone().unwrap_or(vec![]);
-
-    Ok(PrfActivate {
-      current,
-      chain,
-      valid,
-    })
-  }
 }
 
 #[derive(Default, Clone)]
 pub struct PrfActivate {
-  pub current: Mapping,
-  pub chain: Vec<ChainItem>,
-  pub valid: Vec<String>,
+    pub current: Mapping,
+    pub chain: Vec<ChainItem>,
+    pub valid: Vec<String>,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct RuntimeResult {
-  pub config: Option<Mapping>,
-  pub config_yaml: Option<String>,
-  // 记录在配置中(包括merge和script生成的)出现过的keys
-  // 这些keys不一定都生效
-  pub exists_keys: Vec<String>,
-  pub chain_logs: HashMap<String, Vec<(String, String)>>,
+    pub config: Option<Mapping>,
+    pub config_yaml: Option<String>,
+    // 记录在配置中(包括merge和script生成的)出现过的keys
+    // 这些keys不一定都生效
+    pub exists_keys: Vec<String>,
+    pub chain_logs: HashMap<String, Vec<(String, String)>>,
 }
diff --git a/src-tauri/src/data/verge.rs b/src-tauri/src/data/verge.rs
index 9a5519e324ffc08422b2b1f588c6f28502a7e0cb..97c20166afc28f48fb9df587d730a782c3addec9 100644
--- a/src-tauri/src/data/verge.rs
+++ b/src-tauri/src/data/verge.rs
@@ -5,132 +5,132 @@ use serde::{Deserialize, Serialize};
 /// ### `verge.yaml` schema
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct Verge {
-  /// app listening port
-  /// for app singleton
-  pub app_singleton_port: Option<u16>,
+    /// app listening port
+    /// for app singleton
+    pub app_singleton_port: Option<u16>,
 
-  // i18n
-  pub language: Option<String>,
+    // i18n
+    pub language: Option<String>,
 
-  /// `light` or `dark` or `system`
-  pub theme_mode: Option<String>,
+    /// `light` or `dark` or `system`
+    pub theme_mode: Option<String>,
 
-  /// enable blur mode
-  /// maybe be able to set the alpha
-  pub theme_blur: Option<bool>,
+    /// enable blur mode
+    /// maybe be able to set the alpha
+    pub theme_blur: Option<bool>,
 
-  /// enable traffic graph default is true
-  pub traffic_graph: Option<bool>,
+    /// enable traffic graph default is true
+    pub traffic_graph: Option<bool>,
 
-  /// clash tun mode
-  pub enable_tun_mode: Option<bool>,
+    /// clash tun mode
+    pub enable_tun_mode: Option<bool>,
 
-  /// windows service mode
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub enable_service_mode: Option<bool>,
+    /// windows service mode
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub enable_service_mode: Option<bool>,
 
-  /// can the app auto startup
-  pub enable_auto_launch: Option<bool>,
+    /// can the app auto startup
+    pub enable_auto_launch: Option<bool>,
 
-  /// not show the window on launch
-  pub enable_silent_start: Option<bool>,
+    /// not show the window on launch
+    pub enable_silent_start: Option<bool>,
 
-  /// set system proxy
-  pub enable_system_proxy: Option<bool>,
+    /// set system proxy
+    pub enable_system_proxy: Option<bool>,
 
-  /// enable proxy guard
-  pub enable_proxy_guard: Option<bool>,
+    /// enable proxy guard
+    pub enable_proxy_guard: Option<bool>,
 
-  /// set system proxy bypass
-  pub system_proxy_bypass: Option<String>,
+    /// set system proxy bypass
+    pub system_proxy_bypass: Option<String>,
 
-  /// proxy guard duration
-  pub proxy_guard_duration: Option<u64>,
+    /// proxy guard duration
+    pub proxy_guard_duration: Option<u64>,
 
-  /// theme setting
-  pub theme_setting: Option<VergeTheme>,
+    /// theme setting
+    pub theme_setting: Option<VergeTheme>,
 
-  /// web ui list
-  pub web_ui_list: Option<Vec<String>>,
+    /// web ui list
+    pub web_ui_list: Option<Vec<String>>,
 
-  /// clash core path
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub clash_core: Option<String>,
+    /// clash core path
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub clash_core: Option<String>,
 
-  /// hotkey map
-  /// format: {func},{key}
-  pub hotkeys: Option<Vec<String>>,
+    /// hotkey map
+    /// format: {func},{key}
+    pub hotkeys: Option<Vec<String>>,
 
-  /// 切换代理时自动关闭连接
-  pub auto_close_connection: Option<bool>,
+    /// 切换代理时自动关闭连接
+    pub auto_close_connection: Option<bool>,
 
-  /// 默认的延迟测试连接
-  pub default_latency_test: Option<String>,
+    /// 默认的延迟测试连接
+    pub default_latency_test: Option<String>,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct VergeTheme {
-  pub primary_color: Option<String>,
-  pub secondary_color: Option<String>,
-  pub primary_text: Option<String>,
-  pub secondary_text: Option<String>,
-
-  pub info_color: Option<String>,
-  pub error_color: Option<String>,
-  pub warning_color: Option<String>,
-  pub success_color: Option<String>,
-
-  pub font_family: Option<String>,
-  pub css_injection: Option<String>,
+    pub primary_color: Option<String>,
+    pub secondary_color: Option<String>,
+    pub primary_text: Option<String>,
+    pub secondary_text: Option<String>,
+
+    pub info_color: Option<String>,
+    pub error_color: Option<String>,
+    pub warning_color: Option<String>,
+    pub success_color: Option<String>,
+
+    pub font_family: Option<String>,
+    pub css_injection: Option<String>,
 }
 
 impl Verge {
-  pub fn new() -> Self {
-    config::read_yaml::<Verge>(dirs::verge_path())
-  }
-
-  /// Save Verge App Config
-  pub fn save_file(&self) -> Result<()> {
-    config::save_yaml(
-      dirs::verge_path(),
-      self,
-      Some("# The Config for Clash Verge App\n\n"),
-    )
-  }
-
-  /// patch verge config
-  /// only save to file
-  pub fn patch_config(&mut self, patch: Verge) -> Result<()> {
-    macro_rules! patch {
-      ($key: tt) => {
-        if patch.$key.is_some() {
-          self.$key = patch.$key;
-        }
-      };
+    pub fn new() -> Self {
+        config::read_yaml::<Verge>(dirs::verge_path())
+    }
+
+    /// Save Verge App Config
+    pub fn save_file(&self) -> Result<()> {
+        config::save_yaml(
+            dirs::verge_path(),
+            self,
+            Some("# The Config for Clash Verge App\n\n"),
+        )
     }
 
-    patch!(language);
-    patch!(theme_mode);
-    patch!(theme_blur);
-    patch!(traffic_graph);
-
-    patch!(enable_tun_mode);
-    patch!(enable_service_mode);
-    patch!(enable_auto_launch);
-    patch!(enable_silent_start);
-    patch!(enable_system_proxy);
-    patch!(enable_proxy_guard);
-    patch!(system_proxy_bypass);
-    patch!(proxy_guard_duration);
-
-    patch!(theme_setting);
-    patch!(web_ui_list);
-    patch!(clash_core);
-    patch!(hotkeys);
-
-    patch!(auto_close_connection);
-    patch!(default_latency_test);
-
-    self.save_file()
-  }
+    /// patch verge config
+    /// only save to file
+    pub fn patch_config(&mut self, patch: Verge) -> Result<()> {
+        macro_rules! patch {
+            ($key: tt) => {
+                if patch.$key.is_some() {
+                    self.$key = patch.$key;
+                }
+            };
+        }
+
+        patch!(language);
+        patch!(theme_mode);
+        patch!(theme_blur);
+        patch!(traffic_graph);
+
+        patch!(enable_tun_mode);
+        patch!(enable_service_mode);
+        patch!(enable_auto_launch);
+        patch!(enable_silent_start);
+        patch!(enable_system_proxy);
+        patch!(enable_proxy_guard);
+        patch!(system_proxy_bypass);
+        patch!(proxy_guard_duration);
+
+        patch!(theme_setting);
+        patch!(web_ui_list);
+        patch!(clash_core);
+        patch!(hotkeys);
+
+        patch!(auto_close_connection);
+        patch!(default_latency_test);
+
+        self.save_file()
+    }
 }
diff --git a/src-tauri/src/feat.rs b/src-tauri/src/feat.rs
index 5bf1d49bd36e38f762fa4ffa841cf322face497f..79fade14463383298b043ffe115379c8f3e8bbc8 100644
--- a/src-tauri/src/feat.rs
+++ b/src-tauri/src/feat.rs
@@ -4,99 +4,99 @@ use crate::log_if_err;
 
 // 重启clash
 pub fn restart_clash_core() {
-  let core = Core::global();
-  let mut service = core.service.lock();
-  log_if_err!(service.restart());
-  drop(service);
-  log_if_err!(core.activate());
+    let core = Core::global();
+    let mut service = core.service.lock();
+    log_if_err!(service.restart());
+    drop(service);
+    log_if_err!(core.activate());
 }
 
 // 切换模式
 pub fn change_clash_mode(mode: &str) {
-  let core = Core::global();
-  log_if_err!(core.update_mode(mode));
+    let core = Core::global();
+    log_if_err!(core.update_mode(mode));
 }
 
 // 切换系统代理
 pub fn toggle_system_proxy() {
-  let core = Core::global();
-  let data = Data::global();
+    let core = Core::global();
+    let data = Data::global();
 
-  let verge = data.verge.lock();
-  let enable = !verge.enable_system_proxy.clone().unwrap_or(false);
-  drop(verge);
+    let verge = data.verge.lock();
+    let enable = !verge.enable_system_proxy.clone().unwrap_or(false);
+    drop(verge);
 
-  log_if_err!(core.patch_verge(Verge {
-    enable_system_proxy: Some(enable),
-    ..Verge::default()
-  }));
+    log_if_err!(core.patch_verge(Verge {
+        enable_system_proxy: Some(enable),
+        ..Verge::default()
+    }));
 
-  let handle = core.handle.lock();
-  let _ = handle.refresh_verge();
+    let handle = core.handle.lock();
+    let _ = handle.refresh_verge();
 }
 
 // 打开系统代理
 pub fn enable_system_proxy() {
-  let core = Core::global();
-  log_if_err!(core.patch_verge(Verge {
-    enable_system_proxy: Some(true),
-    ..Verge::default()
-  }));
-
-  let handle = core.handle.lock();
-  let _ = handle.refresh_verge();
+    let core = Core::global();
+    log_if_err!(core.patch_verge(Verge {
+        enable_system_proxy: Some(true),
+        ..Verge::default()
+    }));
+
+    let handle = core.handle.lock();
+    let _ = handle.refresh_verge();
 }
 
 // 关闭系统代理
 pub fn disable_system_proxy() {
-  let core = Core::global();
-  log_if_err!(core.patch_verge(Verge {
-    enable_system_proxy: Some(false),
-    ..Verge::default()
-  }));
-
-  let handle = core.handle.lock();
-  let _ = handle.refresh_verge();
+    let core = Core::global();
+    log_if_err!(core.patch_verge(Verge {
+        enable_system_proxy: Some(false),
+        ..Verge::default()
+    }));
+
+    let handle = core.handle.lock();
+    let _ = handle.refresh_verge();
 }
 
 // 切换tun模式
 pub fn toggle_tun_mode() {
-  let core = Core::global();
-  let data = Data::global();
+    let core = Core::global();
+    let data = Data::global();
 
-  let verge = data.verge.lock();
-  let enable = !verge.enable_tun_mode.clone().unwrap_or(false);
-  drop(verge);
+    let verge = data.verge.lock();
+    let enable = !verge.enable_tun_mode.clone().unwrap_or(false);
+    drop(verge);
 
-  log_if_err!(core.patch_verge(Verge {
-    enable_tun_mode: Some(enable),
-    ..Verge::default()
-  }));
+    log_if_err!(core.patch_verge(Verge {
+        enable_tun_mode: Some(enable),
+        ..Verge::default()
+    }));
 
-  let handle = core.handle.lock();
-  let _ = handle.refresh_verge();
+    let handle = core.handle.lock();
+    let _ = handle.refresh_verge();
 }
 
 // 打开tun模式
 pub fn enable_tun_mode() {
-  let core = Core::global();
-  log_if_err!(core.patch_verge(Verge {
-    enable_tun_mode: Some(true),
-    ..Verge::default()
-  }));
-
-  let handle = core.handle.lock();
-  let _ = handle.refresh_verge();
+    let core = Core::global();
+    log_if_err!(core.patch_verge(Verge {
+        enable_tun_mode: Some(true),
+        ..Verge::default()
+    }));
+
+    let handle = core.handle.lock();
+    let _ = handle.refresh_verge();
 }
 
 // 关闭tun模式
 pub fn disable_tun_mode() {
-  let core = Core::global();
-  log_if_err!(core.patch_verge(Verge {
-    enable_tun_mode: Some(false),
-    ..Verge::default()
-  }));
-
-  let handle = core.handle.lock();
-  let _ = handle.refresh_verge();
+    let core = Core::global();
+    log_if_err!(core.patch_verge(Verge {
+        enable_tun_mode: Some(false),
+        ..Verge::default()
+    }));
+
+    let handle = core.handle.lock();
+    let _ = handle.refresh_verge();
 }
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 0c9dd6742a9dfc2559f892ab914346c5524eda1d..066939bc08fd01f37f0e8feaf44873a67956a541 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -1,6 +1,6 @@
 #![cfg_attr(
-  all(not(debug_assertions), target_os = "windows"),
-  windows_subsystem = "windows"
+    all(not(debug_assertions), target_os = "windows"),
+    windows_subsystem = "windows"
 )]
 
 mod cmds;
@@ -14,129 +14,129 @@ use crate::utils::{init, resolve, server};
 use tauri::{api, Manager, SystemTray};
 
 fn main() -> std::io::Result<()> {
-  // 单例检测
-  if server::check_singleton().is_err() {
-    println!("app exists");
-    return Ok(());
-  }
+    // 单例检测
+    if server::check_singleton().is_err() {
+        println!("app exists");
+        return Ok(());
+    }
 
-  #[cfg(target_os = "windows")]
-  unsafe {
-    use crate::utils::dirs;
-    dirs::init_portable_flag();
-  }
+    #[cfg(target_os = "windows")]
+    unsafe {
+        use crate::utils::dirs;
+        dirs::init_portable_flag();
+    }
 
-  crate::log_if_err!(init::init_config());
+    crate::log_if_err!(init::init_config());
 
-  #[allow(unused_mut)]
-  let mut builder = tauri::Builder::default()
-    .setup(|app| Ok(resolve::resolve_setup(app)))
-    .system_tray(SystemTray::new())
-    .on_system_tray_event(core::tray::Tray::on_system_tray_event)
-    .invoke_handler(tauri::generate_handler![
-      // common
-      cmds::get_sys_proxy,
-      cmds::open_app_dir,
-      cmds::open_logs_dir,
-      cmds::open_web_url,
-      cmds::kill_sidecar,
-      cmds::restart_sidecar,
-      // clash
-      cmds::get_clash_info,
-      cmds::get_clash_logs,
-      cmds::patch_clash_config,
-      cmds::change_clash_core,
-      cmds::get_runtime_config,
-      cmds::get_runtime_yaml,
-      cmds::get_runtime_exists,
-      cmds::get_runtime_logs,
-      // verge
-      cmds::get_verge_config,
-      cmds::patch_verge_config,
-      cmds::update_hotkeys,
-      // profile
-      cmds::view_profile,
-      cmds::patch_profile,
-      cmds::create_profile,
-      cmds::import_profile,
-      cmds::update_profile,
-      cmds::delete_profile,
-      cmds::select_profile,
-      cmds::get_profiles,
-      cmds::enhance_profiles,
-      cmds::change_profile_chain,
-      cmds::change_profile_valid,
-      cmds::read_profile_file,
-      cmds::save_profile_file,
-      // service mode
-      cmds::service::start_service,
-      cmds::service::stop_service,
-      cmds::service::check_service,
-      cmds::service::install_service,
-      cmds::service::uninstall_service,
-    ]);
+    #[allow(unused_mut)]
+    let mut builder = tauri::Builder::default()
+        .setup(|app| Ok(resolve::resolve_setup(app)))
+        .system_tray(SystemTray::new())
+        .on_system_tray_event(core::tray::Tray::on_system_tray_event)
+        .invoke_handler(tauri::generate_handler![
+            // common
+            cmds::get_sys_proxy,
+            cmds::open_app_dir,
+            cmds::open_logs_dir,
+            cmds::open_web_url,
+            cmds::kill_sidecar,
+            cmds::restart_sidecar,
+            // clash
+            cmds::get_clash_info,
+            cmds::get_clash_logs,
+            cmds::patch_clash_config,
+            cmds::change_clash_core,
+            cmds::get_runtime_config,
+            cmds::get_runtime_yaml,
+            cmds::get_runtime_exists,
+            cmds::get_runtime_logs,
+            // verge
+            cmds::get_verge_config,
+            cmds::patch_verge_config,
+            cmds::update_hotkeys,
+            // profile
+            cmds::view_profile,
+            cmds::patch_profile,
+            cmds::create_profile,
+            cmds::import_profile,
+            cmds::update_profile,
+            cmds::delete_profile,
+            cmds::select_profile,
+            cmds::get_profiles,
+            cmds::enhance_profiles,
+            cmds::change_profile_chain,
+            cmds::change_profile_valid,
+            cmds::read_profile_file,
+            cmds::save_profile_file,
+            // service mode
+            cmds::service::start_service,
+            cmds::service::stop_service,
+            cmds::service::check_service,
+            cmds::service::install_service,
+            cmds::service::uninstall_service,
+        ]);
 
-  #[cfg(target_os = "macos")]
-  {
-    use tauri::{Menu, MenuItem, Submenu};
+    #[cfg(target_os = "macos")]
+    {
+        use tauri::{Menu, MenuItem, Submenu};
 
-    builder = builder.menu(
-      Menu::new().add_submenu(Submenu::new(
-        "Edit",
-        Menu::new()
-          .add_native_item(MenuItem::Undo)
-          .add_native_item(MenuItem::Redo)
-          .add_native_item(MenuItem::Copy)
-          .add_native_item(MenuItem::Paste)
-          .add_native_item(MenuItem::Cut)
-          .add_native_item(MenuItem::SelectAll)
-          .add_native_item(MenuItem::CloseWindow)
-          .add_native_item(MenuItem::Quit)
-      )),
-    );
-  }
+        builder = builder.menu(
+            Menu::new().add_submenu(Submenu::new(
+                "Edit",
+                Menu::new()
+                    .add_native_item(MenuItem::Undo)
+                    .add_native_item(MenuItem::Redo)
+                    .add_native_item(MenuItem::Copy)
+                    .add_native_item(MenuItem::Paste)
+                    .add_native_item(MenuItem::Cut)
+                    .add_native_item(MenuItem::SelectAll)
+                    .add_native_item(MenuItem::CloseWindow)
+                    .add_native_item(MenuItem::Quit),
+            )),
+        );
+    }
 
-  #[allow(unused_mut)]
-  let mut app = builder
-    .build(tauri::generate_context!())
-    .expect("error while running tauri application");
+    #[allow(unused_mut)]
+    let mut app = builder
+        .build(tauri::generate_context!())
+        .expect("error while running tauri application");
 
-  #[cfg(target_os = "macos")]
-  app.set_activation_policy(tauri::ActivationPolicy::Accessory);
+    #[cfg(target_os = "macos")]
+    app.set_activation_policy(tauri::ActivationPolicy::Accessory);
 
-  let app_handle = app.app_handle();
-  ctrlc::set_handler(move || {
-    resolve::resolve_reset();
-    app_handle.exit(0);
-  })
-  .expect("error while exiting.");
+    let app_handle = app.app_handle();
+    ctrlc::set_handler(move || {
+        resolve::resolve_reset();
+        app_handle.exit(0);
+    })
+    .expect("error while exiting.");
 
-  #[allow(unused)]
-  app.run(|app_handle, e| match e {
-    tauri::RunEvent::ExitRequested { api, .. } => {
-      api.prevent_exit();
-    }
-    tauri::RunEvent::Exit => {
-      resolve::resolve_reset();
-      api::process::kill_children();
-      app_handle.exit(0);
-    }
-    #[cfg(target_os = "macos")]
-    tauri::RunEvent::WindowEvent { label, event, .. } => {
-      if label == "main" {
-        match event {
-          tauri::WindowEvent::CloseRequested { api, .. } => {
-            api.prevent_close();
-            app_handle.get_window("main").map(|win| {
-              let _ = win.hide();
-            });
-          }
-          _ => {}
+    #[allow(unused)]
+    app.run(|app_handle, e| match e {
+        tauri::RunEvent::ExitRequested { api, .. } => {
+            api.prevent_exit();
         }
-      }
-    }
-    _ => {}
-  });
+        tauri::RunEvent::Exit => {
+            resolve::resolve_reset();
+            api::process::kill_children();
+            app_handle.exit(0);
+        }
+        #[cfg(target_os = "macos")]
+        tauri::RunEvent::WindowEvent { label, event, .. } => {
+            if label == "main" {
+                match event {
+                    tauri::WindowEvent::CloseRequested { api, .. } => {
+                        api.prevent_close();
+                        app_handle.get_window("main").map(|win| {
+                            let _ = win.hide();
+                        });
+                    }
+                    _ => {}
+                }
+            }
+        }
+        _ => {}
+    });
 
-  Ok(())
+    Ok(())
 }
diff --git a/src-tauri/src/utils/config.rs b/src-tauri/src/utils/config.rs
index add4d8bd40d1b0c34f18e45bb7b2ee13be7a9488..17fe14b52a890250d2bc39f9712a39aa50883313 100644
--- a/src-tauri/src/utils/config.rs
+++ b/src-tauri/src/utils/config.rs
@@ -5,55 +5,55 @@ use std::{fs, path::PathBuf};
 
 /// read data from yaml as struct T
 pub fn read_yaml<T: DeserializeOwned + Default>(path: PathBuf) -> T {
-  if !path.exists() {
-    log::error!(target: "app", "file not found \"{}\"", path.display());
-    return T::default();
-  }
-
-  let yaml_str = fs::read_to_string(&path).unwrap_or("".into());
-
-  match serde_yaml::from_str::<T>(&yaml_str) {
-    Ok(val) => val,
-    Err(_) => {
-      log::error!(target: "app", "failed to read yaml file \"{}\"", path.display());
-      T::default()
+    if !path.exists() {
+        log::error!(target: "app", "file not found \"{}\"", path.display());
+        return T::default();
+    }
+
+    let yaml_str = fs::read_to_string(&path).unwrap_or("".into());
+
+    match serde_yaml::from_str::<T>(&yaml_str) {
+        Ok(val) => val,
+        Err(_) => {
+            log::error!(target: "app", "failed to read yaml file \"{}\"", path.display());
+            T::default()
+        }
     }
-  }
 }
 
 /// read mapping from yaml fix #165
 pub fn read_merge_mapping(path: PathBuf) -> Mapping {
-  let map = Mapping::new();
+    let map = Mapping::new();
 
-  if !path.exists() {
-    log::error!(target: "app", "file not found \"{}\"", path.display());
-    return map;
-  }
-
-  let yaml_str = fs::read_to_string(&path).unwrap_or("".into());
-
-  match serde_yaml::from_str::<Value>(&yaml_str) {
-    Ok(mut val) => {
-      crate::log_if_err!(val.apply_merge());
-      val.as_mapping().unwrap_or(&map).to_owned()
+    if !path.exists() {
+        log::error!(target: "app", "file not found \"{}\"", path.display());
+        return map;
     }
-    Err(_) => {
-      log::error!(target: "app", "failed to read yaml file \"{}\"", path.display());
-      map
+
+    let yaml_str = fs::read_to_string(&path).unwrap_or("".into());
+
+    match serde_yaml::from_str::<Value>(&yaml_str) {
+        Ok(mut val) => {
+            crate::log_if_err!(val.apply_merge());
+            val.as_mapping().unwrap_or(&map).to_owned()
+        }
+        Err(_) => {
+            log::error!(target: "app", "failed to read yaml file \"{}\"", path.display());
+            map
+        }
     }
-  }
 }
 
 /// save the data to the file
 /// can set `prefix` string to add some comments
 pub fn save_yaml<T: Serialize>(path: PathBuf, data: &T, prefix: Option<&str>) -> Result<()> {
-  let data_str = serde_yaml::to_string(data)?;
+    let data_str = serde_yaml::to_string(data)?;
 
-  let yaml_str = match prefix {
-    Some(prefix) => format!("{prefix}{data_str}"),
-    None => data_str,
-  };
+    let yaml_str = match prefix {
+        Some(prefix) => format!("{prefix}{data_str}"),
+        None => data_str,
+    };
 
-  let path_str = path.as_os_str().to_string_lossy().to_string();
-  fs::write(path, yaml_str.as_bytes()).context(format!("failed to save file \"{path_str}\""))
+    let path_str = path.as_os_str().to_string_lossy().to_string();
+    fs::write(path, yaml_str.as_bytes()).context(format!("failed to save file \"{path_str}\""))
 }
diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs
index b0cdca13aaca07ef62bff22991032e189a5a462c..b810180e6191cc0762dc0f33f837cdffc923c401 100644
--- a/src-tauri/src/utils/dirs.rs
+++ b/src-tauri/src/utils/dirs.rs
@@ -1,8 +1,8 @@
 use std::env::temp_dir;
 use std::path::PathBuf;
 use tauri::{
-  api::path::{home_dir, resource_dir},
-  Env, PackageInfo,
+    api::path::{home_dir, resource_dir},
+    Env, PackageInfo,
 };
 
 #[cfg(not(feature = "verge-dev"))]
@@ -26,89 +26,89 @@ pub static mut APP_VERSION: &str = "v1.1.1";
 /// initialize portable flag
 #[allow(unused)]
 pub unsafe fn init_portable_flag() {
-  #[cfg(target_os = "windows")]
-  {
-    use tauri::utils::platform::current_exe;
+    #[cfg(target_os = "windows")]
+    {
+        use tauri::utils::platform::current_exe;
 
-    let exe = current_exe().unwrap();
-    let dir = exe.parent().unwrap();
-    let dir = PathBuf::from(dir).join(".config/PORTABLE");
+        let exe = current_exe().unwrap();
+        let dir = exe.parent().unwrap();
+        let dir = PathBuf::from(dir).join(".config/PORTABLE");
 
-    if dir.exists() {
-      PORTABLE_FLAG = true;
+        if dir.exists() {
+            PORTABLE_FLAG = true;
+        }
     }
-  }
 }
 
 /// get the verge app home dir
 pub fn app_home_dir() -> PathBuf {
-  #[cfg(target_os = "windows")]
-  unsafe {
-    use tauri::utils::platform::current_exe;
-
-    if !PORTABLE_FLAG {
-      home_dir().unwrap().join(".config").join(APP_DIR)
-    } else {
-      let app_exe = current_exe().unwrap();
-      let app_exe = dunce::canonicalize(app_exe).unwrap();
-      let app_dir = app_exe.parent().unwrap();
-      PathBuf::from(app_dir).join(".config").join(APP_DIR)
+    #[cfg(target_os = "windows")]
+    unsafe {
+        use tauri::utils::platform::current_exe;
+
+        if !PORTABLE_FLAG {
+            home_dir().unwrap().join(".config").join(APP_DIR)
+        } else {
+            let app_exe = current_exe().unwrap();
+            let app_exe = dunce::canonicalize(app_exe).unwrap();
+            let app_dir = app_exe.parent().unwrap();
+            PathBuf::from(app_dir).join(".config").join(APP_DIR)
+        }
     }
-  }
 
-  #[cfg(not(target_os = "windows"))]
-  home_dir().unwrap().join(".config").join(APP_DIR)
+    #[cfg(not(target_os = "windows"))]
+    home_dir().unwrap().join(".config").join(APP_DIR)
 }
 
 /// get the resources dir
 pub fn app_resources_dir(package_info: &PackageInfo) -> PathBuf {
-  let res_dir = resource_dir(package_info, &Env::default())
-    .unwrap()
-    .join("resources");
+    let res_dir = resource_dir(package_info, &Env::default())
+        .unwrap()
+        .join("resources");
 
-  unsafe {
-    RESOURCE_DIR = Some(res_dir.clone());
+    unsafe {
+        RESOURCE_DIR = Some(res_dir.clone());
 
-    let ver = package_info.version.to_string();
-    let ver_str = format!("v{ver}");
-    APP_VERSION = Box::leak(Box::new(ver_str));
-  }
+        let ver = package_info.version.to_string();
+        let ver_str = format!("v{ver}");
+        APP_VERSION = Box::leak(Box::new(ver_str));
+    }
 
-  res_dir
+    res_dir
 }
 
 /// profiles dir
 pub fn app_profiles_dir() -> PathBuf {
-  app_home_dir().join("profiles")
+    app_home_dir().join("profiles")
 }
 
 /// logs dir
 pub fn app_logs_dir() -> PathBuf {
-  app_home_dir().join("logs")
+    app_home_dir().join("logs")
 }
 
 pub fn clash_path() -> PathBuf {
-  app_home_dir().join(CLASH_CONFIG)
+    app_home_dir().join(CLASH_CONFIG)
 }
 
 pub fn verge_path() -> PathBuf {
-  app_home_dir().join(VERGE_CONFIG)
+    app_home_dir().join(VERGE_CONFIG)
 }
 
 pub fn profiles_path() -> PathBuf {
-  app_home_dir().join(PROFILE_YAML)
+    app_home_dir().join(PROFILE_YAML)
 }
 
 pub fn profiles_temp_path() -> PathBuf {
-  #[cfg(not(feature = "debug-yml"))]
-  return temp_dir().join(PROFILE_TEMP);
+    #[cfg(not(feature = "debug-yml"))]
+    return temp_dir().join(PROFILE_TEMP);
 
-  #[cfg(feature = "debug-yml")]
-  return app_home_dir().join(PROFILE_TEMP);
+    #[cfg(feature = "debug-yml")]
+    return app_home_dir().join(PROFILE_TEMP);
 }
 
 pub fn clash_pid_path() -> PathBuf {
-  unsafe { RESOURCE_DIR.clone().unwrap().join("clash.pid") }
+    unsafe { RESOURCE_DIR.clone().unwrap().join("clash.pid") }
 }
 
 #[cfg(windows)]
@@ -116,23 +116,23 @@ static SERVICE_PATH: &str = "clash-verge-service.exe";
 
 #[cfg(windows)]
 pub fn service_path() -> PathBuf {
-  unsafe {
-    let res_dir = RESOURCE_DIR.clone().unwrap();
-    res_dir.join(SERVICE_PATH)
-  }
+    unsafe {
+        let res_dir = RESOURCE_DIR.clone().unwrap();
+        res_dir.join(SERVICE_PATH)
+    }
 }
 
 #[cfg(windows)]
 pub fn service_log_file() -> PathBuf {
-  use chrono::Local;
+    use chrono::Local;
 
-  let log_dir = app_logs_dir().join("service");
+    let log_dir = app_logs_dir().join("service");
 
-  let local_time = Local::now().format("%Y-%m-%d-%H%M%S").to_string();
-  let log_file = format!("{}.log", local_time);
-  let log_file = log_dir.join(log_file);
+    let local_time = Local::now().format("%Y-%m-%d-%H%M%S").to_string();
+    let log_file = format!("{}.log", local_time);
+    let log_file = log_dir.join(log_file);
 
-  std::fs::create_dir_all(&log_dir).unwrap();
+    std::fs::create_dir_all(&log_dir).unwrap();
 
-  log_file
+    log_file
 }
diff --git a/src-tauri/src/utils/help.rs b/src-tauri/src/utils/help.rs
index b38ed904b781d980ec1dc1eb31e5e17561e10f88..b8ae5580ace82cdff38feb1f2868eeff985236a8 100644
--- a/src-tauri/src/utils/help.rs
+++ b/src-tauri/src/utils/help.rs
@@ -6,67 +6,67 @@ use std::str::FromStr;
 use std::time::{SystemTime, UNIX_EPOCH};
 
 pub fn get_now() -> usize {
-  SystemTime::now()
-    .duration_since(UNIX_EPOCH)
-    .unwrap()
-    .as_secs() as _
+    SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .unwrap()
+        .as_secs() as _
 }
 
 const ALPHABET: [char; 62] = [
-  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
-  'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
-  'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
-  'V', 'W', 'X', 'Y', 'Z',
+    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+    'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
+    'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z',
 ];
 
 /// generate the uid
 pub fn get_uid(prefix: &str) -> String {
-  let id = nanoid!(11, &ALPHABET);
-  format!("{prefix}{id}")
+    let id = nanoid!(11, &ALPHABET);
+    format!("{prefix}{id}")
 }
 
 /// parse the string
 /// xxx=123123; => 123123
 pub fn parse_str<T: FromStr>(target: &str, key: &str) -> Option<T> {
-  target.find(key).and_then(|idx| {
-    let idx = idx + key.len();
-    let value = &target[idx..];
-
-    match value.split(';').nth(0) {
-      Some(value) => value.trim().parse(),
-      None => value.trim().parse(),
-    }
-    .ok()
-  })
+    target.find(key).and_then(|idx| {
+        let idx = idx + key.len();
+        let value = &target[idx..];
+
+        match value.split(';').nth(0) {
+            Some(value) => value.trim().parse(),
+            None => value.trim().parse(),
+        }
+        .ok()
+    })
 }
 
 /// open file
 /// use vscode by default
 pub fn open_file(path: PathBuf) -> Result<()> {
-  // use vscode first
-  if let Ok(code) = which::which("code") {
-    let mut command = Command::new(&code);
-
-    #[cfg(target_os = "windows")]
-    {
-      use std::os::windows::process::CommandExt;
-      if let Err(err) = command.creation_flags(0x08000000).arg(&path).spawn() {
-        log::error!(target: "app", "failed to open with VScode `{err}`");
-        open::that(path)?;
-      }
+    // use vscode first
+    if let Ok(code) = which::which("code") {
+        let mut command = Command::new(&code);
+
+        #[cfg(target_os = "windows")]
+        {
+            use std::os::windows::process::CommandExt;
+            if let Err(err) = command.creation_flags(0x08000000).arg(&path).spawn() {
+                log::error!(target: "app", "failed to open with VScode `{err}`");
+                open::that(path)?;
+            }
+        }
+
+        #[cfg(not(target_os = "windows"))]
+        if let Err(err) = command.arg(&path).spawn() {
+            log::error!(target: "app", "failed to open with VScode `{err}`");
+            open::that(path)?;
+        }
+
+        return Ok(());
     }
 
-    #[cfg(not(target_os = "windows"))]
-    if let Err(err) = command.arg(&path).spawn() {
-      log::error!(target: "app", "failed to open with VScode `{err}`");
-      open::that(path)?;
-    }
-
-    return Ok(());
-  }
-
-  open::that(path)?;
-  Ok(())
+    open::that(path)?;
+    Ok(())
 }
 
 #[macro_export]
@@ -96,27 +96,27 @@ macro_rules! wrap_err {
 /// return the string literal error
 #[macro_export]
 macro_rules! ret_err {
-  ($str: expr) => {
-    return Err($str.into())
-  };
+    ($str: expr) => {
+        return Err($str.into())
+    };
 }
 
 #[test]
 fn test_parse_value() {
-  let test_1 = "upload=111; download=2222; total=3333; expire=444";
-  let test_2 = "attachment; filename=Clash.yaml";
-
-  assert_eq!(parse_str::<usize>(test_1, "upload=").unwrap(), 111);
-  assert_eq!(parse_str::<usize>(test_1, "download=").unwrap(), 2222);
-  assert_eq!(parse_str::<usize>(test_1, "total=").unwrap(), 3333);
-  assert_eq!(parse_str::<usize>(test_1, "expire=").unwrap(), 444);
-  assert_eq!(
-    parse_str::<String>(test_2, "filename=").unwrap(),
-    format!("Clash.yaml")
-  );
-
-  assert_eq!(parse_str::<usize>(test_1, "aaa="), None);
-  assert_eq!(parse_str::<usize>(test_1, "upload1="), None);
-  assert_eq!(parse_str::<usize>(test_1, "expire1="), None);
-  assert_eq!(parse_str::<usize>(test_2, "attachment="), None);
+    let test_1 = "upload=111; download=2222; total=3333; expire=444";
+    let test_2 = "attachment; filename=Clash.yaml";
+
+    assert_eq!(parse_str::<usize>(test_1, "upload=").unwrap(), 111);
+    assert_eq!(parse_str::<usize>(test_1, "download=").unwrap(), 2222);
+    assert_eq!(parse_str::<usize>(test_1, "total=").unwrap(), 3333);
+    assert_eq!(parse_str::<usize>(test_1, "expire=").unwrap(), 444);
+    assert_eq!(
+        parse_str::<String>(test_2, "filename=").unwrap(),
+        format!("Clash.yaml")
+    );
+
+    assert_eq!(parse_str::<usize>(test_1, "aaa="), None);
+    assert_eq!(parse_str::<usize>(test_1, "upload1="), None);
+    assert_eq!(parse_str::<usize>(test_1, "expire1="), None);
+    assert_eq!(parse_str::<usize>(test_2, "attachment="), None);
 }
diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs
index 6752cac43274e6542cba513a733cbc98b872edec..cadb64a69c32e09a24b2c43bfad954612b7669f2 100644
--- a/src-tauri/src/utils/init.rs
+++ b/src-tauri/src/utils/init.rs
@@ -12,94 +12,94 @@ use tauri::PackageInfo;
 
 /// initialize this instance's log file
 fn init_log() -> Result<()> {
-  let log_dir = dirs::app_logs_dir();
-  if !log_dir.exists() {
-    let _ = fs::create_dir_all(&log_dir);
-  }
+    let log_dir = dirs::app_logs_dir();
+    if !log_dir.exists() {
+        let _ = fs::create_dir_all(&log_dir);
+    }
 
-  let local_time = Local::now().format("%Y-%m-%d-%H%M%S").to_string();
-  let log_file = format!("{}.log", local_time);
-  let log_file = log_dir.join(log_file);
+    let local_time = Local::now().format("%Y-%m-%d-%H%M%S").to_string();
+    let log_file = format!("{}.log", local_time);
+    let log_file = log_dir.join(log_file);
 
-  let time_format = "{d(%Y-%m-%d %H:%M:%S)} - {m}{n}";
-  let stdout = ConsoleAppender::builder()
-    .encoder(Box::new(PatternEncoder::new(time_format)))
-    .build();
-  let tofile = FileAppender::builder()
-    .encoder(Box::new(PatternEncoder::new(time_format)))
-    .build(log_file)?;
+    let time_format = "{d(%Y-%m-%d %H:%M:%S)} - {m}{n}";
+    let stdout = ConsoleAppender::builder()
+        .encoder(Box::new(PatternEncoder::new(time_format)))
+        .build();
+    let tofile = FileAppender::builder()
+        .encoder(Box::new(PatternEncoder::new(time_format)))
+        .build(log_file)?;
 
-  let config = Config::builder()
-    .appender(Appender::builder().build("stdout", Box::new(stdout)))
-    .appender(Appender::builder().build("file", Box::new(tofile)))
-    .logger(
-      Logger::builder()
-        .appenders(["file", "stdout"])
-        .additive(false)
-        .build("app", LevelFilter::Info),
-    )
-    .build(Root::builder().appender("stdout").build(LevelFilter::Info))?;
+    let config = Config::builder()
+        .appender(Appender::builder().build("stdout", Box::new(stdout)))
+        .appender(Appender::builder().build("file", Box::new(tofile)))
+        .logger(
+            Logger::builder()
+                .appenders(["file", "stdout"])
+                .additive(false)
+                .build("app", LevelFilter::Info),
+        )
+        .build(Root::builder().appender("stdout").build(LevelFilter::Info))?;
 
-  log4rs::init_config(config)?;
+    log4rs::init_config(config)?;
 
-  Ok(())
+    Ok(())
 }
 
 /// Initialize all the files from resources
 pub fn init_config() -> Result<()> {
-  let _ = init_log();
+    let _ = init_log();
 
-  let app_dir = dirs::app_home_dir();
-  let profiles_dir = dirs::app_profiles_dir();
+    let app_dir = dirs::app_home_dir();
+    let profiles_dir = dirs::app_profiles_dir();
 
-  if !app_dir.exists() {
-    let _ = fs::create_dir_all(&app_dir);
-  }
-  if !profiles_dir.exists() {
-    let _ = fs::create_dir_all(&profiles_dir);
-  }
+    if !app_dir.exists() {
+        let _ = fs::create_dir_all(&app_dir);
+    }
+    if !profiles_dir.exists() {
+        let _ = fs::create_dir_all(&profiles_dir);
+    }
 
-  // target path
-  let clash_path = app_dir.join("config.yaml");
-  let verge_path = app_dir.join("verge.yaml");
-  let profile_path = app_dir.join("profiles.yaml");
+    // target path
+    let clash_path = app_dir.join("config.yaml");
+    let verge_path = app_dir.join("verge.yaml");
+    let profile_path = app_dir.join("profiles.yaml");
 
-  if !clash_path.exists() {
-    fs::File::create(clash_path)?.write(tmpl::CLASH_CONFIG)?;
-  }
-  if !verge_path.exists() {
-    fs::File::create(verge_path)?.write(tmpl::VERGE_CONFIG)?;
-  }
-  if !profile_path.exists() {
-    fs::File::create(profile_path)?.write(tmpl::PROFILES_CONFIG)?;
-  }
-  Ok(())
+    if !clash_path.exists() {
+        fs::File::create(clash_path)?.write(tmpl::CLASH_CONFIG)?;
+    }
+    if !verge_path.exists() {
+        fs::File::create(verge_path)?.write(tmpl::VERGE_CONFIG)?;
+    }
+    if !profile_path.exists() {
+        fs::File::create(profile_path)?.write(tmpl::PROFILES_CONFIG)?;
+    }
+    Ok(())
 }
 
 /// initialize app
 pub fn init_resources(package_info: &PackageInfo) {
-  // create app dir
-  let app_dir = dirs::app_home_dir();
-  let res_dir = dirs::app_resources_dir(package_info);
+    // create app dir
+    let app_dir = dirs::app_home_dir();
+    let res_dir = dirs::app_resources_dir(package_info);
 
-  if !app_dir.exists() {
-    let _ = fs::create_dir_all(&app_dir);
-  }
+    if !app_dir.exists() {
+        let _ = fs::create_dir_all(&app_dir);
+    }
 
-  // copy the resource file
-  let mmdb_path = app_dir.join("Country.mmdb");
-  let mmdb_tmpl = res_dir.join("Country.mmdb");
-  if !mmdb_path.exists() && mmdb_tmpl.exists() {
-    let _ = fs::copy(mmdb_tmpl, mmdb_path);
-  }
+    // copy the resource file
+    let mmdb_path = app_dir.join("Country.mmdb");
+    let mmdb_tmpl = res_dir.join("Country.mmdb");
+    if !mmdb_path.exists() && mmdb_tmpl.exists() {
+        let _ = fs::copy(mmdb_tmpl, mmdb_path);
+    }
 
-  // copy the wintun.dll
-  #[cfg(target_os = "windows")]
-  {
-    let wintun_path = app_dir.join("wintun.dll");
-    let wintun_tmpl = res_dir.join("wintun.dll");
-    if !wintun_path.exists() && wintun_tmpl.exists() {
-      let _ = fs::copy(wintun_tmpl, wintun_path);
+    // copy the wintun.dll
+    #[cfg(target_os = "windows")]
+    {
+        let wintun_path = app_dir.join("wintun.dll");
+        let wintun_tmpl = res_dir.join("wintun.dll");
+        if !wintun_path.exists() && wintun_tmpl.exists() {
+            let _ = fs::copy(wintun_tmpl, wintun_path);
+        }
     }
-  }
 }
diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs
index aa1ba3276cf307938f819ab9d3b48dc93e52708a..16ff18f4ea421b2eeca20e68e6405b6eb453a0ff 100644
--- a/src-tauri/src/utils/resolve.rs
+++ b/src-tauri/src/utils/resolve.rs
@@ -1,110 +1,110 @@
 use crate::{
-  core::{tray, Core},
-  data::Data,
-  utils::init,
-  utils::server,
+    core::{tray, Core},
+    data::Data,
+    utils::init,
+    utils::server,
 };
 use tauri::{App, AppHandle, Manager};
 
 /// handle something when start app
 pub fn resolve_setup(app: &App) {
-  let _ = app
-    .tray_handle()
-    .set_menu(tray::Tray::tray_menu(&app.app_handle()));
+    let _ = app
+        .tray_handle()
+        .set_menu(tray::Tray::tray_menu(&app.app_handle()));
 
-  init::init_resources(app.package_info());
+    init::init_resources(app.package_info());
 
-  let silent_start = {
-    let global = Data::global();
-    let verge = global.verge.lock();
-    let singleton = verge.app_singleton_port.clone();
+    let silent_start = {
+        let global = Data::global();
+        let verge = global.verge.lock();
+        let singleton = verge.app_singleton_port.clone();
 
-    // setup a simple http server for singleton
-    server::embed_server(&app.app_handle(), singleton);
+        // setup a simple http server for singleton
+        server::embed_server(&app.app_handle(), singleton);
 
-    verge.enable_silent_start.clone().unwrap_or(false)
-  };
+        verge.enable_silent_start.clone().unwrap_or(false)
+    };
 
-  // core should be initialized after init_app fix #122
-  let core = Core::global();
-  core.init(app.app_handle());
+    // core should be initialized after init_app fix #122
+    let core = Core::global();
+    core.init(app.app_handle());
 
-  if !silent_start {
-    create_window(&app.app_handle());
-  }
+    if !silent_start {
+        create_window(&app.app_handle());
+    }
 }
 
 /// reset system proxy
 pub fn resolve_reset() {
-  let core = Core::global();
-  let mut sysopt = core.sysopt.lock();
-  crate::log_if_err!(sysopt.reset_sysproxy());
-  drop(sysopt);
+    let core = Core::global();
+    let mut sysopt = core.sysopt.lock();
+    crate::log_if_err!(sysopt.reset_sysproxy());
+    drop(sysopt);
 
-  let mut service = core.service.lock();
-  crate::log_if_err!(service.stop());
+    let mut service = core.service.lock();
+    crate::log_if_err!(service.stop());
 }
 
 /// create main window
 pub fn create_window(app_handle: &AppHandle) {
-  if let Some(window) = app_handle.get_window("main") {
-    let _ = window.unminimize();
-    let _ = window.show();
-    let _ = window.set_focus();
-    return;
-  }
-
-  let builder = tauri::window::WindowBuilder::new(
-    app_handle,
-    "main".to_string(),
-    tauri::WindowUrl::App("index.html".into()),
-  )
-  .title("Clash Verge")
-  .center()
-  .fullscreen(false)
-  .min_inner_size(600.0, 520.0);
-
-  #[cfg(target_os = "windows")]
-  {
-    use crate::utils::winhelp;
-    use std::time::Duration;
-    use tokio::time::sleep;
-    use window_shadows::set_shadow;
-    use window_vibrancy::apply_blur;
-
-    match builder
-      .decorations(false)
-      .transparent(true)
-      .inner_size(800.0, 636.0)
-      .build()
-    {
-      Ok(_) => {
-        let app_handle = app_handle.clone();
-
-        tauri::async_runtime::spawn(async move {
-          sleep(Duration::from_secs(1)).await;
-
-          if let Some(window) = app_handle.get_window("main") {
-            let _ = window.show();
-            let _ = set_shadow(&window, true);
+    if let Some(window) = app_handle.get_window("main") {
+        let _ = window.unminimize();
+        let _ = window.show();
+        let _ = window.set_focus();
+        return;
+    }
 
-            if !winhelp::is_win11() {
-              let _ = apply_blur(&window, None);
+    let builder = tauri::window::WindowBuilder::new(
+        app_handle,
+        "main".to_string(),
+        tauri::WindowUrl::App("index.html".into()),
+    )
+    .title("Clash Verge")
+    .center()
+    .fullscreen(false)
+    .min_inner_size(600.0, 520.0);
+
+    #[cfg(target_os = "windows")]
+    {
+        use crate::utils::winhelp;
+        use std::time::Duration;
+        use tokio::time::sleep;
+        use window_shadows::set_shadow;
+        use window_vibrancy::apply_blur;
+
+        match builder
+            .decorations(false)
+            .transparent(true)
+            .inner_size(800.0, 636.0)
+            .build()
+        {
+            Ok(_) => {
+                let app_handle = app_handle.clone();
+
+                tauri::async_runtime::spawn(async move {
+                    sleep(Duration::from_secs(1)).await;
+
+                    if let Some(window) = app_handle.get_window("main") {
+                        let _ = window.show();
+                        let _ = set_shadow(&window, true);
+
+                        if !winhelp::is_win11() {
+                            let _ = apply_blur(&window, None);
+                        }
+                    }
+                });
             }
-          }
-        });
-      }
-      Err(err) => log::error!(target: "app", "{err}"),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
     }
-  }
 
-  #[cfg(target_os = "macos")]
-  crate::log_if_err!(builder.decorations(true).inner_size(800.0, 642.0).build());
+    #[cfg(target_os = "macos")]
+    crate::log_if_err!(builder.decorations(true).inner_size(800.0, 642.0).build());
 
-  #[cfg(target_os = "linux")]
-  crate::log_if_err!(builder
-    .decorations(false)
-    .transparent(true)
-    .inner_size(800.0, 636.0)
-    .build());
+    #[cfg(target_os = "linux")]
+    crate::log_if_err!(builder
+        .decorations(false)
+        .transparent(true)
+        .inner_size(800.0, 636.0)
+        .build());
 }
diff --git a/src-tauri/src/utils/server.rs b/src-tauri/src/utils/server.rs
index 26caaf04f73aead23ae88a7271fe823f34118add..c0162c6232d5140e03b976b1e29ec7843611eb00 100644
--- a/src-tauri/src/utils/server.rs
+++ b/src-tauri/src/utils/server.rs
@@ -13,32 +13,32 @@ const SERVER_PORT: u16 = 11233;
 
 /// check whether there is already exists
 pub fn check_singleton() -> Result<(), ()> {
-  let verge = Verge::new();
-  let port = verge.app_singleton_port.unwrap_or(SERVER_PORT);
+    let verge = Verge::new();
+    let port = verge.app_singleton_port.unwrap_or(SERVER_PORT);
 
-  if !local_port_available(port) {
-    tauri::async_runtime::block_on(async {
-      let url = format!("http://127.0.0.1:{}/commands/visible", port);
-      reqwest::get(url).await.unwrap();
-      Err(())
-    })
-  } else {
-    Ok(())
-  }
+    if !local_port_available(port) {
+        tauri::async_runtime::block_on(async {
+            let url = format!("http://127.0.0.1:{}/commands/visible", port);
+            reqwest::get(url).await.unwrap();
+            Err(())
+        })
+    } else {
+        Ok(())
+    }
 }
 
 /// The embed server only be used to implement singleton process
 /// maybe it can be used as pac server later
 pub fn embed_server(app_handle: &AppHandle, port: Option<u16>) {
-  let app_handle = app_handle.clone();
-  let port = port.unwrap_or(SERVER_PORT);
+    let app_handle = app_handle.clone();
+    let port = port.unwrap_or(SERVER_PORT);
 
-  tauri::async_runtime::spawn(async move {
-    let commands = warp::path!("commands" / "visible").map(move || {
-      resolve::create_window(&app_handle);
-      return format!("ok");
-    });
+    tauri::async_runtime::spawn(async move {
+        let commands = warp::path!("commands" / "visible").map(move || {
+            resolve::create_window(&app_handle);
+            return format!("ok");
+        });
 
-    warp::serve(commands).bind(([127, 0, 0, 1], port)).await;
-  });
+        warp::serve(commands).bind(([127, 0, 0, 1], port)).await;
+    });
 }
diff --git a/src-tauri/src/utils/winhelp.rs b/src-tauri/src/utils/winhelp.rs
index 8abd7b5cf34b91f645f10502aa150d61de74291b..e903d951c25f6f311579492df9016b0b50726394 100644
--- a/src-tauri/src/utils/winhelp.rs
+++ b/src-tauri/src/utils/winhelp.rs
@@ -1,69 +1,69 @@
-#![cfg(target_os = "windows")]
-#![allow(non_snake_case)]
-#![allow(non_camel_case_types)]
-
-//!
-//! From https://github.com/tauri-apps/window-vibrancy/blob/dev/src/windows.rs
-//!
-
-use windows_sys::Win32::{
-  Foundation::*,
-  System::{LibraryLoader::*, SystemInformation::*},
-};
-
-fn get_function_impl(library: &str, function: &str) -> Option<FARPROC> {
-  assert_eq!(library.chars().last(), Some('\0'));
-  assert_eq!(function.chars().last(), Some('\0'));
-
-  let module = unsafe { LoadLibraryA(library.as_ptr()) };
-  if module == 0 {
-    return None;
-  }
-  Some(unsafe { GetProcAddress(module, function.as_ptr()) })
-}
-
-macro_rules! get_function {
-  ($lib:expr, $func:ident) => {
-    get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0')).map(|f| unsafe {
-      std::mem::transmute::<::windows_sys::Win32::Foundation::FARPROC, $func>(f)
-    })
-  };
-}
-
-/// Returns a tuple of (major, minor, buildnumber)
-fn get_windows_ver() -> Option<(u32, u32, u32)> {
-  type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> i32;
-  let handle = get_function!("ntdll.dll", RtlGetVersion);
-  if let Some(rtl_get_version) = handle {
-    unsafe {
-      let mut vi = OSVERSIONINFOW {
-        dwOSVersionInfoSize: 0,
-        dwMajorVersion: 0,
-        dwMinorVersion: 0,
-        dwBuildNumber: 0,
-        dwPlatformId: 0,
-        szCSDVersion: [0; 128],
-      };
-
-      let status = (rtl_get_version)(&mut vi as _);
-
-      if status >= 0 {
-        Some((vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber))
-      } else {
-        None
-      }
-    }
-  } else {
-    None
-  }
-}
-
-pub fn is_win11() -> bool {
-  let v = get_windows_ver().unwrap_or_default();
-  v.2 >= 22000
-}
-
-#[test]
-fn test_version() {
-  dbg!(get_windows_ver().unwrap_or_default());
-}
+#![cfg(target_os = "windows")]
+#![allow(non_snake_case)]
+#![allow(non_camel_case_types)]
+
+//!
+//! From https://github.com/tauri-apps/window-vibrancy/blob/dev/src/windows.rs
+//!
+
+use windows_sys::Win32::{
+    Foundation::*,
+    System::{LibraryLoader::*, SystemInformation::*},
+};
+
+fn get_function_impl(library: &str, function: &str) -> Option<FARPROC> {
+    assert_eq!(library.chars().last(), Some('\0'));
+    assert_eq!(function.chars().last(), Some('\0'));
+
+    let module = unsafe { LoadLibraryA(library.as_ptr()) };
+    if module == 0 {
+        return None;
+    }
+    Some(unsafe { GetProcAddress(module, function.as_ptr()) })
+}
+
+macro_rules! get_function {
+    ($lib:expr, $func:ident) => {
+        get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0')).map(|f| unsafe {
+            std::mem::transmute::<::windows_sys::Win32::Foundation::FARPROC, $func>(f)
+        })
+    };
+}
+
+/// Returns a tuple of (major, minor, buildnumber)
+fn get_windows_ver() -> Option<(u32, u32, u32)> {
+    type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> i32;
+    let handle = get_function!("ntdll.dll", RtlGetVersion);
+    if let Some(rtl_get_version) = handle {
+        unsafe {
+            let mut vi = OSVERSIONINFOW {
+                dwOSVersionInfoSize: 0,
+                dwMajorVersion: 0,
+                dwMinorVersion: 0,
+                dwBuildNumber: 0,
+                dwPlatformId: 0,
+                szCSDVersion: [0; 128],
+            };
+
+            let status = (rtl_get_version)(&mut vi as _);
+
+            if status >= 0 {
+                Some((vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber))
+            } else {
+                None
+            }
+        }
+    } else {
+        None
+    }
+}
+
+pub fn is_win11() -> bool {
+    let v = get_windows_ver().unwrap_or_default();
+    v.2 >= 22000
+}
+
+#[test]
+fn test_version() {
+    dbg!(get_windows_ver().unwrap_or_default());
+}
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index cfd09d4551a54d4cc133cc3b6bcc6793d6195efc..55cb11f514ae6145609818261f388224e1e5beb4 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -25,13 +25,8 @@
         "icons/icon-new.icns",
         "icons/icon.ico"
       ],
-      "resources": [
-        "resources"
-      ],
-      "externalBin": [
-        "sidecar/clash",
-        "sidecar/clash-meta"
-      ],
+      "resources": ["resources"],
+      "externalBin": ["sidecar/clash", "sidecar/clash-meta"],
       "copyright": "© 2022 zzzgydi All Rights Reserved",
       "category": "DeveloperTool",
       "shortDescription": "A Clash GUI based on tauri.",
@@ -51,10 +46,7 @@
         "digestAlgorithm": "sha256",
         "timestampUrl": "",
         "wix": {
-          "language": [
-            "zh-CN",
-            "en-US"
-          ]
+          "language": ["zh-CN", "en-US"]
         }
       }
     },
@@ -86,4 +78,4 @@
       "csp": "script-src 'unsafe-eval' 'self'; default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; img-src data: 'self';"
     }
   }
-}
\ No newline at end of file
+}