verge.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. use crate::utils::{config, dirs, sysopt::SysProxyConfig};
  2. use auto_launch::{AutoLaunch, AutoLaunchBuilder};
  3. use serde::{Deserialize, Serialize};
  4. use tauri::api::path::resource_dir;
  5. /// ### `verge.yaml` schema
  6. #[derive(Default, Debug, Clone, Deserialize, Serialize)]
  7. pub struct VergeConfig {
  8. /// `light` or `dark`
  9. pub theme_mode: Option<String>,
  10. /// enable blur mode
  11. /// maybe be able to set the alpha
  12. pub theme_blur: Option<bool>,
  13. /// can the app auto startup
  14. pub enable_auto_launch: Option<bool>,
  15. /// set system proxy
  16. pub enable_system_proxy: Option<bool>,
  17. /// set system proxy bypass
  18. pub system_proxy_bypass: Option<String>,
  19. }
  20. static VERGE_CONFIG: &str = "verge.yaml";
  21. impl VergeConfig {
  22. pub fn new() -> Self {
  23. config::read_yaml::<VergeConfig>(dirs::app_home_dir().join(VERGE_CONFIG))
  24. }
  25. /// Save Verge App Config
  26. pub fn save_file(&self) -> Result<(), String> {
  27. config::save_yaml(
  28. dirs::app_home_dir().join(VERGE_CONFIG),
  29. self,
  30. Some("# The Config for Clash Verge App\n\n"),
  31. )
  32. }
  33. }
  34. /// Verge App abilities
  35. #[derive(Debug)]
  36. pub struct Verge {
  37. pub config: VergeConfig,
  38. pub old_sysproxy: Option<SysProxyConfig>,
  39. pub cur_sysproxy: Option<SysProxyConfig>,
  40. pub auto_launch: Option<AutoLaunch>,
  41. }
  42. impl Default for Verge {
  43. fn default() -> Self {
  44. Verge::new()
  45. }
  46. }
  47. impl Verge {
  48. pub fn new() -> Self {
  49. Verge {
  50. config: VergeConfig::new(),
  51. old_sysproxy: None,
  52. cur_sysproxy: None,
  53. auto_launch: None,
  54. }
  55. }
  56. /// init the sysproxy
  57. pub fn init_sysproxy(&mut self, port: Option<String>) {
  58. if let Some(port) = port {
  59. let enable = self.config.enable_system_proxy.clone().unwrap_or(false);
  60. self.old_sysproxy = match SysProxyConfig::get_sys() {
  61. Ok(proxy) => Some(proxy),
  62. Err(_) => None,
  63. };
  64. let bypass = self.config.system_proxy_bypass.clone();
  65. let sysproxy = SysProxyConfig::new(enable, port, bypass);
  66. if enable {
  67. if sysproxy.set_sys().is_err() {
  68. log::error!("failed to set system proxy");
  69. }
  70. }
  71. self.cur_sysproxy = Some(sysproxy);
  72. }
  73. }
  74. /// reset the sysproxy
  75. pub fn reset_sysproxy(&mut self) {
  76. if let Some(sysproxy) = self.old_sysproxy.take() {
  77. match sysproxy.set_sys() {
  78. Ok(_) => self.cur_sysproxy = None,
  79. Err(_) => log::error!("failed to reset proxy for"),
  80. }
  81. }
  82. }
  83. /// init the auto launch
  84. pub fn init_launch(&mut self, package_info: &tauri::PackageInfo) {
  85. let app_name = "clash-verge";
  86. let app_path = get_app_path(app_name);
  87. let app_path = resource_dir(package_info).unwrap().join(app_path);
  88. let app_path = app_path.as_os_str().to_str().unwrap();
  89. let auto = AutoLaunchBuilder::new()
  90. .set_app_name(app_name)
  91. .set_app_path(app_path)
  92. .build();
  93. self.auto_launch = Some(auto);
  94. }
  95. /// sync the startup when run the app
  96. pub fn sync_launch(&self) -> Result<(), String> {
  97. let enable = self.config.enable_auto_launch.clone().unwrap_or(false);
  98. if !enable {
  99. return Ok(());
  100. }
  101. if self.auto_launch.is_none() {
  102. return Err("should init the auto launch first".into());
  103. }
  104. let auto_launch = self.auto_launch.clone().unwrap();
  105. let is_enabled = auto_launch.is_enabled().unwrap_or(false);
  106. if !is_enabled {
  107. if let Err(_) = auto_launch.enable() {
  108. return Err("failed to enable auto-launch".into());
  109. }
  110. }
  111. Ok(())
  112. }
  113. /// update the startup
  114. fn update_launch(&mut self, enable: bool) -> Result<(), String> {
  115. let conf_enable = self.config.enable_auto_launch.clone().unwrap_or(false);
  116. if enable == conf_enable {
  117. return Ok(());
  118. }
  119. let auto_launch = self.auto_launch.clone().unwrap();
  120. let result = if enable {
  121. auto_launch.enable()
  122. } else {
  123. auto_launch.disable()
  124. };
  125. match result {
  126. Ok(_) => Ok(()),
  127. Err(err) => {
  128. log::error!("{err}");
  129. Err("failed to set system startup info".into())
  130. }
  131. }
  132. }
  133. // fn guard_thread(&mut self) -> Result<(), String> {
  134. // let sysproxy = self.cur_sysproxy.clone();
  135. // use std::{thread, time};
  136. // tauri::async_runtime::spawn(async move {
  137. // if let Some(sysproxy) = sysproxy {
  138. // sysproxy.set_sys();
  139. // }
  140. // let ten_millis = time::Duration::from_millis(10);
  141. // let now = time::Instant::now();
  142. // thread::sleep(ten_millis);
  143. // });
  144. // Ok(())
  145. // }
  146. /// patch verge config
  147. /// There should be only one update at a time here
  148. /// so call the save_file at the end is savely
  149. pub fn patch_config(&mut self, patch: VergeConfig) -> Result<(), String> {
  150. // only change it
  151. if patch.theme_mode.is_some() {
  152. self.config.theme_mode = patch.theme_mode;
  153. }
  154. if patch.theme_blur.is_some() {
  155. self.config.theme_blur = patch.theme_blur;
  156. }
  157. // should update system startup
  158. if patch.enable_auto_launch.is_some() {
  159. let enable = patch.enable_auto_launch.unwrap();
  160. self.update_launch(enable)?;
  161. self.config.enable_auto_launch = Some(enable);
  162. }
  163. // should update system proxy
  164. if patch.enable_system_proxy.is_some() {
  165. let enable = patch.enable_system_proxy.unwrap();
  166. if let Some(mut sysproxy) = self.cur_sysproxy.take() {
  167. sysproxy.enable = enable;
  168. if sysproxy.set_sys().is_err() {
  169. log::error!("failed to set system proxy");
  170. return Err("failed to set system proxy".into());
  171. }
  172. self.cur_sysproxy = Some(sysproxy);
  173. }
  174. self.config.enable_system_proxy = Some(enable);
  175. }
  176. // todo
  177. // should update system proxy too
  178. if patch.system_proxy_bypass.is_some() {
  179. self.config.system_proxy_bypass = patch.system_proxy_bypass;
  180. }
  181. self.config.save_file()
  182. }
  183. }
  184. // Get the target app_path
  185. fn get_app_path(app_name: &str) -> String {
  186. #[cfg(target_os = "linux")]
  187. let ext = "";
  188. #[cfg(target_os = "macos")]
  189. let ext = "";
  190. #[cfg(target_os = "windows")]
  191. let ext = ".exe";
  192. String::from(app_name) + ext
  193. }