feat(m3u-state): reducers and add selectors

Move playlist reducers into a dedicated reducers module and re-export a
composed playlistReducer built from smaller reducer arrays (epg,
channel, playlist, favorites, filter). This extracts and organizes the
previously monolithic reducer implementation into focused reducer files,
improving modularity and maintainability.

Add simple selectors in the new reducers index for commonly accessed
pieces of PlaylistState (playlists, selected playlist id, epg availability,
active channel, current EPG program, channels list, playlists loaded flag,
current playlist id) so callers can import them from a single place.

These changes make reducer logic easier to reason about, enable
incremental testing and extension of individual reducer groups, and
centralize basic selectors for consistent usage across the app.
This commit is contained in:
4gray committed 2025-12-20 23:59:40 +01:00
1 parent d391514015
commit 68b87040ad
9 files changed
+413 -434

No files matched your search

+64 -134
View File
@@ -1,140 +1,70 @@
import { createAction, props } from '@ngrx/store';
import { createActionGroup, emptyProps, props } from '@ngrx/store';
import { Channel, EpgProgram, Playlist, PlaylistMeta } from 'shared-interfaces';
const STORE_KEY = '[GLOBAL STORE]';
const PLAYLISTS_STORE_KEY = '[PLAYLISTS STORE]';
export const PlaylistActions = createActionGroup({
source: 'Playlists',
events: {
'Load Playlists': emptyProps(),
'Load Playlists Success': props<{ playlists: PlaylistMeta[] }>(),
'Add Playlist': props<{ playlist: Playlist }>(),
'Add Many Playlists': props<{ playlists: Playlist[] }>(),
'Remove Playlist': props<{ playlistId: string }>(),
'Update Playlist Meta': props<{ playlist: PlaylistMeta }>(),
'Update Playlist': props<{ playlist: Playlist; playlistId: string }>(),
'Update Many Playlists': props<{ playlists: Playlist[] }>(),
'Parse Playlist': props<{
uploadType: 'FILE' | 'URL' | 'TEXT';
playlist: string;
title: string;
path?: string;
}>(),
'Set Active Playlist': props<{ playlistId: string }>(),
'Update Playlist Positions': props<{
positionUpdates: { id: string; changes: { position: number } }[];
}>(),
'Remove All Playlists': emptyProps(),
'Set Current Playlist Id': props<{ playlistId: string | undefined }>(),
'Handle Adding Playlist By Url': props<{
isTemporary: boolean;
playlist: Playlist;
}>(),
},
});
export const loadPlaylists = createAction(
`${PLAYLISTS_STORE_KEY} Load playlists from db`
);
export const ChannelActions = createActionGroup({
source: 'Channels',
events: {
'Set Channels': props<{ channels: Channel[] }>(),
'Set Active Channel': props<{ channel: Channel }>(),
'Set Active Channel Success': props<{ channel: Channel }>(),
'Reset Active Channel': emptyProps(),
'Set Adjacent Channel As Active': props<{
direction: 'next' | 'previous';
}>(),
},
});
export const loadPlaylistsSuccess = createAction(
`${PLAYLISTS_STORE_KEY} Successfully loaded playlists from db`,
props<{ playlists: PlaylistMeta[] }>()
);
export const EpgActions = createActionGroup({
source: 'EPG',
events: {
'Set Active Epg Program': props<{ program: EpgProgram }>(),
'Set Current Epg Program': props<{ program: EpgProgram }>(),
'Reset Active Epg Program': emptyProps(),
'Set Epg Available Flag': props<{ value: boolean }>(),
},
});
export const addPlaylist = createAction(
`${PLAYLISTS_STORE_KEY} Add new playlist`,
props<{ playlist: Playlist }>()
);
export const FavoritesActions = createActionGroup({
source: 'Favorites',
events: {
'Update Favorites': props<{ channel: Channel }>(),
'Set Favorites': props<{ channelIds: string[] }>(),
},
});
export const addManyPlaylists = createAction(
`${PLAYLISTS_STORE_KEY} Add many playlists`,
props<{ playlists: Playlist[] }>()
);
export const removePlaylist = createAction(
`${PLAYLISTS_STORE_KEY} Remove playlist by id`,
props<{ playlistId: string }>()
);
export const updatePlaylistMeta = createAction(
`${PLAYLISTS_STORE_KEY} update playlist meta`,
props<{ playlist: PlaylistMeta }>()
);
export const updatePlaylist = createAction(
`${PLAYLISTS_STORE_KEY} update playlist`,
props<{ playlist: Playlist; playlistId: string }>()
);
export const updateManyPlaylists = createAction(
`${PLAYLISTS_STORE_KEY} Update many playlists (auto-update mechanism)`,
props<{ playlists: Playlist[] }>()
);
export const parsePlaylist = createAction(
`${PLAYLISTS_STORE_KEY} parse playlist`,
props<{
uploadType: 'FILE' | 'URL' | 'TEXT';
playlist: string;
title: string;
path?: string;
}>()
);
export const setActivePlaylist = createAction(
`${PLAYLISTS_STORE_KEY} set active playlist`,
props<{ playlistId: string }>()
);
export const updateFavorites = createAction(
`${STORE_KEY} Add/remove provided channel to the favorites`,
props<{ channel: Channel }>()
);
export const setFavorites = createAction(
`${STORE_KEY} Set favorites`,
props<{ channelIds: string[] }>()
);
export const setActiveChannel = createAction(
`${STORE_KEY} Set active channel`,
props<{ channel: Channel }>()
);
export const resetActiveChannel = createAction(
`${STORE_KEY} Reset active channel`
);
export const setActiveChannelSuccess = createAction(
`${STORE_KEY} Set active channel success`,
props<{ channel: Channel }>()
);
export const setActiveEpgProgram = createAction(
`${STORE_KEY} Sets the given timestamp for the epg program`,
props<{ program: EpgProgram }>()
);
export const setCurrentEpgProgram = createAction(
`${STORE_KEY} Updates the active epg program for the active channel`,
props<{ program: EpgProgram }>()
);
export const resetActiveEpgProgram = createAction(
`${STORE_KEY} Reset active epg program`
);
export const setEpgAvailableFlag = createAction(
`${STORE_KEY} Reset active epg program`,
props<{ value: boolean }>()
);
export const setChannels = createAction(
`${STORE_KEY} Set channels`,
props<{ channels: Channel[] }>()
);
export const updatePlaylistPositions = createAction(
`${STORE_KEY} Update playlist positions`,
props<{
positionUpdates: { id: string; changes: { position: number } }[];
}>()
);
export const removeAllPlaylists = createAction(
`${STORE_KEY} Remove all playlists`
);
export const setAdjacentChannelAsActive = createAction(
`${STORE_KEY} Set adjacent channel as active`,
props<{
direction: 'next' | 'previous';
}>()
);
export const setSelectedFilters = createAction(
`${STORE_KEY} Set selected filters`,
props<{ selectedFilters: string[] }>()
);
export const setCurrentPlaylistId = createAction(
`${STORE_KEY} Set current playlist id`,
props<{ playlistId: string | undefined }>()
);
export const handleAddingPlaylistByUrl = createAction(
`${PLAYLISTS_STORE_KEY} Handle adding playlist by URL`,
props<{ isTemporary: boolean; playlist: Playlist }>()
);
export const FilterActions = createActionGroup({
source: 'Filters',
events: {
'Set Selected Filters': props<{ selectedFilters: string[] }>(),
},
});
+13 -8
View File
@@ -24,7 +24,12 @@ import {
STORE_KEY,
VideoPlayer,
} from 'shared-interfaces';
import * as PlaylistActions from './actions';
import {
PlaylistActions,
ChannelActions,
EpgActions,
FavoritesActions,
} from './actions';
import {
selectActive,
selectActivePlaylistId,
@@ -47,7 +52,7 @@ export class PlaylistEffects {
updateFavorites$ = createEffect(
() => {
return this.actions$.pipe(
ofType(PlaylistActions.updateFavorites),
ofType(FavoritesActions.updateFavorites),
combineLatestWith(
this.store.select(selectFavorites),
this.store.select(selectActivePlaylistId)
@@ -70,7 +75,7 @@ export class PlaylistEffects {
setFavorites$ = createEffect(
() => {
return this.actions$.pipe(
ofType(PlaylistActions.setFavorites),
ofType(FavoritesActions.setFavorites),
combineLatestWith(this.store.select(selectActivePlaylistId)),
filter(
([, playlistId]) =>
@@ -92,7 +97,7 @@ export class PlaylistEffects {
setActiveEpgProgram$ = createEffect(
() => {
return this.actions$.pipe(
ofType(PlaylistActions.setActiveEpgProgram),
ofType(EpgActions.setActiveEpgProgram),
combineLatestWith(this.store.select(selectActive)),
map(([, activeChannel]) => {
firstValueFrom(this.storage.get(STORE_KEY.Settings)).then(
@@ -135,7 +140,7 @@ export class PlaylistEffects {
setActiveChannel$ = createEffect(() => {
return this.actions$.pipe(
ofType(PlaylistActions.setActiveChannel),
ofType(ChannelActions.setActiveChannel),
// Skip the effect entirely when channel is falsy
filter((action) => !!action.channel),
map((action) => {
@@ -186,7 +191,7 @@ export class PlaylistEffects {
}
);
return PlaylistActions.setActiveChannelSuccess({
return ChannelActions.setActiveChannelSuccess({
channel: action.channel,
});
})
@@ -400,7 +405,7 @@ export class PlaylistEffects {
setAdjacentChannelAsActive$ = createEffect(() => {
return this.actions$.pipe(
ofType(PlaylistActions.setAdjacentChannelAsActive),
ofType(ChannelActions.setAdjacentChannelAsActive),
withLatestFrom(
this.store.select(selectChannels),
this.store.select(selectActive)
@@ -419,7 +424,7 @@ export class PlaylistEffects {
adjacentChannel = activeChannel;
adjacentChannel = channels[index - 1];
}
return PlaylistActions.setActiveChannelSuccess({
return ChannelActions.setActiveChannelSuccess({
channel: adjacentChannel!,
});
})
+2 -292
View File
@@ -1,292 +1,2 @@
import { createReducer, on } from '@ngrx/store';
import moment from 'moment';
import { Channel } from 'shared-interfaces';
import * as PlaylistActions from './actions';
import { playlistsAdapter } from './playlists.state';
import { PlaylistState, initialState } from './state';
export const playlistReducer = createReducer(
initialState,
on(PlaylistActions.setActiveEpgProgram, (state, action): PlaylistState => {
const { program } = action;
const from = moment(program.start, 'YYYYMMDDHHmm ZZ').unix();
const now = moment(Date.now()).unix();
const epgParams = `?utc=${from}&lutc=${now}`;
return {
...state,
active: { ...state.active, epgParams } as Channel,
};
}),
on(
PlaylistActions.resetActiveEpgProgram,
(state): PlaylistState => ({
...state,
active: { ...state.active, epgParams: '' } as Channel,
})
),
on(
PlaylistActions.setActiveChannelSuccess,
(state, action): PlaylistState => {
const { channel } = action;
return {
...state,
active: { ...channel, epgParams: '' } as Channel,
};
}
),
on(PlaylistActions.resetActiveChannel, (state): PlaylistState => {
return {
...state,
active: undefined,
};
}),
on(
PlaylistActions.setCurrentEpgProgram,
(state, action): PlaylistState => ({
...state,
currentEpgProgram: action.program,
})
),
on(
PlaylistActions.setEpgAvailableFlag,
(state, action): PlaylistState => ({
...state,
epgAvailable: action.value,
})
),
on(PlaylistActions.updateFavorites, (state, action): PlaylistState => {
let favorites;
const { channel } = action;
const playlistFavorites =
state.playlists.entities[state.playlists.selectedId]?.favorites;
if (playlistFavorites?.includes(channel.url)) {
favorites = [
...(playlistFavorites ?? []).filter(
(url: string) => url !== channel.url
),
];
} else {
favorites = [...(playlistFavorites ?? []), channel.url];
}
return {
...state,
playlists: {
...state.playlists,
entities: {
...state.playlists.entities,
[state.playlists.selectedId]: {
...state.playlists.entities[state.playlists.selectedId],
favorites,
},
},
},
};
}),
on(PlaylistActions.setFavorites, (state, action): PlaylistState => {
const { channelIds } = action;
return {
...state,
playlists: {
...state.playlists,
entities: {
...state.playlists.entities,
[state.playlists.selectedId]: {
...state.playlists.entities[state.playlists.selectedId],
favorites: channelIds,
},
},
},
};
}),
on(PlaylistActions.loadPlaylistsSuccess, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.addMany(action.playlists, {
...state.playlists,
allPlaylistsLoaded: true,
}),
};
}),
on(PlaylistActions.removePlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.removeOne(
action.playlistId,
state.playlists
),
};
}),
on(PlaylistActions.updatePlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateOne(
{
id: action.playlistId,
changes: {
...action.playlist,
_id: action.playlistId,
updateDate: Date.now(),
count: action.playlist.playlist.items.length,
userAgent: action.playlist.userAgent,
favorites:
state.playlists.entities[action.playlistId]
?.favorites ?? [],
},
},
state.playlists
),
};
}),
on(PlaylistActions.addPlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.addOne(
action.playlist,
state.playlists
),
};
}),
on(PlaylistActions.addManyPlaylists, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.addMany(
action.playlists,
state.playlists
),
};
}),
on(PlaylistActions.setActivePlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: {
...state.playlists,
selectedId: action.playlistId,
},
};
}),
on(
PlaylistActions.updatePlaylistPositions,
(state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateMany(
action.positionUpdates,
state.playlists
),
};
}
),
on(PlaylistActions.updatePlaylistMeta, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateOne(
{
id: action.playlist._id,
changes: {
title: action.playlist.title,
autoRefresh: action.playlist.autoRefresh || false,
userAgent: action.playlist.userAgent,
...(action.playlist.serverUrl !== null
? { serverUrl: action.playlist.serverUrl }
: {}),
...(action.playlist.username !== null
? { username: action.playlist.username }
: {}),
...(action.playlist.password !== null
? { password: action.playlist.password }
: {}),
...(action.playlist.macAddress !== null
? { macAddress: action.playlist.macAddress }
: {}),
...(action.playlist.portalUrl !== null
? { portalUrl: action.playlist.portalUrl }
: {}),
},
},
state.playlists
),
};
}),
on(PlaylistActions.setChannels, (state, action): PlaylistState => {
return {
...state,
channels: action.channels,
};
}),
on(PlaylistActions.updateManyPlaylists, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateMany(
action.playlists.map((updatedPlaylist) => ({
id: updatedPlaylist._id,
changes: {
...updatedPlaylist,
updateDate: Date.now(),
},
})),
state.playlists
),
};
}),
on(PlaylistActions.removeAllPlaylists, (state): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.removeAll(state.playlists),
};
}),
on(
PlaylistActions.setSelectedFilters,
(state, { selectedFilters }): PlaylistState => {
return {
...state,
playlists: {
...state.playlists,
selectedFilters,
},
};
}
),
on(
PlaylistActions.setCurrentPlaylistId,
(state, { playlistId }): PlaylistState => {
return {
...state,
currentPlaylistId: playlistId,
};
}
),
on(
PlaylistActions.handleAddingPlaylistByUrl,
(state, action): PlaylistState => {
if (action.isTemporary) {
return {
...state,
channels: action.playlist.playlist.items as Channel[],
};
} else {
return {
...state,
playlists: playlistsAdapter.addOne(
action.playlist,
state.playlists
),
};
}
}
)
);
export const selectPlaylists = (state: PlaylistState) => state.playlists;
export const selectPlaylistId = (state: PlaylistState) =>
state.playlists?.selectedId;
export const selectIsEpgAvailableReducer = (state: PlaylistState) =>
state.epgAvailable;
export const selectActiveReducer = (state: PlaylistState) => state.active;
export const selectCurrentEpgProgramReducer = (state: PlaylistState) =>
state.currentEpgProgram;
export const selectChannelsReducer = (state: PlaylistState) => state.channels;
export const selectPlaylistsLoadingFlagReducer = (state: PlaylistState) =>
state.playlists?.allPlaylistsLoaded;
export const selectCurrentPlaylistIdReducer = (state: PlaylistState) =>
state.currentPlaylistId;
// Re-export from the new modular reducers structure
export * from './reducers/index';
@@ -0,0 +1,29 @@
import { on } from '@ngrx/store';
import { Channel } from 'shared-interfaces';
import { ChannelActions } from '../actions';
import { PlaylistState } from '../state';
export const channelReducers = [
on(
ChannelActions.setActiveChannelSuccess,
(state, action): PlaylistState => {
const { channel } = action;
return {
...state,
active: { ...channel, epgParams: '' } as Channel,
};
}
),
on(ChannelActions.resetActiveChannel, (state): PlaylistState => {
return {
...state,
active: undefined,
};
}),
on(ChannelActions.setChannels, (state, action): PlaylistState => {
return {
...state,
channels: action.channels,
};
}),
];
@@ -0,0 +1,39 @@
import { on } from '@ngrx/store';
import moment from 'moment';
import { Channel } from 'shared-interfaces';
import { EpgActions } from '../actions';
import { PlaylistState } from '../state';
export const epgReducers = [
on(EpgActions.setActiveEpgProgram, (state, action): PlaylistState => {
const { program } = action;
const from = moment(program.start, 'YYYYMMDDHHmm ZZ').unix();
const now = moment(Date.now()).unix();
const epgParams = `?utc=${from}&lutc=${now}`;
return {
...state,
active: { ...state.active, epgParams } as Channel,
};
}),
on(
EpgActions.resetActiveEpgProgram,
(state): PlaylistState => ({
...state,
active: { ...state.active, epgParams: '' } as Channel,
})
),
on(
EpgActions.setCurrentEpgProgram,
(state, action): PlaylistState => ({
...state,
currentEpgProgram: action.program,
})
),
on(
EpgActions.setEpgAvailableFlag,
(state, action): PlaylistState => ({
...state,
epgAvailable: action.value,
})
),
];
@@ -0,0 +1,50 @@
import { on } from '@ngrx/store';
import { FavoritesActions } from '../actions';
import { PlaylistState } from '../state';
export const favoritesReducers = [
on(FavoritesActions.updateFavorites, (state, action): PlaylistState => {
let favorites;
const { channel } = action;
const playlistFavorites =
state.playlists.entities[state.playlists.selectedId]?.favorites;
if (playlistFavorites?.includes(channel.url)) {
favorites = [
...(playlistFavorites ?? []).filter(
(url: string) => url !== channel.url
),
];
} else {
favorites = [...(playlistFavorites ?? []), channel.url];
}
return {
...state,
playlists: {
...state.playlists,
entities: {
...state.playlists.entities,
[state.playlists.selectedId]: {
...state.playlists.entities[state.playlists.selectedId],
favorites,
},
},
},
};
}),
on(FavoritesActions.setFavorites, (state, action): PlaylistState => {
const { channelIds } = action;
return {
...state,
playlists: {
...state.playlists,
entities: {
...state.playlists.entities,
[state.playlists.selectedId]: {
...state.playlists.entities[state.playlists.selectedId],
favorites: channelIds,
},
},
},
};
}),
];
@@ -0,0 +1,18 @@
import { on } from '@ngrx/store';
import { FilterActions } from '../actions';
import { PlaylistState } from '../state';
export const filterReducers = [
on(
FilterActions.setSelectedFilters,
(state, { selectedFilters }): PlaylistState => {
return {
...state,
playlists: {
...state.playlists,
selectedFilters,
},
};
}
),
];
+32
View File
@@ -0,0 +1,32 @@
import { createReducer } from '@ngrx/store';
import { initialState, PlaylistState } from '../state';
import { channelReducers } from './channel.reducers';
import { epgReducers } from './epg.reducers';
import { favoritesReducers } from './favorites.reducers';
import { filterReducers } from './filter.reducers';
import { playlistReducers } from './playlist.reducers';
export const playlistReducer = createReducer(
initialState,
...epgReducers,
...channelReducers,
...playlistReducers,
...favoritesReducers,
...filterReducers
);
// Selectors
export const selectPlaylists = (state: PlaylistState) => state.playlists;
export const selectPlaylistId = (state: PlaylistState) =>
state.playlists?.selectedId;
export const selectIsEpgAvailableReducer = (state: PlaylistState) =>
state.epgAvailable;
export const selectActiveReducer = (state: PlaylistState) => state.active;
export const selectCurrentEpgProgramReducer = (state: PlaylistState) =>
state.currentEpgProgram;
export const selectChannelsReducer = (state: PlaylistState) => state.channels;
export const selectPlaylistsLoadingFlagReducer = (state: PlaylistState) =>
state.playlists?.allPlaylistsLoaded;
export const selectCurrentPlaylistIdReducer = (state: PlaylistState) =>
state.currentPlaylistId;
@@ -0,0 +1,166 @@
import { on } from '@ngrx/store';
import { Channel } from 'shared-interfaces';
import { PlaylistActions } from '../actions';
import { playlistsAdapter } from '../playlists.state';
import { PlaylistState } from '../state';
export const playlistReducers = [
on(PlaylistActions.loadPlaylistsSuccess, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.addMany(action.playlists, {
...state.playlists,
allPlaylistsLoaded: true,
}),
};
}),
on(PlaylistActions.removePlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.removeOne(
action.playlistId,
state.playlists
),
};
}),
on(PlaylistActions.updatePlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateOne(
{
id: action.playlistId,
changes: {
...action.playlist,
_id: action.playlistId,
updateDate: Date.now(),
count: action.playlist.playlist.items.length,
userAgent: action.playlist.userAgent,
favorites:
state.playlists.entities[action.playlistId]
?.favorites ?? [],
},
},
state.playlists
),
};
}),
on(PlaylistActions.addPlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.addOne(
action.playlist,
state.playlists
),
};
}),
on(PlaylistActions.addManyPlaylists, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.addMany(
action.playlists,
state.playlists
),
};
}),
on(PlaylistActions.setActivePlaylist, (state, action): PlaylistState => {
return {
...state,
playlists: {
...state.playlists,
selectedId: action.playlistId,
},
};
}),
on(
PlaylistActions.updatePlaylistPositions,
(state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateMany(
action.positionUpdates,
state.playlists
),
};
}
),
on(PlaylistActions.updatePlaylistMeta, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateOne(
{
id: action.playlist._id,
changes: {
title: action.playlist.title,
autoRefresh: action.playlist.autoRefresh || false,
userAgent: action.playlist.userAgent,
...(action.playlist.serverUrl !== null
? { serverUrl: action.playlist.serverUrl }
: {}),
...(action.playlist.username !== null
? { username: action.playlist.username }
: {}),
...(action.playlist.password !== null
? { password: action.playlist.password }
: {}),
...(action.playlist.macAddress !== null
? { macAddress: action.playlist.macAddress }
: {}),
...(action.playlist.portalUrl !== null
? { portalUrl: action.playlist.portalUrl }
: {}),
},
},
state.playlists
),
};
}),
on(PlaylistActions.updateManyPlaylists, (state, action): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.updateMany(
action.playlists.map((updatedPlaylist) => ({
id: updatedPlaylist._id,
changes: {
...updatedPlaylist,
updateDate: Date.now(),
},
})),
state.playlists
),
};
}),
on(PlaylistActions.removeAllPlaylists, (state): PlaylistState => {
return {
...state,
playlists: playlistsAdapter.removeAll(state.playlists),
};
}),
on(
PlaylistActions.setCurrentPlaylistId,
(state, { playlistId }): PlaylistState => {
return {
...state,
currentPlaylistId: playlistId,
};
}
),
on(
PlaylistActions.handleAddingPlaylistByUrl,
(state, action): PlaylistState => {
if (action.isTemporary) {
return {
...state,
channels: action.playlist.playlist.items as Channel[],
};
} else {
return {
...state,
playlists: playlistsAdapter.addOne(
action.playlist,
state.playlists
),
};
}
}
),
];