Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

SoundCollection.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { connect } from 'react-redux';
  4. import { Audio } from '../../media';
  5. import type { AudioElement } from '../../media';
  6. import { Fragment } from '../../react';
  7. import { _addAudioElement, _removeAudioElement } from '../actions';
  8. import type { Sound } from '../reducer';
  9. /**
  10. * {@link SoundCollection}'s properties.
  11. */
  12. type Props = {
  13. /**
  14. * Dispatches {@link _ADD_AUDIO_ELEMENT} Redux action which will store the
  15. * {@link AudioElement} for a sound in the Redux store.
  16. */
  17. _addAudioElement: Function,
  18. /**
  19. * Dispatches {@link _REMOVE_AUDIO_ELEMENT} Redux action which will remove
  20. * the sound's {@link AudioElement} from the Redux store.
  21. */
  22. _removeAudioElement: Function,
  23. /**
  24. * It's the 'base/sounds' reducer's state mapped to a property. It's used to
  25. * render audio elements for every registered sound.
  26. */
  27. _sounds: Map<string, Sound>
  28. }
  29. /**
  30. * Collections of all global sounds used by the app for playing audio
  31. * notifications in response to various events. It renders <code>Audio</code>
  32. * element for each sound registered in the base/sounds feature. When the audio
  33. * resource is loaded it will emit add/remove audio element actions which will
  34. * attach the element to the corresponding {@link Sound} instance in the Redux
  35. * state. When that happens the sound can be played using the {@link playSound}
  36. * action.
  37. */
  38. class SoundCollection extends Component<Props> {
  39. /**
  40. * Implements React's {@link Component#render()}.
  41. *
  42. * @inheritdoc
  43. * @returns {ReactElement}
  44. */
  45. render() {
  46. let key = 0;
  47. const sounds = [];
  48. for (const [ soundId, sound ] of this.props._sounds.entries()) {
  49. const { options, src } = sound;
  50. sounds.push(
  51. React.createElement(
  52. Audio, {
  53. key,
  54. setRef: this._setRef.bind(this, soundId),
  55. src,
  56. loop: options.loop
  57. }));
  58. key += 1;
  59. }
  60. return (
  61. <Fragment>
  62. {
  63. sounds
  64. }
  65. </Fragment>
  66. );
  67. }
  68. /**
  69. * Set the (reference to the) {@link AudioElement} object which implements
  70. * the audio playback functionality.
  71. *
  72. * @param {string} soundId - The sound Id for the audio element for which
  73. * the callback is being executed.
  74. * @param {AudioElement} element - The {@link AudioElement} instance
  75. * which implements the audio playback functionality.
  76. * @protected
  77. * @returns {void}
  78. */
  79. _setRef(soundId: string, element: ?AudioElement) {
  80. if (element) {
  81. this.props._addAudioElement(soundId, element);
  82. } else {
  83. this.props._removeAudioElement(soundId);
  84. }
  85. }
  86. }
  87. /**
  88. * Maps (parts of) the Redux state to {@code SoundCollection}'s props.
  89. *
  90. * @param {Object} state - The redux state.
  91. * @private
  92. * @returns {{
  93. * _sounds: Map<string, Sound>
  94. * }}
  95. */
  96. function _mapStateToProps(state) {
  97. return {
  98. _sounds: state['features/base/sounds']
  99. };
  100. }
  101. /**
  102. * Maps dispatching of some actions to React component props.
  103. *
  104. * @param {Function} dispatch - Redux action dispatcher.
  105. * @private
  106. * @returns {{
  107. * _addAudioElement: void,
  108. * _removeAudioElement: void
  109. * }}
  110. */
  111. export function _mapDispatchToProps(dispatch: Function) {
  112. return {
  113. /**
  114. * Dispatches action to store the {@link AudioElement} for
  115. * a {@link Sound} identified by given <tt>soundId</tt> in the Redux
  116. * store, so that the playback can be controlled through the Redux
  117. * actions.
  118. *
  119. * @param {string} soundId - A global identifier which will be used to
  120. * identify the {@link Sound} instance for which an audio element will
  121. * be added.
  122. * @param {AudioElement} audioElement - The {@link AudioElement}
  123. * instance that will be stored in the Redux state of the base/sounds
  124. * feature, as part of the {@link Sound} object. At that point the sound
  125. * will be ready for playback.
  126. * @private
  127. * @returns {void}
  128. */
  129. _addAudioElement(soundId: string, audioElement: AudioElement) {
  130. dispatch(_addAudioElement(soundId, audioElement));
  131. },
  132. /**
  133. * Dispatches action to remove {@link AudioElement} from the Redux
  134. * store for specific {@link Sound}, because it is no longer part of
  135. * the DOM tree and the audio resource will be released.
  136. *
  137. * @param {string} soundId - The id of the {@link Sound} instance for
  138. * which an {@link AudioElement} will be removed from the Redux store.
  139. * @private
  140. * @returns {void}
  141. */
  142. _removeAudioElement(soundId: string) {
  143. dispatch(_removeAudioElement(soundId));
  144. }
  145. };
  146. }
  147. export default connect(_mapStateToProps, _mapDispatchToProps)(SoundCollection);