mirror of
https://github.com/modrinth/code.git
synced 2026-08-30 19:46:33 +00:00
refactor: move additional files into download dependencies section
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="dependencyRows.length > 0" class="flex flex-col gap-1">
|
<div v-if="downloadRows.length > 0" class="flex flex-col gap-1">
|
||||||
<div
|
<div
|
||||||
v-if="showTitle || downloadableDependencyFiles.length > 0"
|
v-if="showTitle || downloadableDependencyFiles.length > 0"
|
||||||
class="flex flex-wrap items-center justify-between gap-2"
|
class="flex flex-wrap items-center justify-between gap-2"
|
||||||
>
|
>
|
||||||
<h3 v-if="showTitle" class="m-0 text-base font-semibold text-contrast">
|
<h3 v-if="showTitle" class="m-0 text-base font-semibold text-contrast">
|
||||||
{{ formatMessage(messages.dependenciesTitle) }}
|
{{ sectionTitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<ButtonStyled v-if="downloadableDependencyFiles.length > 0" type="transparent">
|
<ButtonStyled v-if="downloadableDependencyFiles.length > 0" type="transparent">
|
||||||
<button :disabled="downloadingDependencies" @click="downloadAllDependencies">
|
<button :disabled="downloadingDependencies" @click="downloadAllDependencies">
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<DownloadDependency
|
<DownloadDependency
|
||||||
v-for="dependency in dependencyRows"
|
v-for="dependency in downloadRows"
|
||||||
:key="dependency.key"
|
:key="dependency.key"
|
||||||
:dependency="dependency"
|
:dependency="dependency"
|
||||||
@download="emit('download')"
|
@download="emit('download')"
|
||||||
@@ -34,11 +34,12 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Labrinth } from '@modrinth/api-client'
|
import type { Labrinth } from '@modrinth/api-client'
|
||||||
import { DownloadIcon, SpinnerIcon } from '@modrinth/assets'
|
import { DownloadIcon, FileIcon, SpinnerIcon } from '@modrinth/assets'
|
||||||
import {
|
import {
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
type CdnDownloadReason,
|
type CdnDownloadReason,
|
||||||
defineMessages,
|
defineMessages,
|
||||||
|
fileTypeMessages,
|
||||||
injectModrinthClient,
|
injectModrinthClient,
|
||||||
injectNotificationManager,
|
injectNotificationManager,
|
||||||
useVIntl,
|
useVIntl,
|
||||||
@@ -46,7 +47,7 @@ import {
|
|||||||
import type { DisplayProjectType } from '@modrinth/utils'
|
import type { DisplayProjectType } from '@modrinth/utils'
|
||||||
import { useQuery } from '@tanstack/vue-query'
|
import { useQuery } from '@tanstack/vue-query'
|
||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
import { computed, ref } from 'vue'
|
import { type Component, computed, ref } from 'vue'
|
||||||
|
|
||||||
import DownloadDependency from './DownloadDependency.vue'
|
import DownloadDependency from './DownloadDependency.vue'
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ interface DownloadDependencyRow {
|
|||||||
key: string
|
key: string
|
||||||
name: string
|
name: string
|
||||||
icon?: string
|
icon?: string
|
||||||
|
fallbackIcon?: Component
|
||||||
projectHref?: string
|
projectHref?: string
|
||||||
downloadHref?: string
|
downloadHref?: string
|
||||||
filename?: string
|
filename?: string
|
||||||
@@ -87,6 +89,7 @@ const props = withDefaults(
|
|||||||
currentGameVersion?: string | null
|
currentGameVersion?: string | null
|
||||||
currentPlatform?: string | null
|
currentPlatform?: string | null
|
||||||
downloadReason?: CdnDownloadReason
|
downloadReason?: CdnDownloadReason
|
||||||
|
additionalFiles?: Labrinth.Versions.v3.VersionFile[]
|
||||||
showTitle?: boolean
|
showTitle?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
@@ -96,6 +99,7 @@ const props = withDefaults(
|
|||||||
currentGameVersion: null,
|
currentGameVersion: null,
|
||||||
currentPlatform: null,
|
currentPlatform: null,
|
||||||
downloadReason: 'standalone',
|
downloadReason: 'standalone',
|
||||||
|
additionalFiles: () => [],
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -258,8 +262,34 @@ const dependencyRows = computed<DownloadDependencyRow[]>(
|
|||||||
() => props.dependencies || resolvedDependencyRows.value,
|
() => props.dependencies || resolvedDependencyRows.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const additionalFileRows = computed<DownloadDependencyRow[]>(() =>
|
||||||
|
props.additionalFiles.map((file) => ({
|
||||||
|
key: `additional-file-${additionalFileKey(file)}`,
|
||||||
|
name: file.filename,
|
||||||
|
fallbackIcon: FileIcon,
|
||||||
|
downloadHref: getDownloadUrl(file.url),
|
||||||
|
filename: file.filename,
|
||||||
|
typeLabel: fileTypeLabel(file.file_type),
|
||||||
|
unavailableTooltip: formatMessage(messages.unavailableFile),
|
||||||
|
dependencies: [],
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|
||||||
|
const downloadRows = computed<DownloadDependencyRow[]>(() => [
|
||||||
|
...dependencyRows.value,
|
||||||
|
...additionalFileRows.value,
|
||||||
|
])
|
||||||
|
|
||||||
|
const sectionTitle = computed(() =>
|
||||||
|
formatMessage(
|
||||||
|
dependencyRows.value.length > 0
|
||||||
|
? messages.dependenciesTitle
|
||||||
|
: messages.additionalFilesTitle,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
const downloadableDependencyFiles = computed<DownloadableDependencyFile[]>(() =>
|
const downloadableDependencyFiles = computed<DownloadableDependencyFile[]>(() =>
|
||||||
collectDownloadableDependencyFiles(dependencyRows.value),
|
collectDownloadableDependencyFiles(downloadRows.value),
|
||||||
)
|
)
|
||||||
|
|
||||||
const dependencyZipFilename = computed(
|
const dependencyZipFilename = computed(
|
||||||
@@ -336,6 +366,14 @@ function getDownloadUrl(url: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fileTypeLabel(type?: Labrinth.Versions.v3.FileType | null) {
|
||||||
|
return formatMessage(fileTypeMessages[type ?? 'unknown'] ?? fileTypeMessages.unknown)
|
||||||
|
}
|
||||||
|
|
||||||
|
function additionalFileKey(file: Labrinth.Versions.v3.VersionFile) {
|
||||||
|
return file.hashes?.sha1 ?? file.filename
|
||||||
|
}
|
||||||
|
|
||||||
function collectDownloadableDependencyFiles(
|
function collectDownloadableDependencyFiles(
|
||||||
rows: DownloadDependencyRow[],
|
rows: DownloadDependencyRow[],
|
||||||
seenHrefs = new Set<string>(),
|
seenHrefs = new Set<string>(),
|
||||||
@@ -458,6 +496,10 @@ const messages = defineMessages({
|
|||||||
id: 'project.download.dependencies-title',
|
id: 'project.download.dependencies-title',
|
||||||
defaultMessage: 'Dependencies',
|
defaultMessage: 'Dependencies',
|
||||||
},
|
},
|
||||||
|
additionalFilesTitle: {
|
||||||
|
id: 'project.download.additional-files-title',
|
||||||
|
defaultMessage: 'Additional files',
|
||||||
|
},
|
||||||
downloadAllDependencies: {
|
downloadAllDependencies: {
|
||||||
id: 'project.download.dependencies-download-all',
|
id: 'project.download.dependencies-download-all',
|
||||||
defaultMessage: 'Download all',
|
defaultMessage: 'Download all',
|
||||||
@@ -502,5 +544,9 @@ const messages = defineMessages({
|
|||||||
id: 'project.download.dependency-unavailable',
|
id: 'project.download.dependency-unavailable',
|
||||||
defaultMessage: 'This dependency cannot be downloaded',
|
defaultMessage: 'This dependency cannot be downloaded',
|
||||||
},
|
},
|
||||||
|
unavailableFile: {
|
||||||
|
id: 'project.download.file-unavailable',
|
||||||
|
defaultMessage: 'This file cannot be downloaded',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -15,7 +15,11 @@
|
|||||||
v-else
|
v-else
|
||||||
class="flex size-4 flex-shrink-0 items-center justify-center rounded-lg border border-solid border-surface-5 text-secondary"
|
class="flex size-4 flex-shrink-0 items-center justify-center rounded-lg border border-solid border-surface-5 text-secondary"
|
||||||
>
|
>
|
||||||
<PackageIcon aria-hidden="true" class="size-5" />
|
<component
|
||||||
|
:is="dependency.fallbackIcon ?? PackageIcon"
|
||||||
|
aria-hidden="true"
|
||||||
|
class="size-5"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
<a
|
<a
|
||||||
v-if="dependency.projectHref"
|
v-if="dependency.projectHref"
|
||||||
@@ -79,7 +83,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DownloadIcon, PackageIcon } from '@modrinth/assets'
|
import { DownloadIcon, PackageIcon } from '@modrinth/assets'
|
||||||
import { Avatar, ButtonStyled, TagItem, truncatedTooltip } from '@modrinth/ui'
|
import { Avatar, ButtonStyled, TagItem, truncatedTooltip } from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
import { type Component, ref } from 'vue'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'DownloadDependency',
|
name: 'DownloadDependency',
|
||||||
@@ -89,6 +93,7 @@ interface DownloadDependencyRow {
|
|||||||
key: string
|
key: string
|
||||||
name: string
|
name: string
|
||||||
icon?: string
|
icon?: string
|
||||||
|
fallbackIcon?: Component
|
||||||
projectHref?: string
|
projectHref?: string
|
||||||
downloadHref?: string
|
downloadHref?: string
|
||||||
filename?: string
|
filename?: string
|
||||||
|
|||||||
@@ -34,49 +34,9 @@
|
|||||||
:current-game-version="currentGameVersion"
|
:current-game-version="currentGameVersion"
|
||||||
:current-platform="currentPlatform"
|
:current-platform="currentPlatform"
|
||||||
:download-reason="downloadReason"
|
:download-reason="downloadReason"
|
||||||
|
:additional-files="additionalFiles"
|
||||||
@download="onDownload"
|
@download="onDownload"
|
||||||
/>
|
/>
|
||||||
<div v-if="additionalFiles.length > 0" class="flex flex-col gap-2">
|
|
||||||
<h3 class="m-0 text-base font-semibold text-contrast">
|
|
||||||
{{ formatMessage(messages.additionalFilesTitle) }}
|
|
||||||
</h3>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<div
|
|
||||||
v-for="file in additionalFiles"
|
|
||||||
:key="additionalFileKey(file)"
|
|
||||||
class="grid min-h-10 grid-cols-[minmax(0,1fr)_min-content] items-center gap-3 rounded-xl bg-button-bg py-0 pl-3.5 pr-2 text-primary"
|
|
||||||
>
|
|
||||||
<span class="flex min-w-0 items-center gap-3">
|
|
||||||
<FileIcon aria-hidden="true" class="size-5 flex-shrink-0 text-secondary" />
|
|
||||||
<span
|
|
||||||
:ref="(element) => setAdditionalFileNameRef(file, element)"
|
|
||||||
v-tooltip="
|
|
||||||
truncatedTooltip(additionalFileNameRefs[additionalFileKey(file)], file.filename)
|
|
||||||
"
|
|
||||||
class="min-w-0 truncate text-base font-semibold text-contrast"
|
|
||||||
>
|
|
||||||
{{ file.filename }}
|
|
||||||
</span>
|
|
||||||
<TagItem
|
|
||||||
class="shrink-0 border !border-solid border-surface-5 !px-3 !py-1 text-base"
|
|
||||||
>
|
|
||||||
{{ fileTypeLabel(file.file_type) }}
|
|
||||||
</TagItem>
|
|
||||||
</span>
|
|
||||||
<ButtonStyled circular type="transparent">
|
|
||||||
<a
|
|
||||||
v-tooltip="'Download'"
|
|
||||||
:href="getDownloadUrl(file.url)"
|
|
||||||
:download="file.filename"
|
|
||||||
:aria-label="`Download ${file.filename}`"
|
|
||||||
@click="onDownload"
|
|
||||||
>
|
|
||||||
<DownloadIcon aria-hidden="true" class="size-6 text-secondary" />
|
|
||||||
</a>
|
|
||||||
</ButtonStyled>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ServersPromo
|
<ServersPromo
|
||||||
v-if="flags.showProjectPageDownloadModalServersPromo"
|
v-if="flags.showProjectPageDownloadModalServersPromo"
|
||||||
@@ -95,24 +55,20 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Labrinth } from '@modrinth/api-client'
|
import type { Labrinth } from '@modrinth/api-client'
|
||||||
import { DownloadIcon, FileIcon } from '@modrinth/assets'
|
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ButtonStyled,
|
|
||||||
type CdnDownloadReason,
|
type CdnDownloadReason,
|
||||||
defineMessages,
|
defineMessages,
|
||||||
fileTypeMessages,
|
|
||||||
injectModrinthClient,
|
injectModrinthClient,
|
||||||
NewModal,
|
NewModal,
|
||||||
ServersPromo,
|
ServersPromo,
|
||||||
TagItem,
|
|
||||||
truncatedTooltip,
|
truncatedTooltip,
|
||||||
useDebugLogger,
|
useDebugLogger,
|
||||||
useVIntl,
|
useVIntl,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
import type { DisplayProjectType } from '@modrinth/utils'
|
import type { DisplayProjectType } from '@modrinth/utils'
|
||||||
import { useQuery } from '@tanstack/vue-query'
|
import { useQuery } from '@tanstack/vue-query'
|
||||||
import { type ComponentPublicInstance, computed, nextTick, onUnmounted, ref, watch } from 'vue'
|
import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
import { navigateTo } from '#app'
|
import { navigateTo } from '#app'
|
||||||
import { saveFeatureFlags } from '~/composables/featureFlags.ts'
|
import { saveFeatureFlags } from '~/composables/featureFlags.ts'
|
||||||
@@ -173,13 +129,11 @@ const route = useRoute()
|
|||||||
const flags = useFeatureFlags()
|
const flags = useFeatureFlags()
|
||||||
const tags = useGeneratedState()
|
const tags = useGeneratedState()
|
||||||
const client = injectModrinthClient()
|
const client = injectModrinthClient()
|
||||||
const { createProjectDownloadUrl } = useCdnDownloadContext()
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
const debug = useDebugLogger('DownloadModal')
|
const debug = useDebugLogger('DownloadModal')
|
||||||
|
|
||||||
const modal = ref<NewModalRef | null>(null)
|
const modal = ref<NewModalRef | null>(null)
|
||||||
const downloadTitleRef = ref<HTMLElement | null>(null)
|
const downloadTitleRef = ref<HTMLElement | null>(null)
|
||||||
const additionalFileNameRefs = ref<Record<string, HTMLElement | null>>({})
|
|
||||||
const modalOpen = ref(false)
|
const modalOpen = ref(false)
|
||||||
const showProjectId = ref<string | null>(null)
|
const showProjectId = ref<string | null>(null)
|
||||||
const showOptions = ref<ResolvedProjectDownloadModalShowOptions>(getDefaultShowOptions())
|
const showOptions = ref<ResolvedProjectDownloadModalShowOptions>(getDefaultShowOptions())
|
||||||
@@ -285,28 +239,8 @@ const messages = defineMessages({
|
|||||||
id: 'project.download.title',
|
id: 'project.download.title',
|
||||||
defaultMessage: 'Download {title}',
|
defaultMessage: 'Download {title}',
|
||||||
},
|
},
|
||||||
additionalFilesTitle: {
|
|
||||||
id: 'project.download.additional-files-title',
|
|
||||||
defaultMessage: 'Additional files',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function fileTypeLabel(type?: Labrinth.Versions.v3.FileType | null) {
|
|
||||||
return formatMessage(fileTypeMessages[type ?? 'unknown'] ?? fileTypeMessages.unknown)
|
|
||||||
}
|
|
||||||
|
|
||||||
function additionalFileKey(file: Labrinth.Versions.v3.VersionFile) {
|
|
||||||
return file.hashes?.sha1 ?? file.filename
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAdditionalFileNameRef(
|
|
||||||
file: Labrinth.Versions.v3.VersionFile,
|
|
||||||
element: Element | ComponentPublicInstance | null,
|
|
||||||
) {
|
|
||||||
additionalFileNameRefs.value[additionalFileKey(file)] =
|
|
||||||
element instanceof HTMLElement ? element : null
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProjectTypeForUrl(
|
function getProjectTypeForUrl(
|
||||||
type: Labrinth.Projects.v2.ProjectType,
|
type: Labrinth.Projects.v2.ProjectType,
|
||||||
loaders: string[],
|
loaders: string[],
|
||||||
@@ -326,14 +260,6 @@ function getProjectTypeForUrl(
|
|||||||
return 'mod'
|
return 'mod'
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDownloadUrl(url: string) {
|
|
||||||
return createProjectDownloadUrl(url, {
|
|
||||||
reason: props.downloadReason,
|
|
||||||
gameVersion: currentGameVersion.value ?? undefined,
|
|
||||||
loader: currentPlatform.value ?? undefined,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateDownloadQuery({
|
function updateDownloadQuery({
|
||||||
gameVersion,
|
gameVersion,
|
||||||
platform,
|
platform,
|
||||||
|
|||||||
Reference in New Issue
Block a user