Address the file-size review finding and prepare for a future EPG list view by
extracting the view-agnostic pieces out of the 538-line timeline component and
411-line utils file; both are now well under the line ceiling and the shared
building blocks are re-exported from `@iptvnator/ui/epg`.
- `epg-timeline.utils.ts` (227) keeps axis/blocks/date helpers; the
short-programme render strategy (tiers, grouping, zoom bounds) moves to
`epg-timeline-render.util.ts` (re-exported for API compatibility).
- `epg-archive.util.ts` — pure catch-up gating (`isWithinArchiveWindow`,
`canCatchUpProgramme`, `epgDialogActionFor`) off `when`/`startMs` primitives.
- `epg-summary.util.ts` — `EpgTimelineSummary` + collapsed-summary progress maths.
- `epg-programme-dialog.service.ts` — `EpgProgrammeDialogService`, opens the
shared details dialog and returns the chosen action.
- `epg-timeline-scroll.controller.ts` — `TimelineScrollController` owns ribbon
scrolling + channel-select auto-focus (with its migrated spec).
Behaviour unchanged. epg-timeline.component.ts 538→393, epg-timeline.utils.ts
411→227. Tests: ui-epg 78 (10 suites), portal-shared-ui 47, playlist-m3u 30;
lint + web build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the vertical EPG list/panel with a single horizontal timeline ribbon
(`app-epg-timeline`) shared across all live surfaces — the M3U player, the
unified live tab, and the Xtream and Stalker layouts. It preloads a multi-day
window and supports scroll, zoom, day navigation, short-programme tiers and
per-state empty/error views; the programme-details dialog is restyled to match
and now shows the channel logo.
Timeline / UI
- Auto-focus the currently-airing programme on channel select — instant
(`behavior: 'auto'`), centred, and deduped by programme-set identity so the
30s tick / zoom / re-emits never cause flaky re-jumps.
- Wide-tier cards show a dimmed description preview under the title; title and
preview clip on whole lines (`flex-shrink: 0` + `-webkit-line-clamp`), never
mid-line.
- Dynamic bar subtitle: the now-playing / archive programme title instead of a
static "Timeline" label.
- State-aware toolbar: hide Now + zoom when there is no ribbon, and the date
stepper when the channel has no EPG on any day (hidden, not disabled).
- Empty-state fills and centres within the panel area instead of a fixed
min-height that overflowed the compact inline panel and hid the buttons.
EPG current-programme lookup (electron-backend)
- Timezone-aware "airing now" comparison via SQLite `datetime()` (was a lexical
string compare that broke for offset vs UTC `Z` timestamps).
- Unscoped fallback for resolved candidates whose programmes are tagged with an
out-of-scope source (multi-source imports sharing XMLTV ids), so the sidebar
matches the timeline.
- Match channel candidates by the raw (case-sensitive) key as well as `LOWER()`,
since SQLite `LOWER()`/`COLLATE NOCASE` fold only ASCII — fixes Cyrillic /
Greek channel names showing "No program information available".
- Overlap-based day membership (`hasProgramsForDateKey`) so a film spanning
midnight keeps the ribbon on "today" while it airs.
Refactor
- Extract the duplicated channel-list EPG enrichment (progress + side-car map)
into `channel-list-container/epg-enrichment.util.ts`, shared by the
all-channels / groups / favorites / recent views; also fixes recent's and
favorites' unguarded, NaN-prone progress maths.
Tests: ui-epg 75, components 77, electron-backend 432; lint + web build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Implemented a loading state for channel lists in various components, enhancing user experience during data fetching.
- Added `ChannelListLoadingStateComponent` to display loading skeletons for channels and groups.
- Updated `M3uWorkspaceRouteSession` to manage loading states more effectively when fetching playlists.
- Modified `VideoPlayerComponent`, `SidebarComponent`, and `ChannelListContainerComponent` to utilize the new loading state.
- Enhanced tests to cover new loading behaviors and ensure proper dispatching of loading actions.
- Moved Stalker-related components and services from apps/web to libs/portal for better modularity.
- Introduced SQLite DB Worker to handle non-EPG database operations, improving UI responsiveness.
- Updated documentation for the Workspace Dashboard and Shell, detailing current implementation and routing structure.
- Added new EPG fixture scenarios to the Xtream mock server for testing purposes.
- Enhanced the overall architecture documentation to reflect recent changes and improvements.