Dev #26

Open
overseer wants to merge 65 commits from dev into main
2 changed files with 18 additions and 7 deletions
Showing only changes of commit cb549a8803 - Show all commits
+5 -2
View File
@@ -78,7 +78,9 @@ func main() {
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(cfg.WriteTimeout))
// No global request timeout: it cancels the long-lived SSE stream
// (/api/v1/events/stream) — that's why the dashboard never received
// camera events. Closed-LAN kiosk, so dropping it is fine.
// Health check (no auth)
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
@@ -97,7 +99,8 @@ func main() {
Addr: ":" + cfg.Port,
Handler: r,
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
// WriteTimeout intentionally 0: SSE responses are long-lived and a
// write deadline would terminate them mid-stream.
IdleTimeout: cfg.IdleTimeout,
}
+9 -1
View File
@@ -1,4 +1,4 @@
import { useState, useCallback, useMemo } from 'react'
import { useState, useCallback, useMemo, useEffect } from 'react'
import { Camera, Play, Square, Wifi, WifiOff, AlertTriangle } from 'lucide-react'
import { useSSE } from './hooks/useSSE'
import { useCameraStore } from './store/useCameraStore'
@@ -15,6 +15,14 @@ function App() {
// SSE connection + live store
const { connectionState } = useSSE()
// Seed the list once on mount via the REST API. SSE only pushes on change,
// so without this the dashboard is empty until the next status event.
useEffect(() => {
api.getCameras()
.then((list) => useCameraStore.getState().setCameras(list))
.catch(() => { /* SSE will fill in shortly */ })
}, [])
// Subscribe to full camera state — dashboard needs every change
const camerasMap = useCameraStore((s) => s.cameras)
const cameras = useMemo(() => Array.from(camerasMap.values()), [camerasMap])