Skip to content

Commit

Permalink
Move playlist selectors into slice (#2801)
Browse files Browse the repository at this point in the history
* Move playlist selectors into slice

* Compute playlist.active at selection time
  • Loading branch information
goto-bus-stop authored Dec 12, 2023
1 parent 1ada692 commit bbaef5f
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 219 deletions.
9 changes: 3 additions & 6 deletions src/containers/PlaylistManagerPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import React from 'react';
import { useSelector, useDispatch } from '../hooks/useRedux';
import {
filteredSelectedPlaylistItemsSelector,
isSelectedPlaylistLoadingSelector,
playlistItemFilterSelector,
} from '../selectors/playlistSelectors';
import {
cannotDeleteActivePlaylist,
} from '../actions/PlaylistActionCreators';
Expand All @@ -19,6 +14,8 @@ import {
type PlaylistItem,
type InsertTarget,
selectedPlaylistSelector,
filteredSelectedPlaylistItemsSelector,
playlistItemFilterSelector,
setPlaylistFilter,
} from '../reducers/playlists';

Expand All @@ -31,9 +28,9 @@ function PlaylistPanelContainer() {
}

const playlistItems = useSelector(filteredSelectedPlaylistItemsSelector)!;
const loading = useSelector(isSelectedPlaylistLoadingSelector);
const filter = useSelector(playlistItemFilterSelector);
const dispatch = useDispatch();
const loading = playlist.loading ?? false;
const playlistID = playlist._id;

const onShufflePlaylist = useCallback(async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/mobile/containers/MainView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import React from 'react';
import { useSelector, useDispatch } from '../../hooks/useRedux';
import { toggleOverlay } from '../../reducers/activeOverlay';
import { setVideoEnabled, videoEnabledSelector } from '../../reducers/settings';
import { playlistsSelector } from '../../reducers/playlists';
import { mediaSelector, startTimeSelector } from '../../selectors/boothSelectors';
import {
sizeSelector as waitlistSizeSelector,
positionSelector as waitlistPositionSelector,
} from '../../selectors/waitlistSelectors';
import { playlistsSelector } from '../../selectors/playlistSelectors';
import { openDrawer, openUsersDrawer } from '../actions/DrawerActionCreators';
import MainView from '../components/MainView';

Expand Down
8 changes: 4 additions & 4 deletions src/mobile/containers/PlaylistManager.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { useDispatch, useSelector } from '../../hooks/useRedux';
import {
filteredSelectedPlaylistItemsSelector,
} from '../../selectors/playlistSelectors';
import createLazyOverlay from '../../components/LazyOverlay';
import { closeOverlay } from '../../reducers/activeOverlay';
import { selectedPlaylistSelector } from '../../reducers/playlists';
import {
selectedPlaylistSelector,
filteredSelectedPlaylistItemsSelector,
} from '../../reducers/playlists';

const {
useCallback,
Expand Down
12 changes: 4 additions & 8 deletions src/mobile/containers/PlaylistPanel.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { bindActionCreators } from 'redux';
import { createStructuredSelector } from 'reselect';
import { connect } from 'react-redux';
import {
filteredSelectedPlaylistItemsSelector,
isSelectedPlaylistLoadingSelector,
isFilteredSelector,
} from '../../selectors/playlistSelectors';
import { cannotDeleteActivePlaylist } from '../../actions/PlaylistActionCreators';
import PlaylistPanel from '../components/PlaylistManager/PlaylistPanel';
import {
Expand All @@ -15,15 +10,16 @@ import {
renamePlaylist,
activatePlaylist,
movePlaylistItems,
selectedPlaylistSelector,
setPlaylistFilter,
selectedPlaylistSelector,
filteredSelectedPlaylistItemsSelector,
playlistItemFilterSelector,
} from '../../reducers/playlists';

const mapStateToProps = createStructuredSelector({
playlist: selectedPlaylistSelector,
media: filteredSelectedPlaylistItemsSelector,
loading: isSelectedPlaylistLoadingSelector,
isFiltered: isFilteredSelector,
filter: playlistItemFilterSelector,
});

const onMoveMedia = (playlistID) => (media, opts) => (
Expand Down
77 changes: 35 additions & 42 deletions src/reducers/__tests__/playlists.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import createStore from '../../redux/configureStore';
import { favoriteMediaComplete } from '../../actions/VoteActionCreators';
import * as s from '../../selectors/playlistSelectors';
import {
activatePlaylist,
loadPlaylist,
addPlaylistItems,
movePlaylistItems,
selectPlaylist,
} from '../playlists';
import * as p from '../playlists';

function preloadPlaylists(playlists) {
return {
Expand Down Expand Up @@ -36,43 +29,43 @@ const initialisePlaylist = (dispatch) => {
{ _id: 'BeevKCM1NnNeW91leyLZu', artist: 'tricot', title: '99.974°C' },
];
const playlistID = 'ZcU_8-UyI10Tx79R4CjRv';
dispatch(loadPlaylist.fulfilled({
dispatch(p.loadPlaylist.fulfilled({
items,
page: 0,
pageSize: 5,
total: 5,
}, 'tviXX4Jyv0SUTosPCddWA', {
playlistID,
}));
dispatch(selectPlaylist(playlistID));
dispatch(p.selectPlaylist(playlistID));
return { items, playlistID };
};

describe('reducers/playlists', () => {
it('should not respond to unrelated actions', () => {
const { dispatch, getState } = createStore();
expect(s.playlistsSelector(getState())).toEqual([]);
expect(p.playlistsSelector(getState())).toEqual([]);
dispatch({ type: 'randomOtherAction', payload: {} });
expect(s.playlistsSelector(getState())).toEqual([]);
expect(p.playlistsSelector(getState())).toEqual([]);
});

describe('action: playlists/SELECT_PLAYLIST', () => {
it('sets the given playlist as the current playlist', () => {
const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists));

expect(s.selectedPlaylistIDSelector(getState())).toBeNull();
expect(p.selectedPlaylistIDSelector(getState())).toBeNull();

dispatch(selectPlaylist('ZcU_8-UyI10Tx79R4CjRv'));
expect(s.selectedPlaylistIDSelector(getState())).toBe('ZcU_8-UyI10Tx79R4CjRv');
expect(s.selectedPlaylistSelector(getState())).toHaveProperty('_id', 'ZcU_8-UyI10Tx79R4CjRv');
dispatch(p.selectPlaylist('ZcU_8-UyI10Tx79R4CjRv'));
expect(p.selectedPlaylistIDSelector(getState())).toBe('ZcU_8-UyI10Tx79R4CjRv');
expect(p.selectedPlaylistSelector(getState())).toHaveProperty('_id', 'ZcU_8-UyI10Tx79R4CjRv');

dispatch(selectPlaylist('Kzy3kUckOgAV7iwrekHSE'));
expect(s.selectedPlaylistIDSelector(getState())).toBe('Kzy3kUckOgAV7iwrekHSE');
expect(s.selectedPlaylistSelector(getState())).toHaveProperty('_id', 'Kzy3kUckOgAV7iwrekHSE');
dispatch(p.selectPlaylist('Kzy3kUckOgAV7iwrekHSE'));
expect(p.selectedPlaylistIDSelector(getState())).toBe('Kzy3kUckOgAV7iwrekHSE');
expect(p.selectedPlaylistSelector(getState())).toHaveProperty('_id', 'Kzy3kUckOgAV7iwrekHSE');

dispatch(selectPlaylist(null));
expect(s.selectedPlaylistIDSelector(getState())).toBeNull();
expect(s.selectedPlaylistSelector(getState())).toBeNull();
dispatch(p.selectPlaylist(null));
expect(p.selectedPlaylistIDSelector(getState())).toBeNull();
expect(p.selectedPlaylistSelector(getState())).toBeNull();
});
});

Expand All @@ -81,9 +74,9 @@ describe('reducers/playlists', () => {
const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists));
dispatch(initialisePlaylist);

expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5);
expect(p.selectedPlaylistItemsSelector(getState())).toHaveLength(5);

dispatch(addPlaylistItems.fulfilled({
dispatch(p.addPlaylistItems.fulfilled({
playlistSize: 7,
items: [
{ _id: 'VlaaQAxk_Qy5orK1Vcr2C', artist: 'The Microphones', title: 'I Want Wind To Blow' },
Expand All @@ -95,7 +88,7 @@ describe('reducers/playlists', () => {
items: [],
}));

const { media } = s.selectedPlaylistSelector(getState());
const media = p.selectedPlaylistItemsSelector(getState());
expect(media).toHaveLength(7);
expect(media.map((playlistItem) => playlistItem._id)).toEqual([
'Cnun9zo6oNr1wMCFRhnaO', 'PD_n42XxNCdQjDy5VB_SE', '66Z6y6JA4m5WmmNF3O7Ii', 'NkwUIwNmraSZ4A4eiC3GQ', 'VlaaQAxk_Qy5orK1Vcr2C', 'T9sdCu_-3o70qWk0YeDxJ', 'BeevKCM1NnNeW91leyLZu',
Expand All @@ -106,12 +99,12 @@ describe('reducers/playlists', () => {
const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists));
const { playlistID } = dispatch(initialisePlaylist);
// Test an active, but not selected playlist.
dispatch(selectPlaylist(null));
dispatch(activatePlaylist.fulfilled(null, '', playlistID));
dispatch(p.selectPlaylist(null));
dispatch(p.activatePlaylist.fulfilled(null, '', playlistID));

expect(s.activePlaylistSelector(getState()).media).toHaveLength(5);
expect(p.activePlaylistItemsSelector(getState())).toHaveLength(5);

dispatch(addPlaylistItems.fulfilled({
dispatch(p.addPlaylistItems.fulfilled({
playlistSize: 7,
items: [
{ _id: 'VlaaQAxk_Qy5orK1Vcr2C', artist: 'The Microphones', title: 'I Want Wind To Blow' },
Expand All @@ -123,15 +116,15 @@ describe('reducers/playlists', () => {
items: [],
}));

expect(s.activePlaylistSelector(getState()).media).toHaveLength(7);
expect(s.nextMediaSelector(getState())._id).toBe('VlaaQAxk_Qy5orK1Vcr2C');
expect(p.activePlaylistItemsSelector(getState())).toHaveLength(7);
expect(p.nextMediaSelector(getState())._id).toBe('VlaaQAxk_Qy5orK1Vcr2C');
});

it('appends favourited items to the end of the playlist', () => {
const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists));
const { playlistID } = dispatch(initialisePlaylist);

expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5);
expect(p.selectedPlaylistItemsSelector(getState())).toHaveLength(5);

dispatch(favoriteMediaComplete(playlistID, 'vGA5mxhJpYkrsHSfxPcqX', {
playlistSize: 6,
Expand All @@ -140,8 +133,8 @@ describe('reducers/playlists', () => {
],
}));

const { size, media } = s.selectedPlaylistSelector(getState());
expect(size).toBe(6);
expect(p.selectedPlaylistSelector(getState())).toHaveProperty('size', 6);
const media = p.selectedPlaylistItemsSelector(getState());
expect(media).toHaveLength(6);
expect(media[5]._id).toBe('RDeVBExmCGXvmT0mN0P3n');
});
Expand All @@ -152,16 +145,16 @@ describe('reducers/playlists', () => {
const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists));
const { items } = dispatch(initialisePlaylist);

expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5);
expect(p.selectedPlaylistItemsSelector(getState())).toHaveLength(5);

dispatch(movePlaylistItems.fulfilled({
dispatch(p.movePlaylistItems.fulfilled({
location: { after: 'NkwUIwNmraSZ4A4eiC3GQ' },
}, '', {
playlistID: 'ZcU_8-UyI10Tx79R4CjRv',
medias: [items[1], items[2]],
}));

const selectedItemIDs = s.selectedPlaylistSelector(getState()).media
const selectedItemIDs = p.selectedPlaylistItemsSelector(getState())
.map((playlistItem) => playlistItem._id);
expect(selectedItemIDs).toEqual(['Cnun9zo6oNr1wMCFRhnaO', 'NkwUIwNmraSZ4A4eiC3GQ', 'PD_n42XxNCdQjDy5VB_SE', '66Z6y6JA4m5WmmNF3O7Ii', 'BeevKCM1NnNeW91leyLZu']);
});
Expand All @@ -175,27 +168,27 @@ describe('reducers/playlists', () => {
{ _id: 'NkwUIwNmraSZ4A4eiC3GQ', artist: 'Angel Haze', title: 'A Tribe Called Red' },
{ _id: 'BeevKCM1NnNeW91leyLZu', artist: 'tricot', title: '99.974°C' },
];
dispatch(loadPlaylist.fulfilled({
dispatch(p.loadPlaylist.fulfilled({
items,
page: 0,
pageSize: 5,
total: 5,
}, 'W34UluniSyaY6UB3Xz1jy', {
playlistID: 'ZcU_8-UyI10Tx79R4CjRv',
}));
dispatch(selectPlaylist('ZcU_8-UyI10Tx79R4CjRv'));
dispatch(p.selectPlaylist('ZcU_8-UyI10Tx79R4CjRv'));

expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5);
expect(p.selectedPlaylistItemsSelector(getState())).toHaveLength(5);

dispatch(movePlaylistItems.fulfilled({
dispatch(p.movePlaylistItems.fulfilled({
location: { after: 'NkwUIwNmraSZ4A4eiC3GQ' },
}, '', {
playlistID: 'ZcU_8-UyI10Tx79R4CjRv',
medias: [items[0], items[4]],
}));

const getID = (item) => (item ? item._id : null);
expect(s.selectedPlaylistSelector(getState()).media.map(getID)).toEqual([
expect(p.selectedPlaylistItemsSelector(getState()).map(getID)).toEqual([
'PD_n42XxNCdQjDy5VB_SE', null, 'NkwUIwNmraSZ4A4eiC3GQ', 'Cnun9zo6oNr1wMCFRhnaO', 'BeevKCM1NnNeW91leyLZu',
]);
});
Expand Down
Loading

0 comments on commit bbaef5f

Please sign in to comment.