import { kinds, nip19 } from 'nostr-tools' import { useMemo, useState } from 'react' import { Link, useNavigate } from 'react-router-dom' import { A11y, Autoplay, Navigation, Pagination } from 'swiper/modules' import { Swiper, SwiperSlide } from 'swiper/react' import { BlogCard } from '../components/BlogCard' import { GameCard } from '../components/GameCard' import { ModCard } from '../components/ModCard' import { LANDING_PAGE_DATA } from '../constants' import { useDidMount, useGames, useMuteLists, useNDKContext, useNSFWList } from '../hooks' import { appRoutes, getModPageRoute } from '../routes' import { BlogCardDetails, ModDetails } from '../types' import { extractModData, handleModImageError, log, LogType, npubToHex } from '../utils' import '../styles/cardLists.css' import '../styles/SimpleSlider.css' import '../styles/styles.css' // Import Swiper styles import { filterForEventsTaggingId, NDKFilter } from '@nostr-dev-kit/ndk' import 'swiper/css' import 'swiper/css/navigation' import 'swiper/css/pagination' import { extractBlogCardDetails } from 'utils/blog' export const HomePage = () => { const navigate = useNavigate() const games = useGames() const featuredGames = useMemo(() => { return games.filter((game) => LANDING_PAGE_DATA.featuredGames.includes(game['Game Name']) ) }, [games]) return (
{LANDING_PAGE_DATA.featuredSlider.map((naddr) => ( ))}

Cool Games

{featuredGames.map((game) => ( ))}
navigate(appRoutes.games)} > View All

Awesome Mods

{LANDING_PAGE_DATA.awesomeMods.map((naddr) => ( ))}
navigate(appRoutes.mods)} > View All
) } type SlideContentProps = { naddr: string } const SlideContent = ({ naddr }: SlideContentProps) => { const navigate = useNavigate() const { fetchEvent } = useNDKContext() const [mod, setMod] = useState() useDidMount(() => { const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`) const { identifier, kind, pubkey } = decoded.data const ndkFilter: NDKFilter = { '#a': [identifier], authors: [pubkey], kinds: [kind] } fetchEvent(ndkFilter) .then((ndkEvent) => { if (ndkEvent) { const extracted = extractModData(ndkEvent) setMod(extracted) } }) .catch((err) => { log( true, LogType.Error, 'An error occurred in fetching mod details from relays', err ) }) }) if (!mod) return return ( <>

{mod.title}

{mod.summary}

{mod.game}

navigate(getModPageRoute(naddr))} > Check it out
) } type DisplayModProps = { naddr: string } const DisplayMod = ({ naddr }: DisplayModProps) => { const [mod, setMod] = useState() const { fetchEvent } = useNDKContext() useDidMount(() => { const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`) const { identifier, kind, pubkey } = decoded.data const ndkFilter: NDKFilter = { '#a': [identifier], authors: [pubkey], kinds: [kind] } fetchEvent(ndkFilter) .then((ndkEvent) => { if (ndkEvent) { const extracted = extractModData(ndkEvent) setMod(extracted) } }) .catch((err) => { log( true, LogType.Error, 'An error occurred in fetching mod details from relays', err ) }) }) if (!mod) return return } const DisplayLatestMods = () => { const navigate = useNavigate() const { fetchMods } = useNDKContext() const [isFetchingLatestMods, setIsFetchingLatestMods] = useState(true) const [latestMods, setLatestMods] = useState([]) const muteLists = useMuteLists() const nsfwList = useNSFWList() useDidMount(() => { fetchMods({ source: window.location.host }) .then((mods) => { setLatestMods(mods) }) .finally(() => { setIsFetchingLatestMods(false) }) }) const filteredMods = useMemo(() => { const mutedAuthors = [...muteLists.admin.authors, ...muteLists.user.authors] const mutedEvents = [ ...muteLists.admin.replaceableEvents, ...muteLists.user.replaceableEvents ] const filtered = latestMods.filter( (mod) => !mutedAuthors.includes(mod.author) && !mutedEvents.includes(mod.aTag) && !nsfwList.includes(mod.aTag) && !mod.nsfw ) return filtered.slice(0, 4) }, [muteLists, nsfwList, latestMods]) return (

Latest Mods

{isFetchingLatestMods ? ( ) : ( filteredMods.map((mod) => { return }) )}
) } const Spinner = () => { return (
) } const DisplayLatestBlogs = () => { const [blogs, setBlogs] = useState[]>() const { fetchEvents } = useNDKContext() useDidMount(() => { const fetchBlogs = async () => { try { // Show maximum of 4 blog posts // 2 should be featured and the most recent 2 from blog npubs // Populate the filter from known naddr (constants.ts) const filters: NDKFilter[] = [] for (let i = 0; i < LANDING_PAGE_DATA.featuredBlogPosts.length; i++) { try { const naddr = LANDING_PAGE_DATA.featuredBlogPosts[i] const filterId = filterForEventsTaggingId(naddr) if (filterId) { filters.push(filterId) } } catch (error) { // Silently ignore } } // Create a single filter based on multiple #a's const filter = filters.reduce( (filter, id) => { const a = id['#a'] if (a) { filter['#a']?.push(a[0]) } return filter }, { '#a': [] } as NDKFilter ) // Fetch featured blogs posts const featuredBlogPosts = await fetchEvents(filter) // Fetch latest blog npubs posts const blogNpubs = import.meta.env.VITE_BLOG_NPUBS.split(',') const blogHexkeys = blogNpubs .map(npubToHex) .filter((hexkey) => hexkey !== null) // We fetch 4 posts in case of duplicates (from featured) const latestBlogPosts = await fetchEvents({ authors: blogHexkeys, kinds: [kinds.LongFormArticle], limit: 4 }) // Remove duplicates const unique = Array.from( [...featuredBlogPosts, ...latestBlogPosts] .reduce((map, obj) => { map.set(obj.id, obj) return map }, new Map()) .values() ) const latest = unique.slice(0, 4) setBlogs(latest.map(extractBlogCardDetails)) } catch (error) { log( true, LogType.Error, 'An error occurred in fetching blog details from relays', error ) return null } } fetchBlogs() }) return (

Blog Posts

{blogs?.map((b) => ( ))}
View All
) }