mirror of
https://github.com/modrinth/code.git
synced 2026-09-02 13:05:50 +00:00
feat: if only dependency project is listed, find latest compatible dependency version to download in version page
This commit is contained in:
@@ -311,11 +311,25 @@
|
|||||||
<template #dependencyActions="{ dependency }">
|
<template #dependencyActions="{ dependency }">
|
||||||
<ButtonStyled circular>
|
<ButtonStyled circular>
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
v-if="createDependencyLink(dependency)"
|
v-if="
|
||||||
|
createDependencyLink({
|
||||||
|
project: dependency.project,
|
||||||
|
version: dependency.version ?? getDependencyVersion(dependency.dependency),
|
||||||
|
})
|
||||||
|
"
|
||||||
v-tooltip="
|
v-tooltip="
|
||||||
formatMessage(dependency.version ? messages.viewVersion : messages.viewProject)
|
formatMessage(
|
||||||
|
(dependency.version ?? getDependencyVersion(dependency.dependency))
|
||||||
|
? messages.viewVersion
|
||||||
|
: messages.viewProject,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:to="
|
||||||
|
createDependencyLink({
|
||||||
|
project: dependency.project,
|
||||||
|
version: dependency.version ?? getDependencyVersion(dependency.dependency),
|
||||||
|
})
|
||||||
"
|
"
|
||||||
:to="createDependencyLink(dependency)"
|
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<ExternalIcon />
|
<ExternalIcon />
|
||||||
@@ -324,26 +338,29 @@
|
|||||||
<ButtonStyled circular color="brand" color-fill="text">
|
<ButtonStyled circular color="brand" color-fill="text">
|
||||||
<a
|
<a
|
||||||
v-if="
|
v-if="
|
||||||
dependency.version && dependency.dependency.dependency_type !== 'incompatible'
|
(dependency.version ?? getDependencyVersion(dependency.dependency)) &&
|
||||||
|
dependency.dependency.dependency_type !== 'incompatible'
|
||||||
"
|
"
|
||||||
v-tooltip="
|
v-tooltip="
|
||||||
dependencyVersionPrimaryFiles[dependency.version.id]
|
getDependencyPrimaryFileTooltip(
|
||||||
? dependencyVersionPrimaryFiles[dependency.version.id].filename +
|
dependency.version ?? getDependencyVersion(dependency.dependency),
|
||||||
' (' +
|
|
||||||
formatBytes(dependencyVersionPrimaryFiles[dependency.version.id].size) +
|
|
||||||
')'
|
|
||||||
: formatMessage(messages.noPrimaryFile)
|
|
||||||
"
|
|
||||||
:href="
|
|
||||||
createProjectDownloadUrl(
|
|
||||||
dependencyVersionPrimaryFiles[dependency.version.id].url,
|
|
||||||
{
|
|
||||||
reason: 'dependency',
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
:download="dependencyVersionPrimaryFiles[dependency.version.id].filename"
|
:href="
|
||||||
:disabled="dependencyVersionPrimaryFiles[dependency.version.id].url === undefined"
|
getDependencyDownloadUrl(
|
||||||
|
dependency.version ?? getDependencyVersion(dependency.dependency),
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:download="
|
||||||
|
getDependencyPrimaryFile(
|
||||||
|
dependency.version ?? getDependencyVersion(dependency.dependency),
|
||||||
|
)?.filename
|
||||||
|
"
|
||||||
|
:disabled="
|
||||||
|
!getDependencyPrimaryFile(
|
||||||
|
dependency.version ?? getDependencyVersion(dependency.dependency),
|
||||||
|
)?.url
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<DownloadIcon />
|
<DownloadIcon />
|
||||||
</a>
|
</a>
|
||||||
@@ -658,6 +675,73 @@ watch(
|
|||||||
|
|
||||||
const enrichment = computed(() => contextDependencies.value ?? undefined)
|
const enrichment = computed(() => contextDependencies.value ?? undefined)
|
||||||
|
|
||||||
|
const projectOnlyDependencyProjectIds = computed(() => {
|
||||||
|
const projectIds = new Set<string>()
|
||||||
|
for (const dependency of version.value?.dependencies ?? []) {
|
||||||
|
if (
|
||||||
|
dependency.project_id &&
|
||||||
|
!dependency.version_id &&
|
||||||
|
dependency.dependency_type !== 'incompatible'
|
||||||
|
) {
|
||||||
|
projectIds.add(dependency.project_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [...projectIds]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dependencyResolutionLoaders = computed(() => {
|
||||||
|
if (!version.value) return []
|
||||||
|
if (version.value.loaders.includes('mrpack')) {
|
||||||
|
return (version.value.mrpack_loaders ?? []).filter((loader) => loader !== 'minecraft')
|
||||||
|
}
|
||||||
|
return version.value.loaders
|
||||||
|
})
|
||||||
|
|
||||||
|
const { data: projectOnlyDependencyVersions } = useQuery({
|
||||||
|
queryKey: computed(
|
||||||
|
() =>
|
||||||
|
[
|
||||||
|
'version-page',
|
||||||
|
'project-only-dependency-versions',
|
||||||
|
version.value?.id,
|
||||||
|
version.value?.game_versions ?? [],
|
||||||
|
dependencyResolutionLoaders.value,
|
||||||
|
projectOnlyDependencyProjectIds.value,
|
||||||
|
] as const,
|
||||||
|
),
|
||||||
|
queryFn: async () => {
|
||||||
|
const currentVersion = version.value!
|
||||||
|
const entries = await Promise.all(
|
||||||
|
projectOnlyDependencyProjectIds.value.map(async (projectId) => {
|
||||||
|
let versions: Labrinth.Versions.v2.Version[] = []
|
||||||
|
try {
|
||||||
|
versions = await client.labrinth.versions_v2.getProjectVersions(projectId, {
|
||||||
|
game_versions: currentVersion.game_versions,
|
||||||
|
loaders: dependencyResolutionLoaders.value,
|
||||||
|
include_changelog: false,
|
||||||
|
limit: 1,
|
||||||
|
})
|
||||||
|
} catch {
|
||||||
|
return [projectId, undefined] as const
|
||||||
|
}
|
||||||
|
|
||||||
|
return [projectId, versions[0]] as const
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
const versionsByProjectId: Record<string, Labrinth.Versions.v2.Version> = {}
|
||||||
|
for (const [projectId, dependencyVersion] of entries) {
|
||||||
|
if (dependencyVersion) {
|
||||||
|
versionsByProjectId[projectId] = dependencyVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionsByProjectId
|
||||||
|
},
|
||||||
|
enabled: computed(() => !!version.value && projectOnlyDependencyProjectIds.value.length > 0),
|
||||||
|
staleTime: STALE_TIME,
|
||||||
|
})
|
||||||
|
|
||||||
const primaryFile = computed(
|
const primaryFile = computed(
|
||||||
() => version.value?.files?.find((file) => file.primary) ?? version.value?.files?.[0],
|
() => version.value?.files?.find((file) => file.primary) ?? version.value?.files?.[0],
|
||||||
)
|
)
|
||||||
@@ -823,6 +907,10 @@ const messages = defineMessages({
|
|||||||
id: 'version.download.no-primary-file',
|
id: 'version.download.no-primary-file',
|
||||||
defaultMessage: 'Error: No primary file found',
|
defaultMessage: 'Error: No primary file found',
|
||||||
},
|
},
|
||||||
|
downloadVersion: {
|
||||||
|
id: 'version.download.version',
|
||||||
|
defaultMessage: 'Download {version} ({size})',
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
id: 'version.edit.button',
|
id: 'version.edit.button',
|
||||||
defaultMessage: 'Edit',
|
defaultMessage: 'Edit',
|
||||||
@@ -951,13 +1039,20 @@ const copyFileHash = async (
|
|||||||
file: Labrinth.Versions.v3.VersionFile,
|
file: Labrinth.Versions.v3.VersionFile,
|
||||||
method: Labrinth.Versions.v3.FileHashType,
|
method: Labrinth.Versions.v3.FileHashType,
|
||||||
) => {
|
) => {
|
||||||
await navigator.clipboard.writeText(file.hashes[method])
|
await copyToClipboard(file.hashes[method])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyToClipboard(text: string) {
|
||||||
|
await navigator.clipboard.writeText(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
const dependencyVersionPrimaryFiles = computed(() => {
|
const dependencyVersionPrimaryFiles = computed(() => {
|
||||||
const versions = enrichment.value?.versions
|
const versions = [
|
||||||
|
...(enrichment.value?.versions ?? []),
|
||||||
|
...Object.values(projectOnlyDependencyVersions.value ?? {}),
|
||||||
|
]
|
||||||
const primaryFileMap: Record<string, Labrinth.Versions.v2.VersionFile> = {}
|
const primaryFileMap: Record<string, Labrinth.Versions.v2.VersionFile> = {}
|
||||||
versions?.forEach((depVersion) => {
|
versions.forEach((depVersion) => {
|
||||||
const depPrimaryFile = depVersion.files.find((file) => file.primary) ?? depVersion.files[0]
|
const depPrimaryFile = depVersion.files.find((file) => file.primary) ?? depVersion.files[0]
|
||||||
|
|
||||||
primaryFileMap[depVersion.id] = depPrimaryFile
|
primaryFileMap[depVersion.id] = depPrimaryFile
|
||||||
@@ -965,6 +1060,37 @@ const dependencyVersionPrimaryFiles = computed(() => {
|
|||||||
return primaryFileMap
|
return primaryFileMap
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function getDependencyVersion(dependency: Labrinth.Versions.v3.Dependency) {
|
||||||
|
if (dependency.version_id || !dependency.project_id) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectOnlyDependencyVersions.value?.[dependency.project_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDependencyPrimaryFile(version?: Labrinth.Versions.v2.Version) {
|
||||||
|
return version ? dependencyVersionPrimaryFiles.value[version.id] : undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDependencyPrimaryFileTooltip(version?: Labrinth.Versions.v2.Version) {
|
||||||
|
const dependencyPrimaryFile = getDependencyPrimaryFile(version)
|
||||||
|
return dependencyPrimaryFile
|
||||||
|
? formatMessage(messages.downloadVersion, {
|
||||||
|
version: version?.name || version?.version_number || dependencyPrimaryFile.filename,
|
||||||
|
size: formatBytes(dependencyPrimaryFile.size),
|
||||||
|
})
|
||||||
|
: formatMessage(messages.noPrimaryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDependencyDownloadUrl(version?: Labrinth.Versions.v2.Version) {
|
||||||
|
const dependencyPrimaryFile = getDependencyPrimaryFile(version)
|
||||||
|
return dependencyPrimaryFile?.url
|
||||||
|
? createProjectDownloadUrl(dependencyPrimaryFile.url, {
|
||||||
|
reason: 'dependency',
|
||||||
|
})
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
function createDependencyLink(context: {
|
function createDependencyLink(context: {
|
||||||
project?: Labrinth.Projects.v2.Project
|
project?: Labrinth.Projects.v2.Project
|
||||||
version?: Labrinth.Versions.v2.Version
|
version?: Labrinth.Versions.v2.Version
|
||||||
|
|||||||
Reference in New Issue
Block a user