feat: add TDP to quick stats + open-on-DeckyVault button

This commit is contained in:
2026-07-13 06:20:30 +08:00
parent b108f0436b
commit c974699024
3 changed files with 32 additions and 11 deletions
@@ -1,5 +1,6 @@
import { useEffect, useState, useRef } from "react"
import { PanelSectionRow, DropdownItem, staticClasses } from "@decky/ui"
import { PanelSectionRow, DropdownItem, ButtonItem, staticClasses } from "@decky/ui"
import { Router } from "@decky/ui"
import {
fetchPluginGame,
fetchPluginDevices,
@@ -57,7 +58,10 @@ export default function LibraryAppPanel({ appId, title, hardwareSlug, baseUrl }:
.map((d) => ({ label: `${d.name} (${d.count})`, data: d.slug })),
]
// Minimal single-row stats — no header, no entry cards
const gameUrl = data?.game?.slug
? `${baseUrl}/games/${data.game.slug}`
: `${baseUrl}/games`
if (loading) {
return (
<PanelSectionRow>
@@ -90,14 +94,18 @@ export default function LibraryAppPanel({ appId, title, hardwareSlug, baseUrl }:
return (
<>
{/* Quick stats row */}
<PanelSectionRow>
<div className={staticClasses.Text} style={{ display: "flex", alignItems: "center", gap: "8px", fontSize: "13px", padding: "4px 0" }}>
<div className={staticClasses.Text} style={{ padding: "4px 0", fontSize: "13px" }}>
{device && data.estFps ? (
<>
<span style={{ opacity: 0.6 }}>DeckyVault est FPS:</span>
<strong>{data.estFps.avg}</strong>
<span style={{ opacity: 0.4, fontSize: "11px" }}>avg · {data.estFps.low ?? "—"} low · {data.estFps.high ?? "—"} high · {data.estFps.count} entries</span>
</>
<span style={{ display: "flex", flexWrap: "wrap", gap: "4px 12px" }}>
<span><strong>{data.estFps.avg}</strong> <span style={{ opacity: 0.4 }}>avg FPS</span></span>
{data.estFps.onePct != null && <span><strong>{data.estFps.onePct}</strong> <span style={{ opacity: 0.4 }}>1% low</span></span>}
{data.estFps.low != null && <span><strong>{data.estFps.low}</strong> <span style={{ opacity: 0.4 }}>min</span></span>}
{data.estFps.high != null && <span><strong>{data.estFps.high}</strong> <span style={{ opacity: 0.4 }}>max</span></span>}
{data.estFps.tdpAvg != null && <span><strong>{data.estFps.tdpAvg}W</strong> <span style={{ opacity: 0.4 }}>TDP</span></span>}
<span><strong>{data.estFps.count}</strong> <span style={{ opacity: 0.4 }}>entries</span></span>
</span>
) : (
<span style={{ opacity: 0.5, fontSize: "12px" }}>
{device
@@ -107,6 +115,8 @@ export default function LibraryAppPanel({ appId, title, hardwareSlug, baseUrl }:
)}
</div>
</PanelSectionRow>
{/* Device dropdown */}
<PanelSectionRow>
<DropdownItem
rgOptions={deviceOptions}
@@ -114,6 +124,13 @@ export default function LibraryAppPanel({ appId, title, hardwareSlug, baseUrl }:
onChange={(opt) => setDevice(opt.data as string)}
/>
</PanelSectionRow>
{/* Open on DeckyVault button */}
<PanelSectionRow>
<ButtonItem layout="below" onClick={() => Router.NavigateToExternalWeb(gameUrl)}>
View on DeckyVault
</ButtonItem>
</PanelSectionRow>
</>
)
}
+1 -1
View File
@@ -22,7 +22,7 @@ export interface PluginEntry {
export interface PluginGameResponse {
game: { id: string; steamAppId: number | null; title: string; slug: string | null } | null
estFps: { avg: number; low: number | null; onePct: number | null; high: number | null; count: number } | null
estFps: { avg: number; low: number | null; onePct: number | null; high: number | null; count: number; tdpAvg: number | null } | null
topEntries: PluginEntry[]
recentEntries: PluginEntry[]
error?: string