mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
refactor: update settings store
This commit is contained in:
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');
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
},
|
||||
}))
|
||||
);
|
||||
@@ -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">
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in new issue
Block a user