diff --git a/Cargo.lock b/Cargo.lock
index 6418e594..e88d03e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5099,10 +5099,13 @@ dependencies = [
"derive_more 2.0.1",
"dotenvy",
"eyre",
+ "rust_decimal",
"serde",
+ "serde_json",
"tracing",
"tracing-ecs",
"tracing-subscriber",
+ "utoipa",
]
[[package]]
diff --git a/apps/app-frontend/src/pages/instance/Mods.vue b/apps/app-frontend/src/pages/instance/Mods.vue
index 91b9f70f..a2c3c80e 100644
--- a/apps/app-frontend/src/pages/instance/Mods.vue
+++ b/apps/app-frontend/src/pages/instance/Mods.vue
@@ -301,11 +301,13 @@ import {
get_organization_many,
get_project_many,
get_team_many,
+ get_version,
get_version_many,
} from '@/helpers/cache.js'
import { profile_listener } from '@/helpers/events.js'
import {
add_project_from_path,
+ get,
get_projects,
remove_project,
toggle_disable_project,
@@ -314,6 +316,7 @@ import {
} from '@/helpers/profile.js'
import type { CacheBehaviour, ContentFile, GameInstance } from '@/helpers/types'
import { highlightModInProfile } from '@/helpers/utils.js'
+import { installVersionDependencies } from '@/store/install'
const { handleError } = injectNotificationManager()
@@ -627,10 +630,15 @@ const sortProjects = (filter: string) => {
const updateAll = async () => {
const setProjects = []
+ const outdatedProjects = []
+
for (const [i, project] of projects.value.entries()) {
if (project.outdated) {
project.updating = true
setProjects.push(i)
+ if (project.updateVersion) {
+ outdatedProjects.push(project.updateVersion)
+ }
}
}
@@ -646,6 +654,21 @@ const updateAll = async () => {
projects.value[index].updateVersion = undefined
}
}
+
+ if (outdatedProjects.length > 0) {
+ const profile = await get(props.instance.path).catch(handleError)
+
+ if (profile) {
+ for (const versionId of outdatedProjects) {
+ const versionData = await get_version(versionId, 'must_revalidate').catch(handleError)
+
+ if (versionData) {
+ await installVersionDependencies(profile, versionData).catch(handleError)
+ }
+ }
+ }
+ }
+
for (const project of setProjects) {
projects.value[project].updating = false
}
@@ -662,6 +685,19 @@ const updateProject = async (mod: ProjectListEntry) => {
mod.updating = true
await new Promise((resolve) => setTimeout(resolve, 0))
mod.path = await update_project(props.instance.path, mod.path).catch(handleError)
+
+ if (mod.updateVersion) {
+ const versionData = await get_version(mod.updateVersion, 'must_revalidate').catch(handleError)
+
+ if (versionData) {
+ const profile = await get(props.instance.path).catch(handleError)
+
+ if (profile) {
+ await installVersionDependencies(profile, versionData).catch(handleError)
+ }
+ }
+ }
+
mod.updating = false
mod.outdated = false
diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs
index b354b8d7..9ee5e0a9 100644
--- a/apps/app/src/main.rs
+++ b/apps/app/src/main.rs
@@ -2,6 +2,7 @@
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
+#![recursion_limit = "256"]
use native_dialog::{DialogBuilder, MessageLevel};
use std::env;
diff --git a/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue b/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue
index 2b427934..6d8135de 100644
--- a/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue
+++ b/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue
@@ -85,6 +85,7 @@
@@ -446,6 +447,11 @@ function resetProgress() {
localStorage.removeItem(`modpack-permissions-${props.project.id}`)
localStorage.removeItem(`modpack-permissions-index-${props.project.id}`)
+
+ sessionStorage.removeItem(`modpack-permissions-data-${props.project.id}`)
+ sessionStorage.removeItem(`modpack-permissions-permanent-no-${props.project.id}`)
+ sessionStorage.removeItem(`modpack-permissions-updated-${props.project.id}`)
+
modpackPermissionsComplete.value = false
modpackJudgements.value = {}
@@ -1331,6 +1337,11 @@ function clearProjectLocalStorage() {
localStorage.removeItem(`moderation-actions-${props.project.slug}`)
localStorage.removeItem(`moderation-inputs-${props.project.slug}`)
localStorage.removeItem(`moderation-stage-${props.project.slug}`)
+
+ sessionStorage.removeItem(`modpack-permissions-data-${props.project.id}`)
+ sessionStorage.removeItem(`modpack-permissions-permanent-no-${props.project.id}`)
+ sessionStorage.removeItem(`modpack-permissions-updated-${props.project.id}`)
+
actionStates.value = {}
}
diff --git a/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue b/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue
index 8cdbdbe1..4f96a4b7 100644
--- a/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue
+++ b/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue
@@ -161,6 +161,7 @@ import { computed, onMounted, ref, watch } from 'vue'
const props = defineProps<{
projectId: string
+ projectUpdated: string
modelValue?: ModerationJudgements
}>()
@@ -202,6 +203,10 @@ const permanentNoFiles = useSessionStorage(
},
},
)
+const cachedProjectUpdated = useSessionStorage(
+ `modpack-permissions-updated-${props.projectId}`,
+ null,
+)
const currentIndex = ref(0)
const fileApprovalTypes: ModerationModpackPermissionApprovalType[] = [
@@ -363,11 +368,13 @@ async function fetchModPackData(): Promise {
}
modPackData.value = sortedData
+ cachedProjectUpdated.value = props.projectUpdated
persistAll()
} catch (error) {
console.error('Failed to fetch modpack data:', error)
modPackData.value = []
permanentNoFiles.value = []
+ cachedProjectUpdated.value = props.projectUpdated
persistAll()
}
}
@@ -457,7 +464,10 @@ function getJudgements(): ModerationJudgements {
onMounted(() => {
loadPersistedData()
- if (!modPackData.value) {
+
+ const isStale = cachedProjectUpdated.value !== props.projectUpdated
+
+ if (!modPackData.value || isStale) {
fetchModPackData()
}
})
@@ -477,6 +487,7 @@ watch(
() => props.projectId,
() => {
clearPersistedData()
+ cachedProjectUpdated.value = null
loadPersistedData()
if (!modPackData.value) {
fetchModPackData()
diff --git a/apps/frontend/src/pages/servers/manage/[id]/options/index.vue b/apps/frontend/src/pages/servers/manage/[id]/options/index.vue
index ec7e8047..9f228d4b 100644
--- a/apps/frontend/src/pages/servers/manage/[id]/options/index.vue
+++ b/apps/frontend/src/pages/servers/manage/[id]/options/index.vue
@@ -84,16 +84,19 @@
@change="uploadFile"
/>
-
+
-
@@ -112,8 +115,8 @@