verge.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. use crate::utils::{dirs, help};
  2. use anyhow::Result;
  3. use log::LevelFilter;
  4. use serde::{Deserialize, Serialize};
  5. /// ### `verge.yaml` schema
  6. #[derive(Default, Debug, Clone, Deserialize, Serialize)]
  7. pub struct IVerge {
  8. /// app listening port for app singleton
  9. pub app_singleton_port: Option<u16>,
  10. /// app log level
  11. /// silent | error | warn | info | debug | trace
  12. pub app_log_level: Option<String>,
  13. // i18n
  14. pub language: Option<String>,
  15. /// `light` or `dark` or `system`
  16. pub theme_mode: Option<String>,
  17. /// enable blur mode
  18. /// maybe be able to set the alpha
  19. pub theme_blur: Option<bool>,
  20. /// enable traffic graph default is true
  21. pub traffic_graph: Option<bool>,
  22. /// show memory info (only for Clash Meta)
  23. pub enable_memory_usage: Option<bool>,
  24. /// clash tun mode
  25. pub enable_tun_mode: Option<bool>,
  26. /// windows service mode
  27. #[serde(skip_serializing_if = "Option::is_none")]
  28. pub enable_service_mode: Option<bool>,
  29. /// can the app auto startup
  30. pub enable_auto_launch: Option<bool>,
  31. /// not show the window on launch
  32. pub enable_silent_start: Option<bool>,
  33. /// set system proxy
  34. pub enable_system_proxy: Option<bool>,
  35. /// enable proxy guard
  36. pub enable_proxy_guard: Option<bool>,
  37. /// set system proxy bypass
  38. pub system_proxy_bypass: Option<String>,
  39. /// proxy guard duration
  40. pub proxy_guard_duration: Option<u64>,
  41. /// theme setting
  42. pub theme_setting: Option<IVergeTheme>,
  43. /// web ui list
  44. pub web_ui_list: Option<Vec<String>>,
  45. /// clash core path
  46. #[serde(skip_serializing_if = "Option::is_none")]
  47. pub clash_core: Option<String>,
  48. /// hotkey map
  49. /// format: {func},{key}
  50. pub hotkeys: Option<Vec<String>>,
  51. /// 切换代理时自动关闭连接
  52. pub auto_close_connection: Option<bool>,
  53. /// 默认的延迟测试连接
  54. pub default_latency_test: Option<String>,
  55. /// 支持关闭字段过滤,避免meta的新字段都被过滤掉,默认为真
  56. pub enable_clash_fields: Option<bool>,
  57. /// 是否使用内部的脚本支持,默认为真
  58. pub enable_builtin_enhanced: Option<bool>,
  59. /// proxy 页面布局 列数
  60. pub proxy_layout_column: Option<i32>,
  61. /// 日志清理
  62. /// 0: 不清理; 1: 7天; 2: 30天; 3: 90天
  63. pub auto_log_clean: Option<i32>,
  64. /// window size and position
  65. #[serde(skip_serializing_if = "Option::is_none")]
  66. pub window_size_position: Option<Vec<f64>>,
  67. }
  68. #[derive(Default, Debug, Clone, Deserialize, Serialize)]
  69. pub struct IVergeTheme {
  70. pub primary_color: Option<String>,
  71. pub secondary_color: Option<String>,
  72. pub primary_text: Option<String>,
  73. pub secondary_text: Option<String>,
  74. pub info_color: Option<String>,
  75. pub error_color: Option<String>,
  76. pub warning_color: Option<String>,
  77. pub success_color: Option<String>,
  78. pub font_family: Option<String>,
  79. pub css_injection: Option<String>,
  80. }
  81. impl IVerge {
  82. pub fn new() -> Self {
  83. match dirs::verge_path().and_then(|path| help::read_yaml::<IVerge>(&path)) {
  84. Ok(config) => config,
  85. Err(err) => {
  86. log::error!(target: "app", "{err}");
  87. Self::template()
  88. }
  89. }
  90. }
  91. pub fn template() -> Self {
  92. Self {
  93. clash_core: match cfg!(feature = "default-meta") {
  94. false => Some("clash".into()),
  95. true => Some("clash-meta".into()),
  96. },
  97. language: match cfg!(feature = "default-meta") {
  98. false => Some("en".into()),
  99. true => Some("zh".into()),
  100. },
  101. theme_mode: Some("system".into()),
  102. theme_blur: Some(false),
  103. traffic_graph: Some(true),
  104. enable_memory_usage: Some(true),
  105. enable_auto_launch: Some(false),
  106. enable_silent_start: Some(false),
  107. enable_system_proxy: Some(false),
  108. enable_proxy_guard: Some(false),
  109. proxy_guard_duration: Some(30),
  110. auto_close_connection: Some(true),
  111. enable_builtin_enhanced: Some(true),
  112. enable_clash_fields: Some(true),
  113. auto_log_clean: Some(3),
  114. ..Self::default()
  115. }
  116. }
  117. /// Save IVerge App Config
  118. pub fn save_file(&self) -> Result<()> {
  119. help::save_yaml(&dirs::verge_path()?, &self, Some("# Clash Verge Config"))
  120. }
  121. /// patch verge config
  122. /// only save to file
  123. pub fn patch_config(&mut self, patch: IVerge) {
  124. macro_rules! patch {
  125. ($key: tt) => {
  126. if patch.$key.is_some() {
  127. self.$key = patch.$key;
  128. }
  129. };
  130. }
  131. patch!(app_log_level);
  132. patch!(language);
  133. patch!(theme_mode);
  134. patch!(theme_blur);
  135. patch!(traffic_graph);
  136. patch!(enable_memory_usage);
  137. patch!(enable_tun_mode);
  138. patch!(enable_service_mode);
  139. patch!(enable_auto_launch);
  140. patch!(enable_silent_start);
  141. patch!(enable_system_proxy);
  142. patch!(enable_proxy_guard);
  143. patch!(system_proxy_bypass);
  144. patch!(proxy_guard_duration);
  145. patch!(theme_setting);
  146. patch!(web_ui_list);
  147. patch!(clash_core);
  148. patch!(hotkeys);
  149. patch!(auto_close_connection);
  150. patch!(default_latency_test);
  151. patch!(enable_builtin_enhanced);
  152. patch!(proxy_layout_column);
  153. patch!(enable_clash_fields);
  154. patch!(auto_log_clean);
  155. patch!(window_size_position);
  156. }
  157. /// 在初始化前尝试拿到单例端口的值
  158. pub fn get_singleton_port() -> u16 {
  159. #[cfg(not(feature = "verge-dev"))]
  160. const SERVER_PORT: u16 = 33331;
  161. #[cfg(feature = "verge-dev")]
  162. const SERVER_PORT: u16 = 11233;
  163. match dirs::verge_path().and_then(|path| help::read_yaml::<IVerge>(&path)) {
  164. Ok(config) => config.app_singleton_port.unwrap_or(SERVER_PORT),
  165. Err(_) => SERVER_PORT, // 这里就不log错误了
  166. }
  167. }
  168. /// 获取日志等级
  169. pub fn get_log_level(&self) -> LevelFilter {
  170. if let Some(level) = self.app_log_level.as_ref() {
  171. match level.to_lowercase().as_str() {
  172. "silent" => LevelFilter::Off,
  173. "error" => LevelFilter::Error,
  174. "warn" => LevelFilter::Warn,
  175. "info" => LevelFilter::Info,
  176. "debug" => LevelFilter::Debug,
  177. "trace" => LevelFilter::Trace,
  178. _ => LevelFilter::Info,
  179. }
  180. } else {
  181. LevelFilter::Info
  182. }
  183. }
  184. }