diff --git a/Cargo.lock b/Cargo.lock index e7f8cf9..2bc480a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + [[package]] name = "ash" version = "0.37.3+1.3.251" @@ -609,6 +615,27 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -738,6 +765,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "expect-dialog" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d005d67f9ccc51caf22c692c250e175ef9f90a49cadd40799fbeeb7f421314" +dependencies = [ + "native-dialog", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -1522,6 +1558,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "native-dialog" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bbf55edb2747e4e4b3a9cd3989194b88aae32274b4422635dcf98aa6e84197b" +dependencies = [ + "ascii", + "block", + "cocoa", + "dirs-next", + "objc", + "objc-foundation", + "objc_id", + "once_cell", + "raw-window-handle 0.4.3", + "thiserror", + "wfd", + "which", + "winapi", +] + [[package]] name = "ndk" version = "0.7.0" @@ -2059,6 +2116,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "renderdoc-sys" version = "0.7.1" @@ -2069,6 +2137,7 @@ checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" name = "rex2" version = "0.1.0" dependencies = [ + "expect-dialog", "iced", "iced_aw", "nix 0.26.2", @@ -2669,6 +2738,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "wfd" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e713040b67aae5bf1a0ae3e1ebba8cc29ab2b90da9aa1bff6e09031a8a41d7a8" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "wgpu" version = "0.15.1" @@ -2781,6 +2860,17 @@ dependencies = [ "wgpu", ] +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "widestring" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index e35f7a6..1ba6a45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +expect-dialog = "1.0.0" iced = { version = "0.9.0", features = [ "smol" ] } diff --git a/src/depcheck.rs b/src/depcheck.rs index 077f0a0..219dc16 100644 --- a/src/depcheck.rs +++ b/src/depcheck.rs @@ -1,3 +1,4 @@ +use expect_dialog::ExpectDialog; use std::{env, fmt::Display, path::Path}; #[derive(Debug, Clone, PartialEq, Eq)] @@ -47,17 +48,14 @@ fn shared_obj_paths() -> Vec { } fn include_paths() -> Vec { - vec![ - "/usr/include".to_string(), - "/usr/local/include".to_string(), - ] + vec!["/usr/include".to_string(), "/usr/local/include".to_string()] } pub fn check_dependency(dep: Dependency) -> bool { for dir in match dep.dep_type { DepType::SharedObject => shared_obj_paths(), DepType::Executable => env::var("PATH") - .expect("PATH environment variable not defined") + .expect_dialog("PATH environment variable not defined") .split(':') .map(str::to_string) .collect(), diff --git a/src/file_builders/active_runtime_json.rs b/src/file_builders/active_runtime_json.rs index e6600ea..4e301ce 100644 --- a/src/file_builders/active_runtime_json.rs +++ b/src/file_builders/active_runtime_json.rs @@ -1,5 +1,6 @@ use std::{fs::File, io::BufReader, path::Path}; +use expect_dialog::ExpectDialog; use serde::{Deserialize, Serialize}; use crate::file_utils::{get_config_dir, get_writer}; @@ -37,9 +38,9 @@ fn get_active_runtime_from_path(path_s: String) -> Option { if !(path.is_file() || path.is_symlink()) { return None; } - let fd = File::open(path).expect("Unable to open active_runtime.json"); + let fd = File::open(path).expect_dialog("Unable to open active_runtime.json"); let reader = BufReader::new(fd); - Some(serde_json::from_reader(reader).expect("Failed to deserialize active_runtime.json")) + Some(serde_json::from_reader(reader).expect_dialog("Failed to deserialize active_runtime.json")) } pub fn get_current_active_runtime() -> Option { @@ -49,7 +50,7 @@ pub fn get_current_active_runtime() -> Option { fn dump_active_runtime_to_path(active_runtime: ActiveRuntime, path_s: String) { let writer = get_writer(&path_s); // TODO: deal with write protection - serde_json::to_writer_pretty(writer, &active_runtime).expect("Unable to save active runtime"); + serde_json::to_writer_pretty(writer, &active_runtime).expect_dialog("Unable to save active runtime"); } pub fn dump_current_active_runtime(active_runtime: ActiveRuntime) { diff --git a/src/file_builders/openvrpaths_vrpath.rs b/src/file_builders/openvrpaths_vrpath.rs index 2a64034..ca3d796 100644 --- a/src/file_builders/openvrpaths_vrpath.rs +++ b/src/file_builders/openvrpaths_vrpath.rs @@ -1,5 +1,6 @@ use std::{fs::File, io::BufReader, path::Path}; +use expect_dialog::ExpectDialog; use serde::{Deserialize, Serialize}; use crate::file_utils::{get_config_dir, get_writer}; @@ -37,9 +38,9 @@ fn get_openvrpaths_from_path(path_s: String) -> Option { if !(path.is_file() || path.is_symlink()) { return None; } - let fd = File::open(path).expect("Unable to open openvrpaths.vrpath"); + let fd = File::open(path).expect_dialog("Unable to open openvrpaths.vrpath"); let reader = BufReader::new(fd); - Some(serde_json::from_reader(reader).expect("Failed to deserialize openvrpaths.vrpath")) + Some(serde_json::from_reader(reader).expect_dialog("Failed to deserialize openvrpaths.vrpath")) } pub fn get_current_openvrpaths() -> Option { @@ -48,7 +49,7 @@ pub fn get_current_openvrpaths() -> Option { fn dump_openvrpaths_to_path(ovr_paths: OpenVrPaths, path_s: String) { let writer = get_writer(&path_s); - serde_json::to_writer_pretty(writer, &ovr_paths).expect("Unable to save openvrpaths"); + serde_json::to_writer_pretty(writer, &ovr_paths).expect_dialog("Unable to save openvrpaths"); } pub fn dump_current_openvrpaths(ovr_paths: OpenVrPaths) { diff --git a/src/file_utils.rs b/src/file_utils.rs index 45ea317..a0407ea 100644 --- a/src/file_utils.rs +++ b/src/file_utils.rs @@ -1,9 +1,12 @@ use std::{ + env, fs::{create_dir_all, OpenOptions}, io::BufWriter, - path::Path, env, + path::Path, }; +use expect_dialog::ExpectDialog; + use crate::constants::CMD_NAME; pub fn get_writer(path_s: &String) -> BufWriter { @@ -11,7 +14,7 @@ pub fn get_writer(path_s: &String) -> BufWriter { match path.parent() { Some(parent) => { if !parent.is_dir() { - create_dir_all(parent).expect("Could not create dir") + create_dir_all(parent).expect_dialog("Could not create dir") } } None => {} @@ -21,21 +24,17 @@ pub fn get_writer(path_s: &String) -> BufWriter { .create(true) .truncate(true) .open(path) - .expect("Could not open file"); + .expect_dialog("Could not open file"); BufWriter::new(file) } pub fn get_home_dir() -> String { - env::var("HOME").expect("HOME env var not defined") + env::var("HOME").expect_dialog("HOME env var not defined") } pub fn get_config_dir() -> String { match env::var("XDG_CONFIG_HOME") { - Ok(conf_home) => format!( - "{conf_home}/{name}", - conf_home = conf_home, - name = CMD_NAME - ), + Ok(conf_home) => format!("{conf_home}/{name}", conf_home = conf_home, name = CMD_NAME), Err(_) => format!( "{home}/.config/{name}", home = get_home_dir(), @@ -46,11 +45,7 @@ pub fn get_config_dir() -> String { pub fn get_data_dir() -> String { match env::var("XDG_DATA_HOME") { - Ok(data_home) => format!( - "{data_home}/{name}", - data_home = data_home, - name = CMD_NAME - ), + Ok(data_home) => format!("{data_home}/{name}", data_home = data_home, name = CMD_NAME), Err(_) => format!( "{home}/.local/share/{name}", home = get_home_dir(), diff --git a/src/main.rs b/src/main.rs index 9f805fd..a2307e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use expect_dialog::ExpectDialog; use iced::{Application, Settings}; use ui::main_win::MainWin; @@ -6,13 +7,13 @@ pub mod config; pub mod constants; pub mod depcheck; pub mod dependencies; +pub mod file_builders; pub mod file_utils; pub mod profile; pub mod profiles; pub mod runner; pub mod ui; -pub mod file_builders; fn main() { - MainWin::run(Settings::default()).expect("Application encountered an error"); + MainWin::run(Settings::default()).expect_dialog("Application encountered an error"); } diff --git a/src/profile.rs b/src/profile.rs index 5033393..1363432 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -1,10 +1,6 @@ +use expect_dialog::ExpectDialog; use serde::{Deserialize, Serialize}; -use std::{ - collections::HashMap, - fs::File, - io::BufReader, - fmt::Display, -}; +use std::{collections::HashMap, fmt::Display, fs::File, io::BufReader}; use crate::file_utils::get_writer; @@ -28,15 +24,15 @@ impl Display for Profile { } } -pub fn load_profile(path: &String) -> Result { - let file = File::open(path).unwrap(); +pub fn load_profile(path: &String) -> Profile { + let file = File::open(path).expect_dialog("Unable to open profile"); let reader = BufReader::new(file); - serde_json::from_reader(reader) + serde_json::from_reader(reader).expect_dialog("Faiuled to deserialize profile") } pub fn dump_profile(profile: Profile, path_s: &String) -> () { let writer = get_writer(path_s); - serde_json::to_writer_pretty(writer, &profile).expect("Could not write profile") + serde_json::to_writer_pretty(writer, &profile).expect_dialog("Could not write profile") } #[cfg(test)] @@ -48,39 +44,31 @@ mod tests { #[test] fn profile_can_be_loaded() { let profile = load_profile(&"./test/files/profile.json".to_string()); - match profile { - Ok(profile) => { - assert_eq!(profile.name, "Demo profile"); - assert_eq!(profile.monado_path, "/home/user/monado"); - assert_eq!(profile.openovr_path, "/home/user/openovr"); - assert_eq!( - profile.libsurvive_path.as_deref(), - Some("/home/user/libsurvive") - ); - assert_eq!(profile.mercury_path, None); - assert_eq!(profile.basalt_path, None); - assert_eq!(profile.libsurvive_enabled, true); - assert_eq!(profile.basalt_enabled, false); - assert_eq!(profile.mercury_enabled, false); - assert!(profile - .environment - .contains_key("XRT_COMPOSITOR_SCALE_PERCENTAGE")); - assert!(profile.environment.contains_key("XRT_COMPOSITOR_COMPUTE")); - assert!(profile - .environment - .contains_key("SURVIVE_GLOBALSCENESOLVER")); - } - Err(_) => assert!(false), - } + assert_eq!(profile.name, "Demo profile"); + assert_eq!(profile.monado_path, "/home/user/monado"); + assert_eq!(profile.openovr_path, "/home/user/openovr"); + assert_eq!( + profile.libsurvive_path.as_deref(), + Some("/home/user/libsurvive") + ); + assert_eq!(profile.mercury_path, None); + assert_eq!(profile.basalt_path, None); + assert_eq!(profile.libsurvive_enabled, true); + assert_eq!(profile.basalt_enabled, false); + assert_eq!(profile.mercury_enabled, false); + assert!(profile + .environment + .contains_key("XRT_COMPOSITOR_SCALE_PERCENTAGE")); + assert!(profile.environment.contains_key("XRT_COMPOSITOR_COMPUTE")); + assert!(profile + .environment + .contains_key("SURVIVE_GLOBALSCENESOLVER")); } #[test] fn profile_can_be_dumped() { let mut env = HashMap::new(); - env.insert( - "XRT_COMPOSITOR_SCALE_PERCENTAGE".into(), - "140".into(), - ); + env.insert("XRT_COMPOSITOR_SCALE_PERCENTAGE".into(), "140".into()); env.insert("XRT_COMPOSITOR_COMPUTE".into(), "1".into()); let p = Profile { name: "Demo profile".into(), @@ -96,7 +84,7 @@ mod tests { }; let fpath = String::from("./target/testout/testprofile.json"); dump_profile(p, &fpath); - let loaded = load_profile(&fpath).unwrap(); + let loaded = load_profile(&fpath); assert_eq!(loaded.name, "Demo profile"); assert_eq!( loaded.libsurvive_path, diff --git a/src/runner.rs b/src/runner.rs index 64d3b08..c9fcde8 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,3 +1,9 @@ +use crate::{file_utils::get_writer, profile::Profile}; +use expect_dialog::ExpectDialog; +use nix::{ + sys::signal::{kill, Signal::SIGTERM}, + unistd::Pid, +}; use std::{ collections::HashMap, io::{BufRead, BufReader, Write}, @@ -10,13 +16,6 @@ use std::{ vec, }; -use nix::{ - sys::signal::{kill, Signal::SIGTERM}, - unistd::Pid, -}; - -use crate::{file_utils::get_writer, profile::Profile}; - pub struct Runner { pub environment: HashMap, pub command: String, @@ -52,7 +51,7 @@ macro_rules! logger_thread { match $sender .clone() .lock() - .expect("Could not lock sender") + .expect_dialog("Could not lock sender") .send(buf) { Ok(_) => {} @@ -104,7 +103,7 @@ impl Runner { .stderr(Stdio::piped()) .stdout(Stdio::piped()) .spawn() - .expect("Failed to execute runner"), + .expect_dialog("Failed to execute runner"), ); let stdout = self.process.as_mut().unwrap().stdout.take().unwrap(); let stderr = self.process.as_mut().unwrap().stderr.take().unwrap(); @@ -123,15 +122,19 @@ impl Runner { return; } let mut proc = process.unwrap(); - let child_pid = Pid::from_raw(proc.id().try_into().expect("Could not convert pid to u32")); - kill(child_pid, SIGTERM).expect("Could not send sigterm to process"); + let child_pid = Pid::from_raw( + proc.id() + .try_into() + .expect_dialog("Could not convert pid to u32"), + ); + kill(child_pid, SIGTERM).expect_dialog("Could not send sigterm to process"); loop { match self.threads.pop() { None => break, - Some(thread) => thread.join().expect("Failed to join reader thread"), + Some(thread) => thread.join().expect_dialog("Failed to join reader thread"), } } - proc.wait().expect("Failed to wait for process"); + proc.wait().expect_dialog("Failed to wait for process"); } pub fn status(&mut self) -> RunnerStatus { @@ -211,7 +214,7 @@ mod tests { #[test] fn can_create_from_profile() { Runner::monado_runner_from_profile( - load_profile(&"./test/files/profile.json".to_string()).unwrap(), + load_profile(&"./test/files/profile.json".to_string()), ); } } diff --git a/src/ui/main_win.rs b/src/ui/main_win.rs index 92e1d13..faa96d0 100644 --- a/src/ui/main_win.rs +++ b/src/ui/main_win.rs @@ -8,6 +8,7 @@ use crate::{ runner::{Runner, RunnerStatus}, ui::widgets::widgets::vseparator, }; +use expect_dialog::ExpectDialog; use iced::{ executor, theme::{Button, Container}, @@ -140,7 +141,7 @@ impl Application for MainWin { Message::ProfileChanged(profile) => { if self.config.selected_profile_name != profile.name { self.config.selected_profile_name = profile.name; - save_config(&self.config).expect("Failed to save config"); + save_config(&self.config).expect_dialog("Failed to save config"); } } Message::EditProfile => { @@ -148,7 +149,7 @@ impl Application for MainWin { } Message::DebugViewChanged(nval) => { self.config.debug_view_enabled = nval; - save_config(&self.config).expect("Failed to save config"); + save_config(&self.config).expect_dialog("Failed to save config"); } Message::DebugSearchChanged(term) => self.debug_search_term = term, Message::InstallMonado => {