use indicatif::{ProgressBar, ProgressStyle};
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
pub const MIN_SIZE_FOR_PROGRESS: u64 = 1024 * 1024;
pub fn create_file_progress_bar(file_path: &Path, total_bytes: u64) -> Arc<ProgressBar> {
let pb = ProgressBar::new(total_bytes);
pb.set_style(
ProgressStyle::with_template("{msg}\n[{bar:40.cyan/blue}] {bytes}/{total_bytes} ({percent}%) {bytes_per_sec} ETA: {eta}")
.unwrap()
.progress_chars("=>-"),
);
let filename = file_path.file_name().and_then(|n| n.to_str()).unwrap_or("unknown");
let msg = if filename.len() > 60 { format!("{}...", &filename[..57]) } else { filename.to_string() };
pb.set_message(msg);
pb.enable_steady_tick(Duration::from_millis(100));
Arc::new(pb)
}
pub fn create_progress_callback(file_path: &Path, total_bytes: u64) -> Arc<dyn Fn(u64, u64) + Send + Sync> {
let pb = create_file_progress_bar(file_path, total_bytes);
Arc::new(move |bytes_transferred: u64, _total: u64| {
pb.set_position(bytes_transferred);
})
}
#[cfg(test)]
pub fn finish_progress_bar(pb: Arc<ProgressBar>) {
pb.finish_with_message("✓ Transfer complete");
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_min_size_constant() {
assert_eq!(MIN_SIZE_FOR_PROGRESS, 1024 * 1024);
}
#[test]
fn test_create_progress_bar() {
let path = PathBuf::from("/tmp/test.txt");
let pb = create_file_progress_bar(&path, 1000);
assert_eq!(pb.length(), Some(1000));
}
#[test]
fn test_create_progress_bar_long_filename() {
let long_name = "a".repeat(100);
let path = PathBuf::from(format!("/tmp/{}", long_name));
let pb = create_file_progress_bar(&path, 1000);
let msg = pb.message();
assert!(msg.len() <= 63); }
#[test]
fn test_create_progress_callback() {
let path = PathBuf::from("/tmp/test.txt");
let callback = create_progress_callback(&path, 1000);
callback(500, 1000);
callback(1000, 1000);
}
#[test]
fn test_finish_progress_bar() {
let path = PathBuf::from("/tmp/test.txt");
let pb = create_file_progress_bar(&path, 1000);
pb.set_position(1000);
finish_progress_bar(pb);
}
}