Fontend download progress

This commit is contained in:
Samuel Walker 2024-06-23 15:07:25 -06:00
parent 2bb85695c0
commit 6b497d30cd
11 changed files with 128 additions and 38 deletions

View File

@ -8,9 +8,26 @@
"name": "fclauncher", "name": "fclauncher",
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"@tauri-apps/api": "^1.5.6",
"@tauri-apps/cli": "^1" "@tauri-apps/cli": "^1"
} }
}, },
"node_modules/@tauri-apps/api": {
"version": "1.5.6",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.6.tgz",
"integrity": "sha512-LH5ToovAHnDVe5Qa9f/+jW28I6DeMhos8bNDtBOmmnaDpPmJmYLyHdeDblAWWWYc7KKRDg9/66vMuKyq0WIeFA==",
"dev": true,
"license": "Apache-2.0 OR MIT",
"engines": {
"node": ">= 14.6.0",
"npm": ">= 6.6.0",
"yarn": ">= 1.19.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
}
},
"node_modules/@tauri-apps/cli": { "node_modules/@tauri-apps/cli": {
"version": "1.5.14", "version": "1.5.14",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz", "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz",

View File

@ -7,6 +7,7 @@
"tauri": "tauri" "tauri": "tauri"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/api": "^1.5.6",
"@tauri-apps/cli": "^1" "@tauri-apps/cli": "^1"
} }
} }

View File

@ -24,7 +24,7 @@ fn ftp_connection(username: &str, password: &str) -> Result<NativeTlsFtpStream,
} }
pub fn ftp_retr(file: PathBuf , mut writer: impl Write, mut callback: impl FnMut(usize)) -> Result<bool, FtpError> { pub fn ftp_retr(window: Option<tauri::Window>, file: PathBuf , mut writer: impl Write, mut callback: impl FnMut(Option<tauri::Window>, usize, usize)) -> Result<bool, FtpError> {
let mut ftp_stream = ftp_connection_anonymous().unwrap(); let mut ftp_stream = ftp_connection_anonymous().unwrap();
let file = file.to_str().unwrap().replace("\\", "/"); let file = file.to_str().unwrap().replace("\\", "/");
let size = ftp_stream.size(&file)?; let size = ftp_stream.size(&file)?;
@ -36,9 +36,10 @@ pub fn ftp_retr(file: PathBuf , mut writer: impl Write, mut callback: impl FnMut
writer.write_all(&mut tx_bytes.split_at(bytes_read).0).unwrap(); writer.write_all(&mut tx_bytes.split_at(bytes_read).0).unwrap();
total += bytes_read; total += bytes_read;
if total == size || bytes_read == 0 { if total == size || bytes_read == 0 {
callback(window.clone(), 0, size);
break; break;
}else{ }else{
callback(bytes_read); callback(window.clone(), bytes_read, size);
} }
} }
Ok(true) Ok(true)

View File

@ -14,15 +14,13 @@ fn check_java(version: u8) -> bool {
dir.exists() dir.exists()
} }
pub fn install_java(version: u8) { pub fn install_java(version: u8, window: tauri::Window) {
if check_java(version) { if check_java(version) {
return; return;
} }
let ftp_dir = PathBuf::new().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win.zip" } else {"lin.tar.gz"})); let ftp_dir = PathBuf::new().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win.zip" } else {"lin.tar.gz"}));
let mut buff = Cursor::new(vec![]); let mut buff = Cursor::new(vec![]);
let mut total: usize = 0; ftp::ftp_retr(Some(window), ftp_dir, &mut buff, |window, data, size| util::download_callback(format!("Java {}", version), window,data, size)).unwrap();
let size = ftp_get_size(ftp_dir.clone()).unwrap();
ftp::ftp_retr(ftp_dir, &mut buff, |data| util::download_callback(data, &mut total, size)).unwrap();
std::fs::create_dir_all(get_local_data_directory().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win" } else {"lin"}))).unwrap(); std::fs::create_dir_all(get_local_data_directory().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win" } else {"lin"}))).unwrap();
buff.rewind().unwrap(); buff.rewind().unwrap();

View File

@ -29,9 +29,10 @@ fn greet(name: &str) -> String {
fn main() { fn main() {
prism::install_prism(); modpack::get_modpacks();
//prism::install_prism();
tauri::Builder::default() tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, modpack::get_modpacks, modpack::launch_modpack, prism::launch_prism]) .invoke_handler(tauri::generate_handler![greet, modpack::get_modpacks, modpack::launch_modpack, prism::launch_prism, prism::install_prism])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");
} }

