Move app.emit_all to avoid borrowing it

This commit is contained in:
Quentin Legot 2023-04-26 14:17:52 +02:00
parent 6697c38af0
commit be2c15be39
3 changed files with 79 additions and 27 deletions

View File

@ -46,7 +46,7 @@ pub async fn get_version_from_manifest<'a>(manifest: &'a VersionManifestV2, game
pub struct VersionDetail { pub struct VersionDetail {
arguments: Map<String, Value>, arguments: Map<String, Value>,
#[serde(rename(serialize = "assetIndex", deserialize = "assetIndex"))] #[serde(rename(serialize = "assetIndex", deserialize = "assetIndex"))]
asset_index: Map<String, Value>, pub asset_index: AssetIndex,
assets: String, assets: String,
downloads: Map<String, Value>, downloads: Map<String, Value>,
id: String, id: String,
@ -60,6 +60,16 @@ pub struct VersionDetail {
v_type: VersionType v_type: VersionType
} }
#[derive(Serialize, Deserialize)]
pub struct AssetIndex {
pub id: i32,
pub sha1: String,
pub size: usize,
#[serde(rename(serialize = "totalSize", deserialize = "totalSize"))]
pub total_size: usize,
pub url: String
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Library { pub struct Library {
pub downloads: LibraryDownload, pub downloads: LibraryDownload,
@ -109,3 +119,12 @@ pub async fn get_version_detail(reqwest: &Client, version : &Version) -> Result<
.await?; .await?;
Ok(received) Ok(received)
} }
#[derive(Serialize, Deserialize)]
pub struct AssetsManifest {
objects: Map<String, Value>,
}
pub async fn get_version_assets(assets_index: &AssetIndex) -> Result<()> {
bail!("Not yet implemented")
}

View File

@ -1,16 +1,15 @@
mod manifest; mod manifest;
use std::path::{Path, self}; use std::path::{Path, self, PathBuf};
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use reqwest::{Client, StatusCode}; use reqwest::{Client, StatusCode};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use tauri::Manager; use tokio::{fs, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc};
use tokio::{fs, io::{AsyncWriteExt, AsyncSeekExt}};
use crate::authentification::GameProfile; use crate::authentification::GameProfile;
use self::manifest::{VersionDetail, get_version_manifest, get_version_from_manifest, get_version_detail, Library, OSName}; use self::manifest::{VersionDetail, get_version_manifest, get_version_from_manifest, get_version_detail, Library, OSName, get_version_assets};
#[cfg(target_os="windows")] #[cfg(target_os="windows")]
@ -20,8 +19,8 @@ const ACTUAL_OS: OSName = OSName::Linux;
#[cfg(target_os="macos")] #[cfg(target_os="macos")]
const ACTUAL_OS: OSName = OSName::MacOsX; const ACTUAL_OS: OSName = OSName::MacOsX;
#[derive(Clone, serde::Serialize)] #[derive(Clone, serde::Serialize, Debug)]
struct ProgressMessage { pub struct ProgressMessage {
p_type: String, p_type: String,
current: usize, current: usize,
total: usize, total: usize,
@ -29,6 +28,7 @@ struct ProgressMessage {
pub struct ClientOptions<'a> { pub struct ClientOptions<'a> {
pub authorization: GameProfile, pub authorization: GameProfile,
pub log_channel: mpsc::Sender<ProgressMessage>,
pub root_path: &'a Path, pub root_path: &'a Path,
pub java_path: &'a Path, pub java_path: &'a Path,
pub version_number: String, pub version_number: String,
@ -60,10 +60,11 @@ impl<'a> MinecraftClient<'_> {
let manifest = get_version_manifest(&reqwest_client).await?; let manifest = get_version_manifest(&reqwest_client).await?;
let version = get_version_from_manifest(&manifest, opts.version_number.clone(), &opts.version_type).await?; let version = get_version_from_manifest(&manifest, opts.version_number.clone(), &opts.version_type).await?;
let details = get_version_detail(&reqwest_client, version).await?; let details = get_version_detail(&reqwest_client, version).await?;
// let version_assets = get_version_assets(&details.asset_index).await?;
Ok(details) Ok(details)
} }
pub async fn download_assets(&mut self, app: tauri::AppHandle) -> Result<()> { pub async fn download_requirements(&mut self) -> Result<()> {
// create root folder if it doesn't exist // create root folder if it doesn't exist
if !self.opts.root_path.exists() { if !self.opts.root_path.exists() {
fs::create_dir_all(self.opts.root_path).await?; fs::create_dir_all(self.opts.root_path).await?;
@ -72,6 +73,12 @@ impl<'a> MinecraftClient<'_> {
if !lib.exists() { if !lib.exists() {
fs::create_dir(lib).await?; fs::create_dir(lib).await?;
} }
self.download_libraries(lib).await?;
self.opts.log_channel.closed().await;
Ok(())
}
async fn download_libraries(&mut self, lib: &PathBuf) -> Result<()> {
self.filter_non_necessary_librairies(); self.filter_non_necessary_librairies();
let total = self.details.libraries.len(); let total = self.details.libraries.len();
for (progress, i) in self.details.libraries.iter().enumerate() { for (progress, i) in self.details.libraries.iter().enumerate() {
@ -121,9 +128,8 @@ impl<'a> MinecraftClient<'_> {
} else { } else {
println!("{} already downloaded", i.name); println!("{} already downloaded", i.name);
} }
app.emit_all("progress", ProgressMessage { p_type: "libraries".to_string(), current: progress + 1, total })?; self.opts.log_channel.send( ProgressMessage { p_type: "libraries".to_string(), current: progress + 1, total }).await?;
} }
Ok(()) Ok(())
} }
@ -132,6 +138,10 @@ impl<'a> MinecraftClient<'_> {
self.details.libraries.retain(|e| { Self::should_use_library(e) }); self.details.libraries.retain(|e| { Self::should_use_library(e) });
} }
async fn download_assets(&mut self) -> Result<()> {
bail!("Not yet implemented")
}
fn should_use_library(library: &Library) -> bool { fn should_use_library(library: &Library) -> bool {
match &library.rules { match &library.rules {
Some(rules) => { Some(rules) => {

View File

@ -11,7 +11,9 @@ use std::sync::Mutex;
use authentification::{Authentification, Prompt, GameProfile}; use authentification::{Authentification, Prompt, GameProfile};
use anyhow::Result; use anyhow::Result;
use directories::BaseDirs; use directories::BaseDirs;
use launcher::{MinecraftClient, ClientOptions}; use launcher::{MinecraftClient, ClientOptions, ProgressMessage};
use tauri::Manager;
use tokio::sync::mpsc;
struct CustomState (Option<GameProfile>); struct CustomState (Option<GameProfile>);
@ -54,8 +56,10 @@ async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomSta
if game_profile.is_none() { if game_profile.is_none() {
return Err("You're not connected".to_string()); return Err("You're not connected".to_string());
} }
let (sender, receiver) = mpsc::channel(50);
let opts = ClientOptions { let opts = ClientOptions {
authorization: game_profile.unwrap(), authorization: game_profile.unwrap(),
log_channel: sender.clone(),
root_path, root_path,
java_path: &java_path.as_path(), java_path: &java_path.as_path(),
version_number: "1.19.4".to_string(), version_number: "1.19.4".to_string(),
@ -63,28 +67,47 @@ async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomSta
memory_min: "2G".to_string(), memory_min: "2G".to_string(),
memory_max: "4G".to_string(), memory_max: "4G".to_string(),
}; };
let client = MinecraftClient::new(&opts).await; let res = tokio::join!(
match client { download_libraries(opts),
Ok(mut client) => { read_channel(receiver, app),
match client.download_assets(app).await {
Ok(_) => { );
Ok("Content downloaded".to_string()) res.0
},
Err(err) => {
Err(err.to_string())
}
}
},
Err(err) => {
Err(err.to_string())
}
}
} else { } else {
Err("Cannot download files".to_string()) Err("Cannot download files".to_string())
} }
} }
async fn download_libraries(opts: ClientOptions<'_>) -> Result<String, String> {
let client = MinecraftClient::new(&opts).await;
match client {
Ok(mut client) => {
match client.download_requirements().await {
Ok(_) => {
Ok("Content downloaded".to_string())
},
Err(err) => {
Err(err.to_string())
}
}
},
Err(err) => {
Err(err.to_string())
}
}
}
async fn read_channel(mut receiver: mpsc::Receiver<ProgressMessage>, app: tauri::AppHandle) -> Result<()> {
loop {
match receiver.recv().await {
Some(msg) => app.emit_all("progress", msg)?,
None => break Ok(())
}
}
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
tauri::Builder::default() tauri::Builder::default()