mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
Add automatic playlist refresh on application startup by listening for successful playlist load and dispatching an IPC event for any playlists with autoRefresh enabled. - Inject Actions into AppComponent and add triggerAutoUpdatePlaylists that waits for PlaylistActions.loadPlaylistsSuccess, selects selectAllPlaylistsMeta from the store, filters playlists with autoRefresh, and sends AUTO_UPDATE_PLAYLISTS via DataService. - Call triggerAutoUpdatePlaylists from ngOnInit and remove a now- unused commented commands list. - Add helper functions in backend playlist events to fetch and parse playlists from URL or file, consolidating parsing logic and creating playlist objects. This implements the previously noted TODO to trigger playlist auto- refresh and centralizes playlist fetching/parsing for reuse and clarity.
203 lines
7.1 KiB
TypeScript
203 lines
7.1 KiB
TypeScript
import { Component, inject, OnInit } from '@angular/core';
|
|
import { MatDialog } from '@angular/material/dialog';
|
|
import { Router, RouterOutlet } from '@angular/router';
|
|
import { Actions, ofType } from '@ngrx/effects';
|
|
import { Store } from '@ngrx/store';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { filter, take } from 'rxjs';
|
|
/* import * as semver from 'semver'; */
|
|
import * as PlaylistActions from 'm3u-state';
|
|
import { selectAllPlaylistsMeta } from 'm3u-state';
|
|
import { DataService, EpgService } from 'services';
|
|
import {
|
|
AUTO_UPDATE_PLAYLISTS,
|
|
Language,
|
|
OPEN_FILE,
|
|
Settings,
|
|
STORE_KEY,
|
|
Theme,
|
|
} from 'shared-interfaces';
|
|
import { SettingsService } from './services/settings.service';
|
|
import { RecentlyViewedComponent } from './xtream-tauri/recently-viewed/recently-viewed.component';
|
|
import { SearchResultsComponent } from './xtream-tauri/search-results/search-results.component';
|
|
|
|
@Component({
|
|
selector: 'app-root',
|
|
templateUrl: './app.component.html',
|
|
imports: [RouterOutlet],
|
|
})
|
|
export class AppComponent implements OnInit {
|
|
private actions$ = inject(Actions);
|
|
private dataService = inject(DataService);
|
|
private dialog = inject(MatDialog);
|
|
private epgService = inject(EpgService);
|
|
private router = inject(Router);
|
|
private store = inject(Store);
|
|
private translate = inject(TranslateService);
|
|
private settingsService = inject(SettingsService);
|
|
|
|
/** Default language as fallback */
|
|
private readonly DEFAULT_LANG = Language.ENGLISH;
|
|
|
|
constructor() {
|
|
if (
|
|
((this.dataService.isElectron &&
|
|
this.dataService?.remote?.process.platform === 'linux') ||
|
|
this.dataService?.remote?.process.platform === 'win32') &&
|
|
this.dataService.remote.process.argv.length > 2
|
|
) {
|
|
const filePath = this.dataService.remote.process.argv.find(
|
|
(filepath) =>
|
|
filepath.endsWith('.m3u') || filepath.endsWith('.m3u8')
|
|
);
|
|
if (filePath) {
|
|
const filePathsArray = filePath.split('/');
|
|
const fileName = filePathsArray[filePathsArray.length - 1];
|
|
this.dataService.sendIpcEvent(OPEN_FILE, {
|
|
filePath,
|
|
fileName,
|
|
});
|
|
}
|
|
}
|
|
/* if (isTauri()) {
|
|
document.addEventListener('keydown', (event) => {
|
|
if (event.ctrlKey || event.metaKey) {
|
|
if (event.key === 'f') {
|
|
event.preventDefault();
|
|
this.openGlobalSearch();
|
|
} else if (event.key === 'r') {
|
|
event.preventDefault();
|
|
this.openGlobalRecent();
|
|
}
|
|
}
|
|
});
|
|
} */
|
|
}
|
|
|
|
ngOnInit() {
|
|
this.store.dispatch(PlaylistActions.loadPlaylists());
|
|
this.translate.setDefaultLang(this.DEFAULT_LANG);
|
|
|
|
this.initSettings();
|
|
this.triggerAutoUpdatePlaylists();
|
|
}
|
|
|
|
/**
|
|
* Reads the settings object from local storage and initializes the
|
|
* application based on them
|
|
*/
|
|
initSettings(): void {
|
|
this.settingsService
|
|
.getValueFromLocalStorage(STORE_KEY.Settings)
|
|
.subscribe((settings: Settings) => {
|
|
if (settings && Object.keys(settings).length > 0) {
|
|
// No need to send settings to Electron on init
|
|
// Settings are stored in IndexedDB and loaded by the settings store
|
|
// Only specific Electron settings (MPV/VLC paths) are sent when changed in settings component
|
|
|
|
this.translate.use(settings.language ?? this.DEFAULT_LANG);
|
|
|
|
// Fetch EPG if URLs are configured
|
|
if (
|
|
window.electron &&
|
|
settings.epgUrl?.length > 0 &&
|
|
settings.epgUrl?.some((u) => u !== '')
|
|
) {
|
|
this.epgService.fetchEpg(settings.epgUrl);
|
|
}
|
|
|
|
if (settings.theme) {
|
|
this.settingsService.changeTheme(settings.theme);
|
|
} else {
|
|
this.detectDarkMode();
|
|
}
|
|
} else {
|
|
this.detectDarkMode();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Detects if the operation system uses dark mode and changes the theme
|
|
*/
|
|
detectDarkMode(): void {
|
|
if (
|
|
window.matchMedia &&
|
|
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
) {
|
|
this.settingsService.changeTheme(Theme.DarkTheme);
|
|
this.settingsService.setValueToLocalStorage(STORE_KEY.Settings, {
|
|
theme: Theme.DarkTheme,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Navigate to the specified route
|
|
* @param route route to navigate to
|
|
*/
|
|
navigateToRoute(route: string) {
|
|
this.router.navigateByUrl(route);
|
|
}
|
|
|
|
openGlobalSearch(): void {
|
|
this.dialog.open(SearchResultsComponent, {
|
|
width: '100%',
|
|
height: '100%',
|
|
maxWidth: '100%',
|
|
panelClass: 'global-search-overlay',
|
|
data: { isGlobalSearch: true },
|
|
});
|
|
}
|
|
|
|
openGlobalRecent(): void {
|
|
this.dialog.open(RecentlyViewedComponent, {
|
|
width: '100%',
|
|
height: '100%',
|
|
maxWidth: '100%',
|
|
panelClass: 'global-search-overlay',
|
|
data: { isGlobal: true },
|
|
hasBackdrop: true,
|
|
disableClose: false,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Triggers auto-update for playlists that have autoRefresh enabled
|
|
*/
|
|
private triggerAutoUpdatePlaylists(): void {
|
|
// Wait for playlists to be loaded successfully
|
|
this.actions$
|
|
.pipe(
|
|
ofType(PlaylistActions.loadPlaylistsSuccess),
|
|
take(1) // Only trigger once on app startup
|
|
)
|
|
.subscribe(() => {
|
|
// Get all playlists from store
|
|
this.store
|
|
.select(selectAllPlaylistsMeta)
|
|
.pipe(
|
|
take(1),
|
|
filter((playlists) => playlists.length > 0)
|
|
)
|
|
.subscribe((playlists) => {
|
|
// Filter playlists with autoRefresh enabled
|
|
const playlistsToUpdate = playlists.filter(
|
|
(playlist) => playlist.autoRefresh === true
|
|
);
|
|
|
|
// Trigger auto-update if there are playlists to update
|
|
if (playlistsToUpdate.length > 0) {
|
|
console.log(
|
|
`Auto-updating ${playlistsToUpdate.length} playlist(s) on startup`
|
|
);
|
|
this.dataService.sendIpcEvent(
|
|
AUTO_UPDATE_PLAYLISTS,
|
|
playlistsToUpdate
|
|
);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|