desktop.rs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. use std::{
  2. process::exit,
  3. time::{Duration, Instant},
  4. };
  5. use crate::{
  6. path,
  7. usecase::{view::Event, DesktopServiceState},
  8. BUFFER,
  9. };
  10. use async_std::task::sleep;
  11. use crossbeam_channel::{Receiver, Sender};
  12. use tauri::{
  13. CustomMenuItem, Manager, Menu, MenuItem, Submenu, SystemTray, SystemTrayEvent, SystemTrayMenu,
  14. SystemTrayMenuItem, WindowEvent,
  15. };
  16. pub async fn run(sender: Sender<Event>, receiver: Receiver<Event>) {
  17. let setup_sender = sender.clone();
  18. let menu_sender = sender.clone();
  19. let tray_sender = sender.clone();
  20. let menu = Menu::new()
  21. .add_submenu(Submenu::new(
  22. "Service",
  23. Menu::new()
  24. .add_item(CustomMenuItem::new("restart", "Restart"))
  25. .add_native_item(MenuItem::Separator)
  26. .add_item(CustomMenuItem::new("start", "Start"))
  27. .add_item(CustomMenuItem::new("stop", "Stop")),
  28. ))
  29. .add_submenu(Submenu::new(
  30. "Logs",
  31. Menu::new()
  32. .add_item(CustomMenuItem::new("hbbs.out", "hbbs.out"))
  33. .add_item(CustomMenuItem::new("hbbs.err", "hbbs.err"))
  34. .add_native_item(MenuItem::Separator)
  35. .add_item(CustomMenuItem::new("hbbr.out", "hbbr.out"))
  36. .add_item(CustomMenuItem::new("hbbr.err", "hbbr.err")),
  37. ))
  38. .add_submenu(Submenu::new(
  39. "Configuration",
  40. Menu::new().add_item(CustomMenuItem::new(".env", ".env")),
  41. ));
  42. let tray = SystemTray::new().with_menu(
  43. SystemTrayMenu::new()
  44. .add_item(CustomMenuItem::new("restart", "Restart"))
  45. .add_native_item(SystemTrayMenuItem::Separator)
  46. .add_item(CustomMenuItem::new("start", "Start"))
  47. .add_item(CustomMenuItem::new("stop", "Stop"))
  48. .add_native_item(SystemTrayMenuItem::Separator)
  49. .add_item(CustomMenuItem::new("exit", "Exit GUI")),
  50. );
  51. let mut app = tauri::Builder::default()
  52. .on_window_event(|event| match event.event() {
  53. // WindowEvent::Resized(size) => {
  54. // if size.width == 0 && size.height == 0 {
  55. // event.window().hide().unwrap();
  56. // }
  57. // }
  58. WindowEvent::CloseRequested { api, .. } => {
  59. api.prevent_close();
  60. event.window().minimize().unwrap();
  61. event.window().hide().unwrap();
  62. }
  63. _ => {}
  64. })
  65. .menu(menu)
  66. .on_menu_event(move |event| {
  67. // println!(
  68. // "send {}: {}",
  69. // std::time::SystemTime::now()
  70. // .duration_since(std::time::UNIX_EPOCH)
  71. // .unwrap_or_default()
  72. // .as_millis(),
  73. // event.menu_item_id()
  74. // );
  75. menu_sender
  76. .send(Event::ViewAction(event.menu_item_id().to_owned()))
  77. .unwrap_or_default()
  78. })
  79. .system_tray(tray)
  80. .on_system_tray_event(move |app, event| match event {
  81. SystemTrayEvent::LeftClick { .. } => {
  82. let main = app.get_window("main").unwrap();
  83. if main.is_visible().unwrap() {
  84. main.hide().unwrap();
  85. } else {
  86. main.show().unwrap();
  87. main.unminimize().unwrap();
  88. main.set_focus().unwrap();
  89. }
  90. }
  91. SystemTrayEvent::MenuItemClick { id, .. } => {
  92. tray_sender.send(Event::ViewAction(id)).unwrap_or_default();
  93. }
  94. _ => {}
  95. })
  96. .setup(move |app| {
  97. setup_sender.send(Event::ViewInit).unwrap_or_default();
  98. app.listen_global("__action__", move |msg| {
  99. match msg.payload().unwrap_or_default() {
  100. r#""__init__""# => setup_sender.send(Event::BroswerInit).unwrap_or_default(),
  101. r#""restart""# => setup_sender
  102. .send(Event::BrowserAction("restart".to_owned()))
  103. .unwrap_or_default(),
  104. _ => (),
  105. }
  106. });
  107. Ok(())
  108. })
  109. .invoke_handler(tauri::generate_handler![root])
  110. .build(tauri::generate_context!())
  111. .expect("error while running tauri application");
  112. let mut now = Instant::now();
  113. let mut blink = false;
  114. let mut span = 0;
  115. let mut title = "".to_owned();
  116. let product = "RustDesk Server";
  117. let buffer = BUFFER.get().unwrap().to_owned();
  118. loop {
  119. for _ in 1..buffer {
  120. match receiver.recv_timeout(Duration::from_nanos(1)) {
  121. Ok(event) => {
  122. let main = app.get_window("main").unwrap();
  123. let menu = main.menu_handle();
  124. let tray = app.tray_handle();
  125. match event {
  126. Event::BrowserUpdate((action, data)) => match action.as_str() {
  127. "file" => {
  128. let list = ["hbbs.out", "hbbs.err", "hbbr.out", "hbbr.err", ".env"];
  129. let id = data.as_str();
  130. if list.contains(&id) {
  131. for file in list {
  132. menu.get_item(file)
  133. .set_selected(file == id)
  134. .unwrap_or_default();
  135. }
  136. // println!(
  137. // "emit {}: {}",
  138. // std::time::SystemTime::now()
  139. // .duration_since(std::time::UNIX_EPOCH)
  140. // .unwrap_or_default()
  141. // .as_millis(),
  142. // data
  143. // );
  144. app.emit_all("__update__", (action, data))
  145. .unwrap_or_default();
  146. }
  147. }
  148. _ => (),
  149. },
  150. Event::ViewRenderAppExit => exit(0),
  151. Event::ViewRenderServiceState(state) => {
  152. let enabled = |id, enabled| {
  153. menu.get_item(id).set_enabled(enabled).unwrap_or_default();
  154. tray.get_item(id).set_enabled(enabled).unwrap_or_default();
  155. };
  156. title = format!("{} {:?}", product, state);
  157. main.set_title(title.as_str()).unwrap_or_default();
  158. match state {
  159. DesktopServiceState::Started => {
  160. enabled("start", false);
  161. enabled("stop", true);
  162. enabled("restart", true);
  163. blink = false;
  164. }
  165. DesktopServiceState::Stopped => {
  166. enabled("start", true);
  167. enabled("stop", false);
  168. enabled("restart", false);
  169. blink = true;
  170. }
  171. _ => {
  172. enabled("start", false);
  173. enabled("stop", false);
  174. enabled("restart", false);
  175. blink = true;
  176. }
  177. }
  178. }
  179. _ => (),
  180. }
  181. }
  182. Err(_) => break,
  183. }
  184. }
  185. let elapsed = now.elapsed().as_micros();
  186. if elapsed > 16666 {
  187. now = Instant::now();
  188. // println!("{}ms", elapsed as f64 * 0.001);
  189. let iteration = app.run_iteration();
  190. if iteration.window_count == 0 {
  191. break;
  192. }
  193. if blink {
  194. if span > 1000000 {
  195. span = 0;
  196. app.get_window("main")
  197. .unwrap()
  198. .set_title(title.as_str())
  199. .unwrap_or_default();
  200. } else {
  201. span += elapsed;
  202. if span > 500000 {
  203. app.get_window("main")
  204. .unwrap()
  205. .set_title(product)
  206. .unwrap_or_default();
  207. }
  208. }
  209. }
  210. } else {
  211. sleep(Duration::from_micros(999)).await;
  212. }
  213. }
  214. }
  215. #[tauri::command]
  216. fn root() -> String {
  217. path().to_str().unwrap_or_default().to_owned()
  218. }