Commit graph

3 commits

Author SHA1 Message Date
BoulderBadgeDad
878e467f69 video enrichment: backfill season posters from TMDB (server usually lacks them)
The media server rarely has distinct per-season art, so season cards fell back to
a gradient. TMDB's show detail carries a poster_path per season — the show worker
now returns those, and enrichment_apply backfills seasons.poster_url for seasons
the server left without art (gap-only, never clobbers server art). The image
proxy streams a stored full URL (TMDB) directly vs. proxying a server path.

Seam tests: TMDB returns season posters, backfill fills only missing seasons.
2026-06-14 17:57:24 -07:00
BoulderBadgeDad
9b607b3d1b video: detail-page data layer (show tree + movie) + backdrop proxy
Backend for the upcoming TV/movie detail pages, isolated to video.db:
- show_detail(id): show + seasons->episodes tree with owned/total roll-ups
  (season 0 -> 'Specials', missing-season-row episodes still grouped).
- movie_detail(id): movie + owned flag + best media-file (resolution/quality).
- get_art_ref generalizes the poster ref to poster|backdrop; new
  /api/video/backdrop/<kind>/<id> streams the hero art server-side (Jellyfin
  Backdrop vs Primary handled).
- /api/video/detail/{show,movie}/<id> endpoints.

Seam tests for the tree roll-ups, owned/file, art ref, and both endpoints.
2026-06-14 15:52:22 -07:00
BoulderBadgeDad
fba47e9665 video Library page: music-library visuals + posters + search + A-Z
Rebuilt the Library page to reuse the music library's exact look — no
reinvention, just new data:
- Same classes: .library-container, .library-artist-card grid, .alphabet-
  selector, .library-search-input, loading/empty states. Movies/Shows tab pill
  is the only video-specific bit.
- Real posters via a server-side proxy: GET /api/video/poster/<kind>/<id>
  streams the Plex/Jellyfin artwork (token stays server-side); cards fall back
  to an emoji on miss. list_movies/list_shows now expose has_poster (no raw
  server paths leaked).
- Client-side search + A-Z letter filter (article-aware) over the loaded set;
  cards are divs (not clickable yet, per request). Scan button in the header
  reuses the shared scan controller and reloads on done.
110 tests green.
2026-06-14 00:51:47 -07:00