import { createFileRoute, useSearch } from '@tanstack/react-router'; import { useFocusable, FocusContext, getCurrentFocusKey } from "@noriginmedia/norigin-spatial-navigation"; import { MissingEmulatorsSection } from "../../../components/store/MissingEmulatorsSection"; import { EmulatorsSection } from "../../../components/store/EmulatorsSection"; import { GamesSection } from "../../../components/store/GamesSection"; import { StatsSection } from "../../../components/store/StatsSection"; import { FrontEndGameTypeDetailed, RPC_URL } from '@/shared/constants'; import { useContext, useEffect, useRef, useState } from 'react'; import { scrollIntoViewHandler } from '@/mainview/scripts/utils'; import { StoreContext } from '@/mainview/scripts/contexts'; import { useInterval } from 'usehooks-ts'; import { Button } from '@/mainview/components/options/Button'; import { Gamepad2, HardDrive, Search, Star } from 'lucide-react'; import { GetFocusedElement } from '@/mainview/scripts/spatialNavigation'; import { useQuery } from '@tanstack/react-query'; import { autoEmulatorsQuery } from '@queries/settings'; import { storeEmulatorsRecommendedQuery, storeFeaturedGamesQuery } from '@queries/store'; export const Route = createFileRoute('/store/tab/')({ component: RouteComponent }); function Main (data: { games?: FrontEndGameTypeDetailed[]; }) { const [selectedGame, setSelectedGame] = useState(0); const [nextSwitch, setNextSwitch] = useState(new Date().getTime() + 10000); const progressRef = useRef(null); const { ref, focusKey } = useFocusable({ focusKey: 'main-featured-area' }); const game = data.games ? data.games[selectedGame] : undefined; useInterval(() => { if (!data.games) return; setSelectedGame(current => (current + 1) % data.games!.length); setNextSwitch(new Date().getTime() + 10000); }, 10000); useEffect(() => { if (!data.games) return; setSelectedGame(new Date().getSeconds() % data.games.length); }, [data.games]); useInterval(() => { var time = (nextSwitch - new Date().getTime()) / 10000; if (progressRef.current) progressRef.current.value = time; }, 10); const storeContext = useContext(StoreContext); const previewUrl = data.games ? new URL(`${RPC_URL(__HOST__)}${data.games[selectedGame].path_cover}`) : undefined; previewUrl?.searchParams.set('blur', '16'); return
{game ?
{ e.currentTarget.classList.toggle('opacity-0', false); e.currentTarget.classList.toggle('scale-110', false); }} />
{!!data.games && }

{game.name}

{game.summary}

:
}
{data.games?.map((g, i) =>
{g.name}
{i === selectedGame && }
) ?? Array.from({ length: 3 }).map((_, i) =>
)}
; } export function RouteComponent () { const { focus } = useSearch({ from: '/store/tab' }); const { data: crucialEmulators, isSuccess } = useQuery({ ...autoEmulatorsQuery, select: (data) => data.filter(e => !e.validSource && e.isCritical) }); const { data: featuredGames } = useQuery(storeFeaturedGamesQuery); const { data: recommendedEmulators } = useQuery(storeEmulatorsRecommendedQuery); const { focusKey, ref, focusSelf } = useFocusable({ focusKey: 'main-area', preferredChildFocusKey: focus ?? "recommended-emulators" }); const storeContext = useContext(StoreContext); useEffect(() => { if (focus && !GetFocusedElement(getCurrentFocusKey())) { focusSelf({ instant: true }); } }, [focus, isSuccess]); return (
{
} {!!crucialEmulators && crucialEmulators?.length > 0 && storeContext.showDetails('emulator', 'store', id, focus)} emulators={crucialEmulators} />}
storeContext.showDetails('emulator', 'store', id, focus)} onFocus={scrollIntoViewHandler({ block: 'end' })} emulators={recommendedEmulators} />

Featured Games

Creator Picks
storeContext.showDetails('game', id.source, id.id, focus)} onFocus={scrollIntoViewHandler({ block: 'center' })} games={featuredGames} />
); }