Skip to content

Commit

Permalink
Merge pull request #293 from Financial-Times/x-audio-close-on-end
Browse files Browse the repository at this point in the history
Add an `ended` notifier so consumers can respond to this event
  • Loading branch information
benbarnett authored May 14, 2019
2 parents fa71007 + 2a8d547 commit c20b298
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`actions and reducer Ended action sets ended to false 1`] = `
Object {
"currentTime": 0,
"ended": true,
"loading": false,
"playing": true,
}
`;

exports[`actions and reducer Loaded action sets loading to false 1`] = `
Object {
"currentTime": 0,
"ended": false,
"loading": false,
"playing": false,
}
Expand All @@ -11,6 +21,7 @@ Object {
exports[`actions and reducer Loading action sets loading to true 1`] = `
Object {
"currentTime": 0,
"ended": false,
"loading": true,
"playing": false,
}
Expand All @@ -19,6 +30,7 @@ Object {
exports[`actions and reducer Pause action sets playing to false 1`] = `
Object {
"currentTime": 0,
"ended": false,
"loading": false,
"playing": false,
}
Expand All @@ -27,14 +39,34 @@ Object {
exports[`actions and reducer Play action sets playing to true 1`] = `
Object {
"currentTime": 0,
"ended": false,
"loading": false,
"playing": true,
}
`;

exports[`actions and reducer Playing audio after previous has ended resets ended state 1`] = `
Object {
"currentTime": 0,
"ended": false,
"loading": false,
"playing": true,
}
`;

exports[`actions and reducer Requesting new audio play resets ended state 1`] = `
Object {
"currentTime": 0,
"ended": false,
"loading": false,
"playing": false,
}
`;

exports[`actions and reducer Update current time action updates currentTime 1`] = `
Object {
"currentTime": 10,
"ended": false,
"loading": false,
"playing": false,
}
Expand Down
25 changes: 25 additions & 0 deletions components/x-audio/src/redux/__tests__/player-logic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ describe('actions and reducer', () => {
expect(updatedState).toMatchSnapshot();
});

test('Ended action sets ended to false', () => {
const updatedState = runActions(initialState, actions.play(), actions.ended());

expect(updatedState).toMatchSnapshot();
});

test('Playing audio after previous has ended resets ended state', () => {
const updatedState = runActions(initialState, actions.ended(), actions.play());

expect(updatedState).toMatchSnapshot();
});

test('Requesting new audio play resets ended state', () => {
const updatedState = runActions(initialState, actions.ended(), actions.requestPlay());

expect(updatedState).toMatchSnapshot();
});

test('Update current time action updates currentTime', () => {
const currentTime = 10;
const updatedState = runActions(initialState, actions.updateCurrentTime({currentTime}));
Expand Down Expand Up @@ -98,6 +116,13 @@ describe('middleware', () => {
expect(store.dispatch).toHaveBeenCalledWith(actions.pause());
});

test('HTML ended event dispatches ended action', () => {
const { store, audio } = create();
audio.dispatchEvent(new Event('ended'));

expect(store.dispatch).toHaveBeenCalledWith(actions.ended());
});

[
'waiting',
'stalled',
Expand Down
23 changes: 16 additions & 7 deletions components/x-audio/src/redux/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,33 @@ export default function connectPlayer (Player) {
return;
}

if (this.stateAndPropsNeedSync()) {
this.updateStateFromProps(prevProps);
this.notifyStateChanges(prevState);
if (this.playingStateAndPropsNeedSync()) {
this.updatePlayingStateFromProps(prevProps);
this.notifyPlayingState(prevState);
}

if (this.audioHasEnded(prevState)) {
this.props.notifiers.ended();
}
}

audioHasEnded(prevState) {
return !prevState.ended && this.state.ended === true;
}

stateAndPropsNeedSync() {
playingStateAndPropsNeedSync() {
return this.state.playing !== this.props.playing;
}

updateStateFromProps(prevProps) {
updatePlayingStateFromProps(prevProps) {
if (!prevProps.playing && this.props.playing) {
playerActions.onPlayClick();
} else if (prevProps.playing && !this.props.playing) {
playerActions.onPauseClick();
}
}

notifyStateChanges(prevState) {
notifyPlayingState(prevState) {
if (!prevState.playing && this.state.playing) {
this.props.notifiers.play();
} else if (prevState.playing && !this.state.playing) {
Expand Down Expand Up @@ -103,7 +111,8 @@ export default function connectPlayer (Player) {
ConnectedPlayer.defaultProps = {
notifiers: {
pause: () => {},
play: () => {}
play: () => {},
ended: () => {}
},
onCloseClick: () => {}
}
Expand Down
22 changes: 16 additions & 6 deletions components/x-audio/src/redux/player-logic.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@
export const initialState = {
playing: false,
loading: false,
currentTime: 0
currentTime: 0,
ended: false
}

// reducer
export function reducer (state = initialState, action) {
switch (action.type) {
case 'PLAY':
return {...state, playing: true };
return { ...state, playing: true, ended: false };
case 'PAUSE':
return {...state, playing: false };
return { ...state, playing: false };
case 'LOADING':
return {...state, loading: true };
return { ...state, loading: true };
case 'LOADED':
return {...state, loading: false };
return { ...state, loading: false };
case 'UPDATE_CURRENT_TIME':
return {...state, currentTime: action.currentTime };
return { ...state, currentTime: action.currentTime };
case 'ENDED':
return { ...state, ended: true };
case 'REQUEST_PLAY':
return { ...state, ended: false };
default:
return state;
}
Expand Down Expand Up @@ -48,6 +53,9 @@ export const actions = {
updateCurrentTime: ({ currentTime }) => ({
type: 'UPDATE_CURRENT_TIME',
currentTime
}),
ended: () => ({
type: 'ENDED'
})
}

Expand Down Expand Up @@ -92,6 +100,8 @@ export const middleware = (store, audio = new Audio()) => {
}
});

audio.addEventListener('ended', () => store.dispatch(actions.ended()));

return next => action => {
switch (action.type) {
case 'REQUEST_PLAY':
Expand Down

0 comments on commit c20b298

Please sign in to comment.