Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions apps/frontend/src/pages/hosting/manage/[id]/options/loader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,18 @@ const addonsQuery = useQuery({

const modpack = computed(() => addonsQuery.data.value?.modpack ?? null)

const modpackProjectId = computed(() => {
const spec = modpack.value?.spec
return spec?.platform === 'modrinth' ? spec.project_id : null
})

const modpackVersionsQuery = useQuery({
queryKey: computed(() => ['labrinth', 'versions', 'v2', modpack.value?.spec.project_id]),
queryKey: computed(() => ['labrinth', 'versions', 'v2', modpackProjectId.value]),
queryFn: () =>
client.labrinth.versions_v2.getProjectVersions(modpack.value!.spec.project_id, {
client.labrinth.versions_v2.getProjectVersions(modpackProjectId.value!, {
include_changelog: false,
}),
enabled: computed(() => !!modpack.value?.spec.project_id),
enabled: computed(() => !!modpackProjectId.value),
})

const auth = await useAuth()
Expand Down Expand Up @@ -321,17 +326,20 @@ provideInstallationSettings({
}),
isLinked: computed(() => {
const val = !!modpack.value
debug('isLinked:', val, 'modpack:', modpack.value?.spec?.project_id)
debug('isLinked:', val, 'modpack:', modpackProjectId.value)
return val
}),
isBusy: isInstalling,
modpack: computed(() => {
if (!modpack.value) return null
const isLocal = modpack.value.spec.platform === 'local_file'
return {
iconUrl: modpack.value.icon_url,
title: modpack.value.title ?? modpack.value.spec.project_id,
link: `/project/${modpack.value.spec.project_id}`,
title:
modpack.value.title ?? (isLocal ? modpack.value.spec.name : modpack.value.spec.project_id),
link: modpackProjectId.value ? `/project/${modpackProjectId.value}` : undefined,
versionNumber: modpack.value.version_number,
filename: isLocal ? modpack.value.spec.filename : undefined,
owner: modpack.value.owner
? {
id: modpack.value.owner.id,
Expand Down Expand Up @@ -460,7 +468,7 @@ provideInstallationSettings({
},

async reinstallModpack() {
if (!modpack.value) return
if (!modpack.value || modpack.value.spec.platform !== 'modrinth') return
debug(
'reinstallModpack: called, project:',
modpack.value.spec.project_id,
Expand Down Expand Up @@ -531,10 +539,11 @@ provideInstallationSettings({
getCachedModpackVersions: () => modpackVersionsQuery.data.value ?? null,

async fetchModpackVersions() {
debug('fetchModpackVersions: called, project:', modpack.value?.spec.project_id)
debug('fetchModpackVersions: called, project:', modpackProjectId.value)
if (!modpackProjectId.value) throw new Error('No modpack project ID')
try {
const versions = await client.labrinth.versions_v2.getProjectVersions(
modpack.value!.spec.project_id,
modpackProjectId.value,
{
include_changelog: false,
},
Expand Down Expand Up @@ -562,7 +571,7 @@ provideInstallationSettings({
},

async onModpackVersionConfirm(version) {
if (!modpack.value) return
if (!modpackProjectId.value) return
debug('onModpackVersionConfirm: called, version:', version.id)
debug('onModpackVersionConfirm: emitting reinstall before API call')
emit('reinstall')
Expand All @@ -571,7 +580,7 @@ provideInstallationSettings({
content_variant: 'modpack',
spec: {
platform: 'modrinth',
project_id: modpack.value.spec.project_id,
project_id: modpackProjectId.value,
version_id: version.id,
},
soft_override: true,
Expand All @@ -590,18 +599,18 @@ provideInstallationSettings({

updaterModalProps: computed(() => ({
isApp: false,
currentVersionId: modpack.value?.spec.version_id ?? '',
currentVersionId:
modpack.value?.spec.platform === 'modrinth' ? modpack.value.spec.version_id : '',
projectIconUrl: modpack.value?.icon_url ?? undefined,
projectName:
modpack.value?.title ??
modpack.value?.spec.project_id ??
formatMessage(commonMessages.modpackLabel),
modpack.value?.title ?? modpackProjectId.value ?? formatMessage(commonMessages.modpackLabel),
currentGameVersion: addonsQuery.data.value?.game_version ?? server.value?.mc_version ?? '',
currentLoader: addonsQuery.data.value?.modloader ?? server.value?.loader ?? '',
})),

isServer: true,
isApp: false,
showModpackVersionActions: computed(() => modpack.value?.spec.platform === 'modrinth'),

lockPlatform: true,
hideLoaderVersion: true,
Expand Down
13 changes: 12 additions & 1 deletion packages/api-client/src/modules/archon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export namespace Archon {
disabled: boolean
kind: AddonKind
from_modpack: boolean
pack_client_retained: boolean
pack_client_depends: boolean
has_update: string | null
name: string | null
project_id: string | null
Expand Down Expand Up @@ -68,12 +70,21 @@ export namespace Archon {
| 'purpur'
| 'vanilla'

export type ModpackSpec = {
export type ModpackSpecModrinth = {
platform: 'modrinth'
project_id: string
version_id: string
}

export type ModpackSpecLocalFile = {
platform: 'local_file'
filename: string
name: string
description: string | null
}

export type ModpackSpec = ModpackSpecModrinth | ModpackSpecLocalFile

export type ModpackOwner = {
id: string
name: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="flex gap-1.5 items-center justify-between px-3 pr-1.5 py-1.5 rounded-2xl bg-bg">
<div class="grid grid-cols-[auto_1fr] gap-1.5 items-center">
<Avatar :src="icon" size="34px" class="!rounded-xl !shadow-none" />
<Avatar :src="icon" size="34px" class="!rounded-xl !shadow-none" raised />
<div class="flex flex-col items-start overflow-hidden">
<div
v-tooltip="showCustomModpackTooltip ? formatMessage(messages.customModpackTooltip) : name"
Expand All @@ -12,6 +12,14 @@
{{ name }}
</div>
<div
v-if="filename"
v-tooltip="filename"
class="truncate text-sm text-secondary max-w-full"
>
{{ filename }}
</div>
<div
v-if="versionNumber"
v-tooltip="versionNumber"
class="truncate font-medium text-sm max-w-full"
:class="onclickVersion ? 'hover:underline cursor-pointer' : ''"
Expand All @@ -38,7 +46,8 @@ import ButtonStyled from '../../base/ButtonStyled.vue'

defineProps<{
name: string
versionNumber: string
versionNumber?: string
filename?: string
icon?: string
onclickName?: () => void
onclickVersion?: () => void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import { useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
import { truncatedTooltip } from '#ui/utils/truncate'

import type { ContentCardProject, ContentCardVersion, ContentOwner } from '../types'
import type {
ClientWarningType,
ContentCardProject,
ContentCardVersion,
ContentOwner,
} from '../types'

const { formatMessage } = useVIntl()

Expand All @@ -39,6 +44,8 @@ interface Props {
installing?: boolean
hasUpdate?: boolean
isClientOnly?: boolean
clientWarning?: ClientWarningType | null
hideSwitchVersion?: boolean
overflowOptions?: OverflowMenuOption[]
disabled?: boolean
showCheckbox?: boolean
Expand All @@ -55,6 +62,8 @@ const props = withDefaults(defineProps<Props>(), {
installing: false,
hasUpdate: false,
isClientOnly: false,
clientWarning: null,
hideSwitchVersion: false,
overflowOptions: undefined,
disabled: false,
showCheckbox: false,
Expand Down Expand Up @@ -83,6 +92,17 @@ const fileNameRef = ref<HTMLElement | null>(null)

const isDisabled = computed(() => props.disabled || props.installing)

const clientWarningMessage = computed(() => {
switch (props.clientWarning) {
case 'retained':
return commonMessages.clientRetainedWarning
case 'depends':
return commonMessages.clientDependsWarning
default:
return commonMessages.clientOnlyWarning
}
})

const { shift: shiftHeld } = useMagicKeys()
const deleteHovered = ref(false)
</script>
Expand Down Expand Up @@ -147,7 +167,7 @@ const deleteHovered = ref(false)
<TriangleAlertIcon class="size-4 shrink-0 text-orange" />
<template #popper>
<div class="max-w-[18rem] text-sm">
{{ formatMessage(commonMessages.clientOnlyWarning) }}
{{ formatMessage(clientWarningMessage) }}
</div>
</template>
</Tooltip>
Expand Down Expand Up @@ -260,7 +280,11 @@ const deleteHovered = ref(false)
<DownloadIcon class="size-5" />
</button>
</ButtonStyled>
<ButtonStyled v-else-if="hasSwitchVersionListener && version" circular type="transparent">
<ButtonStyled
v-else-if="hasSwitchVersionListener && version && !hideSwitchVersion"
circular
type="transparent"
>
<button
v-tooltip="formatMessage(commonMessages.switchVersionButton)"
:disabled="isDisabled"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ function handleSort(column: ContentCardTableSortColumn) {
:installing="item.installing"
:has-update="item.hasUpdate"
:is-client-only="item.isClientOnly"
:client-warning="item.clientWarning"
:hide-switch-version="item.hideSwitchVersion"
:overflow-options="item.overflowOptions"
:disabled="item.disabled"
:show-checkbox="showSelection"
Expand Down Expand Up @@ -329,6 +331,8 @@ function handleSort(column: ContentCardTableSortColumn) {
:enabled="item.enabled"
:installing="item.installing"
:has-update="item.hasUpdate"
:is-client-only="item.isClientOnly"
:client-warning="item.clientWarning"
:overflow-options="item.overflowOptions"
:disabled="item.disabled"
:show-checkbox="showSelection"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,28 @@ onUnmounted(() => {
class="@container flex flex-col gap-4 rounded-[20px] bg-bg-raised p-6 shadow-md"
:class="{ 'opacity-50': disabled }"
>
<div class="flex flex-wrap items-start justify-between gap-4">
<div class="flex min-w-0 flex-1 items-start gap-4">
<div class="flex flex-wrap items-center justify-between gap-4">
<div class="flex min-w-0 flex-1 items-center gap-4">
<AutoLink :to="projectLink" class="shrink-0">
<Avatar :src="project.icon_url" :alt="project.title" size="5rem" no-shadow raised />
</AutoLink>
<div class="flex flex-col gap-1.5">
<AutoLink
:to="projectLink"
class="text-xl font-semibold leading-8 text-contrast hover:underline"
<div class="flex min-w-0 flex-col gap-1.5">
<div class="flex min-w-0 flex-col">
<AutoLink
:to="projectLink"
class="truncate text-xl font-semibold text-contrast"
:class="projectLink ? 'hover:underline' : ''"
>
{{ project.title }}
</AutoLink>
<span v-if="project.filename" class="truncate text-secondary mb-2">
{{ project.filename }}
</span>
</div>
<div
v-if="owner || version"
class="flex flex-nowrap items-center gap-2 overflow-hidden text-secondary"
>
{{ project.title }}
</AutoLink>
<div class="flex flex-nowrap items-center gap-2 overflow-hidden text-secondary">
<AutoLink
v-if="owner"
:to="owner.link"
Expand Down Expand Up @@ -346,13 +355,16 @@ onUnmounted(() => {
{{ project.description }}
</span>

<div class="flex flex-wrap items-center gap-3">
<div v-if="project.downloads !== undefined" class="flex items-center gap-2 text-secondary">
<div
v-if="project.downloads != null || project.followers != null || categories?.length"
class="flex flex-wrap items-center gap-3"
>
<div v-if="project.downloads != null" class="flex items-center gap-2 text-secondary">
<DownloadIcon class="size-5" />
<span class="font-medium">{{ formatCompact(project.downloads) }}</span>
</div>

<div v-if="project.followers !== undefined" class="flex items-center gap-2 text-secondary">
<div v-if="project.followers != null" class="flex items-center gap-2 text-secondary">
<HeartIcon class="size-5" />
<span class="font-medium">{{ formatCompact(project.followers) }}</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
normalizeProjectType,
} from '#ui/utils/common-messages'

import { isClientOnlyEnvironment } from '../../composables/content-filtering'
import { getClientWarningType, isClientOnlyEnvironment } from '../../composables/content-filtering'
import type { ContentCardTableItem, ContentItem } from '../../types'
import ContentCardTable from '../ContentCardTable.vue'
import ContentSelectionBar from '../ContentSelectionBar.vue'
Expand Down Expand Up @@ -239,7 +239,11 @@ const tableItems = computed<ContentCardTableItem[]>(() =>
}
: undefined,
...(props.enableToggle ? { enabled: item.enabled } : {}),
isClientOnly: isClientOnlyEnvironment(item.environment),
isClientOnly:
isClientOnlyEnvironment(item.environment) ||
!!item.pack_client_retained ||
!!item.pack_client_depends,
clientWarning: getClientWarningType(item),
disabled: disabledIds.value.has(item.file_name),
overflowOptions: [
...(props.switchVersion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@ import { computed, ref, watch } from 'vue'
import { useVIntl } from '#ui/composables/i18n'
import { commonProjectTypeCategoryMessages, normalizeProjectType } from '#ui/utils/common-messages'

import type { ContentItem } from '../types'
import type { ClientWarningType, ContentItem } from '../types'

const CLIENT_ONLY_ENVIRONMENTS = new Set(['client_only', 'singleplayer_only'])

export function isClientOnlyEnvironment(env?: string | null): boolean {
return !!env && CLIENT_ONLY_ENVIRONMENTS.has(env)
}

export function getClientWarningType(item: ContentItem): ClientWarningType | null {
if (item.pack_client_retained) return 'retained'
if (item.pack_client_depends) return 'depends'
if (isClientOnlyEnvironment(item.environment)) return 'environment'
return null
}

export interface ContentFilterOption {
id: string
label: string
Expand Down Expand Up @@ -55,10 +62,7 @@ export function useContentFilters(items: Ref<ContentItem[]>, config?: ContentFil
options.push({ id: 'updates', label: 'Updates' })
}

if (
config?.showClientOnlyFilter &&
items.value.some((m) => isClientOnlyEnvironment(m.environment))
) {
if (config?.showClientOnlyFilter && items.value.some((m) => getClientWarningType(m) !== null)) {
options.push({ id: 'client-only', label: 'Client-only' })
}

Expand Down Expand Up @@ -102,7 +106,7 @@ export function useContentFilters(items: Ref<ContentItem[]>, config?: ContentFil
for (const filter of activeAttributes) {
if (filter === 'updates' && !item.has_update) return false
if (filter === 'disabled' && item.enabled) return false
if (filter === 'client-only' && !isClientOnlyEnvironment(item.environment)) return false
if (filter === 'client-only' && getClientWarningType(item) === null) return false
}

return true
Expand Down
Loading
Loading