diff --git a/Cargo.lock b/Cargo.lock index 79689f77..a25761b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,12 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + [[package]] name = "async-broadcast" version = "0.5.1" @@ -2379,6 +2385,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -2732,6 +2747,29 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "native-dialog" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e7038885d2aeab236bd60da9e159a5967b47cde3292da3b15ff1bec27c039f" +dependencies = [ + "ascii", + "block", + "cocoa 0.25.0", + "core-foundation", + "dirs-next", + "objc", + "objc-foundation", + "objc_id", + "once_cell", + "raw-window-handle", + "thiserror", + "versions", + "wfd", + "which", + "winapi", +] + [[package]] name = "ndk" version = "0.6.0" @@ -5133,6 +5171,7 @@ dependencies = [ "dirs", "futures", "lazy_static", + "native-dialog", "objc", "once_cell", "opener", @@ -5665,6 +5704,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "versions" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c73a36bc44e3039f51fbee93e39f41225f6b17b380eb70cc2aab942df06b34dd" +dependencies = [ + "itertools", + "nom", +] + [[package]] name = "void" version = "1.0.2" @@ -5935,6 +5984,28 @@ dependencies = [ "windows-metadata", ] +[[package]] +name = "wfd" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e713040b67aae5bf1a0ae3e1ebba8cc29ab2b90da9aa1bff6e09031a8a41d7a8" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.34", +] + [[package]] name = "whoami" version = "1.5.1" diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 5c0c095c..819ddaf7 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -126,6 +126,7 @@ initialize_state() }) const handleClose = async () => { + await saveWindowState(StateFlags.ALL) await TauriWindow.getCurrent().close() } @@ -293,16 +294,7 @@ async function handleCommand(e) { - diff --git a/apps/app/Cargo.toml b/apps/app/Cargo.toml index 3dfc03ae..9f78db9d 100644 --- a/apps/app/Cargo.toml +++ b/apps/app/Cargo.toml @@ -48,6 +48,8 @@ paste = "1.0.15" opener = { version = "0.7.2", features = ["reveal", "dbus-vendored"] } +native-dialog = "0.7.0" + [target.'cfg(not(target_os = "linux"))'.dependencies] window-shadows = "0.2.1" diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs index 8d013197..f6084cc4 100644 --- a/apps/app/src/main.rs +++ b/apps/app/src/main.rs @@ -3,7 +3,9 @@ windows_subsystem = "windows" )] +use native_dialog::{MessageDialog, MessageType}; use tauri::{Manager, PhysicalSize}; +use tauri_plugin_window_state::{StateFlags, WindowExt}; use theseus::prelude::*; mod api; @@ -31,15 +33,28 @@ async fn initialize_state(app: tauri::AppHandle) -> api::Result<()> { #[tauri::command] fn show_window(app: tauri::AppHandle) { let win = app.get_window("main").unwrap(); - win.show().unwrap(); - win.set_focus().unwrap(); + if let Err(e) = win.show() { + MessageDialog::new() + .set_type(MessageType::Error) + .set_title("Initialization error") + .set_text(&format!( + "Cannot display application window due to an error:\n{}", + e + )) + .show_alert() + .unwrap(); + panic!("cannot display application window") + } else { + let _ = win.restore_state(StateFlags::all()); + let _ = win.set_focus(); - // fix issue where window shows as extremely small - if let Ok(size) = win.inner_size() { - let width = if size.width < 1100 { 1280 } else { size.width }; - let height = if size.height < 700 { 800 } else { size.height }; + // fix issue where window shows as extremely small + if let Ok(size) = win.inner_size() { + let width = if size.width < 1100 { 1280 } else { size.width }; + let height = if size.height < 700 { 800 } else { size.height }; - win.set_size(PhysicalSize::new(width, height)).unwrap(); + let _ = win.set_size(PhysicalSize::new(width, height)); + } } } @@ -160,7 +175,7 @@ fn main() { if let Some(window) = app.get_window("main") { // Hide window to prevent white flash on startup - window.hide().unwrap(); + let _ = window.hide(); #[cfg(not(target_os = "linux"))] { @@ -215,7 +230,34 @@ fn main() { show_window, ]); - builder - .run(tauri::generate_context!()) - .expect("error while running tauri application"); + if let Err(e) = builder.run(tauri::generate_context!()) { + #[cfg(target_os = "windows")] + { + // tauri doesn't expose runtime errors, so matching a string representation seems like the only solution + if format!("{:?}", e) + .contains("Runtime(CreateWebview(WebView2Error(WindowsError") + { + MessageDialog::new() + .set_type(MessageType::Error) + .set_title("Initialization error") + .set_text("Your Microsoft Edge WebView2 installation is corrupt.\n\nMicrosoft Edge WebView2 is required to run Modrinth App.\n\nLearn how to repair it at https://docs.modrinth.com/faq/app/webview2") + .show_alert() + .unwrap(); + + panic!("webview2 initialization failed") + } + } + + MessageDialog::new() + .set_type(MessageType::Error) + .set_title("Initialization error") + .set_text(&format!( + "Cannot initialize application due to an error:\n{:?}", + e + )) + .show_alert() + .unwrap(); + + panic!("{1}: {:?}", e, "error while running tauri application") + } } diff --git a/packages/app-lib/src/api/profile/mod.rs b/packages/app-lib/src/api/profile/mod.rs index 7def3a37..4ca41b50 100644 --- a/packages/app-lib/src/api/profile/mod.rs +++ b/packages/app-lib/src/api/profile/mod.rs @@ -515,7 +515,9 @@ pub async fn export_mrpack( let relative_path = pack_get_relative_path(&profile_base_path, &path)?; if packfile.files.iter().any(|f| f.path == relative_path) - || !included_candidates_set.contains(&relative_path) + || !included_candidates_set + .iter() + .any(|x| relative_path.starts_with(&**x)) { continue; }