diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5c9c929..ffea245 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -909,6 +909,7 @@ name = "cultivation" version = "1.1.1" dependencies = [ "anime-launcher-sdk", + "anyhow", "args", "cc", "ctrlc", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c6a0c6d..e79a83f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -23,6 +23,7 @@ registry = "1.2.1" sudo = "0.6.0" [target.'cfg(target_os = "linux")'.dependencies] +anyhow = "1.0.58" term-detect = "0.1.7" [dependencies] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 116a144..ab457f0 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -411,7 +411,6 @@ fn restart_grasscutter(_window: tauri::Window) { } } -#[cfg(windows)] #[tauri::command] fn enable_grasscutter_watcher(window: tauri::Window, process: String) { let grasscutter_name = process.clone(); @@ -472,13 +471,6 @@ fn enable_grasscutter_watcher(window: tauri::Window, process: String) { }); } -#[cfg(unix)] -#[tauri::command] -fn enable_grasscutter_watcher(_window: tauri::Window, _process: String) { - let gc_pid = Pid::from(696969); - *GC_PID.lock().unwrap() = gc_pid.into(); -} - #[tauri::command] async fn connect(port: u16, certificate_path: String) { // Log message to console. diff --git a/src-tauri/src/system_helpers.rs b/src-tauri/src/system_helpers.rs index d6bd1b4..4969395 100644 --- a/src-tauri/src/system_helpers.rs +++ b/src-tauri/src/system_helpers.rs @@ -1,8 +1,9 @@ use ini::Ini; -use std::ffi::OsStr; use std::path::PathBuf; use std::process::Command; +#[cfg(windows)] +use std::ffi::OsStr; #[cfg(windows)] use { registry::{Data, Hive, Security}, @@ -15,7 +16,7 @@ use crate::AAGL_THREAD; #[cfg(target_os = "linux")] use anime_launcher_sdk::genshin::game; #[cfg(target_os = "linux")] -use std::thread; +use std::{process::Stdio, thread}; #[cfg(target_os = "linux")] use term_detect::get_terminal; @@ -29,6 +30,29 @@ fn guess_user_terminal() -> String { "xterm".to_string() } +#[cfg(target_os = "linux")] +pub trait SpawnItsFineReally { + fn spawn_its_fine_really(&mut self, msg: &str) -> anyhow::Result<()>; +} + +#[cfg(target_os = "linux")] +impl SpawnItsFineReally for Command { + fn spawn_its_fine_really(&mut self, msg: &str) -> anyhow::Result<()> { + let res = self.status(); + let Ok(status) = res else { + let error = res.unwrap_err(); + println!("{}: {}", msg, &error); + return Err(error.into()); + }; + if !status.success() { + println!("{}: {}", msg, status); + Err(anyhow::anyhow!("{}: {}", msg, status)) + } else { + Ok(()) + } + } +} + #[tauri::command] pub fn run_program(path: String, args: Option) { // Without unwrap_or, this can crash when UAC prompt is denied @@ -326,9 +350,41 @@ pub fn service_status(service: String) -> bool { } } -#[cfg(unix)] +#[cfg(target_os = "linux")] +fn to_linux_service_name(service: &str) -> Option { + Some(format!( + "{}.service", + match service { + "MongoDB" => "mongod", + _ => return None, + } + )) +} + +#[cfg(target_os = "linux")] #[tauri::command] -pub fn service_status(_service: String) {} +pub fn service_status(service: String) -> bool { + // Change Windows service name into Linux service name + let service_lnx = to_linux_service_name(&service); + if service_lnx.is_none() { + return false; + } + let service_lnx = service_lnx.unwrap(); + let status = Command::new("systemctl") + .arg("is-active") + .arg(service_lnx) + .stdout(Stdio::null()) + .status(); + if status.is_err() { + return false; + } + let status = status.unwrap().success(); + if status { + status + } else { + start_service(service) + } +} #[cfg(windows)] #[tauri::command] @@ -349,10 +405,20 @@ pub fn start_service(service: String) -> bool { true } -#[cfg(unix)] +#[cfg(target_os = "linux")] #[tauri::command] -pub fn start_service(_service: String) { - let _started = OsStr::new("Started service!"); +pub fn start_service(service: String) -> bool { + println!("Starting service: {}", service); + let service_lnx = to_linux_service_name(&service); + if service_lnx.is_none() { + return false; + } + let service_lnx = service_lnx.unwrap(); + Command::new("systemctl") + .arg("start") + .arg(service_lnx) + .spawn_its_fine_really(&format!("Failed to stop service {}", service)) + .is_ok() } #[cfg(windows)] @@ -374,9 +440,21 @@ pub fn stop_service(service: String) -> bool { true } -#[cfg(unix)] +#[cfg(target_os = "linux")] #[tauri::command] -pub fn stop_service(_service: String) {} +pub fn stop_service(service: String) -> bool { + println!("Stopping service: {}", service); + let service_lnx = to_linux_service_name(&service); + if service_lnx.is_none() { + return false; + } + let service_lnx = service_lnx.unwrap(); + Command::new("systemctl") + .arg("stop") + .arg(service_lnx) + .spawn_its_fine_really(&format!("Failed to start service {}", service)) + .is_ok() +} #[cfg(unix)] #[tauri::command] diff --git a/src/ui/components/ServerLaunchSection.tsx b/src/ui/components/ServerLaunchSection.tsx index 55776c3..d8e0ccd 100644 --- a/src/ui/components/ServerLaunchSection.tsx +++ b/src/ui/components/ServerLaunchSection.tsx @@ -216,7 +216,7 @@ export default class ServerLaunchSection extends React.Component process: proc_name || grasscutter_jar, }) // Check if MongoDB is running and start it if not - await invoke('service_status', { service: 'MongoDB' }) + invoke('service_status', { service: 'MongoDB' }) } let jarFolder = config.grasscutter_path