Implementation of ProgressBar (#1)

Co-authored-by: Waradu <waradu@outlook.com>
This commit is contained in:
PandaDEV 2024-10-21 00:30:58 +10:00 committed by GitHub
parent c7e859badf
commit 7a101fde14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 202 additions and 68 deletions

View file

@ -1,7 +1,11 @@
use std::{io::Write, time::Instant};
use clap::{CommandFactory, Parser};
use kdam::{tqdm, BarExt, Column, RichProgress, Spinner, term::Colorizer};
use streamshare::{delete, upload};
use std::io::{stderr, IsTerminal};
use std::fs;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::thread;
#[derive(Parser, Debug)]
#[command(name = "toss", version, about, long_about = None)]
@ -18,7 +22,7 @@ struct Args {
}
#[tokio::main]
async fn main() {
async fn main() -> std::io::Result<()> {
let args = Args::parse();
if let Some(delete_param) = args.delete {
@ -31,50 +35,83 @@ async fn main() {
eprintln!("Invalid format for --delete. Use 'file_identifier/deletion_token' (e.g., 'abc123/def456')");
}
} else if let Some(file_path) = args.file {
let start_time = Instant::now();
let mut file_size: u64 = 0;
let show_progress = |uploaded_bytes, total_bytes| {
let percentage = (uploaded_bytes as f64 / total_bytes as f64) * 100.0;
let uploaded = readable(uploaded_bytes);
let total = readable(total_bytes);
let elapsed_secs = start_time.elapsed().as_secs_f64();
let speed = readable((uploaded_bytes as f64 / elapsed_secs) as u64);
file_size = total_bytes;
kdam::term::init(stderr().is_terminal());
kdam::term::hide_cursor()?;
print!(
"\r\x1b[2K{:.2}% {}/{} ({}/s)",
percentage, uploaded, total, speed
);
std::io::stdout().flush().unwrap();
};
let file_size = fs::metadata(&file_path)?.len();
match upload(&file_path, show_progress).await {
let pb = RichProgress::new(
tqdm!(
total = file_size as usize,
unit_scale = true,
unit_divisor = 1024,
unit = "B",
mininterval = 0.01,
dynamic_ncols = true,
colour = "green"
),
vec![
Column::Spinner(Spinner::new(&["", "", "", "", "", "", "", "", "", ""], 80.0, 1.0)),
Column::Percentage(1),
Column::Text("".to_owned()),
Column::Animation,
Column::Text("".to_owned()),
Column::CountTotal,
Column::Text("".to_owned()),
Column::Rate,
Column::Text("".to_owned()),
Column::RemainingTime,
],
);
let pb_arc = Arc::new(Mutex::new(pb));
let current_progress = Arc::new(Mutex::new(0));
let pb_arc_clone = pb_arc.clone();
let current_progress_clone = current_progress.clone();
let update_thread = thread::spawn(move || {
loop {
thread::sleep(Duration::from_millis(50));
let progress = *current_progress_clone.lock().unwrap();
if progress >= file_size {
break;
}
pb_arc_clone.lock().unwrap().update_to(progress as usize).unwrap();
}
});
match upload(&file_path, move |current, _total| {
*current_progress.lock().unwrap() = current;
}).await {
Ok((file_identifier, deletion_token)) => {
let mut pb = pb_arc.lock().unwrap();
pb.update_to(file_size as usize).unwrap();
println!("\n{}", "".to_owned() + &"".repeat(79) + "");
println!("{:^90}", "Upload Complete!".colorize("bold green"));
println!("{}", "".repeat(79));
let download_url = format!(
"https://streamshare.wireway.ch/download/{}",
file_identifier
);
let elapsed_secs = start_time.elapsed().as_secs_f64();
println!(
"\r\x1b[2K100.00% {}/{} (Upload completed in {:.2}s)",
readable(file_size),
readable(file_size),
elapsed_secs
);
println!();
println!("File uploaded successfully");
println!("Download URL: {}", download_url);
println!("File Identifier: {}", file_identifier);
println!("Deletion Token: {}", deletion_token);
println!("{:<15} {:<31}", "URL:".colorize("bold yellow"), download_url);
println!("{:<15} {:<68}", "File ID:".colorize("bold yellow"), file_identifier);
println!("{:<15} {:<61}", "Deletion Token:".colorize("bold yellow"), deletion_token);
println!("{}", "".to_owned() + &"".repeat(79) + "");
}
Err(e) => eprintln!("Error: {}", e),
Err(e) => eprintln!("{}", format!("Error: {}", e).colorize("bold red")),
}
update_thread.join().unwrap();
kdam::term::show_cursor()?;
} else {
Args::command().print_help().unwrap();
}
Ok(())
}
fn parse_delete_param(param: &str) -> Option<(&str, &str)> {
@ -84,20 +121,4 @@ fn parse_delete_param(param: &str) -> Option<(&str, &str)> {
} else {
None
}
}
fn readable(bytes: u64) -> String {
const KB: f64 = 1024.0;
const MB: f64 = KB * 1024.0;
const GB: f64 = MB * 1024.0;
if bytes as f64 >= GB {
format!("{:.2}gb", bytes as f64 / GB)
} else if bytes as f64 >= MB {
format!("{:.2}mb", bytes as f64 / MB)
} else if bytes as f64 >= KB {
format!("{:.2}kb", bytes as f64 / KB)
} else {
format!("{}b", bytes)
}
}
}