import { useEffect, useState, useRef } from "react" import { PanelSectionRow, DropdownItem, staticClasses } from "@decky/ui" import { fetchPluginGame, fetchPluginDevices, setPluginApiBaseUrl, type PluginGameResponse, type PluginDeviceRow, } from "../lib/plugin-api" interface Props { appId: number title: string hardwareSlug: string | null // detected device baseUrl: string } export default function LibraryAppPanel({ appId, title, hardwareSlug, baseUrl }: Props) { const [data, setData] = useState(null) const [devices, setDevices] = useState([]) const [loading, setLoading] = useState(true) const [device, setDevice] = useState(hardwareSlug ?? "") // "" = all devices const [fetchError, setFetchError] = useState("") const reqIdRef = useRef(0) useEffect(() => { setPluginApiBaseUrl(baseUrl) let cancelled = false const id = ++reqIdRef.current async function load() { setLoading(true) try { const d = await fetchPluginGame(appId, device || null, 3) if (cancelled || id !== reqIdRef.current) return setFetchError(d.error && !d.game ? d.error : "") setData(d) setLoading(false) const devs = await fetchPluginDevices(appId) if (!cancelled && id === reqIdRef.current) setDevices(devs) } catch { if (!cancelled && id === reqIdRef.current) { setData(null) setFetchError("Request failed") setLoading(false) } } } load() return () => { cancelled = true } }, [appId, device, baseUrl]) const deviceOptions = [ { label: "All devices", data: "" }, ...(hardwareSlug ? [{ label: `Your device (${hardwareSlug})`, data: hardwareSlug }] : []), ...devices .filter((d) => d.slug !== hardwareSlug) .map((d) => ({ label: `${d.name} (${d.count})`, data: d.slug })), ] // Minimal single-row stats — no header, no entry cards if (loading) { return (
DeckyVault loading…
) } if (fetchError) { return (
DeckyVault: {fetchError}
) } if (!data || !data.game) { return (
Not on DeckyVault — add it
) } return ( <>
{device && data.estFps ? ( <> DeckyVault est FPS: {data.estFps.avg} avg · {data.estFps.low ?? "—"} low · {data.estFps.high ?? "—"} high · {data.estFps.count} entries ) : ( {device ? "No entries for this device yet" : "Select a device to see estimated FPS"} )}
setDevice(opt.data as string)} /> ) }