diff --git a/js/actionCreators/index.ts b/js/actionCreators/index.ts index 83f3473c..62249bff 100644 --- a/js/actionCreators/index.ts +++ b/js/actionCreators/index.ts @@ -49,6 +49,7 @@ export { seekForward, seekBackward, setVolume, + playTrack, adjustVolume, scrollVolume, setBalance, diff --git a/js/actionCreators/media.ts b/js/actionCreators/media.ts index b1941c1d..25692163 100644 --- a/js/actionCreators/media.ts +++ b/js/actionCreators/media.ts @@ -11,6 +11,7 @@ import { PLAY_TRACK, TOGGLE_TIME_MODE, BUFFER_TRACK, + IS_STOPPED, } from "../actionTypes"; import { MEDIA_STATUS } from "../constants"; @@ -18,25 +19,7 @@ import { openMediaFileDialog } from "./"; import { GetState, Dispatch, Dispatchable } from "../types"; import * as Selectors from "../selectors"; -function playRandomTrack(): Dispatchable { - return (dispatch: Dispatch, getState: GetState) => { - const { - playlist: { trackOrder, currentTrack }, - } = getState(); - if (trackOrder.length === 0) { - return; - } - let nextId; - do { - nextId = trackOrder[Math.floor(trackOrder.length * Math.random())]; - } while (nextId === currentTrack && trackOrder.length > 1); - // TODO: Sigh... Technically, we should detect if we are looping only repeat if we are. - // I think this would require pre-computing the "random" order of a playlist. - dispatch(playTrack(nextId)); - }; -} - -function playTrack(id: number): Dispatchable { +export function playTrack(id: number): Dispatchable { return (dispatch, getState) => { const state = getState(); const isStopped = Selectors.getMediaStatus(state) === MEDIA_STATUS.STOPPED; @@ -80,13 +63,9 @@ export function stop(): Dispatchable { export function nextN(n: number): Dispatchable { return (dispatch, getState) => { - const state = getState(); - if (state.media.shuffle) { - dispatch(playRandomTrack()); - return; - } - const nextTrackId = Selectors.nextTrack(state, n); + const nextTrackId = Selectors.getNextTrackId(getState(), n); if (nextTrackId == null) { + dispatch({ type: IS_STOPPED }); return; } dispatch(playTrack(nextTrackId)); diff --git a/js/mediaMiddleware.ts b/js/mediaMiddleware.ts index c839bb2f..9eafb91e 100644 --- a/js/mediaMiddleware.ts +++ b/js/mediaMiddleware.ts @@ -1,7 +1,6 @@ import Media from "./media"; import { IS_PLAYING, - IS_STOPPED, PAUSE, PLAY, SEEK_TO_PERCENT_COMPLETE, @@ -44,7 +43,6 @@ export default (media: Media) => (store: MiddlewareStore) => { }); media.on("ended", () => { - store.dispatch({ type: IS_STOPPED }); store.dispatch(nextTrack()); }); diff --git a/js/selectors.ts b/js/selectors.ts index d51bc8e1..b2457f48 100644 --- a/js/selectors.ts +++ b/js/selectors.ts @@ -146,11 +146,30 @@ export const getCurrentTrackNumber = createSelector( export const getCurrentTrackId = (state: AppState) => state.playlist.currentTrack; -export const nextTrack = (state: AppState, n = 1) => { +// TODO: Sigh... Technically, we should detect if we are looping only repeat if we are. +// I think this would require pre-computing the "random" order of a playlist. +export const getRandomTrackId = (state: AppState): number | null => { + const { + playlist: { trackOrder, currentTrack }, + } = state; + if (trackOrder.length === 0) { + return null; + } + let nextId; + do { + nextId = trackOrder[Math.floor(trackOrder.length * Math.random())]; + } while (nextId === currentTrack && trackOrder.length > 1); + return nextId; +}; + +export const getNextTrackId = (state: AppState, n = 1) => { const { playlist: { trackOrder }, - media: { repeat }, + media: { repeat, shuffle }, } = state; + if (shuffle) { + return getRandomTrackId(state); + } const trackCount = getTrackCount(state); if (trackCount === 0) { return null;