mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
docs: update EPG documentation to reflect new bulk handling and fallback logic
This commit is contained in:
1 parent
545dfd8c67
commit
7cc25380dd
5 files changed
+250
-143
No files matched your search
@@ -31,6 +31,7 @@ The application is a cross-platform, open-source project built with Electron and
|
||||
- EPG support (TV Guide) with detailed information
|
||||
- TV archive/catchup/timeshift functionality
|
||||
- Group-based channel list
|
||||
- Read-only M3U channel details from the channel context menu
|
||||
- Favorite channels management
|
||||
- Global favorites aggregated from all playlists
|
||||
- HTML video player with HLS.js support or Video.js-based player
|
||||
|
||||
@@ -67,8 +67,8 @@ All endpoints are served at `GET /portal.php?action=<action>&...` matching the r
|
||||
| `get_ordered_list` | Paginated content list; if `movie_id` is present → returns seasons |
|
||||
| `create_link` | Returns a real public HLS stream URL for playback |
|
||||
| `favorites` | Add / remove / get favorites (in-memory, resets on restart) |
|
||||
| `get_short_epg` | EPG program list for a channel (`ch_id`) |
|
||||
| `get_epg_info` | Alias for `get_short_epg` |
|
||||
| `get_short_epg` | Current-and-upcoming EPG window for a channel (`ch_id`, `size`) |
|
||||
| `get_epg_info` | Bulk EPG keyed by channel id for a requested `period` window |
|
||||
|
||||
## Cover Images
|
||||
|
||||
@@ -99,6 +99,18 @@ nx e2e web-e2e --grep "@stalker"
|
||||
|
||||
The test suite uses `00:1A:79:00:00:01` (default scenario) for most tests, and calls `POST /reset` in `beforeEach` to ensure a clean state between tests.
|
||||
|
||||
## EPG Behavior
|
||||
|
||||
The mock server generates a 7-day EPG schedule for every ITV channel using
|
||||
2-hour slots starting at the current UTC day boundary.
|
||||
|
||||
- `get_short_epg` returns the current program and upcoming items from that
|
||||
schedule, limited by `size`
|
||||
- `get_epg_info` returns bulk data in the shape
|
||||
`{ js: { data: Record<channelId, program[]> } }`
|
||||
- `get_epg_info` filters the bulk response from the current UTC day start through
|
||||
`now + period`
|
||||
|
||||
## Architecture
|
||||
|
||||
See [`docs/architecture/stalker-mock-server.md`](../../docs/architecture/stalker-mock-server.md) for full implementation details.
|
||||
@@ -123,6 +135,7 @@ apps/stalker-mock-server/
|
||||
│ ├── get-seasons.handler.ts
|
||||
│ ├── create-link.handler.ts
|
||||
│ ├── favorites.handler.ts
|
||||
│ ├── get-epg-info.handler.ts
|
||||
│ ├── get-short-epg.handler.ts
|
||||
│ └── get-genres.handler.ts
|
||||
├── project.json
|
||||
|
||||
+192
-137
@@ -1,6 +1,7 @@
|
||||
# Stalker Portal EPG Architecture
|
||||
|
||||
This document describes the EPG (Electronic Program Guide) implementation for Stalker/Ministra portal live TV (ITV) streams.
|
||||
This document describes the current EPG implementation for Stalker/Ministra ITV
|
||||
channels in IPTVnator.
|
||||
|
||||
Related architecture docs:
|
||||
|
||||
@@ -9,48 +10,72 @@ Related architecture docs:
|
||||
|
||||
## Overview
|
||||
|
||||
The Stalker ITV live stream layout displays EPG data in the right panel when a live channel is playing. EPG is fetched per-channel using the Stalker `get_short_epg` API action, which returns the current program plus the next ~5 upcoming programs. The response is mapped to the shared `EpgItem` interface and rendered by the reusable `EpgViewComponent`.
|
||||
Stalker now uses two EPG paths with different purposes:
|
||||
|
||||
- The active channel EPG panel uses `get_epg_info` as a bulk endpoint, fetches a
|
||||
7-day window once per playlist session, caches programs by channel id, and
|
||||
renders the selected channel through the shared `app-epg-list` component.
|
||||
- Channel rows no longer send preview EPG requests during initial category load.
|
||||
They stay empty until bulk EPG has been fetched once, then derive their
|
||||
current program and progress bar from the cached bulk map.
|
||||
- If a portal does not return usable bulk data for the selected channel, the
|
||||
active panel falls back to `get_short_epg`.
|
||||
|
||||
This keeps the live list cheap while giving the active panel the same
|
||||
date-navigator UI used in the M3U/Xtream flows.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────────────┐
|
||||
│ StalkerLiveStreamLayoutComponent │
|
||||
│ libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/ │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────────────┐ ┌─────────────────────┐ │
|
||||
│ │ Sidebar │ │ Video Player │ │ EPG Panel │ │
|
||||
│ │ (channels) │ │ (WebPlayerView) │ │ (EpgViewComponent) │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ click ──────┼────┼──► playChannel() ────┼────┼──► loadEpgFor...() │ │
|
||||
│ └──────────────┘ └──────────────────────┘ └─────────────────────┘ │
|
||||
│ │ │ │
|
||||
└──────────────────────────────┼────────────────────────────┼───────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────────┐ ┌────────────────────────┐
|
||||
│ StalkerStore │ │ StalkerStore │
|
||||
│ fetchLinkToPlay() │ │ fetchChannelEpg() │
|
||||
└──────────┬───────────┘ └────────────┬───────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Stalker Portal API │
|
||||
│ action=create_link action=get_short_epg │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
```text
|
||||
┌────────────────────────────────────────────────────────────────────────────┐
|
||||
│ StalkerLiveStreamLayoutComponent │
|
||||
│ libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/ │
|
||||
│ │
|
||||
│ sidebar rows active channel panel │
|
||||
│ ──────────── ─────────────────── │
|
||||
│ row preview map playChannel() │
|
||||
│ from bulk cache │ │
|
||||
│ │ ▼ │
|
||||
│ │ ensureBulkItvEpg(168) │
|
||||
│ │ selectedItvEpgPrograms() │
|
||||
│ ▼ │ │
|
||||
│ current program preview ├── bulk hit → app-epg-list │
|
||||
│ after first bulk load └── empty/unsupported → short fallback │
|
||||
└────────────────────────────────────────────────────────────────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────────────────────────────────────────────────────────────────────────┐
|
||||
│ with-stalker-epg.feature │
|
||||
│ │
|
||||
│ bulkItvEpgByChannel: Record<string, EpgProgram[]> │
|
||||
│ bulkItvEpgPlaylistId / bulkItvEpgPeriodHours / bulkItvEpgLoaded │
|
||||
│ ensureBulkItvEpg() selectedItvEpgPrograms() │
|
||||
└────────────────────────────────────────────────────────────────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Stalker Portal API │
|
||||
│ │
|
||||
│ action=create_link action=get_short_epg action=get_epg_info │
|
||||
└────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Stalker EPG API
|
||||
|
||||
### `get_short_epg` (per-channel)
|
||||
### `get_short_epg` (active-panel fallback)
|
||||
|
||||
**Request:**
|
||||
```
|
||||
GET load.php?type=itv&action=get_short_epg&ch_id={channel_id}&JsHttpRequest=1-xml
|
||||
```
|
||||
Uses standard Stalker auth headers (Bearer token + MAC cookie).
|
||||
**Request**
|
||||
|
||||
```text
|
||||
GET load.php?type=itv&action=get_short_epg&ch_id={channel_id}&size={n}&JsHttpRequest=1-xml
|
||||
```
|
||||
|
||||
**Current usage**
|
||||
|
||||
- Active panel fallback path: `size=10`
|
||||
|
||||
**Response**
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"js": {
|
||||
@@ -64,149 +89,179 @@ Uses standard Stalker auth headers (Bearer token + MAC cookie).
|
||||
"time_to": "2025-01-15 14:30:00",
|
||||
"duration": "1800",
|
||||
"start_timestamp": "1736949600",
|
||||
"stop_timestamp": "1736951400",
|
||||
"t_time": "14:00",
|
||||
"t_time_to": "14:30"
|
||||
"stop_timestamp": "1736951400"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- If the channel has no `xmltv_id` set on the server, returns an empty array
|
||||
- Response normalization handles both `{ js: { data: [...] } }` and `{ js: [...] }` formats
|
||||
- No backend (Electron IPC) changes needed — the generic `stalker.events.ts` handler forwards any `params` to the portal URL
|
||||
**Notes**
|
||||
|
||||
### `get_epg_info` (bulk — reserved for future use)
|
||||
- The response is normalized into shared `EpgItem[]`
|
||||
- The list-preview path uses this directly
|
||||
- The active-panel fallback maps the result into controlled `EpgProgram[]`
|
||||
|
||||
```
|
||||
### `get_epg_info` (bulk active-panel source)
|
||||
|
||||
**Request**
|
||||
|
||||
```text
|
||||
GET load.php?type=itv&action=get_epg_info&period={hours}&JsHttpRequest=1-xml
|
||||
```
|
||||
|
||||
Returns EPG for all channels for a given time period. Currently unused but the enum value `StalkerPortalActions.GetEpgInfo` is defined for future bulk EPG features.
|
||||
**Current usage**
|
||||
|
||||
- Fetched once with `period=168`
|
||||
- Scoped to the current playlist session
|
||||
- Not refetched on active-channel change
|
||||
|
||||
**Expected response**
|
||||
|
||||
```json
|
||||
{
|
||||
"js": {
|
||||
"data": {
|
||||
"45": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Program Title",
|
||||
"descr": "Program description",
|
||||
"time": "2025-01-15 14:00:00",
|
||||
"time_to": "2025-01-15 16:00:00",
|
||||
"start_timestamp": "1736949600",
|
||||
"stop_timestamp": "1736956800"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**
|
||||
|
||||
- The store supports the channel-keyed bulk shape above as the primary contract
|
||||
- For weak or mock-style portals that still return array-style data, the store
|
||||
treats the result as compatibility input and leaves the short-EPG fallback path
|
||||
available
|
||||
|
||||
## Data Mapping
|
||||
|
||||
### Stalker EPG → `EpgItem` Interface
|
||||
### Fallback data (`get_short_epg`) → `EpgItem`
|
||||
|
||||
| Stalker field | `EpgItem` field | Notes |
|
||||
|--------------------|--------------------|-------|
|
||||
| `id` | `id` | Converted to string |
|
||||
| `ch_id` | `channel_id` | Falls back to passed `channelId` |
|
||||
| `name` | `title` | |
|
||||
| `descr` | `description` | |
|
||||
| `time` | `start` | Full datetime string |
|
||||
| `time_to` | `end`, `stop` | Both set to same value |
|
||||
| `start_timestamp` | `start_timestamp` | Unix timestamp as string |
|
||||
| `stop_timestamp` | `stop_timestamp` | Unix timestamp as string |
|
||||
| _(n/a)_ | `epg_id` | Empty string |
|
||||
| _(n/a)_ | `lang` | Empty string |
|
||||
The short EPG path now exists only for the active-panel fallback flow.
|
||||
|
||||
### `EpgItem` Interface
|
||||
Key mapped fields:
|
||||
|
||||
```typescript
|
||||
// libs/shared/interfaces/src/lib/epg-item.interface.ts
|
||||
interface EpgItem {
|
||||
id: string;
|
||||
epg_id: string;
|
||||
title: string;
|
||||
lang: string;
|
||||
start: string;
|
||||
end: string;
|
||||
stop: string;
|
||||
description: string;
|
||||
channel_id: string;
|
||||
start_timestamp: string;
|
||||
stop_timestamp: string;
|
||||
}
|
||||
```
|
||||
| Stalker field | `EpgItem` field |
|
||||
| --- | --- |
|
||||
| `id` | `id` |
|
||||
| `ch_id` | `channel_id` |
|
||||
| `name` | `title` |
|
||||
| `descr` | `description` |
|
||||
| `time` | `start` |
|
||||
| `time_to` | `end`, `stop` |
|
||||
| `start_timestamp` | `start_timestamp` |
|
||||
| `stop_timestamp` | `stop_timestamp` |
|
||||
|
||||
### Active panel data (`get_epg_info` / fallback) → `EpgProgram`
|
||||
|
||||
The active panel uses controlled `EpgProgram[]` because `app-epg-list` filters
|
||||
and groups by day.
|
||||
|
||||
Normalization rules:
|
||||
|
||||
- `start` / `end` are converted to ISO strings
|
||||
- `startTimestamp` / `stopTimestamp` are always populated
|
||||
- Programs are sorted by start time per channel
|
||||
- `selectedItvId` is used to project cached bulk data to the active channel
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Key Files
|
||||
### Key files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `libs/shared/interfaces/src/lib/stalker-portal-actions.enum.ts` | `GetShortEpg`, `GetEpgInfo` enum values |
|
||||
| `libs/portal/stalker/data-access/src/lib/stalker.store.ts` | `fetchChannelEpg()` method |
|
||||
| `libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/stalker-live-stream-layout.component.ts` | EPG signals + `loadEpgForChannel()` |
|
||||
| `libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/stalker-live-stream-layout.component.html` | `<app-epg-view>` integration |
|
||||
| `libs/ui/shared-portals/src/lib/epg-view/epg-view.component.ts` | Shared EPG display component |
|
||||
| --- | --- |
|
||||
| `libs/portal/stalker/data-access/src/lib/stores/features/with-stalker-epg.feature.ts` | bulk cache and fallback handling |
|
||||
| `libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/stalker-live-stream-layout.component.ts` | active-channel EPG loading and controlled `app-epg-list` wiring |
|
||||
| `libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/stalker-live-stream-layout.component.html` | active panel template |
|
||||
| `libs/portal/stalker/feature/src/lib/stalker-collection-channels-list/stalker-collection-channels-list.component.ts` | row preview loading |
|
||||
| `libs/ui/shared-portals/src/lib/epg-list/epg-list.component.ts` | shared controlled EPG list with date navigator |
|
||||
|
||||
### StalkerStore.fetchChannelEpg()
|
||||
### Store API
|
||||
|
||||
Location: `libs/portal/stalker/data-access/src/lib/stalker.store.ts` (in `withMethods`)
|
||||
The Stalker EPG feature exposes one bulk method plus the short-EPG fallback:
|
||||
|
||||
```typescript
|
||||
async fetchChannelEpg(channelId: number | string): Promise<EpgItem[]>
|
||||
```ts
|
||||
fetchChannelEpg(channelId: number | string, size?: number): Promise<EpgItem[]>
|
||||
ensureBulkItvEpg(periodHours = 168): Promise<void>
|
||||
```
|
||||
|
||||
- Sends `get_short_epg` request with `ch_id` param
|
||||
- Supports both full Stalker portals (authenticated via `StalkerSessionService`) and simple portals (direct IPC)
|
||||
- Returns mapped `EpgItem[]` or empty array on failure
|
||||
- No store state mutation — returns data directly to the component
|
||||
It also exposes:
|
||||
|
||||
### StalkerLiveStreamLayoutComponent EPG Integration
|
||||
- `selectedItvEpgPrograms`
|
||||
- `clearBulkItvEpgCache()`
|
||||
|
||||
The component manages EPG state locally with signals:
|
||||
Bulk state is keyed by playlist so cached results do not leak between Stalker
|
||||
playlists.
|
||||
|
||||
```typescript
|
||||
readonly epgItems = signal<EpgItem[]>([]);
|
||||
readonly isLoadingEpg = signal(false);
|
||||
```
|
||||
### Active panel flow
|
||||
|
||||
**Flow:**
|
||||
1. User clicks a channel in the sidebar → `playChannel(item)`
|
||||
2. `fetchLinkToPlay()` gets the stream URL
|
||||
3. If using embedded player, `streamUrl` is set and `loadEpgForChannel(item.id)` is called
|
||||
4. `loadEpgForChannel()` sets loading state, calls `stalkerStore.fetchChannelEpg()`, updates `epgItems`
|
||||
5. Template renders `<app-epg-view [epgItems]="epgItems()">` or a loading spinner
|
||||
1. User activates a live channel
|
||||
2. The component ensures playback link resolution as before
|
||||
3. The component calls `ensureBulkItvEpg(168)` on first use for the playlist
|
||||
4. `selectedItvEpgPrograms()` feeds `app-epg-list`
|
||||
5. If the selected channel has no bulk programs, the component falls back to
|
||||
`get_short_epg`
|
||||
|
||||
### EpgViewComponent (shared)
|
||||
The active panel no longer uses local EPG pagination or a "Load more" button.
|
||||
|
||||
Location: `libs/ui/shared-portals/src/lib/epg-view/`
|
||||
### Channel row preview flow
|
||||
|
||||
Reusable component shared between Stalker and Xtream live stream layouts:
|
||||
- **Input:** `epgItems: EpgItem[]`
|
||||
- Displays program list with time, title, and info button
|
||||
- Highlights current program with green progress bar
|
||||
- Handles empty state (shows "EPG not available" message)
|
||||
- Info button opens `EpgItemDescriptionComponent` dialog with title and description
|
||||
Before the first live-channel playback, channel rows do not fetch EPG at all.
|
||||
|
||||
**Current program detection:**
|
||||
```typescript
|
||||
isCurrentProgram(item: EpgItem): boolean {
|
||||
const now = new Date().getTime();
|
||||
const start = new Date(item.start).getTime();
|
||||
const stop = new Date(item.stop ?? item.end).getTime();
|
||||
return now >= start && now <= stop;
|
||||
}
|
||||
```
|
||||
After bulk EPG has been loaded once for the playlist, visible row previews are
|
||||
derived locally from `bulkItvEpgByChannel`:
|
||||
|
||||
This works with Stalker's datetime format (`"2025-01-15 14:00:00"`) because `new Date()` parses it correctly.
|
||||
- pick the current program for the channel, if one exists
|
||||
- compute progress from the cached program timestamps
|
||||
- leave the row in its existing placeholder state when no current program exists
|
||||
|
||||
## Cache Lifecycle
|
||||
|
||||
- Bulk EPG is fetched once per playlist session
|
||||
- Channel switches only read from `bulkItvEpgByChannel`
|
||||
- The cache is cleared when the Stalker playlist changes
|
||||
- This implementation does not add TTL-based refresh or background polling
|
||||
|
||||
## Authentication
|
||||
|
||||
EPG requests follow the same authentication pattern as all Stalker API calls:
|
||||
EPG requests follow the standard Stalker request path:
|
||||
|
||||
| Portal Type | Auth Method |
|
||||
|-------------|-------------|
|
||||
| **Full Stalker** (`isFullStalkerPortal: true`) | `StalkerSessionService.makeAuthenticatedRequest()` — handles token refresh and retry on 401 |
|
||||
| **Simple Stalker** | Direct IPC via `DataService.sendIpcEvent(STALKER_REQUEST, ...)` — no auth headers |
|
||||
| Portal type | Auth path |
|
||||
| --- | --- |
|
||||
| Full Stalker portal | `StalkerSessionService.makeAuthenticatedRequest()` |
|
||||
| Simple Stalker portal | generic IPC request path via Electron |
|
||||
|
||||
No EPG-specific backend transport was needed; the Electron Stalker request
|
||||
handler forwards portal params directly.
|
||||
|
||||
## Fallback Behavior
|
||||
|
||||
Some providers do not implement `get_epg_info` consistently. The active panel
|
||||
therefore falls back to `get_short_epg` when:
|
||||
|
||||
- the bulk request fails
|
||||
- the bulk response is empty
|
||||
- the selected channel has no programs in the cached bulk map
|
||||
|
||||
This keeps the panel usable even on limited portals, while still taking
|
||||
advantage of the richer bulk API when it is available. Row previews do not
|
||||
fallback to per-channel requests in this mode; they remain empty until bulk EPG
|
||||
is available.
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Bulk EPG in Channel List Sidebar
|
||||
|
||||
Use `get_epg_info` with `period=3` to pre-fetch current program titles for all channels when a category is selected:
|
||||
- Call `get_epg_info` after category selection
|
||||
- Build a `Map<channelId, currentProgram>`
|
||||
- Show current program name below channel title in the sidebar
|
||||
- Display progress bar per channel item
|
||||
|
||||
This is a separate task due to Stalker's lazy-loaded channel pagination model.
|
||||
|
||||
### EPG Auto-Refresh
|
||||
|
||||
Currently EPG is fetched once per channel selection. A future enhancement could add a timer to refresh EPG data periodically (e.g., every 5 minutes) to keep the "current program" indicator accurate during long viewing sessions.
|
||||
- add cache refresh / invalidation for long-running live sessions
|
||||
- add Stalker catch-up support to `app-epg-list` once the playback flow exists
|
||||
- optionally add category-level prefetch timing metrics for bulk EPG
|
||||
@@ -152,9 +152,9 @@ The stream URL is selected from a pool of 4 real public HLS test streams. The ch
|
||||
"id": "1",
|
||||
"name": "Channel Name: Program Title",
|
||||
"start": "2026-02-21T10:00:00.000Z",
|
||||
"stop": "2026-02-21T10:30:00.000Z",
|
||||
"stop": "2026-02-21T12:00:00.000Z",
|
||||
"start_timestamp": 1740128400,
|
||||
"stop_timestamp": 1740130200,
|
||||
"stop_timestamp": 1740135600,
|
||||
"descr": "...",
|
||||
"category": "News"
|
||||
}
|
||||
@@ -163,7 +163,37 @@ The stream URL is selected from a pool of 4 real public HLS test streams. The ch
|
||||
}
|
||||
```
|
||||
|
||||
EPG programs are generated as 30-minute slots spanning 3 hours past to 3 hours future relative to the time of generation.
|
||||
`get_short_epg` returns the current program and upcoming items from the
|
||||
generated schedule, limited by the requested `size`.
|
||||
|
||||
### `get_epg_info`
|
||||
|
||||
```json
|
||||
{
|
||||
"js": {
|
||||
"data": {
|
||||
"10000": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Channel Name: Program Title",
|
||||
"start": "2026-02-21T10:00:00.000Z",
|
||||
"stop": "2026-02-21T12:00:00.000Z",
|
||||
"start_timestamp": 1740128400,
|
||||
"stop_timestamp": 1740135600,
|
||||
"descr": "...",
|
||||
"category": "News"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`get_epg_info` returns bulk EPG keyed by channel id and filters the generated
|
||||
7-day schedule from the current UTC day start through `now + period`.
|
||||
|
||||
EPG programs are generated as 2-hour slots across 7 days for each channel,
|
||||
starting at the current UTC day boundary.
|
||||
|
||||
## Scenarios
|
||||
|
||||
|
||||
@@ -138,7 +138,15 @@ See full backend and web-remote flow in [Remote Control Architecture](./remote-c
|
||||
|
||||
## EPG Integration
|
||||
|
||||
EPG in Stalker ITV uses `get_short_epg` and shared `EpgViewComponent`. Full details are documented in [Stalker Portal EPG Architecture](./stalker-epg.md).
|
||||
Stalker ITV now splits EPG usage:
|
||||
|
||||
- active channel panel: bulk `get_epg_info` cached once per playlist and rendered
|
||||
through shared `app-epg-list`
|
||||
- channel row preview: no pre-playback network requests; previews are derived
|
||||
from cached bulk EPG only after the first active-channel fetch succeeds
|
||||
- active panel fallback: `get_short_epg` when bulk EPG is missing or unsupported
|
||||
|
||||
Full details are documented in [Stalker Portal EPG Architecture](./stalker-epg.md).
|
||||
|
||||
## Shared/Reusable Infrastructure
|
||||
|
||||
|
||||
Reference in new issue
Block a user