You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Audio.js 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // @flow
  2. import React from 'react';
  3. import AbstractAudio from '../AbstractAudio';
  4. import type { AudioElement } from '../AbstractAudio';
  5. /**
  6. * The React/Web {@link Component} which is similar to and wraps around
  7. * {@code HTMLAudioElement} in order to facilitate cross-platform source code.
  8. */
  9. export default class Audio extends AbstractAudio {
  10. /**
  11. * Set to <code>true</code> when the whole file is loaded.
  12. */
  13. _audioFileLoaded: boolean;
  14. /**
  15. * Reference to the HTML audio element, stored until the file is ready.
  16. */
  17. _ref: ?AudioElement;
  18. /**
  19. * Creates new <code>Audio</code> element instance with given props.
  20. *
  21. * @param {Object} props - The read-only properties with which the new
  22. * instance is to be initialized.
  23. */
  24. constructor(props: Object) {
  25. super(props);
  26. // Bind event handlers so they are only bound once for every instance.
  27. this._onCanPlayThrough = this._onCanPlayThrough.bind(this);
  28. this._setRef = this._setRef.bind(this);
  29. }
  30. /**
  31. * Implements React's {@link Component#render()}.
  32. *
  33. * @inheritdoc
  34. * @returns {ReactElement}
  35. */
  36. render() {
  37. return (
  38. <audio
  39. onCanPlayThrough = { this._onCanPlayThrough }
  40. preload = 'auto'
  41. // $FlowFixMe
  42. ref = { this._setRef }
  43. src = { this.props.src } />
  44. );
  45. }
  46. /**
  47. * If audio element reference has been set and the file has been
  48. * loaded then {@link setAudioElementImpl} will be called to eventually add
  49. * the audio to the Redux store.
  50. *
  51. * @private
  52. * @returns {void}
  53. */
  54. _maybeSetAudioElementImpl() {
  55. if (this._ref && this._audioFileLoaded) {
  56. this.setAudioElementImpl(this._ref);
  57. }
  58. }
  59. _onCanPlayThrough: () => void;
  60. /**
  61. * Called when 'canplaythrough' event is triggered on the audio element,
  62. * which means that the whole file has been loaded.
  63. *
  64. * @private
  65. * @returns {void}
  66. */
  67. _onCanPlayThrough() {
  68. this._audioFileLoaded = true;
  69. this._maybeSetAudioElementImpl();
  70. }
  71. _setRef: (?AudioElement) => void;
  72. /**
  73. * Sets the reference to the HTML audio element.
  74. *
  75. * @param {HTMLAudioElement} audioElement - The HTML audio element instance.
  76. * @private
  77. * @returns {void}
  78. */
  79. _setRef(audioElement: ?AudioElement) {
  80. this._ref = audioElement;
  81. if (audioElement) {
  82. this._maybeSetAudioElementImpl();
  83. } else {
  84. // AbstractAudioElement is supposed to trigger "removeAudio" only if
  85. // it was previously added, so it's safe to just call it.
  86. this.setAudioElementImpl(null);
  87. // Reset the loaded flag, as the audio element is being removed from
  88. // the DOM tree.
  89. this._audioFileLoaded = false;
  90. }
  91. }
  92. }