"use client"; import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; import ForumFeedToolbar from "@/components/forum/ForumFeedToolbar"; import { ForumPostCard } from "@/components/forum/ForumPostCard"; import { FORUM_RINGS } from "@/lib/forumRings"; import { threadMatchesQuery } from "@/lib/forumFeedFilter"; import { isPinnedThread, loadForum, sortPinnedThreads, type ForumThread, } from "@/lib/forumState"; import { sortThreads, type ForumSortMode } from "@/lib/forumSort"; export default function VoidAggregateHomePage() { const [threads, setThreads] = useState([]); const [sort, setSort] = useState("hot"); const [ringFilter, setRingFilter] = useState(null); const [search, setSearch] = useState(""); const [hydrated, setHydrated] = useState(false); const [, setVoteBump] = useState(0); useEffect(() => { setThreads(loadForum()); setHydrated(true); }, []); const filtered = useMemo(() => { return threads.filter((t) => { if (ringFilter !== null && t.topicSlug !== ringFilter) return false; return threadMatchesQuery(t, search); }); }, [threads, ringFilter, search]); const { pinnedList, feedList } = useMemo(() => { const pinned = sortPinnedThreads(filtered.filter(isPinnedThread)); const rest = filtered.filter((t) => !isPinnedThread(t)); return { pinnedList: pinned, feedList: sortThreads(rest, sort) }; }, [filtered, sort]); const totalShown = pinnedList.length + feedList.length; return (
{!hydrated ? (

Loading feed…

) : totalShown === 0 ? (

No threads match.

Clear search or pick another ring.

Start a thread
) : ( <> {pinnedList.length ? (

Pinned · rules & mirrors

{pinnedList.map((t) => ( setVoteBump((x) => x + 1)} /> ))}
) : null} {feedList.length ? (
{pinnedList.length ? (

Feed

) : null} {feedList.map((t) => ( setVoteBump((x) => x + 1)} /> ))}
) : null} )}
); }