From a975497c1695ecef0cbde607ffaf3e4817d5db32 Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Mon, 13 Jul 2026 04:38:56 +0800 Subject: [PATCH] fix(plugin): block no-FPS uploads and clamp FPS before submit --- .../src/components/session-form.tsx | 4 ++++ plugins/decky-vault/src/lib/store.ts | 22 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/plugins/decky-vault/src/components/session-form.tsx b/plugins/decky-vault/src/components/session-form.tsx index 9cab570..dd23809 100644 --- a/plugins/decky-vault/src/components/session-form.tsx +++ b/plugins/decky-vault/src/components/session-form.tsx @@ -211,6 +211,10 @@ export default function SessionForm({ setError("No API key configured. Set one in the Settings tab.") return } + if (session.fpsAvg == null || session.fpsAvg <= 0) { + setError("No FPS data captured. Re-record the session, or use Export to File only.") + return + } setError("") setUploadStatus("loading") setStatusMessage("Uploading entry…") diff --git a/plugins/decky-vault/src/lib/store.ts b/plugins/decky-vault/src/lib/store.ts index b6d5553..96bd46d 100644 --- a/plugins/decky-vault/src/lib/store.ts +++ b/plugins/decky-vault/src/lib/store.ts @@ -235,6 +235,20 @@ export function useGameDetection( return { detecting } } +// ── FPS Sanitizer ──────────────────────────────────────────────── + +const FPS_MAX = 1000 + +/** Clamp/cap an FPS value to [0, 1000]; return null for null/undefined/NaN. */ +export function sanitizeFps(value: number | null | undefined): number | null { + if (value == null) return null + const n = Number(value) + if (isNaN(n)) return null + if (n < 0) return 0 + if (n > FPS_MAX) return FPS_MAX + return n +} + // ── Payload Builder ───────────────────────────────────────────── export function buildImportPayload(sess: SessionData): DeckyVaultImportV1 { @@ -242,10 +256,10 @@ export function buildImportPayload(sess: SessionData): DeckyVaultImportV1 { version: 1, steamAppId: sess.appId ?? 0, hardwareSlug: sess.hardwareSlug, - fpsAvg: sess.fpsAvg ?? 0, - fpsLow: sess.fpsLow, - fpsOnePercentLow: sess.fpsOnePercentLow, - fpsHigh: sess.fpsHigh, + fpsAvg: sess.fpsAvg == null || sess.fpsAvg <= 0 ? 0 : sanitizeFps(sess.fpsAvg)!, + fpsLow: sanitizeFps(sess.fpsLow), + fpsOnePercentLow: sanitizeFps(sess.fpsOnePercentLow), + fpsHigh: sanitizeFps(sess.fpsHigh), protonVersion: sess.protonVersion || null, osVersion: sess.osVersion || null, versionString: sess.versionString || null,