Performance improvements (#114)

* Performance improvements

* run fmt

* optimize creation modal

* remove print, fix mod loader editing

* Fix library update

* update extract loading bar

* Update theseus_gui/src-tauri/src/api/metadata.rs

Co-authored-by: triphora <emma@modrinth.com>

* fix cli

---------

Co-authored-by: triphora <emma@modrinth.com>
This commit is contained in:
Geometrically
2023-05-11 18:11:15 -07:00
committed by GitHub
parent 7a0798d9d0
commit ee0c91aa80
28 changed files with 326 additions and 234 deletions

View File

@@ -25,3 +25,11 @@ pub async fn get_forge_versions() -> crate::Result<Manifest> {
Ok(tags)
}
#[tracing::instrument]
pub async fn get_quilt_versions() -> crate::Result<Manifest> {
let state = State::get().await?;
let tags = state.metadata.read().await.quilt.clone();
Ok(tags)
}

View File

@@ -13,7 +13,8 @@ pub mod tags;
pub mod data {
pub use crate::state::{
DirectoryInfo, Hooks, JavaSettings, MemorySettings, ModLoader,
ProfileMetadata, Settings, Theme, WindowSize,
ModrinthProject, ModrinthTeamMember, ModrinthUser, ModrinthVersion,
ProfileMetadata, ProjectMetadata, Settings, Theme, WindowSize,
};
}

View File

@@ -6,7 +6,8 @@ use crate::event::emit::{
};
use crate::event::{LoadingBarId, LoadingBarType};
use crate::state::{
LinkedData, ModrinthProject, ModrinthVersion, ProfileInstallStage, SideType,
LinkedData, ModrinthProject, ModrinthVersion, Profile, ProfileInstallStage,
SideType,
};
use crate::util::fetch::{
fetch, fetch_advanced, fetch_json, fetch_mirrors, write, write_cached_icon,
@@ -325,6 +326,7 @@ async fn install_pack(
prof.metadata.icon = icon.clone();
prof.metadata.game_version = game_version.clone();
prof.metadata.loader_version = loader_version.clone();
prof.metadata.loader = mod_loader.unwrap_or(ModLoader::Vanilla);
async { Ok(()) }
})
@@ -409,83 +411,79 @@ async fn install_pack(
)
.await?;
let extract_overrides = |overrides: String| async {
let reader = Cursor::new(&file);
let mut overrides_zip =
ZipFileReader::new(reader).await.map_err(|_| {
crate::Error::from(crate::ErrorKind::InputError(
"Failed extract overrides Zip".to_string(),
))
})?;
let profile = profile.clone();
async move {
for index in 0..overrides_zip.file().entries().len() {
let file = overrides_zip
.file()
.entries()
.get(index)
.unwrap()
.entry()
.clone();
let file_path = PathBuf::from(file.filename());
if file.filename().starts_with(&overrides)
&& !file.filename().ends_with('/')
{
// Reads the file into the 'content' variable
let mut content = Vec::new();
let mut reader =
overrides_zip.entry(index).await?;
reader
.read_to_end_checked(&mut content, &file)
.await?;
let mut new_path = PathBuf::new();
let components = file_path.components().skip(1);
for component in components {
new_path.push(component);
}
if new_path.file_name().is_some() {
write(
&profile.join(new_path),
&content,
&state.io_semaphore,
)
.await?;
}
}
}
Ok::<(), crate::Error>(())
}
.await
};
emit_loading(&loading_bar, 0.0, Some("Extracting overrides"))
.await?;
extract_overrides("overrides".to_string()).await?;
extract_overrides("client_overrides".to_string()).await?;
emit_loading(
&loading_bar,
29.9,
Some("Done extracting overrides"),
)
.await?;
if let Some(profile) =
crate::api::profile::get(&profile).await?
let mut total_len = 0;
for index in 0..zip_reader.file().entries().len() {
let file =
zip_reader.file().entries().get(index).unwrap().entry();
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
total_len += 1;
}
}
for index in 0..zip_reader.file().entries().len() {
let file = zip_reader
.file()
.entries()
.get(index)
.unwrap()
.entry()
.clone();
let file_path = PathBuf::from(file.filename());
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
// Reads the file into the 'content' variable
let mut content = Vec::new();
let mut reader = zip_reader.entry(index).await?;
reader.read_to_end_checked(&mut content, &file).await?;
let mut new_path = PathBuf::new();
let components = file_path.components().skip(1);
for component in components {
new_path.push(component);
}
if new_path.file_name().is_some() {
write(
&profile.join(new_path),
&content,
&state.io_semaphore,
)
.await?;
}
emit_loading(
&loading_bar,
30.0 / total_len as f64,
Some(&format!(
"Extracting override {}/{}",
index, total_len
)),
)
.await?;
}
}
if let Some(profile_val) =
crate::api::profile::get(&profile, None).await?
{
tokio::try_join!(
super::profile::sync(&profile.path),
crate::launcher::install_minecraft(
&profile,
Some(loading_bar)
),
)?;
Profile::sync_projects_task(profile.clone());
crate::launcher::install_minecraft(
&profile_val,
Some(loading_bar),
)
.await?;
}
Ok::<PathBuf, crate::Error>(profile.clone())

View File

@@ -12,6 +12,7 @@ pub use crate::{
state::{JavaSettings, Profile},
State,
};
use std::collections::HashMap;
use std::{
future::Future,
path::{Path, PathBuf},
@@ -40,11 +41,21 @@ pub async fn remove(path: &Path) -> crate::Result<()> {
/// Get a profile by path,
#[tracing::instrument]
pub async fn get(path: &Path) -> crate::Result<Option<Profile>> {
pub async fn get(
path: &Path,
clear_projects: Option<bool>,
) -> crate::Result<Option<Profile>> {
let state = State::get().await?;
let profiles = state.profiles.read().await;
let mut profile = profiles.0.get(path).cloned();
Ok(profiles.0.get(path).cloned())
if clear_projects.unwrap_or(false) {
if let Some(profile) = &mut profile {
profile.projects = HashMap::new();
}
}
Ok(profile)
}
/// Edit a profile using a given asynchronous closure
@@ -79,11 +90,23 @@ where
/// Get a copy of the profile set
#[tracing::instrument]
pub async fn list() -> crate::Result<std::collections::HashMap<PathBuf, Profile>>
{
pub async fn list(
clear_projects: Option<bool>,
) -> crate::Result<HashMap<PathBuf, Profile>> {
let state = State::get().await?;
let profiles = state.profiles.read().await;
Ok(profiles.0.clone())
Ok(profiles
.0
.clone()
.into_iter()
.map(|mut x| {
if clear_projects.unwrap_or(false) {
x.1.projects = HashMap::new();
}
x
})
.collect())
}
/// Query + sync profile's projects with the UI from the FS
@@ -117,7 +140,7 @@ pub async fn sync(path: &Path) -> crate::Result<()> {
/// Installs/Repairs a profile
#[tracing::instrument]
pub async fn install(path: &Path) -> crate::Result<()> {
let profile = get(path).await?;
let profile = get(path, None).await?;
if let Some(profile) = profile {
crate::launcher::install_minecraft(&profile, None).await?;
@@ -398,7 +421,7 @@ pub async fn run_credentials(
let state = State::get().await?;
let settings = state.settings.read().await;
let metadata = state.metadata.read().await;
let profile = get(path).await?.ok_or_else(|| {
let profile = get(path, None).await?.ok_or_else(|| {
crate::ErrorKind::OtherError(format!(
"Tried to run a nonexistent or unloaded profile at path {}!",
path.display()