Skip to content

feat(live): per-user favorite cameras with a Live view filter - #628

Open
matteius wants to merge 1 commit into
mainfrom
feat/live-camera-favorites
Open

matteius wants to merge 1 commit into
mainfrom
feat/live-camera-favorites

Conversation

@matteius

@matteius matteius commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Replacement for the favorites half of #624 (thanks @zirocool93 for the idea and the groundwork). Each signed-in user gets a personal set of favorite cameras: a star on every Live tile adds or removes a camera, and a Favorites toggle in the Live toolbar filters the grid. The filter is persisted in the URL (?favorites=1) like the collection and tag filters.

Unlike #624 this lives inside the existing LiveView rather than a separate mobile surface, has no forced UI-mode selector, and every string goes through i18n.

Design notes

  • Dedicated table, not a collection. Camera collections have a globally unique name and default to shared, and saved layouts are grids, so neither models a private per-user camera set without schema contortions. Migration 0088 adds camera_favorites(user_id, camera_uuid, created_at) with cascading deletes from users and streams.
  • Auth-disabled installs. A NULL user_id holds the single installation-wide set, the same convention live_saved_layouts uses for its owner, so favorites work without logins.
  • Scope. GET only returns cameras inside the caller's current live-view scope (same AUTHZ_LIVE_VIEW filter as layouts). PUT answers 404 for unknown and out-of-scope cameras alike. Demo and scoped-token identities are read-only.
  • Not audited. Favorites are a personal preference, not camera configuration.

API

GET    /api/camera-favorites                 -> {favorites:[{camera_uuid, created_at}], can_modify}
PUT    /api/camera-favorites/{camera_uuid}   -> the record (idempotent)
DELETE /api/camera-favorites/{camera_uuid}   -> {success, removed} (idempotent)

Documented in docs/API.md under Camera Favorites.

Frontend

  • web/js/components/preact/live/cameraFavorites.js: pure helpers (set derivation, filtering, cache update, request shape) plus useCameraFavorites() over the query cache with optimistic cache update and invalidation.
  • LiveView.jsx: toolbar toggle (shown when the user can modify favorites or already has some), tile star overlay (hidden in reorder mode and when controls are hidden), favorites-aware empty state. A stale ?favorites=1 does not blank the grid if favorites are unavailable.
  • Star styling in live.css, larger hit target on coarse pointers.

Testing

  • test_db_camera_favorites (6): idempotent add keeps created_at, per-user scoping, installation scope without a user, invalid and unknown cameras, user-deletion cascade, soft vs permanent stream deletion.
  • test_api_handlers_camera_favorites (3): put/list/delete round trip, 400/404 paths, demo identity read-only with 403 on writes.
  • web/tests/cameraFavorites.spec.js (4): set derivation and filtering, cache update ordering, request method and UUID encoding, failure propagation.
  • All targets build clean; npx vite build clean; Jest 311/311; full ctest 144/145 with the one failure being the known local FFmpeg header mismatch in test_mp4_segment_boundaries.
  • Not yet exercised in a browser against a running server; the hook and handlers are covered by unit tests.

Not included

  • Favorites on the recordings page or in the operator navigator. The API is page-agnostic, so those are follow-ups.
  • The mobile-specific live surface and UI-mode selector from Codex/mobile live favorites #624.

🤖 Generated with Claude Code

Add a personal set of favorite cameras for each signed-in user. The Live
view gets a star on every tile to add or remove a camera and a Favorites
toggle in the toolbar that filters the grid, persisted in the URL like the
collection and tag filters.

Backend
- Migration 0088 adds camera_favorites(user_id, camera_uuid, created_at)
  with cascading deletes from users and streams. A NULL user_id holds the
  installation-wide set used while authentication is disabled, the same
  convention as live_saved_layouts.
- GET /api/camera-favorites lists the caller's favorites filtered to the
  cameras in their live-view scope; PUT and DELETE
  /api/camera-favorites/{camera_uuid} add and remove idempotently. Demo
  and scoped-token identities are read-only (403 on writes). PUT answers
  404 for unknown and out-of-scope cameras alike.
- Favorites are a personal preference, not camera configuration, so they
  are not audited.

Frontend
- live/cameraFavorites.js exposes pure helpers plus a hook over the query
  cache; the tile star and toolbar toggle live inside the existing
  LiveView rather than a separate surface. All strings go through i18n.

Replaces the favorites half of #624 by zirocool93 with an implementation
that fits the existing live view and the project's language conventions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant