refactor(web): replace individual action imports with namespaced

imports and update dispatch calls

Replace multiple direct or wildcard imports for actions with
namespaced action groups from 'm3u-state' (e.g. PlaylistActions,
ChannelActions, EpgActions). Update dispatch calls to use the
namespaced action creators (for example, setAdjacentChannelAsActive,
setEpgAvailableFlag, resetActiveEpgProgram, setCurrentEpgProgram,
setActiveEpgProgram, addPlaylist).

This cleans up imports, improves tree-shaking and readability,
and standardizes how actions are referenced across components. It
also fixes inconsistent import styles (wildcard vs. named) and
prepares the codebase for clearer action organization.
This commit is contained in:
4gray committed 2025-12-21 00:42:48 +01:00
1 parent 68b87040ad
commit ac31cf18e5
20 files changed
+46 -50

No files matched your search

+4 -4
View File
@@ -4,10 +4,8 @@ import { Router, RouterOutlet } from '@angular/router';
import { Actions, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import { PlaylistActions, selectAllPlaylistsMeta } from 'm3u-state';
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,
@@ -28,7 +26,9 @@ import { SearchResultsComponent } from './xtream-tauri/search-results/search-res
})
export class AppComponent implements OnInit {
@HostBinding('class.macos-platform') get isMacOS() {
return window.electron && navigator.platform.toLowerCase().includes('mac');
return (
window.electron && navigator.platform.toLowerCase().includes('mac')
);
}
private actions$ = inject(Actions);
private dataService = inject(DataService);
@@ -2,7 +2,7 @@ import { Component, EventEmitter, inject, Output } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
import { addPlaylist } from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { DragDropFileUploadDirective } from './drag-drop-file-upload.directive';
@Component({
@@ -45,7 +45,7 @@ export class FileUploadComponent {
playlistObject
);
this.store.dispatch(
addPlaylist({ playlist: playlistObject })
PlaylistActions.addPlaylist({ playlist: playlistObject })
);
} else {
// User canceled the dialog
@@ -11,7 +11,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
import { addPlaylist } from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { DataService } from 'services';
import { Playlist } from 'shared-interfaces';
import { v4 as uuid } from 'uuid';
@@ -67,7 +67,7 @@ export class StalkerPortalImportComponent {
this.form.value.portalUrl
);
this.store.dispatch(
addPlaylist({ playlist: this.form.value as Playlist })
PlaylistActions.addPlaylist({ playlist: this.form.value as Playlist })
);
this.addClicked.emit();
}
@@ -27,7 +27,7 @@ import {
ToolbarComponent,
VjsPlayerComponent,
} from 'components';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions, ChannelActions, FavoritesActions } from 'm3u-state';
import {
selectActive,
selectChannels,
@@ -169,7 +169,7 @@ export class VideoPlayerComponent implements OnInit {
}
this.store.dispatch(
PlaylistActions.setChannels({
ChannelActions.setChannels({
channels: playlist.playlist.items,
})
);
@@ -180,14 +180,14 @@ export class VideoPlayerComponent implements OnInit {
playlist.favorites.length > 0
) {
this.store.dispatch(
PlaylistActions.setFavorites({
FavoritesActions.setFavorites({
channelIds: playlist.favorites,
})
);
} else {
// Clear favorites if playlist has none
this.store.dispatch(
PlaylistActions.setFavorites({
FavoritesActions.setFavorites({
channelIds: [],
})
);
@@ -255,7 +255,7 @@ export class VideoPlayerComponent implements OnInit {
// Dispatch action to change channel
const nextChannel = channels[nextIndex];
this.store.dispatch(
PlaylistActions.setActiveChannel({
ChannelActions.setActiveChannel({
channel: nextChannel,
})
);
@@ -444,7 +444,7 @@ export class VideoPlayerComponent implements OnInit {
.subscribe((channel) => {
if (channel) {
this.store.dispatch(
PlaylistActions.setActiveChannel({ channel })
ChannelActions.setActiveChannel({ channel })
);
}
});
@@ -12,7 +12,7 @@ import { MatIcon } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
import { addPlaylist } from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { PortalStatus, PortalStatusService } from 'services';
import { Playlist } from 'shared-interfaces';
import { v4 as uuid } from 'uuid';
@@ -137,7 +137,7 @@ export class XtreamCodeImportComponent {
url.port ? ':' + url.port : ''
}`;
this.store.dispatch(
addPlaylist({
PlaylistActions.addPlaylist({
playlist: {
...this.form.value,
serverUrl,
@@ -3,7 +3,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { Params } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { DataService } from 'services';
import {
AUTO_UPDATE_PLAYLISTS,
+1 -1
View File
@@ -5,7 +5,7 @@ import { Params } from '@angular/router';
import { SwUpdate } from '@angular/service-worker';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { catchError, firstValueFrom, throwError } from 'rxjs';
import { DataService } from 'services';
import {
@@ -35,8 +35,7 @@ import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { QRCodeComponent } from 'angularx-qrcode';
import { DialogService } from 'components';
import * as PlaylistActions from 'm3u-state';
import { selectIsEpgAvailable } from 'm3u-state';
import { PlaylistActions, selectIsEpgAvailable } from 'm3u-state';
import { take } from 'rxjs';
import { DataService, EpgService, PlaylistsService } from 'services';
import {
@@ -8,7 +8,7 @@ import {
import { MatSnackBar } from '@angular/material/snack-bar';
import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { parsePlaylist } from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { getFilenameFromUrl } from 'm3u-utils';
import { DataService } from 'services';
import { PLAYLIST_PARSE_BY_URL } from 'shared-interfaces';
@@ -57,11 +57,11 @@ export class AddPlaylistDialogComponent {
.result as string;
this.store.dispatch(
parsePlaylist({
PlaylistActions.parsePlaylist({
uploadType: 'FILE',
playlist,
title: payload.file.name,
path: (payload.file as any).path,
path: (payload.file as File & { path?: string }).path,
})
);
this.closeDialog();
@@ -93,7 +93,7 @@ export class AddPlaylistDialogComponent {
*/
uploadAsText(playlist: string): void {
this.store.dispatch(
parsePlaylist({
PlaylistActions.parsePlaylist({
uploadType: 'TEXT',
playlist,
title: this.translateService.instant('HOME.IMPORTED_AS_TEXT'),
@@ -1,7 +1,7 @@
import { Component, effect, inject, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { Store } from '@ngrx/store';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { selectPlaylistById } from 'm3u-state';
import { NavigationComponent } from '../../xtream-tauri/navigation/navigation.component';
import { NavigationItem } from '../../xtream-tauri/navigation/navigation.interface';
@@ -6,7 +6,7 @@ import { Router, RouterLink } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { DialogService, PlaylistInfoComponent } from 'components';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { selectCurrentPlaylist } from 'm3u-state';
import { DatabaseService } from 'services';
import { Playlist } from 'shared-interfaces';
@@ -2,7 +2,7 @@ import { Component, effect, inject } from '@angular/core';
import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { LoadingOverlayComponent } from '../loading-overlay/loading-overlay.component';
import { NavigationComponent } from '../navigation/navigation.component';
import { NavigationItem } from '../navigation/navigation.interface';
@@ -6,7 +6,7 @@ import { Router, RouterLink } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { DialogService, PlaylistInfoComponent } from 'components';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { selectCurrentPlaylist } from 'm3u-state';
import { Playlist } from 'shared-interfaces';
@@ -12,7 +12,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatSliderModule } from '@angular/material/slider';
import { Store } from '@ngrx/store';
import { setAdjacentChannelAsActive } from 'm3u-state';
import { ChannelActions } from 'm3u-state';
@Component({
selector: 'app-audio-player',
@@ -125,6 +125,6 @@ export class AudioPlayerComponent implements OnChanges {
}
switchChannel(direction: 'next' | 'previous') {
this.store.dispatch(setAdjacentChannelAsActive({ direction }));
this.store.dispatch(ChannelActions.setAdjacentChannelAsActive({ direction }));
}
}
@@ -28,7 +28,7 @@ import { Store } from '@ngrx/store';
import { StorageMap } from '@ngx-pwa/local-storage';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import * as _ from 'lodash';
import * as PlaylistActions from 'm3u-state';
import { ChannelActions, FavoritesActions } from 'm3u-state';
import {
selectActive,
selectActivePlaylistId,
@@ -165,7 +165,7 @@ export class ChannelListContainerComponent implements OnInit, OnDestroy {
* @param channel selected channel
*/
selectChannel(channel: Channel): void {
this.store.dispatch(PlaylistActions.setActiveChannel({ channel }));
this.store.dispatch(ChannelActions.setActiveChannel({ channel }));
// Use tvg-id for EPG matching, fallback to channel name if not available
const epgChannelId = channel?.tvg?.id?.trim() || channel?.name.trim();
@@ -187,7 +187,7 @@ export class ChannelListContainerComponent implements OnInit, OnDestroy {
undefined,
{ duration: 2000 }
);
this.store.dispatch(PlaylistActions.updateFavorites({ channel }));
this.store.dispatch(FavoritesActions.updateFavorites({ channel }));
}
trackByFn(_: number, channel: Channel): string {
@@ -197,7 +197,7 @@ export class ChannelListContainerComponent implements OnInit, OnDestroy {
drop(event: CdkDragDrop<Channel[]>, favorites: Channel[]) {
moveItemInArray(favorites, event.previousIndex, event.currentIndex);
this.store.dispatch(
PlaylistActions.setFavorites({
FavoritesActions.setFavorites({
channelIds: favorites.map((item) => item.url),
})
);
@@ -230,7 +230,7 @@ export class ChannelListContainerComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.store.dispatch(PlaylistActions.setChannels({ channels: [] }));
this.store.dispatch(ChannelActions.setChannels({ channels: [] }));
if (this.epgRefreshInterval) {
clearInterval(this.epgRefreshInterval);
@@ -8,11 +8,8 @@ import { MomentDatePipe } from '@iptvnator/pipes';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
import {
resetActiveEpgProgram,
selectActive,
setActiveEpgProgram,
setCurrentEpgProgram,
setEpgAvailableFlag,
EpgActions,
} from 'm3u-state';
import moment from 'moment';
import { BehaviorSubject, combineLatest, map } from 'rxjs';
@@ -157,7 +154,7 @@ export class EpgListComponent implements OnInit {
// Dispatch EPG availability flag
this.store.dispatch(
setEpgAvailableFlag({ value: programs.length > 0 })
EpgActions.setEpgAvailableFlag({ value: programs.length > 0 })
);
if (programs.length > 0) {
@@ -165,7 +162,7 @@ export class EpgListComponent implements OnInit {
} else {
this.channel = {} as EpgChannel;
// Clear the current EPG program when no programs available
this.store.dispatch(resetActiveEpgProgram());
this.store.dispatch(EpgActions.resetActiveEpgProgram());
}
// Trigger change detection for OnPush strategy
@@ -223,7 +220,7 @@ export class EpgListComponent implements OnInit {
// Always dispatch the action, even when playingNow is null/undefined
// This ensures the store is updated and old EPG data is cleared
this.store.dispatch(
setCurrentEpgProgram({ program: this.playingNow })
EpgActions.setCurrentEpgProgram({ program: this.playingNow })
);
// Trigger change detection for OnPush strategy
this.cdr.markForCheck();
@@ -242,10 +239,10 @@ export class EpgListComponent implements OnInit {
timeshift?: boolean
): void {
if (isLive) {
this.store.dispatch(resetActiveEpgProgram());
this.store.dispatch(EpgActions.resetActiveEpgProgram());
} else {
if (!timeshift) return;
this.store.dispatch(setActiveEpgProgram({ program }));
this.store.dispatch(EpgActions.setActiveEpgProgram({ program }));
}
this.playingNow = program;
// Trigger change detection for OnPush strategy
@@ -17,7 +17,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { MatTooltip } from '@angular/material/tooltip';
import { Store } from '@ngrx/store';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import { firstValueFrom } from 'rxjs';
import { DatabaseService, PlaylistsService } from 'services';
import { Playlist, PlaylistMeta } from 'shared-interfaces';
@@ -9,7 +9,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import * as PlaylistActions from 'm3u-state';
import { PlaylistActions } from 'm3u-state';
import {
selectActiveTypeFilters,
selectAllPlaylistsMeta,
@@ -6,7 +6,7 @@ import { MatTooltip } from '@angular/material/tooltip';
import { Router, RouterLink } from '@angular/router';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
import * as PlaylistActions from 'm3u-state';
import { ChannelActions } from 'm3u-state';
import { selectPlaylistTitle } from 'm3u-state';
import { Channel, SidebarView } from 'shared-interfaces';
import { RecentPlaylistsComponent } from '../../recent-playlists/recent-playlists.component';
@@ -38,7 +38,7 @@ export class SidebarComponent {
goBack() {
if (this.sidebarView === 'PLAYLISTS') {
this.store.dispatch(PlaylistActions.resetActiveChannel());
this.store.dispatch(ChannelActions.resetActiveChannel());
this.router.navigate(['/']);
} else {
this.sidebarView = 'PLAYLISTS';
@@ -11,7 +11,7 @@ import {
selectActivePlaylistId,
selectFavorites,
selectIsEpgAvailable,
updateFavorites,
FavoritesActions,
} from 'm3u-state';
import { Channel } from 'shared-interfaces';
@@ -46,6 +46,6 @@ export class ToolbarComponent {
readonly playlistId$ = this.store.select(selectActivePlaylistId);
updateFavoriteStatus(channel: Channel) {
this.store.dispatch(updateFavorites({ channel }));
this.store.dispatch(FavoritesActions.updateFavorites({ channel }));
}
}