diff --git a/components/ModCard.tsx b/components/ModCard.tsx index 64c5c65..d50f1d9 100644 --- a/components/ModCard.tsx +++ b/components/ModCard.tsx @@ -7,6 +7,12 @@ import { useIntl } from 'react-intl' import { IMod } from '../database/models/Mod' import InvisibleLink from './InvisibleLink' +export const LIB_CATEGORIES: ReadonlyArray = ['library', 'api-and-library'] + +export function isLibrary(mod: Pick) { + return mod.categories.some(it => LIB_CATEGORIES.includes(it)) +} + type Scheme = 'highlighted' | 'library' | 'major' export type ModProps = IMod & { @@ -18,12 +24,12 @@ export type ModProps = IMod & { const ICON_SIZE = 200 -const ModCard: FC = ({ websiteUrl, name, icon, library, pages, slug, highlight, fade, ...events }) => { +const ModCard: FC = ({ websiteUrl, categories, name, icon, pages, slug, highlight, fade, ...events }) => { const scheme = useMemo(() => { if (highlight) return 'highlighted' - if (library) return 'library' + if (isLibrary({ categories })) return 'library' if (pages?.some(p => p.mods.find(m => m.slug === slug && m.relevance === 'major'))) return 'major' - }, [library, pages, highlight, slug]) + }, [pages, highlight, slug]) const { formatMessage } = useIntl() @@ -42,7 +48,6 @@ const ModCard: FC = ({ websiteUrl, name, icon, library, pages, slug, h {icon ? {name} : {name}}

{name}

- {library && Library} {pages && pages.length > 0 && }
@@ -75,14 +80,6 @@ const Info = styled.span` } ` -const Lib = styled.span` - background: #0003; - margin: 0.4rem; - margin-left: auto; - padding: 0.2rem 0.5rem; - border-radius: 99999px; -` - const Card = styled.div<{ glow?: boolean; fade?: boolean; scheme?: Scheme }>` position: relative; text-align: center; @@ -100,7 +97,7 @@ const Card = styled.div<{ glow?: boolean; fade?: boolean; scheme?: Scheme }>` ${p => p.scheme === 'library' && css` - background: '#559aed77'; + background: #559aed77; `} ${p => @@ -135,7 +132,7 @@ const Card = styled.div<{ glow?: boolean; fade?: boolean; scheme?: Scheme }>` 'title' 4rem; h3 { - padding: 1rem 0; + padding: 1rem 0.5rem; } img { diff --git a/components/Modlist.tsx b/components/Modlist.tsx index 3e99e36..c6dd845 100644 --- a/components/Modlist.tsx +++ b/components/Modlist.tsx @@ -4,49 +4,51 @@ import { flatten, uniq } from 'lodash' import { invert } from 'polished' import { FC, useCallback, useMemo, useState } from 'react' import { IMod } from '../database/models/Mod' -import ModCard, { ModProps } from './ModCard' +import ModCard, { LIB_CATEGORIES, ModProps, isLibrary } from './ModCard' import useTooltip from './hooks/useTooltip' -// TODO -const HIDDEN_CATEGORIES = ['4780'] +const HIDDEN_CATEGORIES: string[] = ['addons', 'miscellaneous'] const Modlist: FC<{ mods: ModProps[] onHover?: (mod?: IMod) => void -}> = ({ mods, ...events }) => { +}> = ({ mods: rawMods, ...events }) => { const [hoveredCategory, hoverCategory] = useState() const [selectedCategory, selectCategory] = useState() - const libs = useMemo(() => mods.filter(m => m.library).length, [mods]) - const categories = useMemo(() => uniq(flatten(mods.map(m => m.categories))).filter(c => !HIDDEN_CATEGORIES.includes(c)), [mods]) + const mods = useMemo(() => rawMods.map(({ library, ...it }) => (library ? { ...it, categories: [...it.categories, LIB_CATEGORIES[0]] } : it)), [rawMods]) + + const categories = useMemo(() => uniq(flatten(mods.filter(it => !isLibrary(it)).map(m => m.categories))).filter(c => !HIDDEN_CATEGORIES.includes(c)), [mods]) const rankOf = useCallback((mod: IMod) => { let rank = mod.popularityScore ?? 0 - if (mod.library) rank -= 100000000000 + if (isLibrary(mod)) rank -= 100000000000 if (mod.pages?.some(p => p.mods.find(m => m.slug === mod.slug && m.relevance === 'major'))) rank += 1000000000 return rank }, []) - const [librariesShown, showLibraries] = useState(false) - const filtered = useMemo(() => (librariesShown ? mods : mods.filter(it => !it.library)), [mods, librariesShown]) + const librariesShown = useMemo(() => LIB_CATEGORIES.includes(selectedCategory!), [selectedCategory]) - const sorted = useMemo( + const filtered = useMemo( () => - filtered + mods .filter(m => !selectedCategory || m.categories.some(c => c === selectedCategory)) .map(m => ({ ...m, highlight: m.highlight || m.categories.some(c => c === hoveredCategory) })) .sort((a, b) => rankOf(b) - rankOf(a)), - [filtered, hoveredCategory, selectedCategory, rankOf] + [mods, hoveredCategory, selectedCategory, rankOf] ) - const somethingHighlighted = useMemo(() => sorted.some(m => m.highlight), [sorted]) + const nonLibs = useMemo(() => filtered.filter(it => !isLibrary(it)), [filtered]) + const shown = useMemo(() => (librariesShown ? filtered : nonLibs), [librariesShown, filtered, nonLibs]) + + const somethingHighlighted = useMemo(() => shown.some(m => m.highlight), [shown]) const tooltip = useTooltip('mod-info') return ( {tooltip}

- {mods.length - libs} mods ({libs} libraries showLibraries(e.target.checked)} />) + {nonLibs.length} mods ({filtered.length - nonLibs.length} libraries)

@@ -63,7 +65,7 @@ const Modlist: FC<{ - {sorted.map(mod => ( + {shown.map(mod => ( events.onHover?.(mod)} onBlur={() => events.onHover?.()} fade={somethingHighlighted && !mod.highlight} /> ))} diff --git a/database/models/Mod.ts b/database/models/Mod.ts index 40b0cee..7099ed5 100644 --- a/database/models/Mod.ts +++ b/database/models/Mod.ts @@ -4,6 +4,9 @@ import { IPage } from './Page' export interface IMod { id: string name: string + /** + * @deprecated + */ library?: boolean websiteUrl?: string summary?: string