From 34daffbc966755568153130052c7d3219847e770 Mon Sep 17 00:00:00 2001
From: GyDi <zzzgydi@gmail.com>
Date: Fri, 18 Nov 2022 09:35:05 +0800
Subject: [PATCH] refactor: adjust all path methods and reduce unwrap

---
 src-tauri/src/cmds.rs            |  6 +--
 src-tauri/src/config/clash.rs    | 23 +++++++++-
 src-tauri/src/config/prfitem.rs  | 10 ++---
 src-tauri/src/config/profiles.rs | 72 +++++++++++++++++--------------
 src-tauri/src/config/verge.rs    | 34 ++++++++++++---
 src-tauri/src/core/clash_api.rs  |  2 +-
 src-tauri/src/core/core.rs       | 17 ++++----
 src-tauri/src/utils/config.rs    | 53 +++++++++--------------
 src-tauri/src/utils/dirs.rs      | 73 ++++++++++++++++++++------------
 src-tauri/src/utils/init.rs      | 60 +++++++++++++-------------
 src-tauri/src/utils/tmpl.rs      | 37 ----------------
 11 files changed, 205 insertions(+), 182 deletions(-)

diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index 2dbb5e4..c96e90e 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -121,7 +121,7 @@ pub fn view_profile(index: String) -> CmdResult {
             .ok_or("the file field is null")
     }?;
 
-    let path = dirs::app_profiles_dir().join(file);
+    let path = wrap_err!(dirs::app_profiles_dir())?.join(file);
     if !path.exists() {
         ret_err!("the file not found");
     }
