diff --git a/src-tauri/src/core/clash.rs b/src-tauri/src/core/clash.rs index 0105f4f..0f7a304 100644 --- a/src-tauri/src/core/clash.rs +++ b/src-tauri/src/core/clash.rs @@ -1,12 +1,12 @@ -use std::collections::HashMap; - use super::{Profiles, Verge}; -use crate::utils::{config, dirs}; +use crate::utils::{config, dirs, help}; use anyhow::{bail, Result}; use reqwest::header::HeaderMap; use serde::{Deserialize, Serialize}; use serde_yaml::{Mapping, Value}; +use std::{collections::HashMap, time::Duration}; use tauri::api::process::{Command, CommandChild, CommandEvent}; +use tokio::time::sleep; #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct ClashInfo { @@ -241,17 +241,8 @@ impl Clash { self.save_config() } - /// activate the profile - pub fn activate(&self, profiles: &Profiles) -> Result<()> { + fn _activate(info: ClashInfo, config: Mapping) -> Result<()> { let temp_path = dirs::profiles_temp_path(); - let info = self.info.clone(); - let mut config = self.config.clone(); - let gen_config = profiles.gen_activate()?; - - for (key, value) in gen_config.into_iter() { - config.insert(key, value); - } - config::save_yaml(temp_path.clone(), &config, Some("# Clash Verge Temp File"))?; tauri::async_runtime::spawn(async move { @@ -288,6 +279,49 @@ impl Clash { Ok(()) } + + /// activate the profile + pub fn activate(&self, profiles: &Profiles) -> Result<()> { + let info = self.info.clone(); + let mut config = self.config.clone(); + let gen_map = profiles.gen_activate()?; + + for (key, value) in gen_map.into_iter() { + config.insert(key, value); + } + + Self::_activate(info, config) + } + + /// enhanced profiles mode + pub fn activate_enhanced(&self, profiles: &Profiles, win: tauri::Window) -> Result<()> { + let event_name = help::get_uid("e"); + let event_name = format!("script-cb-{event_name}"); + + let info = self.info.clone(); + let mut config = self.config.clone(); + + win.once(&event_name, move |event| { + if let Some(result) = event.payload() { + let gen_map: Mapping = serde_json::from_str(result).unwrap(); + + for (key, value) in gen_map.into_iter() { + config.insert(key, value); + } + Self::_activate(info, config).unwrap(); + } + }); + + // generate the payload + let payload = profiles.gen_enhanced(); + + tauri::async_runtime::spawn(async move { + sleep(Duration::from_secs(5)).await; + win.emit("script-handler", payload).unwrap(); + }); + + Ok(()) + } } impl Default for Clash { diff --git a/src-tauri/src/core/profiles.rs b/src-tauri/src/core/profiles.rs index 23836df..d4504cb 100644 --- a/src-tauri/src/core/profiles.rs +++ b/src-tauri/src/core/profiles.rs @@ -436,4 +436,72 @@ impl Profiles { bail!("failed to found the uid \"{current}\""); } + + /// gen the enhanced profiles + pub fn gen_enhanced(&self) -> PrfEnhanced { + let current = self.gen_activate().unwrap(); + + let chain = match self.chain.as_ref() { + Some(chain) => chain + .iter() + .map(|uid| self.get_item(uid)) + .filter(|item| item.is_ok()) + .map(|item| item.unwrap()) + .map(|item| PrfData::from_item(item)) + .filter(|o| o.is_some()) + .map(|o| o.unwrap()) + .collect::>(), + None => vec![], + }; + + PrfEnhanced { current, chain } + } +} + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct PrfEnhanced { + current: Mapping, + + chain: Vec, +} + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct PrfData { + item: PrfItem, + + #[serde(skip_serializing_if = "Option::is_none")] + merge: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + script: Option, +} + +impl PrfData { + pub fn from_item(item: &PrfItem) -> Option { + match item.itype.as_ref() { + Some(itype) => { + let file = item.file.clone()?; + let path = dirs::app_profiles_dir().join(file); + + if !path.exists() { + return None; + } + + match itype.as_str() { + "script" => Some(PrfData { + item: item.clone(), + script: Some(fs::read_to_string(path).unwrap_or("".into())), + merge: None, + }), + "merge" => Some(PrfData { + item: item.clone(), + merge: Some(config::read_yaml::(path)), + script: None, + }), + _ => None, + } + } + None => None, + } + } } diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs index 9753940..f1b6037 100644 --- a/src-tauri/src/utils/resolve.rs +++ b/src-tauri/src/utils/resolve.rs @@ -26,6 +26,10 @@ pub fn resolve_setup(app: &App) { *profiles = Profiles::read_file(); log_if_err!(clash.activate(&profiles)); + app + .get_window("main") + .map(|win| log_if_err!(clash.activate_enhanced(&profiles, win))); + verge.init_sysproxy(clash.info.port.clone()); // enable tun mode if verge.config.enable_tun_mode.clone().unwrap_or(false)