main.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #![cfg_attr(
  2. all(not(debug_assertions), target_os = "windows"),
  3. windows_subsystem = "windows"
  4. )]
  5. mod cmds;
  6. mod core;
  7. mod states;
  8. mod utils;
  9. use crate::{
  10. core::VergeConfig,
  11. utils::{resolve, server},
  12. };
  13. use tauri::{
  14. api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
  15. };
  16. fn main() -> std::io::Result<()> {
  17. if server::check_singleton().is_err() {
  18. println!("app exists");
  19. return Ok(());
  20. }
  21. let tray_menu = SystemTrayMenu::new()
  22. .add_item(CustomMenuItem::new("open_window", "Show"))
  23. .add_item(CustomMenuItem::new("system_proxy", "System Proxy"))
  24. .add_item(CustomMenuItem::new("restart_clash", "Restart Clash"))
  25. .add_native_item(SystemTrayMenuItem::Separator)
  26. .add_item(CustomMenuItem::new("quit", "Quit").accelerator("CmdOrControl+Q"));
  27. #[allow(unused_mut)]
  28. let mut builder = tauri::Builder::default()
  29. .manage(states::VergeState::default())
  30. .manage(states::ClashState::default())
  31. .manage(states::ProfilesState::default())
  32. .setup(|app| Ok(resolve::resolve_setup(app)))
  33. .system_tray(SystemTray::new().with_menu(tray_menu))
  34. .on_system_tray_event(move |app_handle, event| match event {
  35. SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
  36. "open_window" => {
  37. let window = app_handle.get_window("main").unwrap();
  38. window.unminimize().unwrap();
  39. window.show().unwrap();
  40. window.set_focus().unwrap();
  41. }
  42. "system_proxy" => {
  43. let verge_state = app_handle.state::<states::VergeState>();
  44. let mut verge = verge_state.0.lock().unwrap();
  45. let old_value = verge.config.enable_system_proxy.clone().unwrap_or(false);
  46. let new_value = !old_value;
  47. match verge.patch_config(VergeConfig {
  48. enable_system_proxy: Some(new_value),
  49. ..VergeConfig::default()
  50. }) {
  51. Ok(_) => {
  52. app_handle
  53. .tray_handle()
  54. .get_item(id.as_str())
  55. .set_selected(new_value)
  56. .unwrap();
  57. // update verge config
  58. let window = app_handle.get_window("main").unwrap();
  59. window.emit("verge://refresh-verge-config", "yes").unwrap();
  60. }
  61. Err(err) => log::error!("{err}"),
  62. }
  63. }
  64. "restart_clash" => {
  65. let clash_state = app_handle.state::<states::ClashState>();
  66. let profiles_state = app_handle.state::<states::ProfilesState>();
  67. let mut clash = clash_state.0.lock().unwrap();
  68. let mut profiles = profiles_state.0.lock().unwrap();
  69. crate::log_if_err!(clash.restart_sidecar(&mut profiles));
  70. }
  71. "quit" => {
  72. resolve::resolve_reset(app_handle);
  73. api::process::kill_children();
  74. std::process::exit(0);
  75. }
  76. _ => {}
  77. },
  78. #[cfg(target_os = "windows")]
  79. SystemTrayEvent::LeftClick { .. } => {
  80. let window = app_handle.get_window("main").unwrap();
  81. window.unminimize().unwrap();
  82. window.show().unwrap();
  83. window.set_focus().unwrap();
  84. }
  85. _ => {}
  86. })
  87. .invoke_handler(tauri::generate_handler![
  88. // common
  89. cmds::restart_sidecar,
  90. cmds::get_sys_proxy,
  91. cmds::get_cur_proxy,
  92. cmds::kill_sidecars,
  93. cmds::open_app_dir,
  94. cmds::open_logs_dir,
  95. // clash
  96. cmds::get_clash_info,
  97. cmds::patch_clash_config,
  98. // verge
  99. cmds::get_verge_config,
  100. cmds::patch_verge_config,
  101. // profile
  102. cmds::view_profile,
  103. cmds::patch_profile,
  104. cmds::create_profile,
  105. cmds::import_profile,
  106. cmds::update_profile,
  107. cmds::delete_profile,
  108. cmds::select_profile,
  109. cmds::get_profiles,
  110. cmds::sync_profiles,
  111. cmds::enhance_profiles,
  112. cmds::change_profile_chain,
  113. cmds::read_profile_file,
  114. cmds::save_profile_file
  115. ]);
  116. #[cfg(target_os = "macos")]
  117. {
  118. use tauri::{Menu, MenuItem, Submenu};
  119. let submenu_file = Submenu::new(
  120. "File",
  121. Menu::new()
  122. .add_native_item(MenuItem::Undo)
  123. .add_native_item(MenuItem::Redo)
  124. .add_native_item(MenuItem::Copy)
  125. .add_native_item(MenuItem::Paste)
  126. .add_native_item(MenuItem::Cut)
  127. .add_native_item(MenuItem::SelectAll),
  128. );
  129. builder = builder.menu(Menu::new().add_submenu(submenu_file));
  130. }
  131. builder
  132. .build(tauri::generate_context!())
  133. .expect("error while running tauri application")
  134. .run(|app_handle, e| match e {
  135. tauri::RunEvent::WindowEvent { label, event, .. } => match event {
  136. tauri::WindowEvent::CloseRequested { api, .. } => {
  137. let app_handle = app_handle.clone();
  138. api.prevent_close();
  139. app_handle.get_window(&label).unwrap().hide().unwrap();
  140. }
  141. _ => {}
  142. },
  143. tauri::RunEvent::ExitRequested { .. } => {
  144. resolve::resolve_reset(app_handle);
  145. api::process::kill_children();
  146. }
  147. _ => {}
  148. });
  149. Ok(())
  150. }