diff options
author | elilchen <[email protected]> | 2023-02-12 00:48:38 +0800 |
---|---|---|
committer | elilchen <[email protected]> | 2023-02-12 00:48:38 +0800 |
commit | 7a0e300ff9d5190a31b49155df51dde5c0db2a29 (patch) | |
tree | 064916b7e8c0eb78f012cbcfbfa61567ebc32ada /ui/src/adapter | |
parent | b2f381913df6583f215e50faa28dc5e1333d40e6 (diff) | |
download | rustdesk-server-7a0e300ff9d5190a31b49155df51dde5c0db2a29.tar.gz rustdesk-server-7a0e300ff9d5190a31b49155df51dde5c0db2a29.zip |
UI
Diffstat (limited to 'ui/src/adapter')
-rw-r--r-- | ui/src/adapter/mod.rs | 5 | ||||
-rw-r--r-- | ui/src/adapter/service/mod.rs | 3 | ||||
-rw-r--r-- | ui/src/adapter/service/windows.rs | 130 | ||||
-rw-r--r-- | ui/src/adapter/view/desktop.rs | 220 | ||||
-rw-r--r-- | ui/src/adapter/view/mod.rs | 3 |
5 files changed, 361 insertions, 0 deletions
diff --git a/ui/src/adapter/mod.rs b/ui/src/adapter/mod.rs new file mode 100644 index 0000000..a8a9a3c --- /dev/null +++ b/ui/src/adapter/mod.rs @@ -0,0 +1,5 @@ +pub mod view; +pub mod service; + +pub use view::*; +pub use service::*; diff --git a/ui/src/adapter/service/mod.rs b/ui/src/adapter/service/mod.rs new file mode 100644 index 0000000..b64742e --- /dev/null +++ b/ui/src/adapter/service/mod.rs @@ -0,0 +1,3 @@ +pub mod windows; + +pub use windows::*; diff --git a/ui/src/adapter/service/windows.rs b/ui/src/adapter/service/windows.rs new file mode 100644 index 0000000..3c1e9a8 --- /dev/null +++ b/ui/src/adapter/service/windows.rs @@ -0,0 +1,130 @@ +use std::{ffi::OsStr, process::Command}; + +use crate::{path, usecase::service::*}; +use derive_new::new; +use windows_service::{ + service::ServiceAccess, + service_manager::{ServiceManager, ServiceManagerAccess}, +}; + +#[derive(Debug, new)] +pub struct WindowsDesktopService { + #[new(value = "DesktopServiceState::Stopped")] + pub state: DesktopServiceState, +} + +impl IDesktopService for WindowsDesktopService { + fn start(&mut self) { + call( + [ + "echo.", + "%nssm% stop hbbr", + "%nssm% remove hbbr confirm", + "%nssm% stop hbbs", + "%nssm% remove hbbs confirm", + "mkdir logs", + "echo.", + "service\\run.cmd hbbs", + "echo.", + "service\\run.cmd hbbr", + "echo.", + "@ping 127.1 -n 3 >nul", + ] + .join(" & "), + ); + self.check(); + } + fn stop(&mut self) { + call( + [ + "echo.", + "%nssm% stop hbbr", + "%nssm% remove hbbr confirm", + "echo.", + "%nssm% stop hbbs", + "%nssm% remove hbbs confirm", + "echo.", + "@ping 127.1 -n 3 >nul", + ] + .join(" & "), + ); + self.check(); + } + fn restart(&mut self) { + nssm(["restart", "hbbs"].map(|x| x.to_owned())); + nssm(["restart", "hbbr"].map(|x| x.to_owned())); + self.check(); + } + fn pause(&mut self) { + call( + [ + "echo.", + "%nssm% stop hbbr", + "echo.", + "%nssm% stop hbbs", + "echo.", + "@ping 127.1 -n 3 >nul", + ] + .join(" & "), + ); + self.check(); + } + fn check(&mut self) -> DesktopServiceState { + self.state = match service_status("hbbs").as_str() { + "Running" => DesktopServiceState::Started, + // "Stopped" => DeskServerServiceState::Paused, + _ => DesktopServiceState::Stopped, + }; + self.state.to_owned() + } +} + +fn call(cmd: String) { + Command::new("cmd") + .current_dir(&path()) + .env("nssm", "service\\nssm.exe") + .arg("/c") + .arg("start") + .arg("cmd") + .arg("/c") + .arg(cmd) + .output() + .expect("cmd exec error!"); +} + +fn exec<I, S>(program: S, args: I) -> String +where + I: IntoIterator<Item = S>, + S: AsRef<OsStr>, +{ + match Command::new(program).args(args).output() { + Ok(out) => String::from_utf8(out.stdout).unwrap_or("".to_owned()), + Err(e) => e.to_string(), + } +} + +fn nssm<I>(args: I) -> String +where + I: IntoIterator<Item = String>, +{ + exec( + format!("{}\\service\\nssm.exe", path().to_str().unwrap_or_default()), + args, + ) + .replace("\0", "") + .trim() + .to_owned() +} + +fn service_status(name: &str) -> String { + match ServiceManager::local_computer(None::<&OsStr>, ServiceManagerAccess::CONNECT) { + Ok(manager) => match manager.open_service(name, ServiceAccess::QUERY_STATUS) { + Ok(service) => match service.query_status() { + Ok(status) => format!("{:?}", status.current_state), + Err(e) => e.to_string(), + }, + Err(e) => e.to_string(), + }, + Err(e) => e.to_string(), + } +} diff --git a/ui/src/adapter/view/desktop.rs b/ui/src/adapter/view/desktop.rs new file mode 100644 index 0000000..328d587 --- /dev/null +++ b/ui/src/adapter/view/desktop.rs @@ -0,0 +1,220 @@ +use std::{ + process::exit, + time::{Duration, Instant}, +}; + +use crate::{ + path, + usecase::{view::Event, DesktopServiceState}, + BUFFER, +}; +use async_std::task::sleep; +use crossbeam_channel::{Receiver, Sender}; +use tauri::{ + CustomMenuItem, Manager, Menu, MenuItem, Submenu, SystemTray, SystemTrayEvent, SystemTrayMenu, + SystemTrayMenuItem, WindowEvent, +}; + +pub async fn run(sender: Sender<Event>, receiver: Receiver<Event>) { + let setup_sender = sender.clone(); + let menu_sender = sender.clone(); + let tray_sender = sender.clone(); + let menu = Menu::new() + .add_submenu(Submenu::new( + "Service", + Menu::new() + .add_item(CustomMenuItem::new("restart", "Restart")) + .add_native_item(MenuItem::Separator) + .add_item(CustomMenuItem::new("start", "Start")) + .add_item(CustomMenuItem::new("stop", "Stop")), + )) + .add_submenu(Submenu::new( + "Logs", + Menu::new() + .add_item(CustomMenuItem::new("hbbs.out", "hbbs.out")) + .add_item(CustomMenuItem::new("hbbs.err", "hbbs.err")) + .add_native_item(MenuItem::Separator) + .add_item(CustomMenuItem::new("hbbr.out", "hbbr.out")) + .add_item(CustomMenuItem::new("hbbr.err", "hbbr.err")), + )) + .add_submenu(Submenu::new( + "Configuration", + Menu::new().add_item(CustomMenuItem::new(".env", ".env")), + )); + let tray = SystemTray::new().with_menu( + SystemTrayMenu::new() + .add_item(CustomMenuItem::new("restart", "Restart")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("start", "Start")) + .add_item(CustomMenuItem::new("stop", "Stop")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("exit", "Exit GUI")), + ); + let mut app = tauri::Builder::default() + .on_window_event(|event| match event.event() { + // WindowEvent::Resized(size) => { + // if size.width == 0 && size.height == 0 { + // event.window().hide().unwrap(); + // } + // } + WindowEvent::CloseRequested { api, .. } => { + api.prevent_close(); + event.window().hide().unwrap(); + } + _ => {} + }) + .menu(menu) + .on_menu_event(move |event| { + // println!( + // "send {}: {}", + // std::time::SystemTime::now() + // .duration_since(std::time::UNIX_EPOCH) + // .unwrap_or_default() + // .as_millis(), + // event.menu_item_id() + // ); + menu_sender + .send(Event::ViewAction(event.menu_item_id().to_owned())) + .unwrap_or_default() + }) + .system_tray(tray) + .on_system_tray_event(move |app, event| match event { + SystemTrayEvent::LeftClick { .. } => { + let main = app.get_window("main").unwrap(); + if main.is_visible().unwrap() { + main.hide().unwrap(); + } else { + main.show().unwrap(); + main.unminimize().unwrap(); + main.set_focus().unwrap(); + } + } + SystemTrayEvent::MenuItemClick { id, .. } => { + tray_sender.send(Event::ViewAction(id)).unwrap_or_default(); + } + _ => {} + }) + .setup(move |app| { + setup_sender.send(Event::ViewInit).unwrap_or_default(); + app.listen_global("__action__", move |msg| { + match msg.payload().unwrap_or_default() { + r#""__init__""# => setup_sender.send(Event::BroswerInit).unwrap_or_default(), + r#""restart""# => setup_sender + .send(Event::BrowserAction("restart".to_owned())) + .unwrap_or_default(), + _ => (), + } + }); + Ok(()) + }) + .invoke_handler(tauri::generate_handler![root]) + .build(tauri::generate_context!()) + .expect("error while running tauri application"); + let mut now = Instant::now(); + let mut blink = false; + let mut span = 0; + let mut title = "".to_owned(); + let product = "RustDesk Server"; + let buffer = BUFFER.get().unwrap().to_owned(); + loop { + for _ in 1..buffer { + match receiver.recv_timeout(Duration::from_nanos(1)) { + Ok(event) => { + let main = app.get_window("main").unwrap(); + let menu = main.menu_handle(); + let tray = app.tray_handle(); + match event { + Event::BrowserUpdate((action, data)) => match action.as_str() { + "file" => { + let list = ["hbbs.out", "hbbs.err", "hbbr.out", "hbbr.err", ".env"]; + let id = data.as_str(); + if list.contains(&id) { + for file in list { + menu.get_item(file) + .set_selected(file == id) + .unwrap_or_default(); + } + // println!( + // "emit {}: {}", + // std::time::SystemTime::now() + // .duration_since(std::time::UNIX_EPOCH) + // .unwrap_or_default() + // .as_millis(), + // data + // ); + app.emit_all("__update__", (action, data)) + .unwrap_or_default(); + } + } + _ => (), + }, + Event::ViewRenderAppExit => exit(0), + Event::ViewRenderServiceState(state) => { + let enabled = |id, enabled| { + menu.get_item(id).set_enabled(enabled).unwrap_or_default(); + tray.get_item(id).set_enabled(enabled).unwrap_or_default(); + }; + title = format!("{} {:?}", product, state); + main.set_title(title.as_str()).unwrap_or_default(); + match state { + DesktopServiceState::Started => { + enabled("start", false); + enabled("stop", true); + enabled("restart", true); + blink = false; + } + DesktopServiceState::Stopped => { + enabled("start", true); + enabled("stop", false); + enabled("restart", false); + blink = true; + } + _ => { + enabled("start", false); + enabled("stop", false); + enabled("restart", false); + blink = true; + } + } + } + _ => (), + } + } + Err(_) => break, + } + } + let elapsed = now.elapsed().as_micros(); + if elapsed > 16666 { + now = Instant::now(); + // println!("{}ms", elapsed as f64 * 0.001); + let iteration = app.run_iteration(); + if iteration.window_count == 0 { + break; + } + if blink { + if span > 1000000 { + span = 0; + app.get_window("main") + .unwrap() + .set_title(title.as_str()) + .unwrap_or_default(); + } else { + span += elapsed; + if span > 500000 { + app.get_window("main") + .unwrap() + .set_title(product) + .unwrap_or_default(); + } + } + } + } else { + sleep(Duration::from_micros(999)).await; + } + } +} + +#[tauri::command] +fn root() -> String { + path().to_str().unwrap_or_default().to_owned() +} diff --git a/ui/src/adapter/view/mod.rs b/ui/src/adapter/view/mod.rs new file mode 100644 index 0000000..8569296 --- /dev/null +++ b/ui/src/adapter/view/mod.rs @@ -0,0 +1,3 @@ +pub mod desktop; + +pub use desktop::*; |