feat: implement persistent rolling log system with tauri-plugin-log

This commit is contained in:
NimBold
2026-06-16 15:19:57 +03:30
parent 85cdabd72b
commit 4027ac39ab
9 changed files with 441 additions and 27 deletions
+10
View File
@@ -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",
+1
View File
@@ -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",
+332 -5
View File
@@ -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"
+2
View File
@@ -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"
+56 -10
View File
@@ -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<Regex> = 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::<Aria2DaemonGuard>();
*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())
+5 -1
View File
@@ -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<K extends CommandName>(
command: K,
...args: CommandArgs<K> extends undefined ? [] : [args: CommandArgs<K>]
): Promise<CommandResult<K>> {
return tauriInvoke<CommandResult<K>>(command, args[0]);
return tauriInvoke<CommandResult<K>>(command, args[0]).catch(err => {
logError(`Invoke command ${command} failed: ${err}`);
throw err;
});
}
type EventMap = {
+13 -3
View File
@@ -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<SettingsState>()(
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',
+8 -1
View File
@@ -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<DownloadState>((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<DownloadState>((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<DownloadState>((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<DownloadState>((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<DownloadState>((set, get) => ({
)
}));
info(`Queue ${queueId} started, ${runnableIds.length} items queued`);
await get().processQueue();
return runnableIds.length;
},
@@ -242,6 +248,7 @@ export const useDownloadStore = create<DownloadState>((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;
+14 -7
View File
@@ -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<SettingsState>()(
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<SettingsState>()(
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]
})),