feat: clean up browse shared layout logic + introduce queuing (#6030)

* feat: clean up edge case behaviour and add queued to install logic

* fix: remove version choice modal

* feat: queued flow

* feat: standardize headers in app on proj pages

* fix: clear btn

* feat: installing floating popup

* fix: lint

* fix: onboarding/reset logic change for modpacks

* qa: big ol qa

* fix: lint

* fix: lint

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
Calum H.
2026-05-09 19:01:23 +00:00
committed by GitHub
co-authored by Prospector
parent 671f6d264a
commit a79b8e0777
40 changed files with 3726 additions and 664 deletions
@@ -6,7 +6,6 @@ import Admonition from '#ui/components/base/Admonition.vue'
import StackedAdmonitions, {
type StackedAdmonitionItem,
} from '#ui/components/base/StackedAdmonitions.vue'
import { ServerIcon } from '#ui/components/servers/icons'
import InstallingBanner, {
type ContentError,
type SyncProgress,
@@ -23,7 +22,6 @@ import UploadAdmonition from './UploadAdmonition.vue'
const props = defineProps<{
syncProgress?: SyncProgress | null
contentError?: ContentError | null
serverImage?: string
}>()
const emit = defineEmits<{
@@ -59,7 +57,13 @@ const isOnContentTab = computed(() => route.path.includes('/content'))
const isOnFilesTab = computed(() => route.path.includes('/files'))
const bannerCoversInstalling = computed(
() => ctx.server.value?.status === 'installing' || ctx.isSyncingContent.value,
() =>
ctx.server.value?.status === 'installing' ||
ctx.isSyncingContent.value ||
ctx.busyReasons.value.some(
(r) =>
r.reason.id === 'servers.busy.installing' || r.reason.id === 'servers.busy.syncing-content',
),
)
function isBackupReason(id: string) {
@@ -165,8 +169,7 @@ type ServerAdmonitionItem = StackedAdmonitionItem & {
const showInstallingBanner = computed(() => {
if (!ctx.server.value) return false
const installing =
ctx.server.value.status === 'installing' || ctx.isSyncingContent.value || !!props.contentError
const installing = bannerCoversInstalling.value || !!props.contentError
if (!installing) return false
if (contentErrorKey.value && dismissedContentErrorKey.value === contentErrorKey.value)
return false
@@ -366,15 +369,12 @@ function onContentErrorDismiss() {
<InstallingBanner
v-if="item.kind === 'installing'"
:progress="syncProgress"
:fallback-phase="isOnContentTab && !syncProgress ? 'Addons' : null"
:content-error="contentError"
:dismissible="dismissible && !!contentError"
@dismiss="onContentErrorDismiss"
@retry="emit('content-retry')"
>
<template #icon>
<ServerIcon :image="serverImage" class="!h-6 !w-6" />
</template>
</InstallingBanner>
/>
<UploadAdmonition v-else-if="item.kind === 'upload'" />
<FileOperationAdmonition
v-else-if="item.kind === 'fs-op'"