Skip to content

Scanner · Search params & storage

3 modules · 29 exports · 0 repositories · 14 e2e tests · 1 route

The state Scanner keeps in the URL and in the browser's storage. Every param has a default and never fails to decode, see Search params, and each definition should have an assertRoundTrips test. The definitions of the whole app are listed in the reference.

Search params

URL scannerSearchParams

app/features/scanner/scanner-search-params.ts:18

ParamValueDefaultLoaderDescription
view v.picklist(SCANNER_VIEWS)"home"false
id v.nullable(v.pipe(v.number(), v.integer(), v.minValue(0)))nullfalse

view=session: the session's key — its first detection's wall-clock ms

name v.nullable(v.pipe(v.string(), v.maxLength(300)))nullfalse

view=vod, view=coach: the scanned file's name

t v.nullable(v.pipe(v.number(), v.integer(), v.minValue(0)))nullfalse

view=coach: the file second the video opens at (a game card's start)

q v.pipe(v.string(), v.maxLength(200))""false

Fixtures view filter: comma-separated substrings, any match keeps a case

inspect v.nullable(v.pipe(v.string(), v.maxLength(100)))nullfalse

Inspect handoff key: the debug view claims this frame on load

telemetry v.boolean()falsefalse

Opt-in scan telemetry: accumulated and shown only when set by hand in the URL (no link points at it)

debug v.boolean()falsefalse

Opens the debug tools for anyone (devs and admins have them regardless)

Used in ClipsView.tsxCoachView.tsxFixturesPage.tsxLandingView.tsxLiveView.tsxNotFound.tsxPastSessionView.tsxScannerApp.tsxScreenshotPage.tsxSessionHeader.tsxSettingsPopover.tsxVodView.tsxuse-debug.tsscanner.tsx

Web storage

localStorage clipVolumePersisted

app/features/scanner/components/clip-volume.ts:5

The volume and mute state clips play at, remembered across visits.

Keyscanner:clip-volume
Value
v.object({
	volume: v.pipe(v.number(), v.minValue(0), v.maxValue(1)),
	muted: v.boolean(),
})
Default{ volume: 1, muted: false }

Used in ClipVideo.tsx

localStorage scannerSettingsPersisted

app/features/scanner/components/settings.ts:52

An unreadable setting falls back to its default on its own

Keyscanner:settings
Value
v.object({
	sourceDeviceId: v.fallback(v.string(), DEFAULT_SETTINGS.sourceDeviceId),
	audioSource: v.fallback(
		v.custom<AudioSource>(isAudioSource),
		DEFAULT_SETTINGS.audioSource,
	),
	upload: v.fallback(v.boolean(), DEFAULT_SETTINGS.upload),
	saveClips: v.fallback(v.boolean(), DEFAULT_SETTINGS.saveClips),
	clipMinKills: v.fallback(
		v.picklist(CLIP_MIN_KILLS_OPTIONS),
		DEFAULT_SETTINGS.clipMinKills,
	),
	audioOffsetMs: v.fallback(
		v.pipe(
			v.number(),
			v.finite(),
			v.transform((ms) =>
				Math.max(-AUDIO_OFFSET_LIMIT_MS, Math.min(AUDIO_OFFSET_LIMIT_MS, ms)),
			),
		),
		DEFAULT_SETTINGS.audioOffsetMs,
	),
	webgpu: v.fallback(v.boolean(), DEFAULT_SETTINGS.webgpu),
})
DefaultDEFAULT_SETTINGS

Used in settings.ts (own file)

localStorage montageCriteriaPersisted

app/features/scanner/scanner-persisted.ts:6

What makes a montage clip candidate, an unreadable part falls back to its default

Keyscanner:montage-criteria
Value
v.object({
	minKills: v.fallback(v.number(), DEFAULT_MONTAGE_CRITERIA.minKills),
	/** counts missing from it use the default */
	maxSecondsByKills: v.fallback(
		v.record(v.string(), v.number()),
		DEFAULT_MONTAGE_CRITERIA.maxSecondsByKills,
	),
})
DefaultDEFAULT_MONTAGE_CRITERIA

Used in montage.ts

localStorage montageCollapsedGroupsPersisted

app/features/scanner/scanner-persisted.ts:21

Base weapon ids (as strings, "null" for unknown) of the collapsed montage clip groups

Keyscanner:montage-collapsed-groups
Valuev.array(v.string())
Default[]

Used in MontageView.tsx