123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- // @flow
-
- import React, { Component } from 'react';
- import { connect } from 'react-redux';
-
- import { Audio } from '../../media';
- import type { AudioElement } from '../../media';
- import { Fragment } from '../../react';
-
- import { _addAudioElement, _removeAudioElement } from '../actions';
- import type { Sound } from '../reducer';
-
- /**
- * {@link SoundCollection}'s properties.
- */
- type Props = {
-
- /**
- * Dispatches {@link _ADD_AUDIO_ELEMENT} Redux action which will store the
- * {@link AudioElement} for a sound in the Redux store.
- */
- _addAudioElement: Function,
-
- /**
- * Dispatches {@link _REMOVE_AUDIO_ELEMENT} Redux action which will remove
- * the sound's {@link AudioElement} from the Redux store.
- */
- _removeAudioElement: Function,
-
- /**
- * It's the 'base/sounds' reducer's state mapped to a property. It's used to
- * render audio elements for every registered sound.
- */
- _sounds: Map<string, Sound>
- }
-
- /**
- * Collections of all global sounds used by the app for playing audio
- * notifications in response to various events. It renders <code>Audio</code>
- * element for each sound registered in the base/sounds feature. When the audio
- * resource is loaded it will emit add/remove audio element actions which will
- * attach the element to the corresponding {@link Sound} instance in the Redux
- * state. When that happens the sound can be played using the {@link playSound}
- * action.
- */
- class SoundCollection extends Component<Props> {
- /**
- * Implements React's {@link Component#render()}.
- *
- * @inheritdoc
- * @returns {ReactElement}
- */
- render() {
- let key = 0;
- const sounds = [];
-
- for (const [ soundId, sound ] of this.props._sounds.entries()) {
- sounds.push(
- React.createElement(
- Audio, {
- key,
- setRef: this._setRef.bind(this, soundId),
- src: sound.src
- }));
- key += 1;
- }
-
- return (
- <Fragment>
- {
- sounds
- }
- </Fragment>
- );
- }
-
- /**
- * Set the (reference to the) {@link AudioElement} object which implements
- * the audio playback functionality.
- *
- * @param {string} soundId - The sound Id for the audio element for which
- * the callback is being executed.
- * @param {AudioElement} element - The {@link AudioElement} instance
- * which implements the audio playback functionality.
- * @protected
- * @returns {void}
- */
- _setRef(soundId: string, element: ?AudioElement) {
- if (element) {
- this.props._addAudioElement(soundId, element);
- } else {
- this.props._removeAudioElement(soundId);
- }
- }
- }
-
- /**
- * Maps (parts of) the Redux state to {@code SoundCollection}'s props.
- *
- * @param {Object} state - The redux state.
- * @private
- * @returns {{
- * _sounds: Map<string, Sound>
- * }}
- */
- function _mapStateToProps(state) {
- return {
- _sounds: state['features/base/sounds']
- };
- }
-
- /**
- * Maps dispatching of some actions to React component props.
- *
- * @param {Function} dispatch - Redux action dispatcher.
- * @private
- * @returns {{
- * _addAudioElement: void,
- * _removeAudioElement: void
- * }}
- */
- export function _mapDispatchToProps(dispatch: Function) {
- return {
- /**
- * Dispatches action to store the {@link AudioElement} for
- * a {@link Sound} identified by given <tt>soundId</tt> in the Redux
- * store, so that the playback can be controlled through the Redux
- * actions.
- *
- * @param {string} soundId - A global identifier which will be used to
- * identify the {@link Sound} instance for which an audio element will
- * be added.
- * @param {AudioElement} audioElement - The {@link AudioElement}
- * instance that will be stored in the Redux state of the base/sounds
- * feature, as part of the {@link Sound} object. At that point the sound
- * will be ready for playback.
- * @private
- * @returns {void}
- */
- _addAudioElement(soundId: string, audioElement: AudioElement) {
- dispatch(_addAudioElement(soundId, audioElement));
- },
-
- /**
- * Dispatches action to remove {@link AudioElement} from the Redux
- * store for specific {@link Sound}, because it is no longer part of
- * the DOM tree and the audio resource will be released.
- *
- * @param {string} soundId - The id of the {@link Sound} instance for
- * which an {@link AudioElement} will be removed from the Redux store.
- * @private
- * @returns {void}
- */
- _removeAudioElement(soundId: string) {
- dispatch(_removeAudioElement(soundId));
- }
- };
- }
-
- export default connect(_mapStateToProps, _mapDispatchToProps)(SoundCollection);
|