import { useEffect, useRef } from "react"
import {
PanelSection,
PanelSectionRow,
staticClasses,
} from "@decky/ui"
import {
definePlugin,
} from "@decky/api"
import { FaDatabase } from "react-icons/fa"
import MainPanel from "./components/main-panel"
import SettingsPanel from "./components/settings-panel"
import { useSettings, useSession } from "./lib/store"
import {
readAndParseMangohudLog,
clearMangohudLog,
getHardwareInfo,
getOsVersion,
getProtonVersion,
getLaunchOptions,
} from "./lib/api"
function Content() {
const { settings, updateSetting, loaded } = useSettings()
const {
recordingState,
session,
recentSessions,
error,
setError,
startRecording,
stopRecording,
updateSession,
addToRecent,
reset,
onGameStart,
onGameStop,
} = useSession()
const gameStartedUnregRef = useRef<{ unregister: () => void } | null>(null)
const gameStoppedUnregRef = useRef<{ unregister: () => void } | null>(null)
// ── Register SteamClient game events ──────────────────────────
useEffect(() => {
try {
const startedReg = SteamClient.Apps.RegisterForGameStarted(async (appId: number) => {
let gameName = `App ${appId}`
try {
const info = await SteamClient.Apps.GetCurrentGameInfo()
if (info.appId === appId) {
gameName = info.strAppName
}
} catch {
// GetCurrentGameInfo may not be available in all contexts
}
onGameStart(appId, gameName)
})
gameStartedUnregRef.current = startedReg
const stoppedReg = SteamClient.Apps.RegisterForGameStopped((_appId: number) => {
onGameStop()
})
gameStoppedUnregRef.current = stoppedReg
} catch (e) {
console.warn("[DeckyVault] SteamClient event registration failed:", e)
}
return () => {
try {
gameStartedUnregRef.current?.unregister()
gameStoppedUnregRef.current?.unregister()
} catch {
// ignore
}
}
}, [onGameStart, onGameStop])
// ── Handle start recording ────────────────────────────────────
async function handleStart() {
// Clear any previous log file
await clearMangohudLog()
startRecording()
}
// ── Handle stop recording: parse log + read system info ────────
async function handleStop() {
stopRecording()
// Parse the MangoHud log
const logResult = await readAndParseMangohudLog()
if (logResult.error) {
setError(logResult.error)
// Still transition to stopped state so user can see the error + manual fields
return
}
// Read system info in parallel
const [hwInfo, osVersion] = await Promise.all([
getHardwareInfo(),
getOsVersion(),
])
// Read Proton version + launch options if we have an app ID
let protonVersion = ""
let launchOptions = ""
if (session.appId) {
const [pv, lo] = await Promise.all([
getProtonVersion(session.appId),
getLaunchOptions(session.appId),
])
protonVersion = pv
launchOptions = lo
}
// Use settings hardware override if set, otherwise auto-detected
const hardwareSlug = settings.hardwareSlug || hwInfo.slug
updateSession({
fpsAvg: logResult.fpsAvg ?? null,
fpsLow: logResult.fpsLow ?? null,
fpsHigh: logResult.fpsHigh ?? null,
fpsOnePercentLow: logResult.fpsOnePercentLow ?? null,
tdpWatts: logResult.tdpWatts ?? null,
hardwareSlug,
hardwareName: hwInfo.name,
osVersion,
protonVersion,
launchOptions,
})
}
if (!loaded) {
return (