mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
* feat(updater): nightly builds and a stable/nightly update channel Every master push publishes its artifacts as a prerelease of 4gray/iptvnator-nightly instead of the rolling test-master draft, with a version of <next patch>-nightly.<commit date>.<run number> applied in every build job. Settings → About gains an Update channel switch; AppUpdateService re-points electron-updater per check (feed repository, allowPrerelease, channel name, allowDowngrade reset) and reads release notes from the repository the requested version belongs to. Channel switches are forward-only: a nightly build stays until a newer stable release exists. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(updater): compute the nightly version once and keep re-runs safe Review follow-ups: the nightly version is resolved by a leading job and handed to every build job, and the patch is bumped only when the base tag already exists so the release-cut window stays below the imminent release. A re-run never deletes a published nightly; only a draft left by a failed run is replaced. Typed update-status literals in the remaining specs carry the new channel fields. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test(packaging): expect the nightly-version prerequisite in the build workflow graph Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
229 lines
5.8 KiB
TypeScript
229 lines
5.8 KiB
TypeScript
import {
|
|
CoverSize,
|
|
EpgViewMode,
|
|
StartupBehavior,
|
|
Theme,
|
|
VideoPlayer,
|
|
} from '@iptvnator/shared/interfaces';
|
|
import {
|
|
CoverSizeOption,
|
|
EpgViewModeOption,
|
|
SettingsPlayerOption,
|
|
SettingsSection,
|
|
StartupBehaviorOption,
|
|
StartupWindowModeOption,
|
|
ThemeOption,
|
|
UpdateChannelOption,
|
|
} 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_UPDATE_CHANNEL_OPTIONS: UpdateChannelOption[] = [
|
|
{
|
|
value: 'stable',
|
|
labelKey: 'SETTINGS.APP_UPDATE_CHANNEL_STABLE',
|
|
},
|
|
{
|
|
value: 'nightly',
|
|
labelKey: 'SETTINGS.APP_UPDATE_CHANNEL_NIGHTLY',
|
|
},
|
|
];
|
|
|
|
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,
|
|
},
|
|
];
|
|
}
|