mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 17:14:50 +00:00
* feat: implement access tab with dummy data * fix: spacing * feat: qa * feat: implement backend * qa: qa pass * feat: fix user "search" * fix: lint * feat: change to bitfield * feat: fix fields * fix: lint * fix: lint * feat: hook up api * feat: fix permissions * feat: audit log table event start * feat: better mobile mode for audit log table * feat: i18n * feat: qa * feat: enforce permissions * feat: email template start * feat: qa * fix: tooltip bug * feat: qa * impl: sse support in api-client * feat: sse impl * fix: desync path * feat: time frame picker from analytics * feat: QA * fix: spacing * fix: permisison audit log entries * fix: hosting manage page shared server detection * fix: lint * feat: qa + lint * feat: audit log table sort by time * feat: finish frontend panel stuff * fix: lint * fix: backend alignment * fix: lint * fix: supress friend errors * feat: qa * fix: qa * fix: lint * fix: utils barrel * fix: safari cookies in dev * fix: pin nuxt * feat: fixes + notif fix * fix: notifications * feat: qa * fix: notification sync not happening immediately * fix: qa * fix: qa * feat: qa * blog + prepr * feat: toast shit * blog images * thumbnail update one last time * prepr * feat: use reinvite route * update images * fix: reinvite stuff * fix: lint * fix: alignment of save bar * fix: notif sizing * fix: split up access * fix: lint * fix: lint * fix: link --------- Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
150 lines
3.6 KiB
TypeScript
150 lines
3.6 KiB
TypeScript
import type { FilterValue } from '@modrinth/ui'
|
|
import { LOADER_FILTER_TYPES } from '@modrinth/ui'
|
|
|
|
const TEN_MINUTES = 600
|
|
|
|
export type DownloadContext = {
|
|
gameVersion?: string
|
|
loader?: string
|
|
reason?: 'standalone' | 'dependency' | 'modpack' | 'update'
|
|
}
|
|
|
|
export type FilterSelection = {
|
|
gameVersion?: string
|
|
loader?: string
|
|
}
|
|
|
|
const cookieDefaults = {
|
|
maxAge: TEN_MINUTES,
|
|
sameSite: 'lax' as const,
|
|
path: '/',
|
|
httpOnly: false,
|
|
}
|
|
|
|
function readCookieValue(value: string | null | undefined): string | undefined {
|
|
if (typeof value !== 'string' || !value) {
|
|
return undefined
|
|
}
|
|
return value
|
|
}
|
|
|
|
function newFilterSelection(
|
|
gameVersion: string | undefined,
|
|
loader: string | undefined,
|
|
): FilterSelection | null {
|
|
if (!gameVersion && !loader) {
|
|
return null
|
|
} else if (!gameVersion) {
|
|
return {
|
|
loader,
|
|
}
|
|
} else if (!loader) {
|
|
return {
|
|
gameVersion,
|
|
}
|
|
} else {
|
|
return {
|
|
gameVersion,
|
|
loader,
|
|
}
|
|
}
|
|
}
|
|
|
|
export function useCdnDownloadContext() {
|
|
const config = useRuntimeConfig()
|
|
const cookieOptions = {
|
|
...cookieDefaults,
|
|
secure: config.public.cookieSecure,
|
|
}
|
|
|
|
const filterGameVersionCookie = useCookie<string | null>('mr_download_filter_game_version', {
|
|
...cookieOptions,
|
|
default: () => null,
|
|
})
|
|
|
|
const filterLoaderCookie = useCookie<string | null>('mr_download_filter_loader', {
|
|
...cookieOptions,
|
|
default: () => null,
|
|
})
|
|
|
|
function createProjectDownloadUrl(originalUrl: string, context?: DownloadContext): string {
|
|
if (
|
|
typeof originalUrl !== 'string' ||
|
|
!originalUrl ||
|
|
!originalUrl.startsWith('https://cdn.modrinth.com')
|
|
) {
|
|
return originalUrl
|
|
}
|
|
|
|
const reason = context?.reason
|
|
const gameVersion = context?.gameVersion ?? readCookieValue(filterGameVersionCookie.value)
|
|
const loader = context?.loader ?? readCookieValue(filterLoaderCookie.value)
|
|
|
|
try {
|
|
const url = new URL(originalUrl)
|
|
|
|
if (reason) {
|
|
url.searchParams.set('mr_download_reason', reason)
|
|
}
|
|
if (gameVersion) {
|
|
url.searchParams.set('mr_game_version', gameVersion)
|
|
} else {
|
|
url.searchParams.delete('mr_game_version')
|
|
}
|
|
|
|
if (loader) {
|
|
url.searchParams.set('mr_loader', loader)
|
|
} else {
|
|
url.searchParams.delete('mr_loader')
|
|
}
|
|
return url.toString()
|
|
} catch {
|
|
return originalUrl
|
|
}
|
|
}
|
|
|
|
function persistFilterSelection(selection: FilterSelection | null) {
|
|
if (!selection) {
|
|
filterGameVersionCookie.value = null
|
|
filterLoaderCookie.value = null
|
|
return
|
|
}
|
|
filterGameVersionCookie.value = selection.gameVersion ?? null
|
|
filterLoaderCookie.value = selection.loader ?? null
|
|
}
|
|
|
|
function updateDiscoverFilterContext(filters: FilterValue[]) {
|
|
if (!import.meta.client) {
|
|
return
|
|
}
|
|
const versionFilters = [
|
|
...new Set(filters.filter((f) => f.type === 'game_version').map((f) => f.option)),
|
|
]
|
|
const loaderFilters = [
|
|
...new Set(
|
|
filters
|
|
.filter((f) => (LOADER_FILTER_TYPES as readonly string[]).includes(f.type))
|
|
.map((f) => f.option),
|
|
),
|
|
]
|
|
const gameVersion = versionFilters.length === 1 ? versionFilters[0] : undefined
|
|
const loader = loaderFilters.length === 1 ? loaderFilters[0] : undefined
|
|
persistFilterSelection(newFilterSelection(gameVersion, loader))
|
|
}
|
|
|
|
function updateVersionsFilterContext(gameVersions: string[], loaders: string[]) {
|
|
if (!import.meta.client) {
|
|
return
|
|
}
|
|
const gameVersion = gameVersions.length === 1 ? gameVersions[0] : undefined
|
|
const loader = loaders.length === 1 ? loaders[0] : undefined
|
|
persistFilterSelection(newFilterSelection(gameVersion, loader))
|
|
}
|
|
|
|
return {
|
|
createProjectDownloadUrl,
|
|
updateDiscoverFilterContext,
|
|
updateVersionsFilterContext,
|
|
}
|
|
}
|