From 6a51e93ded3b5cb5cb0c5c0636fbba0b2ff87c8c Mon Sep 17 00:00:00 2001 From: GyDi Date: Wed, 13 Jul 2022 02:26:54 +0800 Subject: [PATCH] refactor: mode manage on tray --- src-tauri/src/core/clash.rs | 13 ----- src-tauri/src/core/mod.rs | 101 +++++++++++++++++++--------------- src-tauri/src/core/service.rs | 68 +++++++---------------- src-tauri/src/main.rs | 17 +----- 4 files changed, 79 insertions(+), 120 deletions(-) diff --git a/src-tauri/src/core/clash.rs b/src-tauri/src/core/clash.rs index d73c574..5d88aaf 100644 --- a/src-tauri/src/core/clash.rs +++ b/src-tauri/src/core/clash.rs @@ -16,9 +16,6 @@ pub struct ClashInfo { /// clash secret pub secret: Option, - - /// mode - pub mode: Option, } impl ClashInfo { @@ -29,7 +26,6 @@ impl ClashInfo { let key_port_2 = Value::from("mixed-port"); let key_server = Value::from("external-controller"); let key_secret = Value::from("secret"); - let key_mode = Value::from("mode"); let port = match config.get(&key_port_1) { Some(value) => match value { @@ -76,20 +72,11 @@ impl ClashInfo { _ => None, }; - let mode = match config.get(&key_mode) { - Some(value) => match value { - Value::String(val_str) => Some(val_str.clone()), - _ => None, - }, - _ => None, - }; - ClashInfo { status: "init".into(), port, server, secret, - mode, } } } diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index b6cb1d8..7adc356 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -3,7 +3,7 @@ use self::sysopt::Sysopt; use self::timer::Timer; use crate::core::enhance::PrfEnhancedResult; use crate::log_if_err; -use crate::utils::{dirs, help}; +use crate::utils::help; use anyhow::{bail, Result}; use parking_lot::Mutex; use serde_yaml::Mapping; @@ -112,6 +112,7 @@ impl Core { log_if_err!(sysopt.init_launch(auto_launch)); log_if_err!(self.update_systray(&app_handle)); + log_if_err!(self.update_systray_clash(&app_handle)); // wait the window setup during resolve app let core = self.clone(); @@ -191,7 +192,7 @@ impl Core { } if changed_mode { - self.update_systray(app_handle)?; + self.update_systray_clash(app_handle)?; } Ok(()) @@ -240,7 +241,7 @@ impl Core { #[cfg(target_os = "windows")] if tun_mode.is_some() && *tun_mode.as_ref().unwrap_or(&false) { - let wintun_dll = dirs::app_home_dir().join("wintun.dll"); + 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`"); } @@ -262,31 +263,39 @@ impl Core { Ok(()) } - /// update the system tray state - pub fn update_systray(&self, app_handle: &AppHandle) -> Result<()> { + // update system tray state (clash config) + pub fn update_systray_clash(&self, app_handle: &AppHandle) -> Result<()> { let clash = self.clash.lock(); - let info = clash.info.clone(); - let mode = info.mode.as_ref(); + let mode = clash + .config + .get(&Value::from("mode")) + .map(|val| val.as_str().unwrap_or("rule")) + .unwrap_or("rule"); + let tray = app_handle.tray_handle(); + + tray.get_item("rule_mode").set_selected(mode == "rule")?; + tray + .get_item("global_mode") + .set_selected(mode == "global")?; + tray + .get_item("direct_mode") + .set_selected(mode == "direct")?; + tray + .get_item("script_mode") + .set_selected(mode == "script")?; + + Ok(()) + } + + /// update the system tray state (verge config) + pub fn update_systray(&self, app_handle: &AppHandle) -> Result<()> { let verge = self.verge.lock(); let tray = app_handle.tray_handle(); let system_proxy = verge.enable_system_proxy.as_ref(); let tun_mode = verge.enable_tun_mode.as_ref(); - tray - .get_item("rule_mode") - .set_selected((*mode.unwrap()).eq("rule"))?; - tray - .get_item("global_mode") - .set_selected((*mode.unwrap()).eq("global"))?; - tray - .get_item("direct_mode") - .set_selected((*mode.unwrap()).eq("direct"))?; - tray - .get_item("script_mode") - .set_selected((*mode.unwrap()).eq("script"))?; - tray .get_item("system_proxy") .set_selected(*system_proxy.unwrap_or(&false))?; @@ -302,6 +311,33 @@ impl Core { Ok(()) } + // update rule/global/direct/script mode + pub fn update_mode(&self, app_handle: &AppHandle, mode: &str) -> Result<()> { + // save config to file + let mut clash = self.clash.lock(); + clash.config.insert(Value::from("mode"), Value::from(mode)); + clash.save_config()?; + + let info = clash.info.clone(); + drop(clash); + + let notice = { + let window = self.window.lock(); + Notice::from(window.clone()) + }; + + let mut mapping = Mapping::new(); + mapping.insert(Value::from("mode"), Value::from(mode)); + + let service = self.service.lock(); + service.patch_config(info, mapping, notice)?; + + // update tray + self.update_systray_clash(app_handle)?; + + Ok(()) + } + /// activate the profile /// auto activate enhanced profile pub fn activate(&self) -> Result<()> { @@ -425,31 +461,6 @@ impl Core { Ok(()) } - - // update rule/global/direct/script mode - pub fn update_mode(&self, app_handle: &AppHandle, mode: &str) -> Result<()> { - let mut mapping = Mapping::new(); - mapping.insert(Value::from("mode"), Value::from(mode)); - - self.patch_clash(mapping, app_handle); - - let (config, info) = { - let clash = self.clash.lock(); - let config = clash.config.clone(); - let info = clash.info.clone(); - (config, info) - }; - - let notice = { - let window = self.window.lock(); - Notice::from(window.clone()) - }; - - let service = self.service.lock(); - service.patch_config(info, config, notice); - - Ok(()) - } } impl Core { diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index 8a9c1ba..8d91d80 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -1,10 +1,8 @@ -use super::Clash; use super::{notice::Notice, ClashInfo}; use crate::log_if_err; use crate::utils::{config, dirs}; use anyhow::{bail, Result}; use reqwest::header::HeaderMap; -use serde::{Deserialize, Serialize}; use serde_yaml::Mapping; use std::{collections::HashMap, time::Duration}; use tauri::api::process::{Command, CommandChild, CommandEvent}; @@ -139,24 +137,7 @@ impl Service { let temp_path = dirs::profiles_temp_path(); config::save_yaml(temp_path.clone(), &config, Some("# Clash Verge Temp File"))?; - if info.server.is_none() { - if info.port.is_none() { - bail!("failed to parse config.yaml file"); - } else { - bail!("failed to parse the server"); - } - } - - let server = info.server.unwrap(); - let server = format!("http://{server}/configs"); - - let mut headers = HeaderMap::new(); - headers.insert("Content-Type", "application/json".parse().unwrap()); - - if let Some(secret) = info.secret.as_ref() { - let secret = format!("Bearer {}", secret.clone()).parse().unwrap(); - headers.insert("Authorization", secret); - } + let (server, headers) = Self::clash_client_info(info)?; tauri::async_runtime::spawn(async move { let mut data = HashMap::new(); @@ -197,6 +178,24 @@ impl Service { bail!("did not start sidecar"); } + let (server, headers) = Self::clash_client_info(info)?; + + tauri::async_runtime::spawn(async move { + if let Ok(client) = reqwest::ClientBuilder::new().no_proxy().build() { + let builder = client.patch(&server).headers(headers.clone()).json(&config); + + match builder.send().await { + Ok(_) => notice.refresh_clash(), + Err(err) => log::error!("{err}"), + } + } + }); + + Ok(()) + } + + /// get clash client url and headers from clash info + fn clash_client_info(info: ClashInfo) -> Result<(String, HeaderMap)> { if info.server.is_none() { if info.port.is_none() { bail!("failed to parse config.yaml file"); @@ -216,34 +215,7 @@ impl Service { headers.insert("Authorization", secret); } - tauri::async_runtime::spawn(async move { - // retry 5 times - for _ in 0..5 { - match reqwest::ClientBuilder::new().no_proxy().build() { - Ok(client) => { - let builder = client.patch(&server).headers(headers.clone()).json(&config); - - match builder.send().await { - Ok(resp) => { - if resp.status() != 204 { - log::error!("failed to activate clash with status \"{}\"", resp.status()); - } - - notice.refresh_clash(); - - // do not retry - break; - } - Err(err) => log::error!("failed to activate for `{err}`"), - } - } - Err(err) => log::error!("failed to activate for `{err}`"), - } - sleep(Duration::from_millis(500)).await; - } - }); - - Ok(()) + Ok((server, headers)) } } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index ea4cf9e..4010509 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -51,21 +51,10 @@ fn main() -> std::io::Result<()> { "open_window" => { resolve::create_window(app_handle); } - "rule_mode" => { + mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => { + let mode = &mode[0..mode.len() - 5]; let core = app_handle.state::(); - crate::log_if_err!(core.update_mode(app_handle, "rule")); - } - "global_mode" => { - let core = app_handle.state::(); - crate::log_if_err!(core.update_mode(app_handle, "global")); - } - "direct_mode" => { - let core = app_handle.state::(); - crate::log_if_err!(core.update_mode(app_handle, "direct")); - } - "script_mode" => { - let core = app_handle.state::(); - crate::log_if_err!(core.update_mode(app_handle, "script")); + crate::log_if_err!(core.update_mode(app_handle, mode)); } "system_proxy" => { let core = app_handle.state::();