fix(plugin): poll-based game detection via Python backend, remove broken SteamClient events
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { useEffect, useRef } from "react"
|
||||
import {
|
||||
PanelSection,
|
||||
PanelSectionRow,
|
||||
@@ -9,7 +8,7 @@ import {
|
||||
} from "@decky/api"
|
||||
import { FaChartLine } from "react-icons/fa"
|
||||
import MainPanel from "./components/main-panel"
|
||||
import { useSettings, useSession } from "./lib/store"
|
||||
import { useSettings, useSession, useGameDetection } from "./lib/store"
|
||||
import {
|
||||
readAndParseMangohudLog,
|
||||
clearMangohudLog,
|
||||
@@ -39,46 +38,9 @@ function Content() {
|
||||
onGameStop,
|
||||
setGameName,
|
||||
} = useSession()
|
||||
const gameStartedUnregRef = useRef<{ unregister: () => void } | null>(null)
|
||||
|
||||
// ── Register SteamClient game events ──────────────────────────
|
||||
useEffect(() => {
|
||||
try {
|
||||
// Use RegisterForAppLifetimeNotifications — the correct API for
|
||||
// detecting when games start/stop on Steam Deck.
|
||||
const reg = SteamClient.GameSessions.RegisterForAppLifetimeNotifications(
|
||||
(notification: AppLifetimeNotification) => {
|
||||
if (notification.bRunning) {
|
||||
// Game started — try to get the display name from appStore
|
||||
let gameName = `App ${notification.unAppID}`
|
||||
try {
|
||||
const overview = window.appStore?.GetAppOverviewByAppID(notification.unAppID)
|
||||
if (overview?.display_name) {
|
||||
gameName = overview.display_name
|
||||
}
|
||||
} catch {
|
||||
// fallback
|
||||
}
|
||||
onGameStart(notification.unAppID, gameName)
|
||||
} else {
|
||||
// Game stopped
|
||||
onGameStop()
|
||||
}
|
||||
},
|
||||
)
|
||||
gameStartedUnregRef.current = reg
|
||||
} catch (e) {
|
||||
console.warn("[DeckyVault] SteamClient event registration failed:", e)
|
||||
}
|
||||
|
||||
return () => {
|
||||
try {
|
||||
gameStartedUnregRef.current?.unregister()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}, [onGameStart, onGameStop])
|
||||
// ── Game detection via polling ────────────────────────────────
|
||||
useGameDetection(setGameName, recordingState)
|
||||
|
||||
// ── Handle start recording ────────────────────────────────────
|
||||
async function handleStart() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useCallback, useRef } from "react"
|
||||
import type { DeckyVaultImportV1, HardwareSlug } from "@deckyvault/shared"
|
||||
import { getSettings, setSetting } from "./api"
|
||||
import { getSettings, setSetting, detectCurrentGame } from "./api"
|
||||
|
||||
// ── Types ───────────────────────────────────────────────────────
|
||||
|
||||
@@ -195,6 +195,42 @@ export function useSession() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Game Detection Hook ──────────────────────────────────────────
|
||||
// Polls the Python backend to detect the currently running game.
|
||||
// Falls back to manual input if no game is detected.
|
||||
|
||||
export function useGameDetection(
|
||||
setGameName: (name: string, appId?: number) => void,
|
||||
recordingState: RecordingState,
|
||||
) {
|
||||
const [detecting, setDetecting] = useState(false)
|
||||
const lastDetectedRef = useRef<string>("")
|
||||
|
||||
useEffect(() => {
|
||||
// Don't poll while recording (user is already in-game)
|
||||
if (recordingState !== "idle") return
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
try {
|
||||
setDetecting(true)
|
||||
const result = await detectCurrentGame()
|
||||
if (result.name && result.name !== lastDetectedRef.current) {
|
||||
lastDetectedRef.current = result.name
|
||||
setGameName(result.name, result.appId ?? undefined)
|
||||
}
|
||||
} catch {
|
||||
// Silently retry
|
||||
} finally {
|
||||
setDetecting(false)
|
||||
}
|
||||
}, 3000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [recordingState, setGameName])
|
||||
|
||||
return { detecting }
|
||||
}
|
||||
|
||||
// ── Payload Builder ─────────────────────────────────────────────
|
||||
|
||||
export function buildImportPayload(sess: SessionData): DeckyVaultImportV1 {
|
||||
|
||||
Reference in New Issue
Block a user