Files
iptvnator/libs/shared/interfaces/src/lib/settings.interface.ts
T
4grayandClaude Opus 4.8 db70b07093 feat(playback): theater stage and opt-in ambient fill for the inline portal player (#1223)
* fix(tmdb): purge obsolete search cache rows

* feat(playback): theater stage and opt-in ambient fill for the inline portal player

On wide-short windows the VOD/series inline player left a strip of app
surface next to the video: with `width: auto`, the viewport's `max-height`
transferred through `aspect-ratio` into a max-width (CSS transferred size
constraints), re-clamping the stage to 16:9 and leaving the leftover
outside it.

- Theater stage: give `.player-shell__viewport` a definite `width: 100%`
  so it always fills the content row; the player renders as the largest
  16:9 box that fits the stage height, centered — the leftover is always
  the stage's black background, never app surface (YouTube-style
  letterbox). Applies to every inline engine.
- Ambient fill: new `playerAmbientMode` setting (default off, Settings >
  Playback, web players only) renders a blurred, dimmed copy of the
  poster behind the player, filling the letterbox margins. Enforced at
  runtime too: Embedded MPV never gets the extra DOM layer. Live channels
  and non-http(s) poster URLs are excluded.

Verified live via CDP at 1720x760 (stage 1362x532, player 946x532 with
symmetric 208px margins) and 1280x950 (stage exactly 16:9, no bars).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(i18n): add ambient-mode setting keys to all remaining locales

The i18n drift gate requires SETTINGS.PLAYER_AMBIENT_MODE and its
description in every locale; the feature commit only covered en and ru.
Translated via the i18n-fill workflow (per-locale patch + mechanical
merge, glossary-matched against each existing file).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(settings): include playerAmbientMode in expected default settings

settings.component.spec asserts the persisted settings object with
toEqual; the new default-off field has to be part of the fixture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 08:02:11 +02:00

162 lines
5.4 KiB
TypeScript

import { Language } from './language.enum';
import { StreamFormat } from './stream-format.enum';
import { Theme } from './theme.enum';
import { TmdbSettings } from './tmdb.interface';
/**
* Contains all types of supported video players
*/
export enum VideoPlayer {
VideoJs = 'videojs',
Html5Player = 'html5',
EmbeddedMpv = 'embedded-mpv',
MPV = 'mpv',
VLC = 'vlc',
ArtPlayer = 'artplayer',
}
export enum StartupBehavior {
FirstView = 'first-view',
RestoreLastView = 'restore-last-view',
}
export type CoverSize = 'small' | 'medium' | 'large';
/** Rendering of the live EPG panel under the player. */
export type EpgViewMode = 'timeline' | 'list';
export interface DashboardRailsSettings {
hero: boolean;
continueWatching: boolean;
liveFavorites: boolean;
recentlyWatchedLive: boolean;
favoriteMoviesAndSeries: boolean;
recentSources: boolean;
xtreamRecentlyAdded: boolean;
/** TMDB "Trending this week" rail (needs the TMDB opt-in; Electron) */
tmdbTrending: boolean;
}
export const DEFAULT_DASHBOARD_RAILS_SETTINGS: DashboardRailsSettings = {
hero: true,
continueWatching: true,
liveFavorites: true,
recentlyWatchedLive: true,
favoriteMoviesAndSeries: true,
recentSources: true,
xtreamRecentlyAdded: true,
tmdbTrending: true,
};
export type DashboardRailsSettingsInput = Partial<
Record<keyof DashboardRailsSettings, boolean | null | undefined>
>;
export function normalizeDashboardRailsSettings(
settings?: DashboardRailsSettingsInput | null
): DashboardRailsSettings {
const normalized = { ...DEFAULT_DASHBOARD_RAILS_SETTINGS };
if (!settings) {
return normalized;
}
const keys = Object.keys(
DEFAULT_DASHBOARD_RAILS_SETTINGS
) as (keyof DashboardRailsSettings)[];
for (const key of keys) {
if (typeof settings[key] === 'boolean') {
normalized[key] = settings[key];
}
}
return normalized;
}
/**
* Describes all available settings options of the application
*/
export interface Settings {
player: VideoPlayer;
/**
* Use IPTVnator's shared controls in HTML5, Video.js, and ArtPlayer.
* Missing values remain off for compatibility with older saved settings.
*/
webPlayerSharedControls?: boolean;
/**
* Fill the empty space around the inline VOD/series player with a blurred,
* dimmed copy of the poster (YouTube "Ambient mode" style) instead of plain
* black bars. Off by default; only affects the built-in web players.
*/
playerAmbientMode?: boolean;
epgUrl: string[];
streamFormat: StreamFormat;
openStreamOnDoubleClick: boolean;
language: Language;
showCaptions: boolean;
showDashboard: boolean;
startupBehavior: StartupBehavior;
/** Show the desktop footer bar for external playback status */
showExternalPlaybackBar?: boolean;
/** Strip country/group prefixes like "US | " or "UK - " from channel names */
stripCountryPrefix?: boolean;
theme: Theme;
mpvPlayerPath: string;
/**
* Extra MPV CLI arguments entered one argument per line. Applied only when
* starting a new external MPV process.
*/
mpvPlayerArguments: string;
mpvReuseInstance: boolean;
vlcPlayerPath: string;
/**
* Extra VLC CLI arguments entered one argument per line. Applied only when
* starting a new external VLC process.
*/
vlcPlayerArguments: string;
vlcReuseInstance: boolean;
remoteControl: boolean;
remoteControlPort: number;
/** Custom download folder path (uses system Downloads folder if not set) */
downloadFolder?: string;
/** Custom live recording folder path (uses system Downloads folder if not set) */
recordingFolder?: string;
/**
* Embedded MPV frame-copy engine (experimental, macOS Apple Silicon and Linux).
* Applied on the next app start — the engine relaxes the window sandbox
* for its preload frame pump, which is fixed at window creation.
*/
embeddedMpvFrameCopy?: boolean;
/** Cover/poster sizing preset applied across grids and rails */
coverSize?: CoverSize;
/** Live EPG panel layout: horizontal timeline (default) or vertical list */
epgViewMode?: EpgViewMode;
/** Per-rail dashboard visibility preferences. Missing keys default on. */
dashboardRails?: DashboardRailsSettings;
/**
* When true, the locally-parsed XMLTV programs (loaded from `epgUrl`)
* take precedence over the Xtream provider's EPG for live TV channels.
* When false (default), the Xtream provider's EPG is preferred and
* XMLTV is consulted only when the provider returns no programs.
* Only meaningful for Xtream playlists in Electron.
*/
preferUploadedEpgOverXtream?: boolean;
/**
* Exact EPG source URLs the user has allowed to resolve to private/LAN
* network addresses. Kept source-scoped instead of disabling SSRF
* protection globally.
*/
trustedPrivateNetworkEpgUrls?: string[];
/**
* Lowercase hostnames whose invalid TLS certificates the user has chosen
* to trust. This is host-scoped and does not disable TLS validation for
* unrelated playlist or EPG hosts.
*/
trustedInsecureTlsHosts?: string[];
/**
* Opt-in TMDB metadata enrichment for VOD/series detail views.
* Disabled by default because enrichment sends content titles to TMDB.
*/
tmdb?: TmdbSettings;
}