main.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #![cfg_attr(
  2. all(not(debug_assertions), target_os = "windows"),
  3. windows_subsystem = "windows"
  4. )]
  5. mod cmds;
  6. mod config;
  7. mod core;
  8. mod data;
  9. mod feat;
  10. mod utils;
  11. use crate::{
  12. data::Verge,
  13. utils::{resolve, server},
  14. };
  15. use tauri::{
  16. api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
  17. };
  18. fn main() -> std::io::Result<()> {
  19. let mut context = tauri::generate_context!();
  20. let verge = Verge::new();
  21. if server::check_singleton(verge.app_singleton_port).is_err() {
  22. println!("app exists");
  23. return Ok(());
  24. }
  25. for win in context.config_mut().tauri.windows.iter_mut() {
  26. if verge.enable_silent_start.unwrap_or(false) {
  27. win.visible = false;
  28. }
  29. }
  30. #[cfg(target_os = "windows")]
  31. unsafe {
  32. use crate::utils::dirs;
  33. dirs::init_portable_flag();
  34. }
  35. let tray_menu = SystemTrayMenu::new()
  36. .add_item(CustomMenuItem::new("open_window", "Show"))
  37. .add_native_item(SystemTrayMenuItem::Separator)
  38. .add_item(CustomMenuItem::new("rule_mode", "Rule Mode"))
  39. .add_item(CustomMenuItem::new("global_mode", "Global Mode"))
  40. .add_item(CustomMenuItem::new("direct_mode", "Direct Mode"))
  41. .add_item(CustomMenuItem::new("script_mode", "Script Mode"))
  42. .add_native_item(SystemTrayMenuItem::Separator)
  43. .add_item(CustomMenuItem::new("system_proxy", "System Proxy"))
  44. .add_item(CustomMenuItem::new("tun_mode", "Tun Mode"))
  45. .add_item(CustomMenuItem::new("restart_clash", "Restart Clash"))
  46. .add_item(CustomMenuItem::new("restart_app", "Restart App"))
  47. .add_native_item(SystemTrayMenuItem::Separator)
  48. .add_item(CustomMenuItem::new("quit", "Quit").accelerator("CmdOrControl+Q"));
  49. #[allow(unused_mut)]
  50. let mut builder = tauri::Builder::default()
  51. .setup(|app| Ok(resolve::resolve_setup(app)))
  52. .system_tray(SystemTray::new().with_menu(tray_menu))
  53. .on_system_tray_event(move |app_handle, event| match event {
  54. SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
  55. "open_window" => {
  56. resolve::create_window(app_handle);
  57. }
  58. mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => {
  59. let mode = &mode[0..mode.len() - 5];
  60. feat::change_clash_mode(mode);
  61. }
  62. "system_proxy" => feat::toggle_system_proxy(),
  63. "tun_mode" => feat::toggle_tun_mode(),
  64. "restart_app" => {
  65. api::process::restart(&app_handle.env());
  66. }
  67. "quit" => {
  68. resolve::resolve_reset();
  69. app_handle.exit(0);
  70. }
  71. _ => {}
  72. },
  73. #[cfg(target_os = "windows")]
  74. SystemTrayEvent::LeftClick { .. } => {
  75. resolve::create_window(app_handle);
  76. }
  77. _ => {}
  78. })
  79. .invoke_handler(tauri::generate_handler![
  80. // common
  81. cmds::get_sys_proxy,
  82. cmds::open_app_dir,
  83. cmds::open_logs_dir,
  84. cmds::open_web_url,
  85. cmds::kill_sidecar,
  86. cmds::restart_sidecar,
  87. // clash
  88. cmds::get_clash_info,
  89. cmds::get_clash_logs,
  90. cmds::patch_clash_config,
  91. cmds::change_clash_core,
  92. cmds::get_runtime_config,
  93. cmds::get_runtime_yaml,
  94. cmds::get_runtime_exists,
  95. cmds::get_runtime_logs,
  96. // verge
  97. cmds::get_verge_config,
  98. cmds::patch_verge_config,
  99. cmds::update_hotkeys,
  100. // profile
  101. cmds::view_profile,
  102. cmds::patch_profile,
  103. cmds::create_profile,
  104. cmds::import_profile,
  105. cmds::update_profile,
  106. cmds::delete_profile,
  107. cmds::select_profile,
  108. cmds::get_profiles,
  109. cmds::enhance_profiles,
  110. cmds::change_profile_chain,
  111. cmds::change_profile_valid,
  112. cmds::read_profile_file,
  113. cmds::save_profile_file,
  114. // service mode
  115. cmds::service::start_service,
  116. cmds::service::stop_service,
  117. cmds::service::check_service,
  118. cmds::service::install_service,
  119. cmds::service::uninstall_service,
  120. ]);
  121. #[cfg(target_os = "macos")]
  122. {
  123. use tauri::{Menu, MenuItem, Submenu};
  124. let submenu_file = Submenu::new(
  125. "File",
  126. Menu::new()
  127. .add_native_item(MenuItem::Undo)
  128. .add_native_item(MenuItem::Redo)
  129. .add_native_item(MenuItem::Copy)
  130. .add_native_item(MenuItem::Paste)
  131. .add_native_item(MenuItem::Cut)
  132. .add_native_item(MenuItem::SelectAll),
  133. );
  134. builder = builder.menu(Menu::new().add_submenu(submenu_file));
  135. }
  136. let app = builder
  137. .build(context)
  138. .expect("error while running tauri application");
  139. let app_handle = app.app_handle();
  140. ctrlc::set_handler(move || {
  141. resolve::resolve_reset();
  142. app_handle.exit(0);
  143. })
  144. .expect("error while exiting.");
  145. #[allow(unused)]
  146. app.run(|app_handle, e| match e {
  147. tauri::RunEvent::ExitRequested { api, .. } => {
  148. api.prevent_exit();
  149. }
  150. tauri::RunEvent::Exit => {
  151. resolve::resolve_reset();
  152. api::process::kill_children();
  153. }
  154. #[cfg(target_os = "macos")]
  155. tauri::RunEvent::WindowEvent { label, event, .. } => {
  156. if label == "main" {
  157. match event {
  158. tauri::WindowEvent::CloseRequested { api, .. } => {
  159. api.prevent_close();
  160. app_handle.get_window("main").map(|win| {
  161. let _ = win.hide();
  162. });
  163. }
  164. _ => {}
  165. }
  166. }
  167. }
  168. _ => {}
  169. });
  170. Ok(())
  171. }