fix(webapp): bind client streams earlier and show diagnostics
This commit is contained in:
@@ -29,6 +29,30 @@
|
||||
const linked = $appState.linkedCameras.find((camera) => camera.cameraDeviceId === $appState.activeCameraDeviceId);
|
||||
return linked?.cameraName || linked?.cameraDeviceId || 'Live Feed Viewer';
|
||||
};
|
||||
|
||||
const activeStreamSessionId = () => {
|
||||
if ($appState.activeStreamSessionId) {
|
||||
return $appState.activeStreamSessionId;
|
||||
}
|
||||
if (!$appState.activeCameraDeviceId) {
|
||||
return null;
|
||||
}
|
||||
return $appState.cameraSessions?.[$appState.activeCameraDeviceId] ?? null;
|
||||
};
|
||||
|
||||
const activeStreamDiagnostics = () => {
|
||||
const streamSessionId = activeStreamSessionId();
|
||||
if (!streamSessionId) {
|
||||
return null;
|
||||
}
|
||||
return $appState.streamDiagnostics?.[streamSessionId] ?? null;
|
||||
};
|
||||
|
||||
const diagnosticLevelClass = (level: string) => {
|
||||
if (level === 'error') return 'border-red-500/20 bg-red-500/10 text-red-200';
|
||||
if (level === 'success') return 'border-emerald-500/20 bg-emerald-500/10 text-emerald-200';
|
||||
return 'border-white/10 bg-white/5 text-gray-300';
|
||||
};
|
||||
</script>
|
||||
|
||||
<AppChrome pageKey="client">
|
||||
@@ -240,6 +264,31 @@
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</CardContent>
|
||||
|
||||
{#if activeStreamDiagnostics()}
|
||||
<div class="border-t border-white/5 bg-black/20 px-5 py-4">
|
||||
<div class="flex flex-wrap items-center gap-2 text-[11px] uppercase tracking-[0.2em] text-gray-500">
|
||||
<span>Live Diagnostics</span>
|
||||
<Badge variant="outline" class="border-white/10 text-[10px] text-gray-400">
|
||||
{activeStreamSessionId()?.slice(0, 8)}
|
||||
</Badge>
|
||||
{#if isCameraLive($appState.activeCameraDeviceId)}
|
||||
<Badge variant="secondary" class="rounded-full px-2 text-[10px] uppercase tracking-wide">Peer connected</Badge>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mt-3 grid gap-2">
|
||||
{#each activeStreamDiagnostics().entries.slice(0, 6) as entry (entry.id)}
|
||||
<div class="rounded-xl border px-3 py-2 {diagnosticLevelClass(entry.level)}">
|
||||
<div class="flex items-center justify-between gap-3">
|
||||
<span class="text-[11px] font-semibold uppercase tracking-[0.18em]">{entry.stage}</span>
|
||||
<span class="text-[10px] text-gray-500">{new Date(entry.createdAt).toLocaleTimeString()}</span>
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-current">{entry.message}</p>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</Card>
|
||||
|
||||
<div class="flex shrink-0 flex-col gap-6 pr-2 xl:max-h-full xl:w-96 xl:overflow-y-auto">
|
||||
|
||||
Reference in New Issue
Block a user