fix: better handling of datapacks in frontend & desync issues between browse page impl in app and website

This commit is contained in:
Calum H. (IMB11)
2026-06-26 17:09:23 +01:00
parent 7618f9bc09
commit 32ca8d549b
7 changed files with 136 additions and 44 deletions
+15 -4
View File
@@ -24,6 +24,8 @@ import {
provideBrowseManager,
requestInstall,
SelectedProjectsFloatingBar,
stripServerRuntimeInstallFilters,
stripServerRuntimeInstallOverrides,
useBrowseSearch,
useStickyObserver,
useVIntl,
@@ -497,7 +499,13 @@ watch(
router.replace({
path: `/browse/${targetProjectType}`,
query: route.query,
query: {
sid: route.query.sid,
wid: route.query.wid,
shi: route.query.shi,
from: route.query.from,
q: route.query.q,
},
})
},
{ immediate: true },
@@ -708,7 +716,6 @@ async function chooseInstanceInstallVersion(
const selectedVersion = getLatestMatchingInstallVersion(
await getInstallProjectVersions(project.project_id),
selectedPreferences,
projectTypeValue,
)
if (!selectedVersion) {
@@ -790,11 +797,15 @@ function getCardActions(
project: projectResult,
contentType,
mode: isModpack ? 'immediate' : 'queue',
selectedFilters: isModpack ? [] : searchState.currentFilters.value,
selectedFilters: isModpack
? []
: stripServerRuntimeInstallFilters(searchState.currentFilters.value),
providedFilters: isModpack ? [] : combinedProvidedFilters.value,
overriddenProvidedFilterTypes: isModpack
? []
: searchState.overriddenProvidedFilterTypes.value,
: stripServerRuntimeInstallOverrides(
searchState.overriddenProvidedFilterTypes.value,
),
targetPreferences: getServerInstallTargetPreferences(contentType),
getProjectVersions: getInstallProjectVersions,
queue: serverInstallQueue,
@@ -567,6 +567,7 @@ export function createServerInstallContent(opts: {
plans.map((plan) => ({
project_id: plan.projectId,
version_id: plan.versionId,
kind: plan.contentType as Archon.Content.v1.AddonKind,
})),
),
onQueueChange: (plans) => setStoredServerInstallPlans(serverId, worldId, plans),
@@ -21,6 +21,8 @@ import {
readStoredServerInstallQueue,
removePendingServerContentInstall,
requestInstall,
stripServerRuntimeInstallFilters,
stripServerRuntimeInstallOverrides,
useVIntl,
writePendingServerContentInstallBaseline,
writeStoredServerInstallQueue,
@@ -217,6 +219,42 @@ export function useServerInstallContent({
enabled: computed(() => !!currentServerId.value && !!currentWorldId.value),
})
const currentWorld = computed(() => {
if (fromContext.value === 'create-instance') return null
const full = serverFullData.value
if (!full) return null
const worldId = currentWorldId.value
if (worldId) {
return full.worlds.find((world) => world.id === worldId) ?? null
}
return full.worlds.find((world) => world.is_active) ?? full.worlds[0] ?? null
})
const serverContextWorldGameVersion = computed(() => {
const worldGameVersion = currentWorld.value?.content?.game_version
if (currentWorldId.value) return worldGameVersion ?? null
return worldGameVersion ?? serverData.value?.mc_version ?? null
})
const serverContextWorldLoader = computed(() => {
const worldLoader = currentWorld.value?.content?.modloader
if (currentWorldId.value) return worldLoader ?? null
return worldLoader ?? serverData.value?.loader ?? null
})
const serverContextWorldLoaderVersion = computed(() => {
const worldLoaderVersion = currentWorld.value?.content?.modloader_version
if (currentWorldId.value) return worldLoaderVersion ?? null
return worldLoaderVersion ?? serverData.value?.loader_version ?? null
})
const serverContentProjectType = computed(() => {
const loader = serverContextWorldLoader.value?.toLowerCase()
if (!loader) return null
if (loader === 'paper' || loader === 'purpur') return 'plugin'
if (loader === 'vanilla') return 'datapack'
return 'mod'
})
function setBrowseSearchState(state: ServerInstallBrowseSearchState) {
browseSearchState = state
}
@@ -353,12 +391,12 @@ export function useServerInstallContent({
)
const filters: FilterValue[] = []
if (serverData.value && projectType.value?.id !== 'modpack') {
const gameVersion = serverData.value.mc_version
const gameVersion = serverContextWorldGameVersion.value
if (gameVersion) {
filters.push({ type: 'game_version', option: gameVersion })
}
const platform = serverData.value.loader?.toLowerCase()
const platform = serverContextWorldLoader.value?.toLowerCase().replaceAll('_', '')
const modLoaders = ['fabric', 'forge', 'quilt', 'neoforge']
if (platform && modLoaders.includes(platform)) {
@@ -416,8 +454,8 @@ export function useServerInstallContent({
function getServerInstallTargetPreferences(contentType: BrowseInstallContentType) {
return getTargetInstallPreferences(
{
gameVersion: serverData.value?.mc_version,
loader: serverData.value?.loader,
gameVersion: serverContextWorldGameVersion.value,
loader: serverContextWorldLoader.value,
},
contentType,
)
@@ -434,7 +472,11 @@ export function useServerInstallContent({
async function resolveQueuedAddonPlans(plans: BrowseInstallPlan<ServerInstallSearchResult>[]) {
const existingProjectIds = getServerInstalledProjectIds()
const resolvedAddons: Array<{ project_id: string; version_id: string }> = []
const resolvedAddons: Array<{
project_id: string
version_id: string
kind: Archon.Content.v1.AddonKind
}> = []
for (const plan of plans) {
const resolved = await client.labrinth.content_v3.resolve({
@@ -453,6 +495,7 @@ export function useServerInstallContent({
resolvedAddons.push({
project_id: item.project_id,
version_id: item.version_id,
kind: plan.contentType as Archon.Content.v1.AddonKind,
})
}
}
@@ -612,11 +655,15 @@ export function useServerInstallContent({
project,
contentType,
mode: isModpack ? 'immediate' : 'queue',
selectedFilters: isModpack ? [] : browseSearchState.currentFilters.value,
selectedFilters: isModpack
? []
: stripServerRuntimeInstallFilters(browseSearchState.currentFilters.value),
providedFilters: isModpack ? [] : serverFilters.value,
overriddenProvidedFilterTypes: isModpack
? []
: browseSearchState.overriddenProvidedFilterTypes.value,
: stripServerRuntimeInstallOverrides(
browseSearchState.overriddenProvidedFilterTypes.value,
),
targetPreferences: getServerInstallTargetPreferences(contentType),
getProjectVersions: getInstallProjectVersions,
queue: serverInstallQueue,
@@ -753,20 +800,6 @@ export function useServerInstallContent({
? formatMessage(messages.createInstanceModpackHeading)
: formatMessage(commonMessages.installingContentLabel),
)
const currentWorld = computed(() => {
if (fromContext.value === 'create-instance') return null
const full = serverFullData.value
if (!full) return null
const worldId = currentWorldId.value
if (worldId) {
return full.worlds.find((world) => world.id === worldId) ?? null
}
return full.worlds.find((world) => world.is_active) ?? full.worlds[0] ?? null
})
const installContext = computed(() => {
if (!serverData.value) return null
return {
@@ -774,10 +807,10 @@ export function useServerInstallContent({
fromContext.value === 'create-instance'
? formatMessage(messages.createInstanceName)
: (currentWorld.value?.name ?? formatMessage(messages.worldFallbackName)),
loader: currentWorld.value?.content?.modloader ?? serverData.value.loader ?? '',
loader: serverContextWorldLoader.value ?? '',
loaderVersion:
currentWorld.value?.content?.modloader_version ?? serverData.value.loader_version ?? '',
gameVersion: currentWorld.value?.content?.game_version ?? serverData.value.mc_version ?? '',
serverContextWorldLoaderVersion.value ?? '',
gameVersion: serverContextWorldGameVersion.value ?? '',
serverId: currentServerId.value,
upstream: serverData.value.upstream,
iconSrc: serverIcon.value,
@@ -843,6 +876,7 @@ export function useServerInstallContent({
currentWorldId,
serverData,
serverContentData,
serverContentProjectType,
serverFilters,
serverHideInstalled,
hideSelectedServerInstalls,
@@ -115,6 +115,7 @@ debug('initial route.params.type:', route.params.type, '→ currentType:', curre
const isServerType = computed(() => currentType.value === 'server')
const projectType = computed(() => tags.value.projectTypes.find((x) => x.id === currentType.value))
const projectTypeId = computed(() => projectType.value?.id ?? 'mod')
watch(
() => projectType.value?.id,
@@ -162,6 +163,7 @@ const {
queuedServerInstallProjectIds,
queuedServerInstallCount,
isInstallingQueuedServerInstalls,
serverContentProjectType,
installContext,
setBrowseSearchState,
syncHiddenInstalledProjectIds,
@@ -174,6 +176,28 @@ const {
onboardingModalRef,
debug,
})
watch(
[currentServerId, fromContext, projectTypeId, serverContentProjectType],
([serverId, from, currentProjectType, targetProjectType]) => {
if (!serverId || from || !targetProjectType) return
if (!['mod', 'plugin', 'datapack'].includes(currentProjectType)) return
if (currentProjectType === targetProjectType) return
navigateTo({
path: `/discover/${targetProjectType}s`,
query: {
sid: route.query.sid,
wid: route.query.wid,
shi: route.query.shi,
from: route.query.from,
q: route.query.q,
},
})
},
{ immediate: true },
)
const stickyInstallHeaderRef = ref<HTMLElement | null>(null)
const { isStuck: isInstallHeaderStuck } = useStickyObserver(
stickyInstallHeaderRef,
@@ -411,8 +435,6 @@ const messages = defineMessages({
},
})
const projectTypeId = computed(() => projectType.value?.id ?? 'mod')
debug('projectTypeId:', projectTypeId.value)
watch(projectTypeId, (val) => debug('projectTypeId changed:', val))