diff --git a/src/app/services/settings-store.service.ts b/src/app/services/settings-store.service.ts new file mode 100644 index 000000000..db817cf1d --- /dev/null +++ b/src/app/services/settings-store.service.ts @@ -0,0 +1,51 @@ +import { Injectable, computed, signal } from '@angular/core'; +import { StorageMap } from '@ngx-pwa/local-storage'; +import { Language } from '../settings/language.enum'; +import { Settings, VideoPlayer } from '../settings/settings.interface'; +import { Theme } from '../settings/theme.enum'; +import { STORE_KEY } from '../shared/enums/store-keys.enum'; + +const DEFAULT_SETTINGS: Settings = { + player: VideoPlayer.VideoJs, + language: Language.ENGLISH, + showCaptions: false, + theme: Theme.LightTheme, + mpvPlayerPath: '', + vlcPlayerPath: '', + remoteControl: false, + remoteControlPort: 3000, + epgUrl: [], +}; + +@Injectable({ + providedIn: 'root', +}) +export class SettingsStore { + private settings = signal(DEFAULT_SETTINGS); + + // Computed values for commonly used settings + readonly player = computed(() => this.settings().player); + readonly showCaptions = computed(() => this.settings().showCaptions); + readonly theme = computed(() => this.settings().theme); + + constructor(private storage: StorageMap) { + this.loadSettings(); + } + + async loadSettings() { + const stored = await this.storage.get(STORE_KEY.Settings).toPromise(); + if (stored) { + this.settings.set({ ...DEFAULT_SETTINGS, ...(stored as Settings) }); + } + } + + async updateSettings(settings: Partial) { + const newSettings = { ...this.settings(), ...settings }; + this.settings.set(newSettings); + await this.storage.set(STORE_KEY.Settings, newSettings).toPromise(); + } + + getSettings() { + return this.settings; + } +} diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index 842b07155..e6fcdae54 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -1,11 +1,15 @@ - +@if (!isDialog) { + +} @else { +

{{ 'SETTINGS.TITLE' | translate }}

+}
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index fe8bb3fe9..205b45c17 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -1,5 +1,6 @@ +/* eslint-disable @typescript-eslint/no-base-to-string */ import { CommonModule } from '@angular/common'; -import { Component, OnInit } from '@angular/core'; +import { Component, Inject, Input, OnInit, Optional } from '@angular/core'; import { FormArray, FormBuilder, @@ -10,6 +11,11 @@ import { } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; +import { + MAT_DIALOG_DATA, + MatDialog, + MatDialogModule, +} from '@angular/material/dialog'; import { MatDividerModule } from '@angular/material/divider'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; @@ -31,13 +37,13 @@ import { DataService } from '../services/data.service'; import { DialogService } from '../services/dialog.service'; import { EpgService } from '../services/epg.service'; import { PlaylistsService } from '../services/playlists.service'; +import { SettingsStore } from '../services/settings-store.service'; import { HeaderComponent } from '../shared/components/header/header.component'; -import { STORE_KEY } from '../shared/enums/store-keys.enum'; import * as PlaylistActions from '../state/actions'; import { selectIsEpgAvailable } from '../state/selectors'; import { SettingsService } from './../services/settings.service'; import { Language } from './language.enum'; -import { Settings, VideoPlayer } from './settings.interface'; +import { VideoPlayer } from './settings.interface'; import { Theme } from './theme.enum'; @Component({ @@ -57,9 +63,11 @@ import { Theme } from './theme.enum'; MatTooltipModule, ReactiveFormsModule, TranslateModule, + MatDialogModule, ], }) export class SettingsComponent implements OnInit { + @Input() isDialog = false; /** List with available languages as enum */ languageEnum = Language; @@ -135,8 +143,13 @@ export class SettingsComponent implements OnInit { private settingsService: SettingsService, private snackBar: MatSnackBar, private store: Store, - private translate: TranslateService - ) {} + private translate: TranslateService, + private matDialog: MatDialog, + private settingsStore: SettingsStore, + @Optional() @Inject(MAT_DIALOG_DATA) data?: { isDialog: boolean } + ) { + this.isDialog = data?.isDialog ?? false; + } /** * Reads the config object from the browsers @@ -151,34 +164,12 @@ export class SettingsComponent implements OnInit { * Sets saved settings from the indexed db store */ setSettings(): void { - this.settingsService - .getValueFromLocalStorage(STORE_KEY.Settings) - .subscribe((settings: Settings) => { - if (settings) { - try { - this.settingsForm.setValue({ - player: settings.player - ? settings.player - : VideoPlayer.VideoJs, - ...(this.isTauri ? { epgUrl: [] } : {}), - language: settings.language ?? Language.ENGLISH, - showCaptions: settings.showCaptions ?? false, - theme: settings.theme ?? Theme.LightTheme, - mpvPlayerPath: settings.mpvPlayerPath ?? '', - vlcPlayerPath: settings.vlcPlayerPath ?? '', - remoteControl: settings.remoteControl ?? false, - remoteControlPort: - settings.remoteControlPort ?? 3000, - }); - } catch (error) { - throw new Error(error); - } + const currentSettings = this.settingsStore.getSettings()(); + this.settingsForm.patchValue(currentSettings); - if (this.isTauri) { - this.setEpgUrls(settings.epgUrl); - } - } - }); + if (this.isTauri && currentSettings.epgUrl) { + this.setEpgUrls(currentSettings.epgUrl); + } } /** @@ -247,31 +238,26 @@ export class SettingsComponent implements OnInit { * the indexed db store */ onSubmit(): void { - this.settingsService - .setValueToLocalStorage( - STORE_KEY.Settings, - this.settingsForm.value, - true - ) - .pipe(take(1)) - .subscribe(() => { - this.applyChangedSettings(); - }); + this.settingsStore.updateSettings(this.settingsForm.value).then(() => { + this.applyChangedSettings(); + this.electronService.sendIpcEvent( + SETTINGS_UPDATE, + this.settingsForm.value + ); - this.electronService.sendIpcEvent( - SETTINGS_UPDATE, - this.settingsForm.value - ); + this.electronService.sendIpcEvent( + SET_MPV_PLAYER_PATH, + this.settingsForm.value.mpvPlayerPath + ); - this.electronService.sendIpcEvent( - SET_MPV_PLAYER_PATH, - this.settingsForm.value.mpvPlayerPath - ); - - this.electronService.sendIpcEvent( - SET_VLC_PLAYER_PATH, - this.settingsForm.value.mpvPlayerPath - ); + this.electronService.sendIpcEvent( + SET_VLC_PLAYER_PATH, + this.settingsForm.value.mpvPlayerPath + ); + }); + if (this.isDialog) { + this.matDialog.closeAll(); + } } /** @@ -308,7 +294,11 @@ export class SettingsComponent implements OnInit { * Navigates back to the applications homepage */ backToHome(): void { - this.router.navigateByUrl('/'); + if (this.isDialog) { + this.matDialog.closeAll(); + } else { + this.router.navigateByUrl('/'); + } } /** @@ -394,6 +384,7 @@ export class SettingsComponent implements OnInit { duration: 2000, } ); + console.error(error); } }; reader.readAsText(file);