Skip to content
Open
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
5 changes: 2 additions & 3 deletions apps/app-frontend/src/pages/Browse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,8 @@ const instanceFilters = computed(() => {
}

const platform = instance.value.loader
const supportedModLoaders = ['fabric', 'forge', 'quilt', 'neoforge']

if (platform && projectType.value === 'mod' && supportedModLoaders.includes(platform)) {
if (platform && projectType.value === 'mod' && MOD_LOADER_SET.has(platform)) {
filters.push({ type: 'mod_loader', option: platform })
}

Expand Down Expand Up @@ -250,7 +249,7 @@ const serverContextFilters = computed(() => {
if (gameVersion) filters.push({ type: 'game_version', option: gameVersion })

const platform = serverContextServerData.value.loader?.toLowerCase()
if (platform && ['fabric', 'forge', 'quilt', 'neoforge'].includes(platform))
if (platform && MOD_LOADER_SET.has(platform))
filters.push({ type: 'mod_loader', option: platform })
if (platform && ['paper', 'purpur'].includes(platform))
filters.push({ type: 'plugin_loader', option: platform })
Expand Down
2 changes: 2 additions & 0 deletions apps/frontend/src/composables/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface LoaderData {
dataPackLoaders: string[]
modLoaders: string[]
hiddenModLoaders: string[]
hiddenModLoaderSet: ReadonlySet<string>
}

// Re-export types from api-client for convenience
Expand Down Expand Up @@ -115,6 +116,7 @@ export const useGeneratedState = () =>
dataPackLoaders: ['datapack'],
modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift', 'neoforge'],
hiddenModLoaders: ['liteloader', 'modloader', 'rift'],
hiddenModLoaderSet: new Set(['liteloader', 'modloader', 'rift']),
},
projectViewModes: ['list', 'grid', 'gallery'],
approvedStatuses: ['approved', 'archived', 'unlisted', 'private'],
Expand Down
3 changes: 1 addition & 2 deletions apps/frontend/src/pages/discover/[type]/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,7 @@ const serverFilters = computed(() => {

const platform = serverData.value.loader?.toLowerCase()

const modLoaders = ['fabric', 'forge', 'quilt', 'neoforge']
if (platform && modLoaders.includes(platform)) {
if (platform && MOD_LOADER_SET.has(platform)) {
filters.push({ type: 'mod_loader', option: platform })
}

Expand Down
4 changes: 2 additions & 2 deletions packages/assets/generated-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import type { FunctionalComponent, SVGAttributes } from 'vue'

export type IconComponent = FunctionalComponent<SVGAttributes>

import _AffiliateIcon from './icons/affiliate.svg?component'
import _AlignLeftIcon from './icons/align-left.svg?component'
import _ArchiveIcon from './icons/archive.svg?component'
Expand Down Expand Up @@ -392,8 +394,6 @@ import _XCircleIcon from './icons/x-circle.svg?component'
import _ZoomInIcon from './icons/zoom-in.svg?component'
import _ZoomOutIcon from './icons/zoom-out.svg?component'

export type IconComponent = FunctionalComponent<SVGAttributes>

export const AffiliateIcon = _AffiliateIcon
export const AlignLeftIcon = _AlignLeftIcon
export const ArchiveIcon = _ArchiveIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,24 @@ export function useBrowseSearch(options: UseBrowseSearchOptions): BrowseSearchSt
LOADER_FILTER_TYPES.includes(f.type as (typeof LOADER_FILTER_TYPES)[number]),
) || ['resourcepack', 'datapack'].includes(options.projectType.value),
)
const loadersNotForThisType = computed(
() =>
options.tags.value?.loaders
?.filter((loader) => !loader.supported_project_types.includes(options.projectType.value))
?.map((loader) => loader.name) ?? [],
)
const deprioritizedTags = computed(() => [
...selectedFilterTags.value,
...loadersNotForThisType.value,
])
const loadersNotForThisType = computed(() => {
const loaders = options.tags.value?.loaders
if (!loaders) return []
const result: string[] = []
for (const loader of loaders) {
if (!loader.supported_project_types.includes(options.projectType.value)) {
result.push(loader.name)
}
}
return result
})
const deprioritizedTags = computed(() => {
const selected = selectedFilterTags.value
const loaders = loadersNotForThisType.value
if (selected.length === 0) return loaders
if (loaders.length === 0) return selected
return [...selected, ...loaders]
})

const loading = ref(true)
const projectHits = shallowRef<BrowseSearchResponse['projectHits']>([])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ const editingGameVersion = ref(server.value?.mc_version ?? '')
const resetToOnboardingModal = ref<InstanceType<typeof ConfirmModal>>()
const isResettingToOnboarding = ref(false)

const modLoaders = ['fabric', 'forge', 'quilt', 'neoforge']
const modLoaders = SUPPORTED_MOD_LOADERS

function toApiLoaderName(loader: string): string {
return loader === 'neoforge' ? 'neo' : loader
Expand Down
162 changes: 88 additions & 74 deletions packages/ui/src/utils/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,75 @@ export function useSearch(
return formatCategory(formatMessage, categoryName)
}

const modLoaderOptions = computed(() =>
tags.value.loaders
.filter(
(loader) =>
loader.supported_project_types.includes('mod') &&
!loader.supported_project_types.includes('plugin') &&
!loader.supported_project_types.includes('datapack'),
)
.map((loader) => ({
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or' as const,
value: `categories:${loader.name}`,
})),
)

const modpackLoaderOptions = computed(() =>
tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('modpack'))
.map((loader) => ({
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or' as const,
value: `categories:${loader.name}`,
})),
)

const pluginLoaderOptions = computed(() =>
tags.value.loaders
.filter(
(loader) =>
loader.supported_project_types.includes('plugin') &&
!PLUGIN_PLATFORMS.includes(loader.name),
)
.map((loader) => ({
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or' as const,
value: `categories:${loader.name}`,
})),
)

const pluginPlatformOptions = computed(() =>
tags.value.loaders
.filter((loader) => PLUGIN_PLATFORMS.includes(loader.name))
.map((loader) => ({
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or' as const,
value: `categories:${loader.name}`,
})),
)

const shaderLoaderOptions = computed(() =>
tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('shader'))
.map((loader) => ({
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or' as const,
value: `categories:${loader.name}`,
})),
)

const filters = computed(() => {
const categoryFilters: Record<string, FilterType> = {}
for (const category of sortedCategories(tags.value, formatCategoryName, locale.value)) {
Expand Down Expand Up @@ -251,22 +320,7 @@ export function useSearch(
supports_negative_filter: true,
default_values: DEFAULT_MOD_LOADERS,
searchable: false,
options: tags.value.loaders
.filter(
(loader) =>
loader.supported_project_types.includes('mod') &&
!loader.supported_project_types.includes('plugin') &&
!loader.supported_project_types.includes('datapack'),
)
.map((loader) => {
return {
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
}),
options: modLoaderOptions.value,
ordering: projectTypes.value.includes('mod') ? 1 : undefined,
},
{
Expand All @@ -282,17 +336,7 @@ export function useSearch(
query_param: 'g',
supports_negative_filter: true,
searchable: false,
options: tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('modpack'))
.map((loader) => {
return {
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
}),
options: modpackLoaderOptions.value,
},
{
id: 'plugin_loader',
Expand All @@ -307,21 +351,7 @@ export function useSearch(
query_param: 'g',
supports_negative_filter: true,
searchable: false,
options: tags.value.loaders
.filter(
(loader) =>
loader.supported_project_types.includes('plugin') &&
!PLUGIN_PLATFORMS.includes(loader.name),
)
.map((loader) => {
return {
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
}),
options: pluginLoaderOptions.value,
},
{
id: 'plugin_platform',
Expand All @@ -336,17 +366,7 @@ export function useSearch(
query_param: 'g',
supports_negative_filter: true,
searchable: false,
options: tags.value.loaders
.filter((loader) => PLUGIN_PLATFORMS.includes(loader.name))
.map((loader) => {
return {
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
}),
options: pluginPlatformOptions.value,
},
{
id: 'shader_loader',
Expand All @@ -362,17 +382,7 @@ export function useSearch(
searchable: false,
display: 'expandable',
default_values: DEFAULT_SHADER_LOADERS,
options: tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('shader'))
.map((loader) => {
return {
id: loader.name,
formatted_name: formatLoader(formatMessage, loader.name),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
}),
options: shaderLoaderOptions.value,
},
{
id: 'license',
Expand Down Expand Up @@ -436,8 +446,8 @@ export function useSearch(
const filterValues = [...filteredFilters, ...validProvidedFilters]

const parts: string[] = []
const orGroups: Record<string, string[]> = {}
const negativeByType: Record<string, string[]> = {}
const orGroups = new Map<string, string[]>()
const negativeByType = new Map<string, string[]>()

for (const filterValue of filterValues) {
const type = filters.value.find((type) => type.id === filterValue.type)
Expand All @@ -464,22 +474,26 @@ export function useSearch(
if (!field || !val) continue

if (filterValue.negative) {
if (!negativeByType[field]) {
negativeByType[field] = []
const existing = negativeByType.get(field)
if (existing) {
existing.push(val)
} else {
negativeByType.set(field, [val])
}
negativeByType[field].push(val)
} else if (option.method === 'or') {
if (!orGroups[field]) {
orGroups[field] = []
const existing = orGroups.get(field)
if (existing) {
existing.push(val)
} else {
orGroups.set(field, [val])
}
orGroups[field].push(val)
} else {
parts.push(`${field} = ${val === 'true' || val === 'false' ? val : `"${val}"`}`)
}
}
}

for (const [field, values] of Object.entries(orGroups)) {
for (const [field, values] of orGroups) {
if (values.length === 1) {
parts.push(`${field} = "${values[0]}"`)
} else {
Expand All @@ -488,7 +502,7 @@ export function useSearch(
}
}

for (const [field, values] of Object.entries(negativeByType)) {
for (const [field, values] of negativeByType) {
const quoted = values.map((v) => `"${v}"`).join(', ')
parts.push(`${field} NOT IN [${quoted}]`)
}
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/utils/tag-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,10 @@ export const categoryMessages = defineMessages({

export const DEFAULT_MOD_LOADERS: string[] = ['fabric', 'forge', 'neoforge']
export const DEFAULT_SHADER_LOADERS: string[] = ['iris', 'optifine', 'vanilla']
export const SUPPORTED_MOD_LOADERS: string[] = ['fabric', 'forge', 'quilt', 'neoforge']
export const MOD_LOADER_SET: ReadonlySet<string> = new Set(SUPPORTED_MOD_LOADERS)
export const HIDDEN_MOD_LOADERS: string[] = ['liteloader', 'modloader', 'rift']
export const HIDDEN_MOD_LOADER_SET: ReadonlySet<string> = new Set(HIDDEN_MOD_LOADERS)

const DEFAULT_LOADER_NAMES = new Set([...DEFAULT_MOD_LOADERS, ...DEFAULT_SHADER_LOADERS])

Expand Down
Loading