- Shipped
- October 14, 2026 at 1:17 AM UTC
- Author
- Kamo
- Commit
- c26c442
- Nav tool 'cameras' (app + VIEW_CAMERAS): saved layouts, groups (each expanding to its cameras), ungrouped cameras with a status dot, Open viewer, Manage cameras for either admin right; live via useOrgChanges('cameras'); a failed load is one retry row, never 'no cameras'; empty state explains that an administrator chooses who may watch. hasAnySettingsRight += **************** pinned-app launcher cameras -> cameras. - Tool window 'cameras' (max 6, 1000x690): WebRTC wall over one-round-trip non-trickle signalling; grids auto/1/2x2/3x3/4x4/1+5/1+7; sub stream in the grid, main for an expanded tile or the only tile of a maximized window; only the selected tile is ever heard (MUTED/UNMUTED/AUTO=focused); muted autoplay with a click-for-sound fallback; capped exponential reconnect; no session for a minimized, covered or long-hidden window, a covered tile, an offline site or a switched-off camera; site offline resumes over realtime; add/remove/drag-swap, Save layout (update / save as new) and delete; group windows follow their group; props are the view (tool:patchProps) and the title follows. - Maximized navigator kind 'cameras': CameraSwitcherColumn (layouts / groups / cameras, active row by sessionGuid, + opens a new maximized viewer), threaded through the width store, panel, tab strip, dock and tests. - Pure decisions in app/lib/cameraViewer.ts with tests; stream lifecycle tested under jsdom.