@@ -236,13 +236,13 @@ pub fn get_clash_logs() -> CmdResult<VecDeque<String>> {
 
 #[tauri::command]
 pub fn open_app_dir() -> CmdResult<()> {
-    let app_dir = dirs::app_home_dir();
+    let app_dir = wrap_err!(dirs::app_home_dir())?;
     wrap_err!(open::that(app_dir))
 }
 
 #[tauri::command]
 pub fn open_logs_dir() -> CmdResult<()> {
-    let log_dir = dirs::app_logs_dir();
+    let log_dir = wrap_err!(dirs::app_logs_dir())?;
     wrap_err!(open::that(log_dir))
 }
 
diff --git a/src-tauri/src/config/clash.rs b/src-tauri/src/config/clash.rs
index d590383..e864d48 100644
--- a/src-tauri/src/config/clash.rs
+++ b/src-tauri/src/config/clash.rs
@@ -8,7 +8,26 @@ pub struct IClashTemp(pub Mapping);
 
 impl IClashTemp {
     pub fn new() -> Self {
-        Self(config::read_merge_mapping(dirs::clash_path()))
+        match dirs::clash_path().and_then(|path| config::read_merge_mapping(&path)) {
+            Ok(map) => Self(map),
+            Err(err) => {
+                log::error!(target: "app", "{err}");
+                Self::template()
+            }
+        }
+    }
+
+    pub fn template() -> Self {
+        let mut map = Mapping::new();
+
+        map.insert("mixed-port".into(), 7892.into());
+        map.insert("log-level".into(), "info".into());
+        map.insert("allow-lan".into(), false.into());
+        map.insert("mode".into(), "rule".into());
+        map.insert("external-controller".into(), "127.0.0.1:9090".into());
+        map.insert("secret".into(), "".into());
+
+        Self(map)
     }
 
     pub fn patch_config(&mut self, patch: Mapping) {
@@ -19,7 +38,7 @@ impl IClashTemp {
 
     pub fn save_config(&self) -> Result<()> {
         config::save_yaml(
-            dirs::clash_path(),
+            dirs::clash_path()?,
             &self.0,
             Some("# Default Config For ClashN Core\n\n"),
         )
diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs
index cb81212..b2e6444 100644
--- a/src-tauri/src/config/prfitem.rs
+++ b/src-tauri/src/config/prfitem.rs
@@ -355,7 +355,7 @@ impl PrfItem {
         }
 
         let file = self.file.clone().unwrap();
-        let path = dirs::app_profiles_dir().join(file);
+        let path = dirs::app_profiles_dir()?.join(file);
         fs::read_to_string(path).context("failed to read the file")
     }
 
@@ -366,7 +366,7 @@ impl PrfItem {
         }
 
         let file = self.file.clone().unwrap();
-        let path = dirs::app_profiles_dir().join(file);
+        let path = dirs::app_profiles_dir()?.join(file);
         fs::write(path, data.as_bytes()).context("failed to save the file")
     }
 
@@ -375,7 +375,7 @@ impl PrfItem {
         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);
+        let path = dirs::app_profiles_dir().ok()?.join(file);
 
         if !path.exists() {
             return None;
@@ -384,11 +384,11 @@ impl PrfItem {
         match itype {
             "script" => Some(ChainItem {
                 uid,
-                data: ChainType::Script(fs::read_to_string(path).unwrap_or("".into())),
+                data: ChainType::Script(fs::read_to_string(path).ok()?),
             }),
             "merge" => Some(ChainItem {
                 uid,
-                data: ChainType::Merge(config::read_merge_mapping(path)),
+                data: ChainType::Merge(config::read_merge_mapping(&path).ok()?),
             }),
             _ => None,
         }
diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs
index 27f9067..847e233 100644
--- a/src-tauri/src/config/profiles.rs
+++ b/src-tauri/src/config/profiles.rs
@@ -32,30 +32,40 @@ macro_rules! patch {
 
 impl IProfiles {
     pub fn new() -> Self {
-        Self::read_file()
+        match dirs::profiles_path().and_then(|path| config::read_yaml::<Self>(&path)) {
+            Ok(mut profiles) => {
+                if profiles.items.is_none() {
+                    profiles.items = Some(vec![]);
+                }
+                // compatible 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
+            }
+            Err(err) => {
+                log::error!(target: "app", "{err}");
+                Self::template()
+            }
+        }
     }
 
-    /// 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 template() -> Self {
+        Self {
+            valid: Some(vec!["dns".into()]),
+            items: Some(vec![]),
+            ..Self::default()
         }
-        // compatible 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
     }
 
     /// save the config to the file
     pub fn save_file(&self) -> Result<()> {
         config::save_yaml(
-            dirs::profiles_path(),
+            dirs::profiles_path()?,
             self,
             Some("# Profiles Config for Clash Verge\n\n"),
         )
@@ -131,7 +141,7 @@ impl IProfiles {
             }
 
             let file = item.file.clone().unwrap();
-            let path = dirs::app_profiles_dir().join(&file);
+            let path = dirs::app_profiles_dir()?.join(&file);
 
             fs::File::create(path)
                 .context(format!("failed to create file \"{}\"", file))?
@@ -200,7 +210,7 @@ impl IProfiles {
                         // the file must exists
                         each.file = Some(file.clone());
 
-                        let path = dirs::app_profiles_dir().join(&file);
+                        let path = dirs::app_profiles_dir()?.join(&file);
 
                         fs::File::create(path)
                             .context(format!("failed to create file \"{}\"", file))?
@@ -235,10 +245,12 @@ impl IProfiles {
 
         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 _ = dirs::app_profiles_dir().map(|path| {
+                    let path = path.join(file);
+                    if path.exists() {
+                        let _ = fs::remove_file(path);
+                    }
+                });
             });
         }
 
@@ -263,22 +275,18 @@ impl IProfiles {
             return Ok(config);
         }
 
-        let current = self.current.clone().unwrap();
+        let current = self.current.as_ref().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),
+            if item.uid.as_ref() == Some(current) {
+                let file_path = match item.file.as_ref() {
+                    Some(file) => dirs::app_profiles_dir()?.join(file),
                     None => bail!("failed to get the file field"),
                 };
 
-                if !file_path.exists() {
-                    bail!("failed to read the file \"{}\"", file_path.display());
-                }
-
-                return Ok(config::read_merge_mapping(file_path.clone()));
+                return Ok(config::read_merge_mapping(&file_path)?);
             }
         }
-        bail!("failed to find current profile \"uid:{current}\"");
+        bail!("failed to find the current profile \"uid:{current}\"");
     }
 
     /// generate the data for activate clash config
diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs
index c5986a9..8c21cfe 100644
--- a/src-tauri/src/config/verge.rs
+++ b/src-tauri/src/config/verge.rs
@@ -85,13 +85,36 @@ pub struct IVergeTheme {
 
 impl IVerge {
     pub fn new() -> Self {
-        config::read_yaml::<IVerge>(dirs::verge_path())
+        match dirs::verge_path().and_then(|path| config::read_yaml::<IVerge>(&path)) {
+            Ok(config) => config,
+            Err(err) => {
+                log::error!(target: "app", "{err}");
+                Self::template()
+            }
+        }
+    }
+
+    pub fn template() -> Self {
+        Self {
+            clash_core: Some("clash".into()),
+            language: Some("en".into()),
+            theme_mode: Some("system".into()),
+            theme_blur: Some(false),
+            traffic_graph: Some(true),
+            enable_auto_launch: Some(false),
+            enable_silent_start: Some(false),
+            enable_system_proxy: Some(false),
+            enable_proxy_guard: Some(false),
+            proxy_guard_duration: Some(30),
+            auto_close_connection: Some(true),
+            ..Self::default()
+        }
     }
 
     /// Save IVerge App Config
     pub fn save_file(&self) -> Result<()> {
         config::save_yaml(
-            dirs::verge_path(),
+            dirs::verge_path()?,
             &self,
             Some("# The Config for Clash IVerge App\n\n"),
         )
@@ -133,13 +156,14 @@ impl IVerge {
 
     /// 在初始化前尝试拿到单例端口的值
     pub fn get_singleton_port() -> u16 {
-        let config = config::read_yaml::<IVerge>(dirs::verge_path());
-
         #[cfg(not(feature = "verge-dev"))]
         const SERVER_PORT: u16 = 33331;
         #[cfg(feature = "verge-dev")]
         const SERVER_PORT: u16 = 11233;
 
-        config.app_singleton_port.unwrap_or(SERVER_PORT)
+        match dirs::verge_path().and_then(|path| config::read_yaml::<IVerge>(&path)) {
+            Ok(config) => config.app_singleton_port.unwrap_or(SERVER_PORT),
+            Err(_) => SERVER_PORT, // 这里就不log错误了
+        }
     }
 }
diff --git a/src-tauri/src/core/clash_api.rs b/src-tauri/src/core/clash_api.rs
index 3dd796c..35e55d2 100644
--- a/src-tauri/src/core/clash_api.rs
+++ b/src-tauri/src/core/clash_api.rs
@@ -9,7 +9,7 @@ pub async fn put_configs() -> Result<()> {
     let (url, headers) = clash_client_info()?;
     let url = format!("{url}/configs");
 
-    let runtime_yaml = dirs::clash_runtime_yaml();
+    let runtime_yaml = dirs::clash_runtime_yaml()?;
     let runtime_yaml = dirs::path_to_str(&runtime_yaml)?;
 
     let mut data = HashMap::new();
diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs
index f9dee69..4011902 100644
--- a/src-tauri/src/core/core.rs
+++ b/src-tauri/src/core/core.rs
@@ -35,8 +35,10 @@ impl CoreManager {
 
     pub fn init(&self) -> Result<()> {
         // kill old clash process
-        if let Ok(pid) = fs::read(dirs::clash_pid_path()) {
-            if let Ok(pid) = String::from_utf8_lossy(&pid).parse() {
+        let _ = dirs::clash_pid_path()
+            .and_then(|path| fs::read(path).map(|p| p.to_vec()).context(""))
+            .and_then(|pid| String::from_utf8_lossy(&pid).parse().context(""))
+            .map(|pid| {
                 let mut system = System::new();
                 system.refresh_all();
                 system.process(Pid::from_u32(pid)).map(|proc| {
@@ -44,8 +46,7 @@ impl CoreManager {
                         proc.kill();
                     }
                 });
-            }
-        }
+            });
 
         tauri::async_runtime::spawn(async {
             // 启动clash
@@ -61,7 +62,7 @@ impl CoreManager {
 
     /// 检查配置是否正确
     pub fn check_config(&self) -> Result<()> {
-        let config_path = dirs::clash_runtime_yaml();
+        let config_path = dirs::clash_runtime_yaml()?;
         let config_path = dirs::path_to_str(&config_path)?;
 
         let clash_core = { Config::verge().latest().clash_core.clone() };
@@ -116,7 +117,7 @@ impl CoreManager {
             let _ = child.kill();
         }
 
-        let app_dir = dirs::app_home_dir();
+        let app_dir = dirs::app_home_dir()?;
         let app_dir = dirs::path_to_str(&app_dir)?;
 
         let clash_core = { Config::verge().latest().clash_core.clone() };
@@ -134,7 +135,7 @@ impl CoreManager {
         // 将pid写入文件中
         crate::log_err!({
             let pid = cmd_child.pid();
-            let path = dirs::clash_pid_path();
+            let path = dirs::clash_pid_path()?;
             fs::File::create(path)
                 .context("failed to create the pid file")?
                 .write(format!("{pid}").as_bytes())
@@ -236,7 +237,7 @@ impl CoreManager {
             enhance::enhance_config(clash_config.0, pa.current, pa.chain, pa.valid, tun_mode);
 
         // 保存到文件中
-        let runtime_path = dirs::clash_runtime_yaml();
+        let runtime_path = dirs::clash_runtime_yaml()?;
         utils::config::save_yaml(runtime_path, &config, Some("# Clash Verge Runtime Config"))?;
 
         // 检查配置是否正常
diff --git a/src-tauri/src/utils/config.rs b/src-tauri/src/utils/config.rs
index bcb99f6..c1c563a 100644
--- a/src-tauri/src/utils/config.rs
+++ b/src-tauri/src/utils/config.rs
@@ -1,47 +1,36 @@
-use anyhow::{Context, Result};
+use anyhow::{anyhow, bail, Context, Result};
 use serde::{de::DeserializeOwned, Serialize};
 use serde_yaml::{Mapping, Value};
 use std::{fs, path::PathBuf};
 
 /// read data from yaml as struct T
-pub fn read_yaml<T: DeserializeOwned + Default>(path: PathBuf) -> T {
+pub fn read_yaml<T: DeserializeOwned>(path: &PathBuf) -> Result<T> {
     if !path.exists() {
-        log::error!(target: "app", "file not found \"{}\"", path.display());
-        return T::default();
+        bail!("file not found \"{}\"", path.display());
     }
 
-    let yaml_str = fs::read_to_string(&path).unwrap_or("".into());
+    let yaml_str = fs::read_to_string(&path)
+        .context(format!("failed to read the file \"{}\"", path.display()))?;
 
-    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()
-        }
-    }
+    serde_yaml::from_str::<T>(&yaml_str).context(format!(
+        "failed to read the file with yaml format \"{}\"",
+        path.display()
+    ))
 }
 
 /// read mapping from yaml fix #165
-pub fn read_merge_mapping(path: PathBuf) -> Mapping {
-    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_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
-        }
-    }
+pub fn read_merge_mapping(path: &PathBuf) -> Result<Mapping> {
+    let mut val: Value = read_yaml(path)?;
+    val.apply_merge()
+        .context(format!("failed to apply merge \"{}\"", path.display()))?;
+
+    Ok(val
+        .as_mapping()
+        .ok_or(anyhow!(
+            "failed to transform to yaml mapping \"{}\"",
+            path.display()
+        ))?
+        .to_owned())
 }
 
 /// save the data to the file
diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs
index 4eb56c5..8c32125 100644
--- a/src-tauri/src/utils/dirs.rs
+++ b/src-tauri/src/utils/dirs.rs
@@ -1,5 +1,5 @@
 use anyhow::Result;
-use std::path::PathBuf;
+use std::{env::temp_dir, path::PathBuf};
 use tauri::{
     api::path::{home_dir, resource_dir},
     Env, PackageInfo,
@@ -13,7 +13,6 @@ static APP_DIR: &str = "clash-verge-dev";
 static CLASH_CONFIG: &str = "config.yaml";
 static VERGE_CONFIG: &str = "verge.yaml";
 static PROFILE_YAML: &str = "profiles.yaml";
-static CLASH_RUNTIME_YAML: &str = "clash-verge-runtime.yaml";
 
 static mut RESOURCE_DIR: Option<PathBuf> = None;
 
@@ -21,7 +20,7 @@ static mut RESOURCE_DIR: Option<PathBuf> = None;
 #[allow(unused)]
 static mut PORTABLE_FLAG: bool = false;
 
-pub static mut APP_VERSION: &str = "v1.1.1";
+pub static mut APP_VERSION: &str = "v1.1.2";
 
 /// initialize portable flag
 #[cfg(target_os = "windows")]
@@ -42,29 +41,37 @@ pub unsafe fn init_portable_flag() -> Result<()> {
 }
 
 /// get the verge app home dir
-pub fn app_home_dir() -> PathBuf {
+pub fn app_home_dir() -> Result<PathBuf> {
     #[cfg(target_os = "windows")]
     unsafe {
         use tauri::utils::platform::current_exe;
 
         if !PORTABLE_FLAG {
-            home_dir().unwrap().join(".config").join(APP_DIR)
+            Ok(home_dir()
+                .ok_or(anyhow::anyhow!("failed to get app home dir"))?
+                .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)
+            let app_exe = current_exe()?;
+            let app_exe = dunce::canonicalize(app_exe)?;
+            let app_dir = app_exe
+                .parent()
+                .ok_or(anyhow::anyhow!("failed to get the portable app dir"))?;
+            Ok(PathBuf::from(app_dir).join(".config").join(APP_DIR))
         }
     }
 
     #[cfg(not(target_os = "windows"))]
-    home_dir().unwrap().join(".config").join(APP_DIR)
+    Ok(home_dir()
+        .ok_or(anyhow::anyhow!("failed to get the app home dir"))?
+        .join(".config")
+        .join(APP_DIR))
 }
 
 /// get the resources dir
-pub fn app_resources_dir(package_info: &PackageInfo) -> PathBuf {
+pub fn app_resources_dir(package_info: &PackageInfo) -> Result<PathBuf> {
     let res_dir = resource_dir(package_info, &Env::default())
-        .unwrap()
+        .ok_or(anyhow::anyhow!("failed to get the resource dir"))?
         .join("resources");
 
     unsafe {
@@ -75,37 +82,49 @@ pub fn app_resources_dir(package_info: &PackageInfo) -> PathBuf {
         APP_VERSION = Box::leak(Box::new(ver_str));
     }
 
-    res_dir
+    Ok(res_dir)
 }
 
 /// profiles dir
-pub fn app_profiles_dir() -> PathBuf {
-    app_home_dir().join("profiles")
+pub fn app_profiles_dir() -> Result<PathBuf> {
+    Ok(app_home_dir()?.join("profiles"))
 }
 
 /// logs dir
-pub fn app_logs_dir() -> PathBuf {
-    app_home_dir().join("logs")
+pub fn app_logs_dir() -> Result<PathBuf> {
+    Ok(app_home_dir()?.join("logs"))
 }
 
-pub fn clash_path() -> PathBuf {
-    app_home_dir().join(CLASH_CONFIG)
+pub fn clash_path() -> Result<PathBuf> {
+    Ok(app_home_dir()?.join(CLASH_CONFIG))
 }
 
-pub fn verge_path() -> PathBuf {
-    app_home_dir().join(VERGE_CONFIG)
+pub fn verge_path() -> Result<PathBuf> {
+    Ok(app_home_dir()?.join(VERGE_CONFIG))
 }
 
-pub fn profiles_path() -> PathBuf {
-    app_home_dir().join(PROFILE_YAML)
+pub fn profiles_path() -> Result<PathBuf> {
+    Ok(app_home_dir()?.join(PROFILE_YAML))
 }
 
-pub fn clash_runtime_yaml() -> PathBuf {
-    app_home_dir().join(CLASH_RUNTIME_YAML)
+pub fn clash_runtime_yaml() -> Result<PathBuf> {
+    Ok(app_home_dir()?.join("clash-verge-runtime.yaml"))
 }
 
-pub fn clash_pid_path() -> PathBuf {
-    unsafe { RESOURCE_DIR.clone().unwrap().join("clash.pid") }
+pub fn clash_check_yaml() -> Result<PathBuf> {
+    Ok(temp_dir().join("clash-verge-check.yaml"))
+}
+
+pub fn app_res_dir() -> Result<PathBuf> {
+    unsafe {
+        Ok(RESOURCE_DIR
+            .clone()
+            .ok_or(anyhow::anyhow!("failed to get the resource dir"))?)
+    }
+}
+
+pub fn clash_pid_path() -> Result<PathBuf> {
+    unsafe { Ok(RESOURCE_DIR.clone().unwrap().join("clash.pid")) }
 }
 
 #[cfg(windows)]
diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs
index 7f6c74a..5f8d2a6 100644
--- a/src-tauri/src/utils/init.rs
+++ b/src-tauri/src/utils/init.rs
@@ -12,7 +12,7 @@ use tauri::PackageInfo;
 
 /// initialize this instance's log file
 fn init_log() -> Result<()> {
-    let log_dir = dirs::app_logs_dir();
+    let log_dir = dirs::app_logs_dir()?;
     if !log_dir.exists() {
         let _ = fs::create_dir_all(&log_dir);
     }
@@ -54,42 +54,40 @@ pub fn init_config() -> Result<()> {
 
     let _ = init_log();
 
-    let app_dir = dirs::app_home_dir();
-    let profiles_dir = dirs::app_profiles_dir();
+    let _ = dirs::app_home_dir().map(|app_dir| {
+        if !app_dir.exists() {
+            let _ = fs::create_dir_all(&app_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)?;
+        // }
+    });
+
+    let _ = dirs::app_profiles_dir().map(|profiles_dir| {
+        if !profiles_dir.exists() {
+            let _ = fs::create_dir_all(&profiles_dir);
+        }
+    });
 
-    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);
-
-    if !app_dir.exists() {
-        let _ = fs::create_dir_all(&app_dir);
-    }
+pub fn init_resources(package_info: &PackageInfo) -> Result<()> {
+    let app_dir = dirs::app_home_dir()?;
+    let res_dir = dirs::app_resources_dir(package_info)?;
 
     // copy the resource file
     for file in ["Country.mmdb", "geoip.dat", "geosite.dat", "wintun.dll"].iter() {
@@ -99,4 +97,6 @@ pub fn init_resources(package_info: &PackageInfo) {
             let _ = fs::copy(src_path, target_path);
         }
     }
+
+    Ok(())
 }
diff --git a/src-tauri/src/utils/tmpl.rs b/src-tauri/src/utils/tmpl.rs
index 69aa805..ec17c33 100644
--- a/src-tauri/src/utils/tmpl.rs
+++ b/src-tauri/src/utils/tmpl.rs
@@ -1,42 +1,5 @@
 ///! Some config file template
 
-/// template for clash core `config.yaml`
-pub const CLASH_CONFIG: &[u8] = br#"# Default Config For Clash Core
-
-mixed-port: 7890
-log-level: info
-allow-lan: false
-external-controller: 127.0.0.1:9090
-mode: rule
-secret: ""
-"#;
-
-/// template for `profiles.yaml`
-pub const PROFILES_CONFIG: &[u8] = b"# Profiles Config for Clash Verge
-
-current: ~
-chain: ~
-valid:
-  - dns
-items: ~
-";
-
-/// template for `verge.yaml`
-pub const VERGE_CONFIG: &[u8] = b"# Default Config For Clash Verge
-
-clash_core: clash
-language: en
-theme_mode: system
-theme_blur: false
-traffic_graph: true
-enable_auto_launch: false
-enable_silent_start: false
-enable_system_proxy: false
-enable_proxy_guard: false
-proxy_guard_duration: 10
-auto_close_connection: true
-";
-
 /// template for new a profile item
 pub const ITEM_LOCAL: &str = "# Profile Template for clash verge
 
-- 
GitLab