refactor: update settings store

This commit is contained in:
4gray committed 2024-12-20 22:59:22 +01:00
1 parent ee490ee05a
commit 13b4cf3992
9 files changed
+87 -69

No files matched your search

@@ -9,6 +9,7 @@ import {
OnDestroy,
OnInit,
effect,
inject,
} from '@angular/core';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBar } from '@angular/material/snack-bar';
@@ -133,6 +134,8 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
volume = 1;
private settingsStore = inject(SettingsStore);
constructor(
private activatedRoute: ActivatedRoute,
private dataService: DataService,
@@ -142,8 +145,7 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
private router: Router,
private snackBar: MatSnackBar,
private storage: StorageMap,
private store: Store,
private settingsStore: SettingsStore
private store: Store
) {
// Initialize volume from localStorage in constructor
const savedVolume = localStorage.getItem('volume');
+3 -4
View File
@@ -17,7 +17,6 @@ export class PlayerService {
private dialog = inject(MatDialog);
private dataService = inject(DataService);
private settingsStore = inject(SettingsStore);
private settings = this.settingsStore.getSettings();
openPlayer(
streamUrl: string,
@@ -26,7 +25,7 @@ export class PlayerService {
hideExternalInfoDialog = false,
isLiveContent = false
) {
const player = this.settings()?.player ?? VideoPlayer.VideoJs;
const player = this.settingsStore.player() ?? VideoPlayer.VideoJs;
if (player === VideoPlayer.MPV) {
if (!hideExternalInfoDialog) {
@@ -34,7 +33,7 @@ export class PlayerService {
}
this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
url: streamUrl,
mpvPlayerPath: this.settings()?.mpvPlayerPath,
mpvPlayerPath: this.settingsStore.mpvPlayerPath(),
title,
thumbnail,
});
@@ -44,7 +43,7 @@ export class PlayerService {
}
this.dataService.sendIpcEvent(OPEN_VLC_PLAYER, {
url: streamUrl,
vlcPlayerPath: this.settings()?.vlcPlayerPath,
vlcPlayerPath: this.settingsStore.vlcPlayerPath(),
});
} else if (!isLiveContent) {
this.dialog.open<PlayerDialogComponent, PlayerDialogData>(
+48 -31
View File
@@ -1,5 +1,13 @@
import { Injectable, computed, signal } from '@angular/core';
import { computed, inject } from '@angular/core';
import {
patchState,
signalStore,
withComputed,
withMethods,
withState,
} from '@ngrx/signals';
import { StorageMap } from '@ngx-pwa/local-storage';
import { firstValueFrom } from 'rxjs';
import { Language } from '../settings/language.enum';
import { Settings, VideoPlayer } from '../settings/settings.interface';
import { Theme } from '../settings/theme.enum';
@@ -17,35 +25,44 @@ const DEFAULT_SETTINGS: Settings = {
epgUrl: [],
};
@Injectable({
providedIn: 'root',
})
export class SettingsStore {
private settings = signal<Settings>(DEFAULT_SETTINGS);
export const SettingsStore = signalStore(
{ providedIn: 'root' },
withState<Settings>(DEFAULT_SETTINGS),
withComputed((store) => ({
player: computed(() => store.player()),
showCaptions: computed(() => store.showCaptions()),
theme: computed(() => store.theme()),
})),
withMethods((store, storage = inject(StorageMap)) => ({
async loadSettings() {
const stored = await firstValueFrom(
storage.get(STORE_KEY.Settings)
);
if (stored) {
patchState(store, {
...DEFAULT_SETTINGS,
...(stored as 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);
async updateSettings(settings: Partial<Settings>) {
patchState(store, settings);
await firstValueFrom(storage.set(STORE_KEY.Settings, settings));
},
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<Settings>) {
const newSettings = { ...this.settings(), ...settings };
this.settings.set(newSettings);
await this.storage.set(STORE_KEY.Settings, newSettings).toPromise();
}
getSettings() {
return this.settings;
}
}
getSettings() {
return {
player: store.player(),
language: store.language(),
showCaptions: store.showCaptions(),
theme: store.theme(),
mpvPlayerPath: store.mpvPlayerPath(),
vlcPlayerPath: store.vlcPlayerPath(),
remoteControl: store.remoteControl(),
remoteControlPort: store.remoteControlPort(),
epgUrl: store.epgUrl(),
};
},
}))
);
+2
View File
@@ -209,6 +209,7 @@
></mat-checkbox>
</div>
</div>
<!-- not ported to tauri yet
@if (isPwa || isTauri) {
<mat-divider />
<div class="row">
@@ -226,6 +227,7 @@
</div>
</div>
}
-->
@if (settingsForm.value.remoteControl === true) {
<mat-divider />
<div class="row">
+11 -3
View File
@@ -1,6 +1,13 @@
/* eslint-disable @typescript-eslint/no-base-to-string */
import { CommonModule } from '@angular/common';
import { Component, Inject, Input, OnInit, Optional } from '@angular/core';
import {
Component,
inject,
Inject,
Input,
OnInit,
Optional,
} from '@angular/core';
import {
FormArray,
FormBuilder,
@@ -136,6 +143,8 @@ export class SettingsComponent implements OnInit {
/** Form array with epg sources */
epgUrl = this.settingsForm.get('epgUrl') as FormArray;
private settingsStore = inject(SettingsStore);
/**
* Creates an instance of SettingsComponent and injects
* required dependencies into the component
@@ -152,7 +161,6 @@ export class SettingsComponent implements OnInit {
private store: Store,
private translate: TranslateService,
private matDialog: MatDialog,
private settingsStore: SettingsStore,
@Optional() @Inject(MAT_DIALOG_DATA) data?: { isDialog: boolean }
) {
this.isDialog = data?.isDialog ?? false;
@@ -172,7 +180,7 @@ export class SettingsComponent implements OnInit {
*/
async setSettings() {
await this.settingsStore.loadSettings();
const currentSettings = this.settingsStore.getSettings()();
const currentSettings = this.settingsStore.getSettings();
this.settingsForm.patchValue(currentSettings);
if (this.isTauri && currentSettings.epgUrl) {
@@ -106,13 +106,13 @@ export class LiveStreamLayoutComponent implements OnInit {
openPlayer(streamUrl: string, title: string, thumbnail: string) {
this.streamUrl = streamUrl;
this.player = this.settings()?.player ?? VideoPlayer.VideoJs;
this.player = this.settingsStore.player() ?? VideoPlayer.VideoJs;
if (this.player === VideoPlayer.MPV) {
if (!this.hideExternalInfoDialog())
this.dialog.open(ExternalPlayerInfoDialogComponent);
this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
url: streamUrl,
mpvPlayerPath: this.settings()?.mpvPlayerPath,
mpvPlayerPath: this.settingsStore.mpvPlayerPath(),
title,
thumbnail,
});
@@ -121,7 +121,7 @@ export class LiveStreamLayoutComponent implements OnInit {
this.dialog.open(ExternalPlayerInfoDialogComponent);
this.dataService.sendIpcEvent(OPEN_VLC_PLAYER, {
url: streamUrl,
vlcPlayerPath: this.settings()?.vlcPlayerPath,
vlcPlayerPath: this.settingsStore.vlcPlayerPath(),
});
} else {
if (this.selectedContentType() !== 'live') {
@@ -4,7 +4,7 @@
class="container"
[style.background]="
item?.info?.backdrop_path && item?.info?.backdrop_path.length > 0
? settings().theme === 'DARK_THEME'
? theme() === 'DARK_THEME'
? 'linear-gradient(to top, rgba(29,29,29,1) 0%, rgba(0,0,0,0.5) 100%), url(' +
item?.info?.backdrop_path[0] +
') repeat-x'
@@ -1,13 +1,11 @@
import { Component, OnDestroy, OnInit, inject } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { MatIcon } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ActivatedRoute } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core';
import { XtreamVodDetails } from '../../../../shared/xtream-vod-details.interface';
import { DataService } from '../../services/data.service';
import { PlayerService } from '../../services/player.service';
import { SettingsStore } from '../../services/settings-store.service';
import { selectActivePlaylist } from '../../state/selectors';
@@ -27,15 +25,13 @@ import { SafePipe } from './safe.pipe';
],
})
export class VodDetailsComponent implements OnInit, OnDestroy {
private dataService = inject(DataService);
private dialog = inject(MatDialog);
private settingsStore = inject(SettingsStore);
private route = inject(ActivatedRoute);
private store = inject(Store);
private readonly xtreamStore = inject(XtreamStore);
private playerService = inject(PlayerService);
readonly settings = this.settingsStore.getSettings();
readonly theme = this.settingsStore.theme;
private readonly selectedContentType = this.xtreamStore.selectedContentType;
private readonly hideExternalInfoDialog =
this.xtreamStore.hideExternalInfoDialog;
@@ -31,8 +31,6 @@ import { VodDetailsComponent } from './vod-details/vod-details.component';
import { MatDialog } from '@angular/material/dialog';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { Router } from '@angular/router';
import { StorageMap } from '@ngx-pwa/local-storage';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import {
@@ -40,7 +38,6 @@ import {
XtreamSerieEpisode,
} from '../../../shared/xtream-serie-details.interface';
import { LiveStreamLayoutComponent } from '../portals/live-stream-layout/live-stream-layout.component';
import { DialogService } from '../services/dialog.service';
import { PlaylistsService } from '../services/playlists.service';
import { SettingsStore } from '../services/settings-store.service';
import { VideoPlayer } from '../settings/settings.interface';
@@ -115,18 +112,15 @@ type LayoutView =
],
})
export class XtreamMainContainerComponent implements OnInit {
dataService = inject(DataService);
dialog = inject(MatDialog);
dialogService = inject(DialogService);
ngZone = inject(NgZone);
playlistService = inject(PlaylistsService);
portalStore = inject(PortalStore);
router = inject(Router);
settingsStore = inject(SettingsStore);
snackBar = inject(MatSnackBar);
storage = inject(StorageMap);
store = inject(Store);
translate = inject(TranslateService);
private readonly dataService = inject(DataService);
private readonly dialog = inject(MatDialog);
private readonly ngZone = inject(NgZone);
private readonly playlistService = inject(PlaylistsService);
private readonly portalStore = inject(PortalStore);
private readonly settingsStore = inject(SettingsStore);
private readonly snackBar = inject(MatSnackBar);
private readonly store = inject(Store);
private readonly translate = inject(TranslateService);
currentPlaylist = this.store.selectSignal(selectCurrentPlaylist);
navigationContentTypes: ContentTypeNavigationItem[] = [
@@ -156,7 +150,7 @@ export class XtreamMainContainerComponent implements OnInit {
selectedContentType = ContentType.VODS;
currentLayout: LayoutView = 'category';
vodDetails!: XtreamVodDetails | XtreamSerieDetails;
settings = this.settingsStore.getSettings();
settings = this.settingsStore;
isLoading = true;
searchPhrase = this.portalStore.searchPhrase();
contentId: number;
@@ -344,20 +338,20 @@ export class XtreamMainContainerComponent implements OnInit {
openPlayer(streamUrl: string, title: string) {
this.streamUrl = streamUrl;
this.player = this.settings()?.player ?? VideoPlayer.VideoJs;
this.player = this.settingsStore.player() ?? VideoPlayer.VideoJs;
if (this.player === VideoPlayer.MPV) {
if (!this.hideExternalInfoDialog())
this.dialog.open(ExternalPlayerInfoDialogComponent);
this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
url: streamUrl,
mpvPlayerPath: this.settings()?.mpvPlayerPath,
mpvPlayerPath: this.settingsStore.mpvPlayerPath(),
});
} else if (this.player === VideoPlayer.VLC) {
if (!this.hideExternalInfoDialog())
this.dialog.open(ExternalPlayerInfoDialogComponent);
this.dataService.sendIpcEvent(OPEN_VLC_PLAYER, {
url: streamUrl,
vlcPlayerPath: this.settings()?.vlcPlayerPath,
vlcPlayerPath: this.settingsStore.vlcPlayerPath(),
});
} else {
if (this.selectedContentType !== ContentType.ITV) {
@@ -382,7 +376,7 @@ export class XtreamMainContainerComponent implements OnInit {
playEpisode(episode: XtreamSerieEpisode) {
const { serverUrl, username, password } = this.currentPlaylist();
const player = this.settings().player;
const player = this.settingsStore.player();
const streamUrl = `${serverUrl}/series/${username}/${password}/${episode.id}.${episode.container_extension}`;
if (player === VideoPlayer.MPV) {
this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, { url: streamUrl });