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.

YoutubeVideoManager.tsx 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* eslint-disable no-invalid-this */
  2. import React from 'react';
  3. import { connect } from 'react-redux';
  4. import YouTube from 'react-youtube';
  5. import { PLAYBACK_STATUSES } from '../../constants';
  6. import AbstractVideoManager, {
  7. IProps,
  8. _mapDispatchToProps,
  9. _mapStateToProps
  10. } from './AbstractVideoManager';
  11. /**
  12. * Manager of shared video.
  13. *
  14. * @returns {void}
  15. */
  16. class YoutubeVideoManager extends AbstractVideoManager {
  17. isPlayerAPILoaded: boolean;
  18. player?: any;
  19. /**
  20. * Initializes a new YoutubeVideoManager instance.
  21. *
  22. * @param {Object} props - This component's props.
  23. *
  24. * @returns {void}
  25. */
  26. constructor(props: IProps) {
  27. super(props);
  28. this.isPlayerAPILoaded = false;
  29. }
  30. /**
  31. * Indicates the playback state of the video.
  32. *
  33. * @returns {string}
  34. */
  35. getPlaybackStatus() {
  36. let status;
  37. if (!this.player) {
  38. return;
  39. }
  40. const playerState = this.player.getPlayerState();
  41. if (playerState === YouTube.PlayerState.PLAYING) {
  42. status = PLAYBACK_STATUSES.PLAYING;
  43. }
  44. if (playerState === YouTube.PlayerState.PAUSED) {
  45. status = PLAYBACK_STATUSES.PAUSED;
  46. }
  47. return status;
  48. }
  49. /**
  50. * Indicates whether the video is muted.
  51. *
  52. * @returns {boolean}
  53. */
  54. isMuted() {
  55. return this.player?.isMuted();
  56. }
  57. /**
  58. * Retrieves current volume.
  59. *
  60. * @returns {number}
  61. */
  62. getVolume() {
  63. return this.player?.getVolume();
  64. }
  65. /**
  66. * Retrieves current time.
  67. *
  68. * @returns {number}
  69. */
  70. getTime() {
  71. return this.player?.getCurrentTime();
  72. }
  73. /**
  74. * Seeks video to provided time.
  75. *
  76. * @param {number} time - The time to seek to.
  77. *
  78. * @returns {void}
  79. */
  80. seek(time: number) {
  81. return this.player?.seekTo(time);
  82. }
  83. /**
  84. * Plays video.
  85. *
  86. * @returns {void}
  87. */
  88. play() {
  89. return this.player?.playVideo();
  90. }
  91. /**
  92. * Pauses video.
  93. *
  94. * @returns {void}
  95. */
  96. pause() {
  97. return this.player?.pauseVideo();
  98. }
  99. /**
  100. * Mutes video.
  101. *
  102. * @returns {void}
  103. */
  104. mute() {
  105. return this.player?.mute();
  106. }
  107. /**
  108. * Unmutes video.
  109. *
  110. * @returns {void}
  111. */
  112. unMute() {
  113. return this.player?.unMute();
  114. }
  115. /**
  116. * Disposes of the current video player.
  117. *
  118. * @returns {void}
  119. */
  120. dispose() {
  121. if (this.player) {
  122. this.player.destroy();
  123. this.player = null;
  124. }
  125. }
  126. /**
  127. * Fired on play state toggle.
  128. *
  129. * @param {Object} event - The yt player stateChange event.
  130. *
  131. * @returns {void}
  132. */
  133. onPlayerStateChange = (event: any) => {
  134. if (event.data === YouTube.PlayerState.PLAYING) {
  135. this.onPlay();
  136. } else if (event.data === YouTube.PlayerState.PAUSED) {
  137. this.onPause();
  138. }
  139. };
  140. /**
  141. * Fired when youtube player is ready.
  142. *
  143. * @param {Object} event - The youtube player event.
  144. *
  145. * @returns {void}
  146. */
  147. onPlayerReady = (event: any) => {
  148. const { _isOwner } = this.props;
  149. this.player = event.target;
  150. this.player.addEventListener('onVolumeChange', () => {
  151. this.onVolumeChange();
  152. });
  153. if (_isOwner) {
  154. this.player.addEventListener('onVideoProgress', this.throttledFireUpdateSharedVideoEvent);
  155. }
  156. this.play();
  157. // sometimes youtube can get muted state from previous videos played in the browser
  158. // and as we are disabling controls we want to unmute it
  159. if (this.isMuted()) {
  160. this.unMute();
  161. }
  162. };
  163. getPlayerOptions = () => {
  164. const { _isOwner, videoId } = this.props;
  165. const showControls = _isOwner ? 1 : 0;
  166. const options = {
  167. id: 'sharedVideoPlayer',
  168. opts: {
  169. height: '100%',
  170. width: '100%',
  171. playerVars: {
  172. 'origin': location.origin,
  173. 'fs': '0',
  174. 'autoplay': 0,
  175. 'controls': showControls,
  176. 'rel': 0
  177. }
  178. },
  179. onError: (e: any) => this.onError(e),
  180. onReady: this.onPlayerReady,
  181. onStateChange: this.onPlayerStateChange,
  182. videoId
  183. };
  184. return options;
  185. };
  186. /**
  187. * Implements React Component's render.
  188. *
  189. * @inheritdoc
  190. */
  191. render() {
  192. return (
  193. <YouTube
  194. { ...this.getPlayerOptions() } />
  195. );
  196. }
  197. }
  198. export default connect(_mapStateToProps, _mapDispatchToProps)(YoutubeVideoManager);