View File

@ -10,6 +10,7 @@ use std::io::{Read, Seek, Write};
use serde_json::Value; use serde_json::Value;
use serde::Serialize; use serde::Serialize;
use serde::Deserialize; use serde::Deserialize;
use crate::util;
@ -61,22 +62,22 @@ fn check_modpack_needs_update(id: String) -> bool{
} }
#[tauri::command] #[tauri::command]
pub fn launch_modpack(id: String){ pub async fn launch_modpack(window: tauri::Window, id: String){
if check_modpack_needs_update(id.clone()) { if check_modpack_needs_update(id.clone()) {
install_modpack(id.clone()); install_modpack(window, id.clone());
} }
// Launch // Launch
let mut child = Command::new(get_local_data_directory().join("prism").join(get_prism_executable())).arg("-l").arg(get_modpack_name(id)).spawn().unwrap(); let mut child = Command::new(get_local_data_directory().join("prism").join(get_prism_executable())).arg("-l").arg(get_modpack_name(id)).spawn().unwrap();
} }
fn install_modpack(id: String){ fn install_modpack(window: tauri::Window, id: String){
let versions = get_versions(id.clone()); let versions = get_versions(id.clone());
let path = env::temp_dir().join(format!("{}.mrpack", get_modpack_name(id.clone()))); let path = env::temp_dir().join(format!("{}.mrpack", get_modpack_name(id.clone())));
let mut file = File::create(path.clone()).unwrap(); let mut file = File::create(path.clone()).unwrap();
let ftp_path = PathBuf::new().join(id.clone()).join(versions[versions.len()-1].file.clone().as_str()); let ftp_path = PathBuf::new().join(id.clone()).join(versions[versions.len()-1].file.clone().as_str());
println!("Downloading file {}", ftp_path.to_str().unwrap()); println!("Downloading file {}", ftp_path.to_str().unwrap());
ftp::ftp_retr(ftp_path, &mut file, |_| return).unwrap(); ftp::ftp_retr(Some(window.clone()), ftp_path, &mut file, |window, data, size| util::download_callback(get_modpack_name(id.clone()), window, data, size)).unwrap();
let mut child = Command::new(get_local_data_directory().join("prism").join(get_prism_executable())).arg("-I").arg(path).spawn().unwrap(); let mut child = Command::new(get_local_data_directory().join("prism").join(get_prism_executable())).arg("-I").arg(path).spawn().unwrap();
loop { loop {
let version_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join(".minecraft").join("version.txt"); let version_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join(".minecraft").join("version.txt");
@ -102,7 +103,7 @@ fn install_modpack(id: String){
} }
} }
let java = get_java_version(mc_version); let java = get_java_version(mc_version);
java::install_java(java); java::install_java(java, window.clone());
let option_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join("instance.cfg"); let option_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join("instance.cfg");
let mut option_file = File::open(option_path.clone()).unwrap(); let mut option_file = File::open(option_path.clone()).unwrap();
@ -132,7 +133,7 @@ pub fn get_modpacks() -> Vec<ModpackEntry> {
static mut modpacks: Vec<ModpackEntry> = Vec::new(); static mut modpacks: Vec<ModpackEntry> = Vec::new();
if modpacks.is_empty() { if modpacks.is_empty() {
let mut buf = Cursor::new(vec![]); let mut buf = Cursor::new(vec![]);
ftp::ftp_retr(PathBuf::new().join("modpacks.json"), &mut buf, |_| return); ftp::ftp_retr(None, PathBuf::new().join("modpacks.json"), &mut buf, |_, _, _| return);
buf.rewind(); buf.rewind();
let v: Value = serde_json::from_reader(buf).unwrap(); let v: Value = serde_json::from_reader(buf).unwrap();
println!("{}", v[0]["name"]); println!("{}", v[0]["name"]);
@ -147,7 +148,7 @@ pub fn get_modpacks() -> Vec<ModpackEntry> {
fn get_versions(id: String) -> Vec<VersionEntry> { fn get_versions(id: String) -> Vec<VersionEntry> {
let mut versions: Vec<VersionEntry> = Vec::new(); let mut versions: Vec<VersionEntry> = Vec::new();
let mut buf = Cursor::new(vec![]); let mut buf = Cursor::new(vec![]);
ftp::ftp_retr(PathBuf::new().join(id).join("versions.json"), &mut buf, |_| return); ftp::ftp_retr(None, PathBuf::new().join(id).join("versions.json"), &mut buf, |_, _, _| return);
buf.rewind(); buf.rewind();
let v: Value = serde_json::from_reader(buf).unwrap(); let v: Value = serde_json::from_reader(buf).unwrap();
for version in v.as_array().unwrap() { for version in v.as_array().unwrap() {

View File

@ -3,7 +3,7 @@ use flate2::read::GzDecoder;
use tar::Archive; use tar::Archive;
use tauri::api::file; use tauri::api::file;
use crate::{ftp, java, system_dirs::{get_local_data_directory, get_prism_executable}}; use crate::{ftp, java, system_dirs::{get_local_data_directory, get_prism_executable}, util};
pub fn check_prism() -> bool { pub fn check_prism() -> bool {
@ -11,21 +11,19 @@ pub fn check_prism() -> bool {
path.exists() path.exists()
} }
pub fn install_prism() -> Result<(), Box<dyn std::error::Error>>{ #[tauri::command]
pub async fn install_prism(window: tauri::Window){
if check_prism() { if check_prism() {
return Ok(()); return;
} }
java::install_java(21); java::install_java(21, window.clone());
let path = PathBuf::new().join("prism").join(format!("prism-{}",if env::consts::OS == "windows" {"win.zip"} else {"lin.tar.gz"})); let path = PathBuf::new().join("prism").join(format!("prism-{}",if env::consts::OS == "windows" {"win.zip"} else {"lin.tar.gz"}));
let size = ftp::ftp_get_size(path.clone())?; let size = ftp::ftp_get_size(path.clone()).unwrap();
let mut buff = Cursor::new(vec![]); let mut buff = Cursor::new(vec![]);
let mut total = 0; let mut total = 0;
ftp::ftp_retr(path, &mut buff, |data| { ftp::ftp_retr(Some(window.clone()), path, &mut buff, |window: Option<tauri::Window>, data, size| util::download_callback("Prism Launcher".to_string(),window, data, size)).unwrap();
total += data; std::fs::create_dir_all(get_local_data_directory().join("prism")).unwrap();
println!("Downloading Prism: {}MB / {}MB", total/(1024*1024), size/(1024*1024)); buff.rewind().unwrap();
}).unwrap();
std::fs::create_dir_all(get_local_data_directory().join("prism"))?;
buff.rewind()?;
if env::consts::OS != "windows" { if env::consts::OS != "windows" {
let tar = GzDecoder::new(buff); let tar = GzDecoder::new(buff);
let mut archive = Archive::new(tar); let mut archive = Archive::new(tar);
@ -39,7 +37,7 @@ pub fn install_prism() -> Result<(), Box<dyn std::error::Error>>{
} }
let mut buff = Cursor::new(vec![]); let mut buff = Cursor::new(vec![]);
ftp::ftp_retr(PathBuf::new().join("prism").join("prismlauncher.cfg"), &mut buff, |_| return).unwrap(); ftp::ftp_retr(Some(window.clone()), PathBuf::new().join("prism").join("prismlauncher.cfg"), &mut buff, |_, _, _| return).unwrap();
buff.rewind(); buff.rewind();
let mut file = File::create(get_local_data_directory().join("prism").join("prismlauncher.cfg")).unwrap(); let mut file = File::create(get_local_data_directory().join("prism").join("prismlauncher.cfg")).unwrap();
loop { loop {
@ -57,7 +55,6 @@ pub fn install_prism() -> Result<(), Box<dyn std::error::Error>>{
} }
Ok(())
} }

View File

@ -1,6 +1,30 @@
use std::clone;
pub fn download_callback(count: usize, total: &mut usize, size: usize){ use serde::Serialize;
*total += count;
println!("Downloading {}MB / {}MB", *total/(1024*1024), size/(1024*1024));
#[derive(Clone, Serialize)]
pub struct DownloadStatus {
downloaded: usize,
total: usize,
time_elapsed: usize,
download_name: String
}
pub fn download_callback(download_name: String, window: Option<tauri::Window>, count: usize, size: usize){
unsafe{
static mut total: usize = 0;
total += count;
if let Some(window1) = window.clone() {
window1.emit("download_progress", DownloadStatus{downloaded: total, total: size, time_elapsed: 0, download_name: download_name});
}
println!("Downloading {}MB / {}MB", total/(1024*1024), size/(1024*1024));
if count == 0 {
if let Some(window2) = window {
window2.emit("download_finished", true);
}
total = 0;
}
}
} }

View File

@ -12,7 +12,7 @@
<body onload="load();"> <body>
<div class="Logo"> <div class="Logo">
<img src="assets/Title.png" alt="Title" id="Title"> <img src="assets/Title.png" alt="Title" id="Title">
@ -28,6 +28,9 @@
<select name="modSelect" id="Modpacks" class="bg-dark text-white"> <select name="modSelect" id="Modpacks" class="bg-dark text-white">
</select> </select>
<p id="download_name"></p>
<p id="download_progress"></p>
<button id="launchGame" type="button">Launch Minecraft</button> <button id="launchGame" type="button">Launch Minecraft</button>

View File

@ -1,13 +1,24 @@
const { invoke } = window.__TAURI__.tauri; const { invoke } = window.__TAURI__.tauri;
const { listen } = window.__TAURI__.event;
//import { listen } from '@tauri-apps/api';
let greetInputEl; let greetInputEl;
let greetMsgEl; let greetMsgEl;
async function greet() {
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command const download_progress = listen("download_progress", (progress) => {
greetMsgEl.textContent = "testing"; console.log("Downloading");
//greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value }); //console.log("Downloaded "+progress.payload.downloaded/(1024*1024) +"MB / " + progress.payload.total/(1024*1024) + "MB");
} document.getElementById("download_name").textContent = "Downloading "+progress.payload.download_name;
document.getElementById("download_progress").textContent = progress.payload.downloaded/(1024*1024) + "MB / "+progress.payload.total/(1024*1024)+"MB";
document.getElementById("launchGame").disabled = true;
});
const download_finished = listen("download_finished", (event) => {
document.getElementById("download_name").textContent = "";
document.getElementById("download_progress").textContent = "";
document.getElementById("launchGame").disabled = false;
});
window.addEventListener("DOMContentLoaded", () => { window.addEventListener("DOMContentLoaded", () => {
@ -29,6 +40,7 @@ function load() {
} }
window.onload = async function() { window.onload = async function() {
invoke("install_prism");
invoke("get_modpacks").then(addModpacks); invoke("get_modpacks").then(addModpacks);
} }
@ -48,6 +60,7 @@ function addModpacks(modpacks) {
function gameLaunch() { function gameLaunch() {
var packId = document.getElementById("Modpacks"); var packId = document.getElementById("Modpacks");
var selectedId = packId.value; var selectedId = packId.value;
document.getElementById("launchGame").disabled = true;
//TODO Launch Game //TODO Launch Game
invoke("launch_modpack", { id: selectedId}).then(window.close); invoke("launch_modpack", { id: selectedId}).then(window.close);

34
FCLauncher/yarn.lock Normal file
View File

@ -0,0 +1,34 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@tauri-apps/api@^1.5.6":
version "1.5.6"
resolved "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.6.tgz"
integrity sha512-LH5ToovAHnDVe5Qa9f/+jW28I6DeMhos8bNDtBOmmnaDpPmJmYLyHdeDblAWWWYc7KKRDg9/66vMuKyq0WIeFA==
"@tauri-apps/cli-linux-x64-gnu@1.5.14":
version "1.5.14"
resolved "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.14.tgz"
integrity sha512-kD9v/UwPDuhIgq2TJj/s2/7rqk+vmExVV6xHPKI8vVbIvlNAOZqmx3fpxjej1241vhJ/piGd/m6q6YMWGsL0oQ==
"@tauri-apps/cli-linux-x64-musl@1.5.14":
version "1.5.14"
resolved "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.14.tgz"
integrity sha512-204Drgg9Zx0+THKndqASz4+iPCwqA3gQVF9C0CDIArNXrjPyJjVvW8VP5CHiZYaTNWxlz/ltyxluM6UFWbXNFw==
"@tauri-apps/cli@^1":
version "1.5.14"
resolved "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz"
integrity sha512-JOSMKymlg116UdEXSj69eg5p1OtZnQkUE0qIGbtNDO1sk3X/KgBN6+oHBW0BzPStp/W0AjBgrMWCqjHPwEpOug==
optionalDependencies:
"@tauri-apps/cli-darwin-arm64" "1.5.14"
"@tauri-apps/cli-darwin-x64" "1.5.14"
"@tauri-apps/cli-linux-arm-gnueabihf" "1.5.14"
"@tauri-apps/cli-linux-arm64-gnu" "1.5.14"
"@tauri-apps/cli-linux-arm64-musl" "1.5.14"
"@tauri-apps/cli-linux-x64-gnu" "1.5.14"
"@tauri-apps/cli-linux-x64-musl" "1.5.14"
"@tauri-apps/cli-win32-arm64-msvc" "1.5.14"
"@tauri-apps/cli-win32-ia32-msvc" "1.5.14"
"@tauri-apps/cli-win32-x64-msvc" "1.5.14"