fix: show "inspecting modpack"

Shows when determining external files for modpacks which have many overrides/over gb of content files.
This commit is contained in:
Calum H. (IMB11)
2026-08-03 19:09:02 +01:00
parent c3249ee51d
commit 5b369f247b
3 changed files with 129 additions and 37 deletions
+41 -12
View File
@@ -1,5 +1,7 @@
use crate::State;
use crate::data::ModLoader;
use crate::event::LoadingBarType;
use crate::event::emit::{emit_loading, init_loading};
use crate::install::{
InstallErrorContext, InstallPhaseDetails, InstallPhaseId, InstallProgress,
InstallProgressReporter,
@@ -18,7 +20,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::future::Future;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::pin::Pin;
#[derive(Serialize, Deserialize, Eq, PartialEq)]
@@ -153,6 +155,17 @@ pub struct CreatePack {
const MAX_LOCAL_FILE_HASH_LOOKUP_SIZE: u64 = 1024 * 1024 * 1024;
pub(crate) fn get_local_pack_instance(path: &Path) -> CreatePackInstance {
CreatePackInstance {
name: path
.file_stem()
.unwrap_or_default()
.to_string_lossy()
.to_string(),
..Default::default()
}
}
#[derive(Clone, Debug)]
pub struct CreatePackDescription {
pub icon: Option<PathBuf>,
@@ -182,11 +195,23 @@ pub async fn get_instance_from_pack(
..Default::default()
}),
CreatePackLocation::FromFile { path } => {
let file_name = path
.file_stem()
.unwrap_or_default()
.to_string_lossy()
.to_string();
let mut instance = get_local_pack_instance(&path);
let inspection = init_loading(
LoadingBarType::PackImport {
pack_name: instance.name.clone(),
},
100.0,
"Inspecting modpack",
)
.await
.ok();
if let Some(inspection) = &inspection {
let _ = emit_loading(
inspection,
1.0,
Some("Reading local modpack"),
);
}
let is_known_file = if tokio::fs::metadata(&path).await?.len()
<= MAX_LOCAL_FILE_HASH_LOOKUP_SIZE
@@ -214,6 +239,13 @@ pub async fn get_instance_from_pack(
} else {
false
};
if let Some(inspection) = &inspection {
let _ = emit_loading(
inspection,
39.0,
Some("Inspecting modpack files"),
);
}
let external_files_in_modpack =
super::install_mrpack::get_external_files_from_mrpack(
@@ -221,12 +253,9 @@ pub async fn get_instance_from_pack(
)
.await?;
Ok(CreatePackInstance {
name: file_name,
unknown_file: !is_known_file,
external_files_in_modpack,
..Default::default()
})
instance.unknown_file = !is_known_file;
instance.external_files_in_modpack = external_files_in_modpack;
Ok(instance)
}
}
}
+3
View File
@@ -157,6 +157,9 @@ pub enum LoadingBarType {
pack_id: Option<String>,
pack_version: Option<String>,
},
PackImport {
pack_name: String,
},
MinecraftDownload {
instance_id: String,
instance_name: String,
+85 -25
View File
@@ -16,6 +16,7 @@ use crate::ErrorKind;
use crate::api::pack::install_from::{
CreatePackLocation, generate_pack_from_file,
generate_pack_from_version_id_with_reporter, get_instance_from_pack,
get_local_pack_instance,
};
use crate::api::pack::install_mrpack::install_zipped_mrpack_files_with_reporter;
use crate::event::InstancePayloadType;
@@ -163,16 +164,6 @@ pub async fn retry_job(job_id: Uuid) -> crate::Result<InstallJobSnapshot> {
job.state.progress.phase = InstallPhaseId::PreparingInstance;
job.state.progress.progress = None;
job.state.progress.details = InstallPhaseDetails::Empty;
if let Err(error) = prepare_initial_instance(&mut job.state, &state).await {
if let Err(cleanup_error) =
recovery::apply_cleanup(&job.state, &state).await
{
tracing::error!(
"Error cleaning up install job {job_id} retry preparation: {cleanup_error}"
);
}
return Err(error);
}
job.state.record_event(InstallJobEventKind::JobQueued {
kind: job.state.request.kind(),
});
@@ -197,6 +188,42 @@ pub async fn retry_job(job_id: Uuid) -> crate::Result<InstallJobSnapshot> {
return Err(error);
}
};
emit_install_job(&record.snapshot()).await?;
if let Err(error) = prepare_initial_instance(&mut job.state, &state).await {
let error_view = install_error_view(
job.state.progress.phase,
&error,
job.state.context.clone(),
);
if let Err(terminal_error) =
terminalize_failed_job(job_id, job.state, error_view, &state).await
{
tracing::error!(
"Failed to terminalize retried install job {job_id}: {terminal_error}"
);
}
return Err(error);
}
let record = match store::update_state(job_id, &job.state, &state).await {
Ok(record) => record,
Err(error) => {
let error_view = install_error_view(
job.state.progress.phase,
&error,
job.state.context.clone(),
);
if let Err(terminal_error) =
terminalize_failed_job(job_id, job.state, error_view, &state)
.await
{
tracing::error!(
"Failed to terminalize retried install job {job_id}: {terminal_error}"
);
}
return Err(error);
}
};
if let Err(error) =
lock_existing_instance_if_needed(&job.state, &state).await
{
@@ -337,31 +364,39 @@ async fn start(request: InstallRequest) -> crate::Result<InstallJobSnapshot> {
let state = State::get().await?;
let id = Uuid::new_v4();
let mut job_state = InstallJobState::new(request);
set_initial_display(&mut job_state);
let record =
store::insert(id, &job_state, InstallJobStatus::Queued, &state).await?;
emit_install_job(&record.snapshot()).await?;
if let Err(error) = prepare_initial_instance(&mut job_state, &state).await {
if let Err(cleanup_error) =
recovery::apply_cleanup(&job_state, &state).await
let error_view = install_error_view(
job_state.progress.phase,
&error,
job_state.context.clone(),
);
if let Err(terminal_error) =
terminalize_failed_job(id, job_state, error_view, &state).await
{
tracing::error!(
"Error cleaning up install job preparation: {cleanup_error}"
"Failed to terminalize install job {id} after setup error: {terminal_error}"
);
}
return Err(error);
}
let record = match store::insert(
id,
&job_state,
InstallJobStatus::Queued,
&state,
)
.await
{
let record = match store::update_state(id, &job_state, &state).await {
Ok(record) => record,
Err(error) => {
if let Err(cleanup_error) =
recovery::apply_cleanup(&job_state, &state).await
let error_view = install_error_view(
job_state.progress.phase,
&error,
job_state.context.clone(),
);
if let Err(terminal_error) =
terminalize_failed_job(id, job_state, error_view, &state).await
{
tracing::error!(
"Error cleaning up untracked install job {id}: {cleanup_error}"
"Failed to terminalize install job {id} after setup error: {terminal_error}"
);
}
return Err(error);
@@ -422,7 +457,12 @@ async fn prepare_initial_instance(
location,
post_install_edit,
} => {
let preview = get_instance_from_pack(location).await?;
let preview = match location {
CreatePackLocation::FromFile { path } => {
get_local_pack_instance(&path)
}
location => get_instance_from_pack(location).await?,
};
let name = post_install_edit
.as_ref()
.and_then(|edit| edit.name.clone())
@@ -1443,6 +1483,26 @@ fn set_display(
job_state.display = Some(InstallJobDisplay { title, icon });
}
fn set_initial_display(job_state: &mut InstallJobState) {
let display = match &job_state.request {
InstallRequest::CreateModpackInstance { location, .. } => {
match location {
CreatePackLocation::FromVersionId {
title, icon_url, ..
} => Some((title.clone(), icon_url.clone())),
CreatePackLocation::FromFile { path } => {
Some((get_local_pack_instance(path).name, None))
}
}
}
_ => None,
};
if let Some((title, icon)) = display {
set_display(job_state, title, icon);
}
}
fn install_error_view(
phase: InstallPhaseId,
error: &crate::Error,