From f574f2b948cdeefd7e04edda5de8ca28992690be Mon Sep 17 00:00:00 2001
From: Kalle <38327916+Sendouc@users.noreply.github.com>
Date: Sun, 20 Sep 2026 13:34:09 +0300
Subject: [PATCH] Screenshot page fixes
---
app/features/scanner/README.md | 11 +--
.../scanner/components/LandingView.tsx | 24 +++++--
.../scanner/components/ScannerApp.tsx | 4 +-
.../components/ScreenshotPage.module.css | 7 ++
.../scanner/components/ScreenshotPage.tsx | 67 +++++++++++--------
.../scanner/components/SettingsPopover.tsx | 26 +++----
6 files changed, 81 insertions(+), 58 deletions(-)
diff --git a/app/features/scanner/README.md b/app/features/scanner/README.md
index 639585cba..ef2d9d81c 100644
--- a/app/features/scanner/README.md
+++ b/app/features/scanner/README.md
@@ -28,7 +28,9 @@ running capture (`LiveView`), a past session (`PastSessionView`) and a
scanned VoD (`VodView`): header, clip strip, then match cards
(`components/MatchCard.tsx`) newest first. Views are picked by the `view`
search param (`scanner-search-params.ts`: `live`, `session&id=`,
-`vod&name=`, `clips`, and the debug-gated `debug` / dev-only `fixtures`).
+`vod&name=`, `clips`, `debug` and the dev-only `fixtures`). Nothing links to
+the `debug` screenshot view: dropping an image on the landing's File card
+opens it, for anyone, through the same handoff Inspect uses.
- **Controllers are module singletons**, not view state: the capture
(`components/live-session.ts`) and a running VoD scan
@@ -61,10 +63,11 @@ search param (`scanner-search-params.ts`: `live`, `session&id=`,
`Matches` (`core/csv/matches.ts`, one row per game, the rows the cards
render) and `Raw detections` (`core/csv/events.ts`, one row per event).
Column names stay English keys.
-- **Debug gate** (`use-debug.ts`: DEV/ADMIN role or `?debug=true`): the
- image/screenshot view (`ScreenshotPage.tsx`), the dev-only fixtures view,
+- **Debug gate** (`use-debug.ts`: DEV/ADMIN role or `?debug=true`):
`Save frame as fixture`, `?telemetry=true`, and the `Raw detections`
- disclosure inside a match card (the per-event cards with Inspect).
+ disclosure inside a match card (the per-event cards with Inspect). The
+ screenshot view (`ScreenshotPage.tsx`) is not gated; the fixtures view is
+ dev-only.
## Clips
diff --git a/app/features/scanner/components/LandingView.tsx b/app/features/scanner/components/LandingView.tsx
index 292344a2e..a95f6cb57 100644
--- a/app/features/scanner/components/LandingView.tsx
+++ b/app/features/scanner/components/LandingView.tsx
@@ -1,7 +1,9 @@
/**
* The landing: two entry cards (Live / File), the clip history strip and
* the sessions list. Anyone can capture, scan files and get clips locally;
- * only uploading needs a login. Dropping a file anywhere here starts a scan.
+ * only uploading needs a login. Dropping a file anywhere here starts a scan;
+ * an image opens the screenshot view instead, through the same handoff
+ * Inspect uses.
*/
import clsx from "clsx";
import { Play, Upload } from "lucide-react";
@@ -17,6 +19,7 @@ import {
import { SCANNER_PAGE } from "~/utils/urls";
import { scannerSearchParams } from "../scanner-search-params";
import { MAX_HISTORY_CLIPS, type ScannerClip } from "../store/clips";
+import { newInspectKey, putInspectFrame } from "../store/inspect";
import { ClipDialog } from "./ClipDialog";
import { ClipStrip } from "./ClipStrip";
import { useClips } from "./clips-feed";
@@ -71,10 +74,20 @@ export function LandingView() {
};
const scanFile = (file: File) => {
+ if (file.type.startsWith("image/")) {
+ void inspectScreenshot(file);
+ return;
+ }
void startVodScan(file, { saveClips: saveClipsFromFile, telemetry });
setParams({ view: "vod", name: file.name });
};
+ const inspectScreenshot = async (file: File) => {
+ const key = newInspectKey();
+ await putInspectFrame(key, file);
+ setParams({ view: "debug", inspect: key });
+ };
+
return (
// biome-ignore lint/a11y/noStaticElementInteractions: drag-and-drop target for the whole landing; the file input is the accessible path
File
-
Scan a recorded VoD.
+
+ Scan a recorded VoD, or a screenshot to see what the scanner reads
+ from it.
+