Files
iptvnator/libs/shared/interfaces/src/lib/xtream-serie-details.interface.ts
T
4grayandClaude Fable 5.1 7790e68147 feat(portal): show each season's own poster beside the season tabs (#1628)
Series detail pages now render the selected season's poster as a season
cover next to the season tabs and description, and the fullscreen episode
panel shows the same poster as a season strip above its tabs.

Resolution is TMDB-first, like the show artwork merge: the lazy season
enrichment stores `/tv/{id}/season/{n}` `poster_path` as a w342 URL in
`tmdb_season_posters` (Xtream) or `StalkerSeriesTmdbSeasonsService.posters()`
(Stalker), under the same write-only-if-changed convergence guard as the
season overview. Xtream falls back to the provider's `seasons[].cover_big`/
`cover` when it is an http(s) URL other than the show poster, because panels
repeat the show poster on every season. Stalker is TMDB-only.

The cover column is not rendered for one-season items, seasons without a
poster, or a failed image, so every fallback is today's markup. It is sized
by a new `--season-cover-width` token (96/120/144px per Settings.coverSize).
The hero poster never follows the season.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-19 11:45:54 +02:00

97 lines
3.0 KiB
TypeScript

import {
TmdbCountryFacet,
TmdbEnrichedCastMember,
TmdbGenreFacet,
TmdbRecommendation,
TmdbSeriesStatus,
} from './tmdb.interface';
export interface XtreamSerieDetails {
seasons: XtreamSerieSeason[];
info: XtreamSerieInfo;
episodes: Record<string, XtreamSerieEpisode[]>;
/**
* Populated by lazy TMDB season enrichment; absent in raw provider
* responses. Keyed by the provider season key (the `episodes` record
* key). Detail views use it as the season-description fallback when
* the provider's `seasons[].overview` is empty or URL-only junk.
*/
tmdb_season_overviews?: Record<string, string>;
/**
* Populated by lazy TMDB season enrichment; absent in raw provider
* responses. Keyed like `tmdb_season_overviews`. Full image URLs of
* each season's own TMDB poster, the first choice for the season
* cover in the detail view and the fullscreen episode panel.
*/
tmdb_season_posters?: Record<string, string>;
}
export interface XtreamSerieInfo {
name: string;
cover: string;
plot: string;
cast: string;
director: string;
genre: string;
releaseDate: string;
/** See `XtreamVodInfo.tmdb_supplied_release_date` — same contract */
tmdb_supplied_release_date?: boolean;
last_modified: string;
rating: string;
rating_5based: number;
backdrop_path: string[];
youtube_trailer: string;
episode_run_time: string;
category_id: string;
/** Populated by TMDB enrichment; absent in raw provider responses */
tmdb_cast?: TmdbEnrichedCastMember[];
/** Directors (movies) / creators (series) as clickable person chips */
tmdb_directors?: TmdbEnrichedCastMember[];
/** Series production status (token, never a raw TMDB string) */
tmdb_status?: TmdbSeriesStatus;
/** Populated by TMDB enrichment; matched against the catalog in views */
tmdb_recommendations?: TmdbRecommendation[];
/** Matched TMDB show id — enables lazy season/episode enrichment */
tmdb_id?: number;
/** Populated by TMDB enrichment; per-entry clickable Discover chips */
tmdb_genres?: TmdbGenreFacet[];
tmdb_countries?: TmdbCountryFacet[];
}
export interface XtreamSerieEpisode {
id: string;
episode_num: number;
title: string;
container_extension: string;
info: XtreamSerieEpisodeInfo | []; // Can be empty array when no metadata available
custom_sid: string;
added: string;
season: number;
direct_source: string;
}
export interface XtreamSerieEpisodeInfo {
tmdb_id?: number;
releasedate?: string;
plot?: string;
duration_secs?: number;
duration?: string;
movie_image?: string;
video?: Record<string, string>; // TODO
audio?: Record<string, string>; // TODO
bitrate?: number;
rating?: number;
season?: string;
}
export interface XtreamSerieSeason {
air_date: string;
episode_count: number;
id: number;
name: string;
overview: string;
season_number: number;
cover: string;
cover_big: string;
}