Files
iptvnator/apps/web/src/app/settings/settings-options.ts
T
4grayandClaude Fable 5.1 fa9084fca3 feat(shell): startup window mode, --fullscreen switch and F11 toggle (#1514)
Settings > General gains "Window on startup" (normal / maximized /
fullscreen), Electron only, mirrored into the main-process config by
SETTINGS_UPDATE and applied at the next window creation. `--fullscreen`
forces one fullscreen launch (consumed by the first window). F11 toggles
OS-level fullscreen through WINDOW:TOGGLE_FULLSCREEN — the exit path on
Windows/Linux where the title bar is hidden — and is skipped while the
player owns document.fullscreenElement.

attachWindowStateEvents tracks native and HTML fullscreen as two flags,
since Electron leaves only the HTML state when the window was already
natively fullscreen. macOS ignores the constructor `fullscreen` option on a
hidden window, so ready-to-show repeats the request after show(). Toggles
are decided by an observe-only, event-fed tracker
(native-fullscreen-transitions.ts), never against isFullScreen().

Closes #1455

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 19:49:41 +02:00

217 lines
5.5 KiB
TypeScript

import {
CoverSize,
EpgViewMode,
StartupBehavior,
Theme,
VideoPlayer,
} from '@iptvnator/shared/interfaces';
import {
CoverSizeOption,
EpgViewModeOption,
SettingsPlayerOption,
SettingsSection,
StartupBehaviorOption,
StartupWindowModeOption,
ThemeOption,
} from './settings.models';
export const SETTINGS_THEME_OPTIONS: ThemeOption[] = [
{
value: Theme.LightTheme,
icon: 'light_mode',
labelKey: 'THEMES.LIGHT_THEME',
},
{
value: Theme.DarkTheme,
icon: 'dark_mode',
labelKey: 'THEMES.DARK_THEME',
},
{
value: Theme.SystemTheme,
icon: 'desktop_windows',
labelKey: 'THEMES.SYSTEM_THEME',
},
];
export const SETTINGS_COVER_SIZE_OPTIONS: CoverSizeOption[] = [
{
value: 'small' satisfies CoverSize,
icon: 'view_module',
labelKey: 'SETTINGS.COVER_SIZE_SMALL',
},
{
value: 'medium' satisfies CoverSize,
icon: 'view_comfy',
labelKey: 'SETTINGS.COVER_SIZE_MEDIUM',
},
{
value: 'large' satisfies CoverSize,
icon: 'view_quilt',
labelKey: 'SETTINGS.COVER_SIZE_LARGE',
},
];
export const SETTINGS_EPG_VIEW_MODE_OPTIONS: EpgViewModeOption[] = [
{
value: 'timeline' satisfies EpgViewMode,
icon: 'view_timeline',
labelKey: 'SETTINGS.EPG_VIEW_MODE_TIMELINE',
},
{
value: 'list' satisfies EpgViewMode,
icon: 'view_list',
labelKey: 'SETTINGS.EPG_VIEW_MODE_LIST',
},
];
export const SETTINGS_STARTUP_BEHAVIOR_OPTIONS: StartupBehaviorOption[] = [
{
value: StartupBehavior.FirstView,
labelKey: 'SETTINGS.STARTUP_BEHAVIOR_FIRST_VIEW',
},
{
value: StartupBehavior.RestoreLastView,
labelKey: 'SETTINGS.STARTUP_BEHAVIOR_RESTORE_LAST_VIEW',
},
];
export const SETTINGS_STARTUP_WINDOW_MODE_OPTIONS: StartupWindowModeOption[] = [
{
value: 'normal',
labelKey: 'SETTINGS.STARTUP_WINDOW_MODE_NORMAL',
},
{
value: 'maximized',
labelKey: 'SETTINGS.STARTUP_WINDOW_MODE_MAXIMIZED',
},
{
value: 'fullscreen',
labelKey: 'SETTINGS.STARTUP_WINDOW_MODE_FULLSCREEN',
},
];
export const SETTINGS_OS_PLAYER_OPTIONS: SettingsPlayerOption[] = [
{
id: VideoPlayer.MPV,
labelKey: 'SETTINGS.PLAYER_MPV',
},
{
id: VideoPlayer.VLC,
labelKey: 'SETTINGS.PLAYER_VLC',
},
];
export const SETTINGS_EMBEDDED_PLAYER_OPTIONS: SettingsPlayerOption[] = [
{
id: VideoPlayer.Html5Player,
labelKey: 'SETTINGS.PLAYER_HTML5',
},
{
id: VideoPlayer.VideoJs,
labelKey: 'SETTINGS.PLAYER_VIDEOJS',
},
{
id: VideoPlayer.ArtPlayer,
labelKey: 'SETTINGS.PLAYER_ARTPLAYER',
},
];
export interface SettingsPlayerAvailability {
supportsEmbeddedMpv: boolean;
supportsManagedExternalPlayers: boolean;
}
/**
* Built-in web players are always offered; the OS-backed ones only show up
* when the current runtime can actually launch them.
*/
export function buildSettingsPlayerOptions({
supportsEmbeddedMpv,
supportsManagedExternalPlayers,
}: SettingsPlayerAvailability): SettingsPlayerOption[] {
return [
...SETTINGS_EMBEDDED_PLAYER_OPTIONS,
...(supportsEmbeddedMpv
? [
{
id: VideoPlayer.EmbeddedMpv,
labelKey: 'SETTINGS.PLAYER_EMBEDDED_MPV',
},
]
: []),
...(supportsManagedExternalPlayers ? SETTINGS_OS_PLAYER_OPTIONS : []),
];
}
export interface SettingsSectionVisibility {
supportsEpg: boolean;
supportsRemoteControl: boolean;
}
export function buildSettingsSectionNavItems({
supportsEpg,
supportsRemoteControl,
}: SettingsSectionVisibility): SettingsSection[] {
return [
{
id: 'general',
label: 'SETTINGS.NAV_GENERAL',
icon: 'tune',
visible: true,
},
{
id: 'playback',
label: 'SETTINGS.NAV_PLAYBACK',
icon: 'play_circle',
visible: true,
},
{
id: 'epg',
label: 'SETTINGS.NAV_EPG',
icon: 'calendar_month',
visible: supportsEpg,
},
{
id: 'dashboard',
label: 'SETTINGS.NAV_DASHBOARD',
icon: 'dashboard',
visible: true,
},
{
// Must match the section's HTML id (`remote-control`) so the
// settings-section-scroll directive can resolve the anchor.
// Was previously '@iptvnator/ui/remote-control' (the NX lib
// name), which meant clicking the nav item silently no-op'd
// because document.getElementById of that string returned null.
id: 'remote-control',
label: 'SETTINGS.NAV_REMOTE',
icon: 'smartphone',
visible: supportsRemoteControl,
},
{
id: 'tmdb',
label: 'SETTINGS.NAV_TMDB',
icon: 'movie',
visible: true,
},
{
id: 'backup',
label: 'SETTINGS.NAV_BACKUP',
icon: 'backup',
visible: true,
},
{
id: 'reset',
label: 'SETTINGS.NAV_RESET',
icon: 'delete_sweep',
visible: true,
},
{
id: 'about',
label: 'SETTINGS.NAV_ABOUT',
icon: 'info',
visible: true,
},
];
}