mirror of
https://github.com/modrinth/code.git
synced 2026-08-26 17:44:50 +00:00
Revert "feat: sync individual content installation states on panel (#6909)"
This reverts commit 9628b4c269.
268 lines
7.3 KiB
Vue
268 lines
7.3 KiB
Vue
<template>
|
|
<Admonition
|
|
:type="contentError ? 'critical' : 'info'"
|
|
:dismissible="dismissible"
|
|
:progress="progressValue"
|
|
progress-color="blue"
|
|
:waiting="isWaiting"
|
|
@dismiss="emit('dismiss')"
|
|
>
|
|
<template #header>
|
|
{{ headerLabel }}
|
|
</template>
|
|
<template v-if="contentError">
|
|
{{ errorLabel }}
|
|
</template>
|
|
<template v-else-if="effectivePhase">{{ phaseLabel }}</template>
|
|
<div v-else class="ticker-container">
|
|
<div class="ticker-content">
|
|
<div
|
|
v-for="(message, index) in tickerMessages"
|
|
:key="message"
|
|
class="ticker-item"
|
|
:class="{ active: index === currentIndex % tickerMessages.length }"
|
|
>
|
|
{{ message }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<template v-if="contentError" #top-right-actions>
|
|
<Button
|
|
v-tooltip="retryDisabled ? retryDisabledTooltip : undefined"
|
|
type="outlined"
|
|
class="!border !text-red [&>svg]:!text-red !shadow-[inset_0_0_0_1px_var(--color-red)]"
|
|
native-type="button"
|
|
:disabled="retryDisabled"
|
|
@click="emit('retry')"
|
|
>
|
|
<RotateCounterClockwiseIcon class="size-5" />
|
|
{{ formatMessage(commonMessages.retryButton) }}
|
|
</Button>
|
|
</template>
|
|
</Admonition>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { RotateCounterClockwiseIcon } from '@modrinth/assets'
|
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
|
|
import { Button } from '#ui/components/base/buttons'
|
|
import { defineMessages, useVIntl } from '#ui/composables/i18n'
|
|
import { commonMessages } from '#ui/utils/common-messages'
|
|
|
|
import Admonition from '../base/Admonition.vue'
|
|
|
|
export interface SyncProgress {
|
|
phase: 'Analyzing' | 'InstallingPack' | 'InstallingLoader' | 'Addons'
|
|
percent: number
|
|
}
|
|
|
|
export interface ContentError {
|
|
step: string
|
|
description: string
|
|
}
|
|
|
|
const props = defineProps<{
|
|
progress?: SyncProgress | null
|
|
fallbackPhase?: SyncProgress['phase'] | null
|
|
contentError?: ContentError | null
|
|
dismissible?: boolean
|
|
retryDisabled?: boolean
|
|
retryDisabledTooltip?: string
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
retry: []
|
|
dismiss: []
|
|
}>()
|
|
|
|
const { formatMessage } = useVIntl()
|
|
|
|
const messages = defineMessages({
|
|
errorHeader: {
|
|
id: 'servers.installing-banner.error.header',
|
|
defaultMessage: 'Installation failed',
|
|
},
|
|
preparingHeader: {
|
|
id: 'servers.installing-banner.preparing.header',
|
|
defaultMessage: "We're preparing your server",
|
|
},
|
|
invalidLoaderVersionError: {
|
|
id: 'servers.installing-banner.error.invalid-loader-version',
|
|
defaultMessage:
|
|
'The specified loader or Minecraft version could not be installed. It may be invalid or unsupported.',
|
|
},
|
|
unsupportedLoaderVersionError: {
|
|
id: 'servers.installing-banner.error.unsupported-loader-version',
|
|
defaultMessage: 'This version of Minecraft or loader is not yet supported by Modrinth Hosting.',
|
|
},
|
|
internalPlatformError: {
|
|
id: 'servers.installing-banner.error.internal-platform',
|
|
defaultMessage: 'An internal error occurred while installing the platform. Please try again.',
|
|
},
|
|
noPrimaryFileError: {
|
|
id: 'servers.installing-banner.error.no-primary-file',
|
|
defaultMessage:
|
|
'This modpack version does not include a downloadable file. It may have been packaged incorrectly.',
|
|
},
|
|
modpackInstallFailedError: {
|
|
id: 'servers.installing-banner.error.modpack-install-failed',
|
|
defaultMessage: 'The modpack could not be installed. It may be corrupted or incompatible.',
|
|
},
|
|
unknownError: {
|
|
id: 'servers.installing-banner.error.unknown',
|
|
defaultMessage: 'An unexpected error occurred during installation.',
|
|
},
|
|
installingPlatform: {
|
|
id: 'servers.installing-banner.phase.installing-platform',
|
|
defaultMessage: 'Installing platform...',
|
|
},
|
|
installingModpack: {
|
|
id: 'servers.installing-banner.phase.installing-modpack',
|
|
defaultMessage: 'Installing modpack...',
|
|
},
|
|
installingAddons: {
|
|
id: 'servers.installing-banner.phase.installing-addons',
|
|
defaultMessage: 'Installing addons...',
|
|
},
|
|
tickerOrganizingFiles: {
|
|
id: 'servers.installing-banner.ticker.organizing-files',
|
|
defaultMessage: 'Organizing files...',
|
|
},
|
|
tickerDownloadingMods: {
|
|
id: 'servers.installing-banner.ticker.downloading-mods',
|
|
defaultMessage: 'Downloading mods...',
|
|
},
|
|
tickerConfiguringServer: {
|
|
id: 'servers.installing-banner.ticker.configuring-server',
|
|
defaultMessage: 'Configuring server...',
|
|
},
|
|
tickerSettingUpEnvironment: {
|
|
id: 'servers.installing-banner.ticker.setting-up-environment',
|
|
defaultMessage: 'Setting up environment...',
|
|
},
|
|
tickerAddingJava: {
|
|
id: 'servers.installing-banner.ticker.adding-java',
|
|
defaultMessage: 'Adding Java...',
|
|
},
|
|
})
|
|
|
|
const errorLabel = computed(() => {
|
|
const desc = props.contentError?.description?.toLowerCase()
|
|
const step = props.contentError?.step
|
|
|
|
if (step === 'modloader') {
|
|
if (desc === 'the specified version may be incorrect') {
|
|
return formatMessage(messages.invalidLoaderVersionError)
|
|
}
|
|
if (desc === 'this version is not yet supported') {
|
|
return formatMessage(messages.unsupportedLoaderVersionError)
|
|
}
|
|
if (desc === 'internal error') {
|
|
return formatMessage(messages.internalPlatformError)
|
|
}
|
|
}
|
|
|
|
if (step === 'modpack') {
|
|
if (desc?.includes('no primary file')) {
|
|
return formatMessage(messages.noPrimaryFileError)
|
|
}
|
|
if (desc?.includes('failed to install')) {
|
|
return formatMessage(messages.modpackInstallFailedError)
|
|
}
|
|
}
|
|
|
|
return props.contentError?.description ?? formatMessage(messages.unknownError)
|
|
})
|
|
|
|
const effectivePhase = computed(() => props.progress?.phase ?? props.fallbackPhase ?? null)
|
|
|
|
const headerLabel = computed(() => {
|
|
if (props.contentError) return formatMessage(messages.errorHeader)
|
|
if (effectivePhase.value === 'Addons') return formatMessage(commonMessages.installingContentLabel)
|
|
return formatMessage(messages.preparingHeader)
|
|
})
|
|
|
|
const phaseLabel = computed(() => {
|
|
switch (effectivePhase.value) {
|
|
case 'InstallingLoader':
|
|
return formatMessage(messages.installingPlatform)
|
|
case 'InstallingPack':
|
|
return formatMessage(messages.installingModpack)
|
|
case 'Addons':
|
|
return formatMessage(messages.installingAddons)
|
|
default:
|
|
return formatMessage(commonMessages.installingLabel)
|
|
}
|
|
})
|
|
|
|
const progressValue = computed(() => {
|
|
if (props.contentError) return undefined
|
|
return props.progress ? props.progress.percent / 100 : 0
|
|
})
|
|
|
|
const isWaiting = computed(() => {
|
|
if (props.contentError) return false
|
|
return !props.progress || props.progress.percent <= 0
|
|
})
|
|
|
|
const tickerMessages = computed(() => [
|
|
formatMessage(messages.tickerOrganizingFiles),
|
|
formatMessage(messages.tickerDownloadingMods),
|
|
formatMessage(messages.tickerConfiguringServer),
|
|
formatMessage(messages.tickerSettingUpEnvironment),
|
|
formatMessage(messages.tickerAddingJava),
|
|
])
|
|
|
|
const currentIndex = ref(0)
|
|
|
|
let intervalId: ReturnType<typeof setInterval> | null = null
|
|
|
|
onMounted(() => {
|
|
intervalId = setInterval(() => {
|
|
currentIndex.value = (currentIndex.value + 1) % tickerMessages.value.length
|
|
}, 3000)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
if (intervalId) {
|
|
clearInterval(intervalId)
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.ticker-container {
|
|
height: 20px;
|
|
width: 100%;
|
|
position: relative;
|
|
}
|
|
|
|
.ticker-content {
|
|
position: relative;
|
|
width: 100%;
|
|
}
|
|
|
|
.ticker-item {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
white-space: nowrap;
|
|
color: var(--color-secondary-text);
|
|
opacity: 0;
|
|
transform: scale(0.9);
|
|
filter: blur(4px);
|
|
transition: all 0.3s ease-in-out;
|
|
}
|
|
|
|
.ticker-item.active {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
filter: blur(0);
|
|
}
|
|
</style>
|