Event handling (#75)

* working on amcros

* fleshed out draft

* added feature support

* finished loading

* Fixed issue with multiple data types in macro

* Working, and added more loading uses

* added window scopes

* clippy, fmt

* working other variants

* fmt; clippy

* prettier

* refactored emissions to use increment

* fixed deadlock

* doc changes

* clippy, prettier

* uuid change

* restructured events to util

* loading restructure

* merge fixes

* comments mistake

* better cfg tauri feature structuring

* added extra fields to some loading enum variants

* removed Option<>

* added pack + version labels

* doc change
This commit is contained in:
Wyatt Verchere
2023-04-16 10:12:37 -07:00
committed by GitHub
parent f8173d3b78
commit b120b5cfa8
22 changed files with 3519 additions and 102 deletions

View File

@@ -45,7 +45,7 @@ pub async fn get_optimal_jre_key(profile: &Profile) -> crate::Result<String> {
.minecraft
.versions
.iter()
.find(|it| it.id == profile.metadata.game_version.as_ref())
.find(|it| it.id == profile.metadata.game_version)
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Invalid or unknown Minecraft version: {}",

View File

@@ -1,12 +1,13 @@
use crate::config::MODRINTH_API_URL;
use crate::data::ModLoader;
use crate::event::emit::{init_loading, loading_try_for_each_concurrent};
use crate::event::LoadingBarType;
use crate::state::{ModrinthProject, ModrinthVersion, SideType};
use crate::util::fetch::{
fetch, fetch_json, fetch_mirrors, write, write_cached_icon,
};
use crate::State;
use async_zip::tokio::read::seek::ZipFileReader;
use futures::TryStreamExt;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -133,19 +134,20 @@ pub async fn install_pack_from_version_id(
None
};
install_pack(file, icon, Some(version.project_id)).await
install_pack(file, icon, Some(version.project_id), Some(version.id)).await
}
pub async fn install_pack_from_file(path: PathBuf) -> crate::Result<PathBuf> {
let file = fs::read(path).await?;
install_pack(bytes::Bytes::from(file), None, None).await
install_pack(bytes::Bytes::from(file), None, None, None).await
}
async fn install_pack(
file: bytes::Bytes,
icon: Option<PathBuf>,
project_id: Option<String>,
version_id: Option<String>,
) -> crate::Result<PathBuf> {
let state = &State::get().await?;
@@ -215,22 +217,39 @@ async fn install_pack(
.into());
};
let pack_name = pack.name.clone();
let profile = crate::api::profile_create::profile_create(
pack.name,
game_version.clone(),
mod_loader.unwrap_or(ModLoader::Vanilla),
loader_version,
icon,
project_id,
project_id.clone(),
)
.await?;
let loading_bar = init_loading(
LoadingBarType::PackDownload {
pack_name ,
pack_id: project_id,
pack_version: version_id,
},
100.0,
"Downloading modpack...",
)
.await?;
let num_files = pack.files.len();
use futures::StreamExt;
futures::stream::iter(pack.files.into_iter())
.map(Ok::<PackFile, crate::Error>)
.try_for_each_concurrent(None, |project| {
loading_try_for_each_concurrent(
futures::stream::iter(pack.files.into_iter())
.map(Ok::<PackFile, crate::Error>),
None,
Some(&loading_bar),
100.0,
num_files,
None,
|project| {
let profile = profile.clone();
async move {
//TODO: Future update: prompt user for optional files in a modpack
if let Some(env) = project.env {
@@ -266,11 +285,11 @@ async fn install_pack(
_ => {}
};
}
Ok(())
}
})
.await?;
},
)
.await?;
let extract_overrides = |overrides: String| async {
let reader = Cursor::new(&file);

View File

@@ -1,6 +1,7 @@
//! Theseus profile management interface
use crate::{
auth::{self, refresh},
event::{emit::emit_profile, ProfilePayloadType},
launcher::download,
state::MinecraftChild,
};
@@ -20,6 +21,17 @@ use tokio::{fs, process::Command, sync::RwLock};
pub async fn remove(path: &Path) -> crate::Result<()> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get(path) {
emit_profile(
profile.uuid,
profile.path.clone(),
&profile.metadata.name,
ProfilePayloadType::Removed,
)
.await?;
}
profiles.remove(path).await?;
Ok(())
@@ -46,7 +58,17 @@ where
let mut profiles = state.profiles.write().await;
match profiles.0.get_mut(path) {
Some(ref mut profile) => action(profile).await,
Some(ref mut profile) => {
emit_profile(
profile.uuid,
profile.path.clone(),
&profile.metadata.name,
ProfilePayloadType::Edited,
)
.await?;
action(profile).await
}
None => Err(crate::ErrorKind::UnmanagedProfileError(
path.display().to_string(),
)
@@ -219,7 +241,7 @@ pub async fn run_credentials(
.minecraft
.versions
.iter()
.find(|it| it.id == profile.metadata.game_version.as_ref())
.find(|it| it.id == profile.metadata.game_version)
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Invalid or unknown Minecraft version: {}",
@@ -325,6 +347,7 @@ pub async fn run_credentials(
&memory,
&resolution,
credentials,
&profile,
)
.await?;
@@ -335,8 +358,9 @@ pub async fn run_credentials(
"Process failed to stay open.".to_string(),
)
})?;
let mchild_arc =
state_children.insert_process(pid, path.to_path_buf(), mc_process);
let mchild_arc = state_children
.insert_process(pid, path.to_path_buf(), mc_process)
.await?;
Ok(mchild_arc)
}

View File

@@ -1,5 +1,9 @@
//! Theseus profile management interface
use crate::{jre, prelude::ModLoader};
use crate::{
event::{emit::emit_profile, ProfilePayloadType},
jre,
prelude::ModLoader,
};
pub use crate::{
state::{JavaSettings, Profile},
State,
@@ -135,7 +139,8 @@ pub async fn profile_create(
// Fully canonicalize now that its created for storing purposes
let path = canonicalize(&path)?;
let mut profile = Profile::new(name, game_version, path.clone()).await?;
let mut profile =
Profile::new(uuid, name, game_version, path.clone()).await?;
if let Some(ref icon) = icon {
let bytes = tokio::fs::read(icon).await?;
profile
@@ -167,9 +172,16 @@ pub async fn profile_create(
println!("Could not detect optimal JRE: {optimal_version_key}, falling back to system default.");
}
emit_profile(
uuid,
path.clone(),
&profile.metadata.name,
ProfilePayloadType::Created,
)
.await?;
{
let mut profiles = state.profiles.write().await;
profiles.insert(profile)?;
profiles.insert(profile).await?;
}
State::sync().await?;