forked from akanyan/STARTLINER
88 lines
2.6 KiB
Rust
88 lines
2.6 KiB
Rust
use std::{collections::HashSet, path::PathBuf};
|
|
use serde::{Deserialize, Serialize};
|
|
use tauri::{AppHandle, Emitter};
|
|
use tokio::fs::File;
|
|
use anyhow::{anyhow, Result};
|
|
|
|
use crate::pkg::{Package, PkgKey, Remote};
|
|
|
|
pub struct DownloadHandler {
|
|
paths: HashSet<PathBuf>,
|
|
app: AppHandle
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct DownloadTick {
|
|
pkg_key: PkgKey,
|
|
ratio: f32,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
pub struct DownloadEndPayload {
|
|
pub key: PkgKey,
|
|
pub enable: bool
|
|
}
|
|
|
|
impl DownloadHandler {
|
|
pub fn new(app: AppHandle) -> DownloadHandler {
|
|
DownloadHandler {
|
|
paths: HashSet::new(),
|
|
app
|
|
}
|
|
}
|
|
|
|
pub fn download_zip(&mut self, zip_path: &PathBuf, pkg: &Package, enable: bool) -> Result<()> {
|
|
let rmt = pkg.rmt.as_ref()
|
|
.ok_or_else(|| anyhow!("Attempted to download a package without remote data"))?
|
|
.clone();
|
|
if self.paths.contains(zip_path) {
|
|
Ok(())
|
|
} else {
|
|
// TODO clear cache button should clear this
|
|
self.paths.insert(zip_path.clone());
|
|
tauri::async_runtime::spawn(Self::download_zip_proc(self.app.clone(), zip_path.clone(), pkg.key(), rmt, enable));
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
async fn download_zip_proc(
|
|
app: AppHandle,
|
|
zip_path: PathBuf,
|
|
pkg_key: PkgKey,
|
|
rmt: Remote,
|
|
enable: bool
|
|
) -> Result<()> {
|
|
use futures::StreamExt;
|
|
use tokio::io::AsyncWriteExt;
|
|
|
|
// let zip_path_part = zip_path.add_extension("part");
|
|
let mut zip_path_part = zip_path.to_owned();
|
|
zip_path_part.set_extension("zip.part");
|
|
|
|
let mut cache_file_w = File::create(&zip_path_part).await?;
|
|
let mut byte_stream = reqwest::get(&rmt.download_url).await?.bytes_stream();
|
|
let mut total_bytes = 0;
|
|
|
|
log::info!("downloading: {}", rmt.download_url);
|
|
while let Some(item) = byte_stream.next().await {
|
|
let i = item?;
|
|
total_bytes += i.len();
|
|
_ = app.emit("download-progress", DownloadTick {
|
|
pkg_key: pkg_key.clone(),
|
|
ratio: (total_bytes as f32) / (rmt.file_size as f32),
|
|
})?;
|
|
cache_file_w.write_all(&mut i.as_ref()).await?;
|
|
}
|
|
cache_file_w.sync_all().await?;
|
|
tokio::fs::rename(&zip_path_part, &zip_path).await?;
|
|
|
|
log::debug!("downloaded to {:?}", zip_path);
|
|
|
|
app.emit("download-end", DownloadEndPayload {
|
|
key: pkg_key,
|
|
enable
|
|
})?;
|
|
|
|
Ok(())
|
|
}
|
|
} |