fix: various content fixes (#5676)

* fix: wrong lock field

* fix: install_stage locking up due to previous failure stored as stale snapshot

* fix: Error when updating instance
Fixes #5671

* fix: prepr
This commit is contained in:
Calum H.
2026-03-26 22:30:17 +00:00
committed by GitHub
parent 36f62a3285
commit b11b54cbc9
5 changed files with 78 additions and 61 deletions

View File

@@ -294,19 +294,13 @@ pub async fn get_optimal_jre_key(
let state = State::get().await?;
if let Some(profile) = get(path).await? {
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
// Fetch version info from stored profile game_version
let version = minecraft
.versions
.iter()
.find(|it| it.id == profile.game_version)
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Invalid or unknown Minecraft version: {}",
profile.game_version
))
})?;
let (minecraft, version_index) =
crate::launcher::resolve_minecraft_manifest(
&profile.game_version,
&state,
)
.await?;
let version = &minecraft.versions[version_index];
let loader_version = crate::launcher::get_loader_version_from_profile(
&profile.game_version,
@@ -352,14 +346,22 @@ pub async fn install(path: &str, force: bool) -> crate::Result<()> {
if let Some(profile) = get(path).await? {
let result =
crate::launcher::install_minecraft(&profile, None, force).await;
if result.is_err()
&& profile.install_stage != ProfileInstallStage::Installed
{
edit(path, |prof| {
prof.install_stage = ProfileInstallStage::NotInstalled;
async { Ok(()) }
})
.await?;
if result.is_err() {
// Re-read the profile to get the current install_stage, as
// install_minecraft may have changed it (e.g. to MinecraftInstalling)
let current_stage = get(path)
.await
.ok()
.flatten()
.map(|p| p.install_stage)
.unwrap_or(ProfileInstallStage::NotInstalled);
if current_stage != ProfileInstallStage::Installed {
edit(path, |prof| {
prof.install_stage = ProfileInstallStage::NotInstalled;
async { Ok(()) }
})
.await?;
}
}
result?;
} else {

View File

@@ -901,15 +901,13 @@ pub async fn get_profile_protocol_version(
return Ok(Some(*protocol_version));
}
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
let version_index = minecraft
.versions
.iter()
.position(|it| it.id == profile.game_version)
.ok_or(ErrorKind::LauncherError(format!(
"Invalid game version: {}",
profile.game_version
)))?;
let state = State::get().await?;
let (minecraft, version_index) =
crate::launcher::resolve_minecraft_manifest(
&profile.game_version,
&state,
)
.await?;
let version = &minecraft.versions[version_index];
let loader_version = get_loader_version_from_profile(

View File

@@ -189,6 +189,46 @@ pub async fn get_loader_version_from_profile(
}
}
/// Resolves the Minecraft version manifest and finds the index for the given
/// game version. If the version isn't found in the cache, forces a manifest
/// refresh to pick up newly-released versions.
pub async fn resolve_minecraft_manifest(
game_version: &str,
state: &State,
) -> crate::Result<(d::minecraft::VersionManifest, usize)> {
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
if let Some(idx) = minecraft
.versions
.iter()
.position(|it| it.id == game_version)
{
return Ok((minecraft, idx));
}
// Version not found in cache — force a manifest refresh in case it was
// released after the cache was populated.
let refreshed = crate::state::CachedEntry::get_minecraft_manifest(
Some(crate::state::CacheBehaviour::MustRevalidate),
&state.pool,
&state.api_semaphore,
)
.await?
.ok_or_else(|| {
crate::ErrorKind::NoValueFor("minecraft versions".to_string())
})?;
let idx = refreshed
.versions
.iter()
.position(|it| it.id == game_version)
.ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {game_version}"
)))?;
Ok((refreshed, idx))
}
#[tracing::instrument(skip(profile))]
pub async fn install_minecraft(
@@ -219,16 +259,8 @@ pub async fn install_minecraft(
let instance_path =
crate::api::profile::get_full_path(&profile.path).await?;
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
let version_index = minecraft
.versions
.iter()
.position(|it| it.id == profile.game_version)
.ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {}",
profile.game_version
)))?;
let (minecraft, version_index) =
resolve_minecraft_manifest(&profile.game_version, &state).await?;
let version = &minecraft.versions[version_index];
let minecraft_updated = version_index
<= minecraft
@@ -481,15 +513,8 @@ pub async fn launch_minecraft(
let instance_path =
crate::api::profile::get_full_path(&profile.path).await?;
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
let version_index = minecraft
.versions
.iter()
.position(|it| it.id == profile.game_version)
.ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {}",
profile.game_version
)))?;
let (minecraft, version_index) =
resolve_minecraft_manifest(&profile.game_version, &state).await?;
let version = &minecraft.versions[version_index];
let minecraft_updated = version_index
<= minecraft

View File

@@ -51,11 +51,7 @@ export function useContentFilters(items: Ref<ContentItem[]>, config?: ContentFil
}
}
if (
config?.showUpdateFilter &&
!config?.isPackLocked?.value &&
items.value.some((m) => m.has_update)
) {
if (config?.showUpdateFilter && items.value.some((m) => m.has_update)) {
options.push({ id: 'updates', label: 'Updates' })
}

View File

@@ -278,7 +278,7 @@ const tableItems = computed<ContentCardTableItem[]>(() => {
isBulkOperating.value ||
item.installing === true,
installing: item.installing === true,
hasUpdate: !ctx.isPackLocked.value && item.has_update,
hasUpdate: item.has_update,
isClientOnly: isClientOnlyEnvironment(item.environment),
overflowOptions: ctx.getOverflowOptions?.(item),
}
@@ -711,7 +711,7 @@ const confirmUnlinkModal = ref<InstanceType<typeof ConfirmUnlinkModal>>()
</div>
<ButtonStyled
v-if="hasBulkUpdateSupport && !ctx.isPackLocked.value && hasOutdatedProjects"
v-if="hasBulkUpdateSupport && hasOutdatedProjects"
color="green"
type="transparent"
color-fill="text"
@@ -814,11 +814,7 @@ const confirmUnlinkModal = ref<InstanceType<typeof ConfirmUnlinkModal>>()
>
<template #actions>
<ButtonStyled
v-if="
hasBulkUpdateSupport &&
!ctx.isPackLocked.value &&
selectedItems.some((m) => m.has_update)
"
v-if="hasBulkUpdateSupport && selectedItems.some((m) => m.has_update)"
type="transparent"
color="green"
color-fill="text"