feat: add dashboard settings and startup behavior options to settings component

This commit is contained in:
4gray committed 2026-04-04 13:38:53 +02:00
1 parent a2e09dacdc
commit 4d047f89ca
11 files changed
+237 -20

No files matched your search

+3
View File
@@ -12,6 +12,7 @@ import { DataService } from 'services';
import {
Language,
Settings,
StartupBehavior,
STORE_KEY,
StreamFormat,
Theme,
@@ -37,6 +38,8 @@ const DEFAULT_SETTINGS: Settings = {
streamFormat: StreamFormat.M3u8StreamFormat,
language: Language.ENGLISH,
showCaptions: false,
showDashboard: true,
startupBehavior: StartupBehavior.FirstView,
showExternalPlaybackBar: true,
theme: Theme.SystemTheme,
mpvPlayerPath: '',
+18
View File
@@ -1,8 +1,10 @@
describe('app routes', () => {
let workspaceChildren: Array<{
canActivate?: unknown[];
data?: Record<string, unknown>;
loadComponent?: unknown;
path?: string;
redirectTo?: unknown;
}> = [];
beforeAll(async () => {
@@ -50,4 +52,20 @@ describe('app routes', () => {
});
expect(typeof globalRecentRoute?.loadComponent).toBe('function');
});
it('uses a dynamic redirect for the default /workspace child route', async () => {
const workspaceDefaultRoute = workspaceChildren.find(
(route) => route.path === ''
);
expect(typeof workspaceDefaultRoute?.redirectTo).toBe('function');
});
it('protects the dashboard route behind a visibility guard', async () => {
const dashboardRoute = workspaceChildren.find(
(route) => route.path === 'dashboard'
);
expect(dashboardRoute?.canActivate).toHaveLength(1);
});
});
+18 -2
View File
@@ -1,5 +1,20 @@
import { Routes } from '@angular/router';
import { inject } from '@angular/core';
import { Router, Routes } from '@angular/router';
import { provideM3uWorkspaceRouteSession } from '@iptvnator/playlist/m3u/feature-player';
import { WorkspaceStartupPreferencesService } from '@iptvnator/workspace/shell/util';
const workspaceEntryRedirect = async () =>
inject(WorkspaceStartupPreferencesService).resolveInitialWorkspacePath();
const dashboardAccessGuard = async () => {
const startupPreferences = inject(WorkspaceStartupPreferencesService);
const router = inject(Router);
const redirectPath = await startupPreferences.resolveDashboardPath();
return redirectPath === '/workspace/dashboard'
? true
: router.parseUrl(redirectPath);
};
export const routes: Routes = [
{
@@ -20,10 +35,11 @@ export const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'dashboard',
redirectTo: workspaceEntryRedirect,
},
{
path: 'dashboard',
canActivate: [dashboardAccessGuard],
loadComponent: () =>
import('workspace-dashboard-feature').then(
(c) => c.WorkspaceDashboardComponent
@@ -119,6 +119,62 @@
</div>
</div>
<div class="setting-item">
<div class="setting-item__meta">
<h4>{{ 'SETTINGS.SHOW_DASHBOARD' | translate }}</h4>
<p>
{{
'SETTINGS.SHOW_DASHBOARD_DESCRIPTION'
| translate
}}
</p>
</div>
<div class="setting-item__control setting-item__toggle">
<mat-checkbox
formControlName="showDashboard"
data-test-id="toggle-show-dashboard"
></mat-checkbox>
</div>
</div>
<div class="setting-item">
<div class="setting-item__meta">
<h4>{{ 'SETTINGS.STARTUP_BEHAVIOR' | translate }}</h4>
<p>
{{
'SETTINGS.STARTUP_BEHAVIOR_DESCRIPTION'
| translate
}}
</p>
</div>
<div class="setting-item__control">
<mat-form-field
appearance="outline"
subscriptSizing="dynamic"
>
<mat-label>{{
'SETTINGS.STARTUP_BEHAVIOR' | translate
}}</mat-label>
<mat-select
formControlName="startupBehavior"
data-test-id="select-startup-behavior"
>
@for (
option of startupBehaviorOptions;
track option.value
) {
<mat-option
[value]="option.value"
[attr.data-test-id]="option.value"
>
{{ option.labelKey | translate }}
</mat-option>
}
</mat-select>
</mat-form-field>
</div>
</div>
<div class="setting-item">
<div class="setting-item__meta">
<h4>{{ 'SETTINGS.SHOW_CAPTIONS' | translate }}</h4>
@@ -28,6 +28,7 @@ import { DialogService } from 'components';
import { DataService, PlaylistsService } from 'services';
import {
Language,
StartupBehavior,
StreamFormat,
Theme,
VideoPlayer,
@@ -58,6 +59,8 @@ const DEFAULT_SETTINGS = {
streamFormat: StreamFormat.M3u8StreamFormat,
language: Language.ENGLISH,
showCaptions: false,
showDashboard: true,
startupBehavior: StartupBehavior.FirstView,
showExternalPlaybackBar: true,
theme: Theme.SystemTheme,
mpvPlayerPath: '',
@@ -405,6 +408,18 @@ describe('SettingsComponent', () => {
expect(component.settingsForm.dirty).toBeTruthy();
});
it('renders workspace startup controls with the expected defaults', () => {
const nativeElement = fixture.nativeElement as HTMLElement;
expect(
nativeElement.querySelector('[data-test-id="toggle-show-dashboard"]')
).not.toBeNull();
expect(component.settingsForm.value.showDashboard).toBe(true);
expect(component.settingsForm.value.startupBehavior).toBe(
StartupBehavior.FirstView
);
});
it('should save settings on submit', async () => {
const mockStore = settingsStore as unknown as MockSettingsStore;
mockStore.updateSettings.mockResolvedValue(undefined);
@@ -44,6 +44,7 @@ import { DataService, PlaylistsService } from 'services';
import {
Language,
Playlist,
StartupBehavior,
StreamFormat,
Theme,
VideoPlayer,
@@ -70,6 +71,11 @@ interface ThemeOption {
labelKey: string;
}
interface StartupBehaviorOption {
value: StartupBehavior;
labelKey: string;
}
@Component({
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.scss'],
@@ -179,6 +185,17 @@ export class SettingsComponent implements OnInit, OnDestroy {
},
];
readonly startupBehaviorOptions: StartupBehaviorOption[] = [
{
value: StartupBehavior.FirstView,
labelKey: 'SETTINGS.STARTUP_BEHAVIOR_FIRST_VIEW',
},
{
value: StartupBehavior.RestoreLastView,
labelKey: 'SETTINGS.STARTUP_BEHAVIOR_RESTORE_LAST_VIEW',
},
];
/** Settings form object */
settingsForm = this.formBuilder.group({
player: [VideoPlayer.VideoJs],
@@ -186,6 +203,8 @@ export class SettingsComponent implements OnInit, OnDestroy {
streamFormat: StreamFormat.M3u8StreamFormat,
language: Language.ENGLISH,
showCaptions: false,
showDashboard: true,
startupBehavior: StartupBehavior.FirstView,
showExternalPlaybackBar: true,
theme: Theme.SystemTheme,
mpvPlayerPath: '',
+32 -6
View File
@@ -243,6 +243,8 @@
"SETTINGS_SAVED": "Einstellungen wurden erfolgreich gespeichert!",
"THEME": "Farbdesign",
"SHOW_CAPTIONS": "Untertitel anzeigen",
"SHOW_DASHBOARD": "Dashboard anzeigen",
"SHOW_DASHBOARD_DESCRIPTION": "Dashboard in der Workspace-Leiste verfügbar halten. Wenn deaktiviert, wird Quellen zur ersten Workspace-Seite.",
"STREAM_FORMAT_DESCRIPTION": "Standard-Streamformat auswählen (Xtream)",
"REMOVE_ALL": "Playlist entfernen",
"REMOVE_ALL_BUTTON": "Entfernen",
@@ -274,6 +276,10 @@
"VLC_PLAYER_PATH_LABEL": "VLC-Pfad",
"VLC_PLAYER_PATH_DESCRIPTION": "Legen Sie den Pfad zum VLC-Player in Ihrem System fest. \nEs wird der bereitgestellte Pfad zu einer VLC-Binärdatei anstelle des Standardpfads für unser System verwendet.",
"THEME_DESCRIPTION": "Wählen Sie das visuelle Thema der Anwendung aus",
"STARTUP_BEHAVIOR": "Startansicht",
"STARTUP_BEHAVIOR_DESCRIPTION": "Legen Sie fest, ob IPTVnator die erste verfügbare Workspace-Ansicht oder Ihre zuletzt geöffnete Abschnittsansicht startet. Erste Ansicht bedeutet Dashboard, wenn aktiviert, sonst Quellen.",
"STARTUP_BEHAVIOR_FIRST_VIEW": "Erste verfügbare Ansicht",
"STARTUP_BEHAVIOR_RESTORE_LAST_VIEW": "Letzte Ansicht wiederherstellen",
"EPG_NOTE": "Derzeit ist EPG nur in der Electron-basierten Version von IPTVnator verfügbar.",
"VLC_PLAYER_PATH": "VLC-Playerpfad",
"IMPORT_EXPORT_DATA_DESCRIPTION": "Exportieren oder importieren Sie Wiedergabelisten im JSON-Format, das in der Anwendung verwendet wird.",
@@ -398,10 +404,18 @@
"COPY_STREAM_URL": "Stream-URL kopieren",
"ERROR_VIEW": {
"DELETE": "Löschen",
"IMPORT_CANCELLED": {
"TITLE": "Import abgebrochen",
"DESCRIPTION": "Der Playlist-Import wurde abgebrochen. Wiederholen Sie ihn, wenn Sie diese Quelle erneut laden möchten."
},
"ACCOUNT_EXPIRED": {
"TITLE": "Konto abgelaufen",
"DESCRIPTION": "Dieses Konto ist abgelaufen. \nBitte überprüfen Sie die Anmeldeinformationen in den Playlist-Einstellungen oder entfernen Sie sie."
},
"ACCOUNT_INACTIVE": {
"TITLE": "Konto inaktiv",
"DESCRIPTION": "Dieses Konto ist inaktiv. Bitte überprüfen Sie die Anmeldeinformationen in den Playlist-Einstellungen oder entfernen Sie es."
},
"HOME": "Startseite",
"EMPTY_CATEGORY": {
"TITLE": "Leere Kategorie",
@@ -419,6 +433,10 @@
"TITLE": "Portal nicht gefunden",
"DESCRIPTION": "Bitte überprüfen Sie die Anmeldeinformationen und die Portal-URL in den Playlist-Einstellungen oder entfernen Sie sie."
},
"PORTAL_UNAVAILABLE": {
"TITLE": "Portal nicht erreichbar",
"DESCRIPTION": "Das Portal konnte nicht erreicht werden. Überprüfen Sie die Server-URL oder versuchen Sie es erneut, wenn die Quelle wieder verfügbar ist."
},
"UNKNOWN_ERROR": {
"TITLE": "Etwas ist schief gelaufen",
"DESCRIPTION": "Unbekannter Fehler, bitte versuchen Sie es später noch einmal"
@@ -590,6 +608,7 @@
"RAIL_DASHBOARD": "Dashboard",
"OPEN_DASHBOARD": "Dashboard öffnen",
"RAIL_SOURCES": "Quellen",
"OPEN_SOURCES": "Quellen öffnen",
"RAIL_SETTINGS": "Einstellungen",
"OPEN_SETTINGS": "Einstellungen öffnen",
"RAIL_LIBRARY": "Bibliothek",
@@ -620,6 +639,7 @@
"NO_SECTION_ACTIONS": "Keine Aktionen für diesen Abschnitt",
"PLAYLIST_INFO": "Playlist-Info",
"ACCOUNT_INFO": "Kontoinfo",
"REFRESH_PLAYLIST": "Playlist aktualisieren",
"CLEAR_COMPLETED_DOWNLOADS_ALL": "Abgeschlossene Downloads löschen (alle Playlists)",
"CLEAR_COMPLETED_DOWNLOADS_ALL_ARIA": "Abgeschlossene Downloads für alle Playlists löschen",
"CLEAR_COMPLETED_DOWNLOADS_THIS_PLAYLIST": "Abgeschlossene Downloads löschen (diese Playlist)",
@@ -632,12 +652,18 @@
"NO_SOURCES_AVAILABLE": "Keine Quellen verfügbar",
"ONE_SOURCE_AVAILABLE": "1 Quelle verfügbar",
"SOURCES_AVAILABLE": "{{count}} Quellen verfügbar",
"XTREAM_IMPORT_PREPARING": "Playlist-Daten werden vorbereitet...",
"XTREAM_IMPORT_SAVING": "Playlist-Inhalte werden gespeichert...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Favoriten werden wiederhergestellt...",
"XTREAM_IMPORT_RESTORING_RECENT": "Zuletzt angesehene Inhalte werden wiederhergestellt...",
"XTREAM_IMPORT_CANCEL": "Import abbrechen",
"XTREAM_IMPORT_CANCELLING": "Import wird abgebrochen...",
"XTREAM_IMPORT_TITLE": "Playlist wird synchronisiert",
"XTREAM_IMPORT_REMOTE_BADGE": "Remote-Quelle",
"XTREAM_IMPORT_LOCAL_BADGE": "Lokale Bibliothek",
"XTREAM_IMPORT_DETAIL_REMOTE": "Warte auf die Antwort des Providers.",
"XTREAM_IMPORT_DETAIL_LOCAL": "Bereitet schnellere Playlist-Wechsel für den nächsten Besuch vor.",
"XTREAM_IMPORT_PREPARING": "Lokale Bibliothek wird vorbereitet...",
"XTREAM_IMPORT_LOADING": "Playlist-Daten werden von der Quelle geladen...",
"XTREAM_IMPORT_SAVING": "Playlist-Daten werden lokal gespeichert...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Favoriten werden aus der lokalen Bibliothek wiederhergestellt...",
"XTREAM_IMPORT_RESTORING_RECENT": "Zuletzt angesehene Inhalte werden aus der lokalen Bibliothek wiederhergestellt...",
"XTREAM_IMPORT_CANCEL": "Synchronisierung stoppen",
"XTREAM_IMPORT_CANCELLING": "Synchronisierung wird gestoppt...",
"COMMANDS": {
"GLOBAL_SEARCH_LABEL": "Alle Xtream-Playlists durchsuchen",
"GLOBAL_SEARCH_DESCRIPTION": "Globale Suchüberlagerung öffnen",
+32 -6
View File
@@ -200,6 +200,8 @@
"SETTINGS_SAVED": "Success! Configuration was saved.",
"THEME": "Visual theme",
"SHOW_CAPTIONS": "Show subtitles",
"SHOW_DASHBOARD": "Show dashboard",
"SHOW_DASHBOARD_DESCRIPTION": "Keep Dashboard available in the workspace rail. When disabled, Sources becomes the first workspace page.",
"ADD_EPG_SOURCE": "Add EPG source",
"CLEAR_EPG_DATA": "Clear EPG data",
"CLEAR_EPG_DIALOG": {
@@ -212,6 +214,10 @@
"STREAM_FORMAT_DESCRIPTION": "Select default stream format (xtream)",
"LANGUAGE_DESCRIPTION": "Select language of the application",
"THEME_DESCRIPTION": "Select visual theme of the application",
"STARTUP_BEHAVIOR": "Startup view",
"STARTUP_BEHAVIOR_DESCRIPTION": "Choose whether IPTVnator opens the first available workspace view or restores your last section-level view. First view means Dashboard when enabled, otherwise Sources.",
"STARTUP_BEHAVIOR_FIRST_VIEW": "First available view",
"STARTUP_BEHAVIOR_RESTORE_LAST_VIEW": "Restore last view",
"SHOW_CAPTIONS_DESCRIPTION": "Show or hide subtitles by default",
"SHOW_EXTERNAL_PLAYBACK_BAR": "Show now playing footer",
"SHOW_EXTERNAL_PLAYBACK_BAR_DESCRIPTION": "Keep the external-player status bar visible at the bottom of the workspace on desktop.",
@@ -469,10 +475,18 @@
"ACCOUNT_INFO": "Account info"
},
"ERROR_VIEW": {
"IMPORT_CANCELLED": {
"TITLE": "Import cancelled",
"DESCRIPTION": "The playlist import was cancelled. Retry when you want to continue loading this source."
},
"ACCOUNT_EXPIRED": {
"TITLE": "Account expired",
"DESCRIPTION": "This account has been expired. Please check the credentials in playlist settings or remove it."
},
"ACCOUNT_INACTIVE": {
"TITLE": "Account inactive",
"DESCRIPTION": "This account is inactive. Please check the credentials in playlist settings or remove it."
},
"UNAUTHORIZED": {
"TITLE": "Unauthorized",
"DESCRIPTION": "Please check the credentials in playlist settings or remove it."
@@ -481,6 +495,10 @@
"TITLE": "Portal not found",
"DESCRIPTION": "Please check the credentials and portal url in playlist settings or remove it."
},
"PORTAL_UNAVAILABLE": {
"TITLE": "Portal unavailable",
"DESCRIPTION": "The portal could not be reached. Check the server URL or retry when the source is available again."
},
"EMPTY_CATEGORY": {
"TITLE": "No content in this category",
"DESCRIPTION": "Select another category or switch the content type."
@@ -661,6 +679,7 @@
"RAIL_DASHBOARD": "Dashboard",
"OPEN_DASHBOARD": "Open dashboard",
"RAIL_SOURCES": "Sources",
"OPEN_SOURCES": "Open sources",
"RAIL_SETTINGS": "Settings",
"OPEN_SETTINGS": "Open settings",
"RAIL_LIBRARY": "Library",
@@ -691,6 +710,7 @@
"NO_SECTION_ACTIONS": "No actions for this section",
"PLAYLIST_INFO": "Playlist info",
"ACCOUNT_INFO": "Account info",
"REFRESH_PLAYLIST": "Refresh playlist",
"CLEAR_COMPLETED_DOWNLOADS_ALL": "Clear completed downloads (all playlists)",
"CLEAR_COMPLETED_DOWNLOADS_ALL_ARIA": "Clear completed downloads for all playlists",
"CLEAR_COMPLETED_DOWNLOADS_THIS_PLAYLIST": "Clear completed downloads (this playlist)",
@@ -703,12 +723,18 @@
"NO_SOURCES_AVAILABLE": "No sources available",
"ONE_SOURCE_AVAILABLE": "1 source available",
"SOURCES_AVAILABLE": "{{count}} sources available",
"XTREAM_IMPORT_PREPARING": "Preparing playlist data...",
"XTREAM_IMPORT_SAVING": "Saving playlist content...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Restoring favorites...",
"XTREAM_IMPORT_RESTORING_RECENT": "Restoring recently viewed...",
"XTREAM_IMPORT_CANCEL": "Cancel import",
"XTREAM_IMPORT_CANCELLING": "Cancelling import...",
"XTREAM_IMPORT_TITLE": "Syncing playlist",
"XTREAM_IMPORT_REMOTE_BADGE": "Remote source",
"XTREAM_IMPORT_LOCAL_BADGE": "Local library",
"XTREAM_IMPORT_DETAIL_REMOTE": "Waiting on the provider response.",
"XTREAM_IMPORT_DETAIL_LOCAL": "Preparing faster playlist switching for the next visit.",
"XTREAM_IMPORT_PREPARING": "Preparing local library...",
"XTREAM_IMPORT_LOADING": "Fetching playlist data from source...",
"XTREAM_IMPORT_SAVING": "Saving playlist data locally...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Restoring favorites from local library...",
"XTREAM_IMPORT_RESTORING_RECENT": "Restoring recently viewed from local library...",
"XTREAM_IMPORT_CANCEL": "Stop sync",
"XTREAM_IMPORT_CANCELLING": "Stopping sync...",
"COMMANDS": {
"GLOBAL_SEARCH_LABEL": "Search all Xtream playlists",
"GLOBAL_SEARCH_DESCRIPTION": "Open global search overlay",
+32 -6
View File
@@ -181,6 +181,8 @@
"SETTINGS_SAVED": "Новые настройки были успешно сохранены!",
"THEME": "Тема оформления",
"SHOW_CAPTIONS": "Отображать субтитры",
"SHOW_DASHBOARD": "Показывать панель",
"SHOW_DASHBOARD_DESCRIPTION": "Оставить Dashboard доступным в боковой панели рабочего пространства. Если отключить, первой страницей будет Источники.",
"ADD_EPG_SOURCE": "Добавить источник EPG",
"CLEAR_EPG_DATA": "Очистить данные EPG",
"CLEAR_EPG_DIALOG": {
@@ -193,6 +195,10 @@
"STREAM_FORMAT_DESCRIPTION": "Выбрать формат потока по умолчанию (Xtream)",
"LANGUAGE_DESCRIPTION": "Выбрать язык приложения",
"THEME_DESCRIPTION": "Выбрать визуальную тему оформления",
"STARTUP_BEHAVIOR": "Начальный экран",
"STARTUP_BEHAVIOR_DESCRIPTION": "Выберите, должен ли IPTVnator открывать первый доступный экран рабочего пространства или восстанавливать последний экран уровня раздела. Первый экран означает Dashboard, если он включён, иначе Источники.",
"STARTUP_BEHAVIOR_FIRST_VIEW": "Первый доступный экран",
"STARTUP_BEHAVIOR_RESTORE_LAST_VIEW": "Восстановить последний экран",
"SHOW_CAPTIONS_DESCRIPTION": "Показать или скрыть субтитры по умолчанию.",
"VERSION_DESCRIPTION": "Текущая версия приложения",
"EPG_NOTE": "На данный момент EPG доступен только в нативной версии IPTVnator.",
@@ -393,10 +399,18 @@
"COPY_STREAM_URL": "Копировать URL-адрес потока",
"ERROR_VIEW": {
"DELETE": "Удалить",
"IMPORT_CANCELLED": {
"TITLE": "Импорт отменён",
"DESCRIPTION": "Импорт плейлиста был отменён. Повторите попытку, когда захотите снова загрузить этот источник."
},
"ACCOUNT_EXPIRED": {
"TITLE": "Срок действия учетной записи истек",
"DESCRIPTION": "Срок действия этой учетной записи истек. \nПожалуйста, проверьте учетные данные в настройках плейлиста или удалите его."
},
"ACCOUNT_INACTIVE": {
"TITLE": "Учётная запись неактивна",
"DESCRIPTION": "Эта учётная запись неактивна. Проверьте учётные данные в настройках плейлиста или удалите источник."
},
"HOME": "На главную",
"EMPTY_CATEGORY": {
"TITLE": "Пустая категория",
@@ -410,6 +424,10 @@
"TITLE": "Портал не найден",
"DESCRIPTION": "Пожалуйста, проверьте учетные данные и URL портала в настройках плейлиста или удалите его."
},
"PORTAL_UNAVAILABLE": {
"TITLE": "Портал недоступен",
"DESCRIPTION": "Не удалось подключиться к порталу. Проверьте URL сервера или повторите попытку позже."
},
"NO_CATEGORY_SELECTED": {
"TITLE": "Категория не выбрана",
"DESCRIPTION": "Пожалуйста, выберите категорию для просмотра содержимого"
@@ -567,6 +585,7 @@
"RAIL_DASHBOARD": "Панель",
"OPEN_DASHBOARD": "Открыть панель",
"RAIL_SOURCES": "Источники",
"OPEN_SOURCES": "Открыть источники",
"RAIL_SETTINGS": "Настройки",
"OPEN_SETTINGS": "Открыть настройки",
"RAIL_LIBRARY": "Библиотека",
@@ -597,6 +616,7 @@
"NO_SECTION_ACTIONS": "Для этого раздела нет действий",
"PLAYLIST_INFO": "Информация о плейлисте",
"ACCOUNT_INFO": "Информация об аккаунте",
"REFRESH_PLAYLIST": "Обновить плейлист",
"CLEAR_COMPLETED_DOWNLOADS_ALL": "Очистить завершенные загрузки (все плейлисты)",
"CLEAR_COMPLETED_DOWNLOADS_ALL_ARIA": "Очистить завершенные загрузки для всех плейлистов",
"CLEAR_COMPLETED_DOWNLOADS_THIS_PLAYLIST": "Очистить завершенные загрузки (этот плейлист)",
@@ -609,12 +629,18 @@
"NO_SOURCES_AVAILABLE": "Нет доступных источников",
"ONE_SOURCE_AVAILABLE": "Доступен 1 источник",
"SOURCES_AVAILABLE": "Доступно источников: {{count}}",
"XTREAM_IMPORT_PREPARING": "Подготовка данных плейлиста...",
"XTREAM_IMPORT_SAVING": "Сохранение контента плейлиста...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Восстановление избранного...",
"XTREAM_IMPORT_RESTORING_RECENT": "Восстановление недавно просмотренного...",
"XTREAM_IMPORT_CANCEL": "Отменить импорт",
"XTREAM_IMPORT_CANCELLING": "Отмена импорта...",
"XTREAM_IMPORT_TITLE": "Синхронизация плейлиста",
"XTREAM_IMPORT_REMOTE_BADGE": "Удалённый источник",
"XTREAM_IMPORT_LOCAL_BADGE": "Локальная библиотека",
"XTREAM_IMPORT_DETAIL_REMOTE": "Ожидание ответа от провайдера.",
"XTREAM_IMPORT_DETAIL_LOCAL": "Подготавливает более быстрые переключения плейлиста при следующем открытии.",
"XTREAM_IMPORT_PREPARING": "Подготовка локальной библиотеки...",
"XTREAM_IMPORT_LOADING": "Получение данных плейлиста из источника...",
"XTREAM_IMPORT_SAVING": "Сохранение данных плейлиста локально...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Восстановление избранного из локальной библиотеки...",
"XTREAM_IMPORT_RESTORING_RECENT": "Восстановление недавно просмотренного из локальной библиотеки...",
"XTREAM_IMPORT_CANCEL": "Остановить синхронизацию",
"XTREAM_IMPORT_CANCELLING": "Остановка синхронизации...",
"COMMANDS": {
"GLOBAL_SEARCH_LABEL": "Искать во всех плейлистах Xtream",
"GLOBAL_SEARCH_DESCRIPTION": "Открыть глобальный поиск",
@@ -11,6 +11,7 @@ import { firstValueFrom } from 'rxjs';
import {
Language,
Settings,
StartupBehavior,
STORE_KEY,
StreamFormat,
Theme,
@@ -22,6 +23,8 @@ const DEFAULT_SETTINGS: Settings = {
streamFormat: StreamFormat.M3u8StreamFormat,
language: Language.ENGLISH,
showCaptions: false,
showDashboard: true,
startupBehavior: StartupBehavior.FirstView,
showExternalPlaybackBar: true,
theme: Theme.SystemTheme,
mpvPlayerPath: '',
@@ -74,6 +77,8 @@ export const SettingsStore = signalStore(
streamFormat: store.streamFormat(),
language: store.language(),
showCaptions: store.showCaptions(),
showDashboard: store.showDashboard(),
startupBehavior: store.startupBehavior(),
showExternalPlaybackBar: store.showExternalPlaybackBar(),
theme: store.theme(),
mpvPlayerPath: store.mpvPlayerPath(),
@@ -13,6 +13,11 @@ export enum VideoPlayer {
ArtPlayer = 'artplayer',
}
export enum StartupBehavior {
FirstView = 'first-view',
RestoreLastView = 'restore-last-view',
}
/**
* Describes all available settings options of the application
*/
@@ -22,6 +27,8 @@ export interface Settings {
streamFormat: StreamFormat;
language: Language;
showCaptions: boolean;
showDashboard: boolean;
startupBehavior: StartupBehavior;
/** Show the desktop footer bar for external playback status */
showExternalPlaybackBar?: boolean;
theme: Theme;