99 lines
3.6 KiB
Rust
99 lines
3.6 KiB
Rust
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
|
|
use base64::{Engine, engine::general_purpose};
|
|
use std::{fs::{create_dir_all, File}, io::{copy, BufReader}, path::PathBuf};
|
|
use tauri::{AppHandle, Emitter, Manager};
|
|
use tauri_plugin_decorum::WebviewWindowExt;
|
|
use tokio::{io::AsyncWriteExt, task::spawn_blocking};
|
|
use zip::ZipArchive;
|
|
use futures_util::stream::StreamExt;
|
|
|
|
pub async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> zip::result::ZipResult<()> {
|
|
spawn_blocking(move || {
|
|
let file = File::open(zip_path)?;
|
|
let mut archive = ZipArchive::new(BufReader::new(file))?;
|
|
|
|
for i in 0..archive.len() {
|
|
let mut file = archive.by_index(i)?;
|
|
let outpath = out_dir.join(file.name());
|
|
|
|
if file.is_dir() {
|
|
create_dir_all(&outpath)?;
|
|
} else {
|
|
if let Some(parent) = outpath.parent() {
|
|
create_dir_all(parent)?;
|
|
}
|
|
let mut outfile = File::create(&outpath)?;
|
|
copy(&mut file, &mut outfile)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
})
|
|
.await
|
|
.map_err(|e| zip::result::ZipError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?
|
|
}
|
|
|
|
#[tauri::command]
|
|
async fn download(app: AppHandle, url: String, name: String) -> Result<(), String> {
|
|
app.emit("download-started", &url).unwrap();
|
|
|
|
let client = reqwest::Client::new();
|
|
let resp = client.get(&url).send().await.map_err(|e| e.to_string())?;
|
|
let total_size = resp.content_length().unwrap_or(0);
|
|
|
|
let mut downloaded: u64 = 0;
|
|
let mut stream = resp.bytes_stream();
|
|
|
|
let downloads_path = app.path().app_local_data_dir().unwrap().join("downloads");
|
|
let game_path = app.path().app_local_data_dir().unwrap().join("game");
|
|
let _ = tokio::fs::create_dir_all(&downloads_path).await;
|
|
if let Ok(true) = tokio::fs::try_exists(&game_path.join(&name)).await {
|
|
let _ = tokio::fs::remove_dir_all(&game_path.join(&name)).await;
|
|
}
|
|
let _ = tokio::fs::create_dir_all(&game_path.join(&name)).await;
|
|
let mut file = tokio::fs::File::create(downloads_path.join(format!("{}.part", name))).await.unwrap();
|
|
|
|
while let Some(chunk) = stream.next().await {
|
|
let chunk = chunk.map_err(|e| e.to_string())?;
|
|
file.write_all(&chunk).await.map_err(|e| e.to_string())?;
|
|
downloaded += chunk.len() as u64;
|
|
|
|
let progress = if total_size > 0 {
|
|
(downloaded * 100 / total_size) as u8
|
|
} else {
|
|
0
|
|
};
|
|
app.emit(
|
|
"download-progress",
|
|
format!("{}:{}", general_purpose::STANDARD.encode(&url), progress),
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
tokio::fs::rename(downloads_path.join(format!("{}.part", name)), downloads_path.join(format!("{}.zip", name))).await.unwrap();
|
|
unzip_to_dir(downloads_path.join(format!("{}.zip", name)), game_path.join(&name)).await.map_err(|e| e.to_string())?;
|
|
tokio::fs::remove_file(downloads_path.join(format!("{}.zip", name))).await.unwrap();
|
|
|
|
app.emit("download-finished", &url).unwrap();
|
|
Ok(())
|
|
}
|
|
|
|
pub fn run() {
|
|
tauri::Builder::default()
|
|
.plugin(tauri_plugin_fs::init())
|
|
.plugin(tauri_plugin_decorum::init())
|
|
.plugin(tauri_plugin_os::init())
|
|
.plugin(tauri_plugin_opener::init())
|
|
.invoke_handler(tauri::generate_handler![download])
|
|
.setup(|app| {
|
|
#[cfg(target_os = "windows")] {
|
|
let main_window = app.get_webview_window("main").unwrap();
|
|
main_window.create_overlay_titlebar().unwrap();
|
|
}
|
|
Ok(())
|
|
})
|
|
.run(tauri::generate_context!())
|
|
.expect("error while running tauri application");
|
|
}
|