Build absolute poster proxy URLs via build_absolute_uri_with_port so
program detail images resolve correctly in dev and behind reverse
proxies. Backfill sd_icon for programs when poster fetch is enabled
but a delta refresh skips program metadata. Add a dev-mode frontend
fallback for relative image paths and correct the poster caching
description in the SD settings UI.
Add content_advisory, content_ratings, event_details, runtime to
ProgramDetailSerializer. Display content advisory, sports venue/teams,
and first-aired date in ProgramDetailModal.
- Move channel name/number into modal header title bar (was empty after removing duplicate title)
- Remove channel logo from modal (didn't fit well)
- Remove custom background color override, inherit from Mantine dark theme for consistency with VOD/Series modals
- Fix wrong channel shown in modal: pass channel directly from renderProgram instead of re-looking up by tvg_id
- Clean up unused imports (getChannelLogoUrl, Image/Group no longer needed in title)
Program title was intentionally being shown in the modal title bar and modal body, but when no program artwork was provided via EPG the title components were layered one after the other, making it look like a duplicated title.
Replace expanded inline cards with a ProgramDetailModal for viewing full program
details. Add real-time progress bars to currently-airing programs using direct DOM manipulation. Extract and display season/episode info from EPG data with a 3-tier fallback (custom_properties → onscreen_episode → description text).
Backend:
- Add ProgramDetailSerializer for rich EPG data (categories, credits, ratings, images, external IDs) served on the detail endpoint
- Add infer_is_live() for status badges (live, new, premiere, finale)
- Add shared S/E extraction utilities in apps/epg/utils.py
- Optimize querysets with select_related("epg")
Frontend:
- ProgramDetailModal with conditional field rendering and image fallback chain
- Progress bars via scaleX transform updated every second
- Parallel data fetching with Promise.all for channels + programs
- Browser tab visibility recovery for progress bars
- Now-line with triangle marker and sub-millisecond precision
- Card layout: title, season/episode + subtitle, time + badges
- Shared formatSeasonEpisode() and external URL helpers