diff --git a/package-lock.json b/package-lock.json index fcd83ce..41b2c99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@tailwindcss/vite": "^4.3.0", "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2.7.1", + "@tauri-apps/plugin-log": "^2.8.0", "@tauri-apps/plugin-notification": "^2.3.3", "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-store": "^2.4.3", @@ -924,6 +925,15 @@ "@tauri-apps/api": "^2.11.0" } }, + "node_modules/@tauri-apps/plugin-log": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-log/-/plugin-log-2.8.0.tgz", + "integrity": "sha512-a+7rOq3MJwpTOLLKbL8d0qGZ85hgHw5pNOWusA9o3cf7cEgtYHiGY/+O8fj8MvywQIGqFv0da2bYQDlrqLE7rw==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.8.0" + } + }, "node_modules/@tauri-apps/plugin-notification": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.3.3.tgz", diff --git a/package.json b/package.json index 21c4fe5..371157f 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@tailwindcss/vite": "^4.3.0", "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2.7.1", + "@tauri-apps/plugin-log": "^2.8.0", "@tauri-apps/plugin-notification": "^2.3.3", "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-store": "^2.4.3", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fba5874..51bd4f3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -8,6 +8,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.6.10" @@ -41,6 +52,23 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log 0.4.32", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -56,6 +84,12 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "async-broadcast" version = "0.7.2" @@ -316,6 +350,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block" version = "0.1.6" @@ -353,6 +399,30 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "brotli" version = "8.0.4" @@ -389,6 +459,40 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byte-unit" +version = "5.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bcaa4a0975bed4a760af3efe4368825098ce5f9d37a30c5a021d635dc63d8f" +dependencies = [ + "rust_decimal", + "schemars 1.2.1", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytemuck" version = "1.25.0" @@ -526,6 +630,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.45" @@ -1137,6 +1247,16 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log 0.4.32", + "regex 1.12.4", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1200,6 +1320,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log 0.4.32", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -1227,6 +1356,7 @@ dependencies = [ "hmac", "keepawake", "keyring", + "log 0.4.32", "objc", "regex 1.12.4", "reqwest 0.12.28", @@ -1241,6 +1371,7 @@ dependencies = [ "tauri-build", "tauri-plugin-deep-link", "tauri-plugin-dialog", + "tauri-plugin-log", "tauri-plugin-notification", "tauri-plugin-opener", "tauri-plugin-shell", @@ -1335,6 +1466,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-channel" version = "0.3.32" @@ -1751,6 +1888,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" @@ -2427,6 +2567,9 @@ name = "log" version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +dependencies = [ + "value-bag", +] [[package]] name = "mac-notification-sys" @@ -2670,6 +2813,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc" version = "0.2.7" @@ -3302,6 +3454,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "pxfm" version = "0.1.29" @@ -3353,14 +3525,41 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -3370,7 +3569,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", ] [[package]] @@ -3479,6 +3687,15 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.12.28" @@ -3594,6 +3811,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rust-ini" version = "0.21.3" @@ -3604,6 +3850,23 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rust_decimal" +version = "1.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be2a24f50780bc85f09cc6ac299bdf1424302742d77221106859c9d8b102126a" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.6", + "rkyv", + "serde", + "serde_json", + "wasm-bindgen", +] + [[package]] name = "rustc-hash" version = "2.1.2" @@ -3752,6 +4015,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "security-framework" version = "3.7.0" @@ -4061,6 +4330,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.3" @@ -4197,6 +4472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] @@ -4353,6 +4629,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.12.16" @@ -4552,6 +4834,28 @@ dependencies = [ "url", ] +[[package]] +name = "tauri-plugin-log" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7545bd67f070a4500432c826e2e0682146a1d6712aee22a2786490156b574d93" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log 0.4.32", + "objc2", + "objc2-foundation", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.18", + "time", +] + [[package]] name = "tauri-plugin-notification" version = "2.3.3" @@ -4560,7 +4864,7 @@ checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc" dependencies = [ "log 0.4.32", "notify-rust", - "rand", + "rand 0.9.4", "serde", "serde_json", "serde_repr", @@ -4846,7 +5150,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" dependencies = [ "deranged", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -5235,7 +5541,7 @@ dependencies = [ "http", "httparse", "log 0.4.32", - "rand", + "rand 0.9.4", "sha1", "thiserror 2.0.18", ] @@ -5371,6 +5677,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" +[[package]] +name = "utf8-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -5389,6 +5701,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "vcpkg" version = "0.2.15" @@ -6381,6 +6699,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11" version = "2.21.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b806e25..2da28a2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -54,6 +54,8 @@ futures-util = { version = "0.3.32", features = ["sink"] } chrono = "0.4.38" url = "2" tauri-plugin-store = "2.4.3" +log = "0.4.32" +tauri-plugin-log = "2" [target.'cfg(target_os = "macos")'.dependencies] cocoa = "0.25" objc = "0.2.7" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index f255937..24f147c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -866,6 +866,7 @@ pub(crate) async fn start_media_download_internal( cmd = cmd.arg("--").arg(&url); let (mut rx, child) = cmd.spawn().map_err(|e| format!("Failed to spawn yt-dlp: {}", e))?; + log::info!("yt-dlp successfully spawned for id: {}", id); // yt-dlp parsing regex static PCT_RE: std::sync::OnceLock = std::sync::OnceLock::new(); @@ -932,21 +933,26 @@ pub(crate) async fn start_media_download_internal( } } } - Some(tauri_plugin_shell::process::CommandEvent::Stderr(_line_bytes)) => { - // Consume stderr to avoid blocking + Some(tauri_plugin_shell::process::CommandEvent::Stderr(line_bytes)) => { + let line = String::from_utf8_lossy(&line_bytes); + let lower = line.to_lowercase(); + if lower.contains("error") || lower.contains("critical") { + log::error!("yt-dlp stderr [{}]: {}", id, line.trim()); + } } Some(tauri_plugin_shell::process::CommandEvent::Error(err)) => { - eprintln!("yt-dlp shell error: {}", err); + log::error!("yt-dlp shell error [{}]: {}", id, err); let _ = app_handle.emit("download-failed", id.to_string()); break; } Some(tauri_plugin_shell::process::CommandEvent::Terminated(payload)) => { - println!("child exit status: {:?}", payload.code); if payload.code == Some(0) { + log::info!("yt-dlp completed successfully for id: {}", id); let _ = app_handle.emit("download-complete", id.to_string()); use tauri_plugin_notification::NotificationExt; let _ = app_handle.notification().builder().title("Download Complete").body(&safe_filename).show(); } else { + log::error!("yt-dlp exited with non-zero code {:?} for id: {}", payload.code, id); let _ = app_handle.emit("download-failed", id.to_string()); } break; @@ -1469,23 +1475,53 @@ pub fn run() { cmd = cmd.arg(format!("--max-overall-download-limit={}", global_speed_limit)); } - cmd.spawn() - .map(|(_, child)| child) - .ok() + match cmd.spawn() { + Ok((mut rx, child)) => { + log::info!("aria2c spawned successfully on port {}", aria2_port); + tauri::async_runtime::spawn(async move { + while let Some(event) = rx.recv().await { + match event { + tauri_plugin_shell::process::CommandEvent::Stderr(bytes) => { + let line = String::from_utf8_lossy(&bytes); + let lower = line.to_lowercase(); + if lower.contains("error") || lower.contains("critical") { + log::error!("aria2c stderr: {}", line.trim()); + } + } + tauri_plugin_shell::process::CommandEvent::Error(err) => { + log::error!("aria2c process error: {}", err); + } + tauri_plugin_shell::process::CommandEvent::Terminated(payload) => { + if payload.code == Some(0) { + log::info!("aria2c completed successfully"); + } else { + log::error!("aria2c exited with non-zero code: {:?}", payload.code); + } + } + _ => {} + } + } + }); + Some(child) + } + Err(e) => { + log::error!("Failed to spawn aria2c: {}", e); + None + } + } } Err(e) => { - eprintln!("Failed to create aria2c sidecar: {}", e); + log::error!("Failed to create aria2c sidecar: {}", e); None } }; match aria2_process { Some(process) => { - println!("Spawned global aria2c daemon on port {}", aria2_port); let guard = app.state::(); *guard.0.lock().unwrap() = Some(process); } - None => eprintln!("Failed to spawn aria2c daemon"), + None => log::error!("Failed to spawn aria2c daemon"), } let app_handle_ws = app.handle().clone(); @@ -1597,6 +1633,16 @@ pub fn run() { }); Ok(()) }) + .plugin( + tauri_plugin_log::Builder::new() + .targets([ + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Stdout), + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::LogDir { file_name: None }), + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Webview), + ]) + .level(if cfg!(debug_assertions) { log::LevelFilter::Debug } else { log::LevelFilter::Info }) + .build(), + ) .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_shell::init()) diff --git a/src/ipc.ts b/src/ipc.ts index 6319877..c901510 100644 --- a/src/ipc.ts +++ b/src/ipc.ts @@ -1,4 +1,5 @@ import { invoke as tauriInvoke } from '@tauri-apps/api/core'; +import { error as logError } from '@tauri-apps/plugin-log'; import { listen as tauriListen, type Event, type EventCallback, type UnlistenFn } from '@tauri-apps/api/event'; import type { DownloadCategory } from './bindings/DownloadCategory'; import type { DownloadProgressEvent } from './bindings/DownloadProgressEvent'; @@ -104,7 +105,10 @@ export function invokeCommand( command: K, ...args: CommandArgs extends undefined ? [] : [args: CommandArgs] ): Promise> { - return tauriInvoke>(command, args[0]); + return tauriInvoke>(command, args[0]).catch(err => { + logError(`Invoke command ${command} failed: ${err}`); + throw err; + }); } type EventMap = { diff --git a/src/store/settingsStore.ts b/src/store/settingsStore.ts index 16558eb..58944de 100644 --- a/src/store/settingsStore.ts +++ b/src/store/settingsStore.ts @@ -1,6 +1,7 @@ import { create } from 'zustand'; import { persist, createJSONStorage, StateStorage } from 'zustand/middleware'; import { LazyStore } from '@tauri-apps/plugin-store'; +import { info } from '@tauri-apps/plugin-log'; export const tauriStore = new LazyStore('store.bin'); @@ -49,9 +50,18 @@ export const useSettingsStore = create()( globalSpeedLimit: 0, concurrentDownloads: 3, - setDefaultDownloadPath: (path) => set({ defaultDownloadPath: path }), - setGlobalSpeedLimit: (limit) => set({ globalSpeedLimit: limit }), - setConcurrentDownloads: (count) => set({ concurrentDownloads: count }), + setDefaultDownloadPath: (path) => { + info(`Settings updated: defaultDownloadPath = ${path}`); + set({ defaultDownloadPath: path }); + }, + setGlobalSpeedLimit: (limit) => { + info(`Settings updated: globalSpeedLimit = ${limit}`); + set({ globalSpeedLimit: limit }); + }, + setConcurrentDownloads: (count) => { + info(`Settings updated: concurrentDownloads = ${count}`); + set({ concurrentDownloads: count }); + }, }), { name: 'firelink-engine-settings', diff --git a/src/store/useDownloadStore.ts b/src/store/useDownloadStore.ts index 5b535b1..f89e8eb 100644 --- a/src/store/useDownloadStore.ts +++ b/src/store/useDownloadStore.ts @@ -1,5 +1,6 @@ import { create } from 'zustand'; import { LazyStore } from '@tauri-apps/plugin-store'; +import { info } from '@tauri-apps/plugin-log'; import { invokeCommand as invoke } from '../ipc'; export const tauriStore = new LazyStore('store.bin'); @@ -140,7 +141,7 @@ export const useDownloadStore = create((set, get) => ({ }, setSelectedPropertiesDownloadId: (id) => set({ selectedPropertiesDownloadId: id }), addDownload: (item) => { - set((state) => ({ downloads: [...state.downloads, item] })); + info(`Download ${item.id} added to queue`); set((state) => ({ downloads: [...state.downloads, item] })); get().processQueue(); }, @@ -161,9 +162,11 @@ export const useDownloadStore = create((set, get) => ({ // If status changed to something that frees up a slot, process queue if (updates.status && ['completed', 'failed', 'paused'].includes(updates.status)) { + info(`Download ${id} status changed to ${updates.status}`); get().processQueue(); syncSystemIntegrations(); } else if (updates.status === 'downloading') { + info(`Download ${id} status changed to downloading`); syncSystemIntegrations(); } }, @@ -187,6 +190,7 @@ export const useDownloadStore = create((set, get) => ({ set((state) => ({ downloads: state.downloads.filter(d => d.id !== id) })); + info(`Download ${id} removed`); get().processQueue(); syncSystemIntegrations(); }, @@ -207,6 +211,7 @@ export const useDownloadStore = create((set, get) => ({ if (wasDownloading) { invoke('pause_download', { id }).catch(console.error); } + info(`Download ${id} redownload requested (queued)`); get().processQueue(); }, startQueue: async (queueId) => { @@ -224,6 +229,7 @@ export const useDownloadStore = create((set, get) => ({ ) })); + info(`Queue ${queueId} started, ${runnableIds.length} items queued`); await get().processQueue(); return runnableIds.length; }, @@ -242,6 +248,7 @@ export const useDownloadStore = create((set, get) => ({ ) })); + info(`Queue ${queueId} paused, ${activeIds.length} items paused`); await Promise.all(activeIds.map(id => invoke('pause_download', { id }).catch(() => {}))); syncSystemIntegrations(); return activeIds.length; diff --git a/src/store/useSettingsStore.ts b/src/store/useSettingsStore.ts index 103e2dc..770de46 100644 --- a/src/store/useSettingsStore.ts +++ b/src/store/useSettingsStore.ts @@ -1,6 +1,7 @@ import { create } from 'zustand'; import { persist, createJSONStorage, StateStorage } from 'zustand/middleware'; import { invokeCommand as invoke } from '../ipc'; +import { info } from '@tauri-apps/plugin-log'; import type { ActiveView } from '../bindings/ActiveView'; import type { AppFontSize } from '../bindings/AppFontSize'; import type { ListRowDensity } from '../bindings/ListRowDensity'; @@ -232,12 +233,14 @@ export const useSettingsStore = create()( extensionPairingToken: generateSecureToken(), autoCheckUpdates: true, - setTheme: (theme) => set({ theme }), - setDefaultDownloadPath: (path) => set({ defaultDownloadPath: path }), + setTheme: (theme) => { info('Settings updated: theme'); set({ theme }); }, + setDefaultDownloadPath: (path) => { info('Settings updated: defaultDownloadPath'); set({ defaultDownloadPath: path }); }, setMaxConcurrentDownloads: (max) => { + info('Settings updated: maxConcurrentDownloads'); set({ maxConcurrentDownloads: max }); }, setGlobalSpeedLimit: (limit) => { + info('Settings updated: globalSpeedLimit'); set({ globalSpeedLimit: limit }); }, setActiveView: (view) => set({ activeView: view }), @@ -266,14 +269,18 @@ export const useSettingsStore = create()( setCustomUserAgent: (customUserAgent) => set({ customUserAgent }), setAskWhereToSaveEachFile: (askWhereToSaveEachFile) => set({ askWhereToSaveEachFile }), setPreventsSleepWhileDownloading: (preventsSleepWhileDownloading) => { + info('Settings updated: preventsSleepWhileDownloading'); set({ preventsSleepWhileDownloading }); if (!preventsSleepWhileDownloading) invoke('set_prevent_sleep', { prevent: false }).catch(console.error); }, - setMediaCookieSource: (mediaCookieSource) => set({ mediaCookieSource }), - setCategoryDirectory: (category, path) => set((state) => ({ - downloadDirectories: { ...state.downloadDirectories, [category]: path } - })), - resetCategoryDirectories: () => set({ downloadDirectories: { ...defaultDirectories } }), + setMediaCookieSource: (mediaCookieSource) => { info('Settings updated: mediaCookieSource'); set({ mediaCookieSource }); }, + setCategoryDirectory: (category, path) => { + info(`Settings updated: category directory ${category}`); + set((state) => ({ + downloadDirectories: { ...state.downloadDirectories, [category]: path } + })); + }, + resetCategoryDirectories: () => { info('Settings updated: resetCategoryDirectories'); set({ downloadDirectories: { ...defaultDirectories } }); }, addSiteLogin: (login) => set((state) => ({ siteLogins: [...state.siteLogins, login] })),