diff options
| author | Naz <ndpm13@ch-naseem.com> | 2025-07-27 14:42:21 +0100 |
|---|---|---|
| committer | Naz <ndpm13@ch-naseem.com> | 2025-07-27 14:42:21 +0100 |
| commit | ccf603c81bd11864aabae5e98c9888854fe885cb (patch) | |
| tree | 2e7d064f97e2e6a4e6d0435bdcceee786faf8d26 | |
| parent | 85fb9fcc50d16f8b8147c117521b836ab750cd98 (diff) | |
✨feat: add AppImage download with progress tracking
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/tui.rs | 14 | ||||
| -rw-r--r-- | src/types.rs | 44 |
3 files changed, 58 insertions, 2 deletions
@@ -1,7 +1,9 @@ mod args; +mod tui; mod types; pub use crate::args::*; +pub use crate::tui::*; pub use crate::types::*; use std::path::PathBuf; diff --git a/src/tui.rs b/src/tui.rs new file mode 100644 index 0000000..df3504d --- /dev/null +++ b/src/tui.rs @@ -0,0 +1,14 @@ +use indicatif::{ProgressBar, ProgressStyle}; + +pub fn make_progress_bar(size: u64) -> ProgressBar { + let bar = ProgressBar::new(size); + bar.set_style( + ProgressStyle::with_template( + "{elapsed_precise:.white.dim} {wide_bar:.cyan} {bytes}/{total_bytes} ({bytes_per_sec}, {eta})", + ) + .unwrap() + .progress_chars("█▉▊▋▌▍▎▏ "), + ); + + bar +} diff --git a/src/types.rs b/src/types.rs index 5636fe9..b20ada1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,8 +1,9 @@ +use futures_util::StreamExt; use serde::Serialize; use std::path::PathBuf; -use tokio::fs; +use tokio::{fs, io::AsyncWriteExt}; -use crate::{index_dir}; +use crate::{appimages_dir, index_dir, make_progress_bar}; #[derive(Debug, Serialize)] pub struct AppImage { @@ -31,4 +32,43 @@ impl AppImage { Ok(()) } + pub async fn download_from_url(&self) -> Result<(), Box<dyn std::error::Error>> { + fs::create_dir_all(&appimages_dir()).await?; + + // Try to extract filename from URL or use default + let url = &self.source.meta.url; + let filename = match url.split('/').next_back() { + Some(name) => name.to_string(), + None => format!("{}.AppImage", &self.executable), + }; + let file_path = &appimages_dir().join(filename); + + let resp = reqwest::get(&url.to_string()).await?; + let total_size = resp.content_length().unwrap_or(0); + + let bar = make_progress_bar(total_size); + let mut out = tokio::fs::File::create(&file_path).await?; + + // Stream download with progress updates + let mut stream = resp.bytes_stream(); + while let Some(chunk) = stream.next().await { + let chunk = chunk?; + let len = chunk.len() as u64; + out.write_all(&chunk).await?; + bar.inc(len); + } + + bar.finish_with_message("Download complete!"); + + // Make executable + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = fs::metadata(&file_path).await?.permissions(); + perms.set_mode(0o755); + fs::set_permissions(&file_path, perms).await?; + } + + Ok(()) + } } |
