import { useEffect, useRef, useState } from "react"; import { useFocusable, FocusContext, setFocus, } from "@noriginmedia/norigin-spatial-navigation"; import { createFileRoute } from "@tanstack/react-router"; import { GamePadButtonCode, useShortcutContext, useShortcuts } from "@/mainview/scripts/shortcuts"; import { Router } from "@/mainview"; import Shortcuts from "@/mainview/components/Shortcuts"; import { AnimatedBackground } from "@/mainview/components/AnimatedBackground"; import { PopSource } from "@/mainview/scripts/spatialNavigation"; import { systemApi } from "@/mainview/scripts/clientApi"; import queries from "@/mainview/scripts/queries"; import { Button } from "@/mainview/components/options/Button"; import { ChevronDown, Download, Info, Settings } from "lucide-react"; import { ContextDialog, ContextList, DialogEntry } from "@/mainview/components/ContextDialog"; import { FrontEndEmulator, RPC_URL } from "@/shared/constants"; import Screenshots from "@/mainview/components/Screenshots"; import { HeaderUI } from "@/mainview/components/Header"; import { useQuery } from "@tanstack/react-query"; import { EmulatorsSection } from "@/mainview/components/store/EmulatorsSection"; import { scrollIntoViewHandler, useStickyDataAttr } from "@/mainview/scripts/utils"; export const Route = createFileRoute('/store/details/emulator/$id')({ component: RouteComponent, async loader (ctx) { const emulator = await ctx.context.queryClient.fetchQuery(queries.store.storeEmulatorDetailsQuery(ctx.params.id)); return { emulator }; } }); function HomePageLink (data: { homepage: string; }) { const { ref } = useFocusable({ focusKey: 'homepage-link' }); return systemApi.api.system.open.post({ url: data.homepage })}>{data.homepage}; } function TitleArea (data: { emulator: FrontEndEmulator; }) { const [installOpen, setInstallOpen] = useState(false); const installOptions: DialogEntry[] = []; const { ref, focusKey } = useFocusable({ focusKey: 'title-area', preferredChildFocusKey: "install-btn", onFocus: () => { (ref.current as HTMLElement).scrollIntoView({ behavior: "smooth", block: 'end' }); } }); return

{data.emulator.name}

{data.emulator.systems.map(({ id, name, icon }) => { return

{!!icon && }

{name}

; })}

{ setInstallOpen(false); setFocus("install-btn"); }}>
; } function Description (data: { emulator: FrontEndEmulator; }) { return

{data.emulator.description}

; } export function RouteComponent () { const { id } = Route.useParams(); const headerRef = useRef(null); const sentinelRef = useRef(null); const { ref, focusKey, focusSelf } = useFocusable({ focusKey: `GAME_DETAIL_${id}`, trackChildren: true, preferredChildFocusKey: 'title-area' }); const { emulator } = Route.useLoaderData(); const { data: recommended } = useQuery(queries.store.storeEmulatorsRecommendedQuery); useShortcuts(focusKey, () => [{ label: "Return", action: () => { const { to, search } = PopSource('store-details'); Router.navigate({ to: to ?? '/store/tab', viewTransition: { types: ['zoom-out'] }, search: search ?? { focus: id } }); }, button: GamePadButtonCode.B }]); useEffect(() => { focusSelf(); }, []); const { shortcuts } = useShortcutContext(); useStickyDataAttr(headerRef, sentinelRef, ref); return (
Stats
    {!!emulator.keywords &&
  • Tags:
    {emulator.keywords?.map(k => {k})}
  • } {!!emulator.status.source &&
  • Source
    {emulator.status.source}
  • } {!!emulator.status.location &&
  • Location
    {emulator.status.location}
  • }
{recommended &&

More Emulators

} onFocus={scrollIntoViewHandler({ block: 'center' })} onSelect={(id, focus) => { setFocus("title-area"); Router.navigate({ to: '/store/details/emulator/$id', params: { id }, viewTransition: { types: ['zoom-in'] } }); }} emulators={recommended} />}
); }