// use self::handle::Handle; // use self::hotkey::Hotkey; // use self::sysopt::Sysopt; // use self::timer::Timer; // // use crate::data::*; // // use crate::enhance::enhance_config; // use crate::log_if_err; // use anyhow::{bail, Result}; // use once_cell::sync::OnceCell; // use parking_lot::Mutex; // use serde_yaml::{Mapping, Value}; // use std::sync::Arc; pub mod clash_api; mod core; pub mod core_service; pub mod handle; pub mod hotkey; pub mod logger; // pub mod service; pub mod sysopt; pub mod timer; pub mod tray; pub use self::core::*; // pub use self::service::*; #[derive(Clone)] pub struct Core {} impl Core { // pub fn global() -> &'static Core { // static CORE: OnceCell = 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) -> 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}\""); // } // 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()?; // } // if clash_mode.is_some() { // let handle = self.handle.lock(); // handle.update_systray_part()?; // } // 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() { // 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(()) // } // /// 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) -> 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()?; // } // Ok(()) // } }