diff --git a/Cargo.lock b/Cargo.lock index fdae39d..05a4fb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,6 +284,19 @@ dependencies = [ "yaml-rust2", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + [[package]] name = "const-random" version = "0.1.18" @@ -414,6 +427,12 @@ dependencies = [ "const-random", ] +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -902,6 +921,19 @@ dependencies = [ "hashbrown 0.16.1", ] +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -1100,6 +1132,7 @@ dependencies = [ "dirs", "fs_extra", "id3", + "indicatif", "mockito", "pathdiff", "reqwest", @@ -1133,6 +1166,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "once_cell" version = "1.21.3" @@ -1301,6 +1340,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "portable-atomic" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" + [[package]] name = "potential_utf" version = "0.1.4" @@ -2049,6 +2094,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "url" version = "2.5.7" @@ -2204,6 +2255,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi-util" version = "0.1.11" diff --git a/Cargo.toml b/Cargo.toml index 57533af..a166786 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,9 @@ pathdiff = "0.2" # CLI clap = { version = "4.0", features = ["derive"] } +# TUI Progress bars +indicatif = "0.17" + # ID3 tag parsing id3 = "1.13" diff --git a/src/lib.rs b/src/lib.rs index 0fcebff..e61297e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ pub mod sync; pub use config::Config; use clap::{Parser, Subcommand}; +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use std::sync::Arc; #[derive(Parser)] #[command(name = "navipod")] @@ -39,7 +41,46 @@ pub async fn run(config: Config) -> anyhow::Result<()> { match cli.command { Commands::Sync { album, artist } => { - sync::sync_content(config, album, artist).await?; + // Create multi-progress for TUI + let multi = MultiProgress::new(); + + // Main progress bar for overall sync + let pb = multi.add(ProgressBar::new(100)); + pb.set_style( + ProgressStyle::default_bar() + .template("{msg}\n{spinner:.green} [{bar:40.cyan/blue}] {pos}/{len} albums ({percent}%)") + .unwrap() + .progress_chars("█▓▒░ "), + ); + pb.set_message("Syncing albums..."); + + // Status line for current activity + let status_pb = multi.add(ProgressBar::new_spinner()); + status_pb.set_style( + ProgressStyle::default_spinner() + .template("{spinner:.green} {msg}") + .unwrap(), + ); + + // Create progress callback + let pb_clone = pb.clone(); + let status_clone = status_pb.clone(); + let progress_callback = Arc::new(move |album: String, song: String, done: usize, total: usize| { + if total > 0 { + pb_clone.set_length(total as u64); + pb_clone.set_position(done as u64); + } + status_clone.set_message(format!("Album: {} | {}", album, song)); + }); + + // Run sync with progress + let result = sync::sync_content_with_progress(config, album, artist, Some(progress_callback)).await; + + // Finish progress bars + pb.finish_with_message("Sync complete!"); + status_pb.finish_and_clear(); + + result?; } Commands::ListAlbums => { let mut navidrome = navidrome::NavidromeClient::new(&config.navidrome)?;