選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Conference.web.js 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* global APP, $, interfaceConfig */
  2. import React, { Component } from 'react';
  3. import { connect as reactReduxConnect } from 'react-redux';
  4. import {
  5. connect,
  6. disconnect
  7. } from '../../base/connection';
  8. /**
  9. * For legacy reasons, inline style for display none.
  10. * @type {{display: string}}
  11. */
  12. const DISPLAY_NONE_STYLE = {
  13. display: 'none'
  14. };
  15. /**
  16. * Implements a React Component which renders initial conference layout
  17. */
  18. class Conference extends Component {
  19. /**
  20. * Until we don't rewrite UI using react components
  21. * we use UI.start from old app. Also method translates
  22. * component right after it has been mounted.
  23. *
  24. * @inheritdoc
  25. */
  26. componentDidMount() {
  27. APP.UI.start();
  28. // XXX Temporary solution until we add React translation.
  29. APP.translation.translateElement($('#videoconference_page'));
  30. this.props.dispatch(connect());
  31. }
  32. /**
  33. * Disconnect from the conference when component will be
  34. * unmounted.
  35. *
  36. * @inheritdoc
  37. */
  38. componentWillUnmount() {
  39. this.props.dispatch(disconnect());
  40. }
  41. /**
  42. * Conference component's property types.
  43. *
  44. * @static
  45. */
  46. static propTypes = {
  47. dispatch: React.PropTypes.func
  48. };
  49. /**
  50. * Initializes Conference component instance.
  51. *
  52. * @param {Object} props - The read-only properties with which the new
  53. * instance is to be initialized.
  54. */
  55. constructor(props) {
  56. super(props);
  57. const showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
  58. const showJitsiWatermark = interfaceConfig.SHOW_JITSI_WATERMARK;
  59. this.state = {
  60. ...this.state,
  61. showBrandWatermark,
  62. showJitsiWatermark,
  63. brandWatermarkLink:
  64. showBrandWatermark ? interfaceConfig.BRAND_WATERMARK_LINK : '',
  65. jitsiWatermarkLink:
  66. showJitsiWatermark ? interfaceConfig.JITSI_WATERMARK_LINK : '',
  67. showPoweredBy: interfaceConfig.SHOW_POWERED_BY
  68. };
  69. }
  70. /**
  71. * Implements React's {@link Component#render()}.
  72. *
  73. * @inheritdoc
  74. * @returns {ReactElement}
  75. */
  76. render() {
  77. return (
  78. <div id = 'videoconference_page'>
  79. <div id = 'mainToolbarContainer'>
  80. <div
  81. className = 'notice'
  82. id = 'notice'
  83. style = { DISPLAY_NONE_STYLE }>
  84. <span
  85. className = 'noticeText'
  86. id = 'noticeText' />
  87. </div>
  88. <div
  89. className = 'toolbar'
  90. id = 'mainToolbar' />
  91. </div>
  92. <div
  93. className = 'hide'
  94. id = 'subject' />
  95. <div
  96. className = 'toolbar'
  97. id = 'extendedToolbar'>
  98. <div id = 'extendedToolbarButtons' />
  99. <a
  100. className = 'button icon-feedback'
  101. id = 'feedbackButton' />
  102. <div id = 'sideToolbarContainer' />
  103. </div>
  104. <div id = 'videospace'>
  105. <div
  106. className = 'videocontainer'
  107. id = 'largeVideoContainer'>
  108. <div id = 'sharedVideo'>
  109. <div id = 'sharedVideoIFrame' />
  110. </div>
  111. <div id = 'etherpad' />
  112. {
  113. this._renderJitsiWatermark()
  114. }
  115. {
  116. this._renderBrandWatermark()
  117. }
  118. {
  119. this._renderPoweredBy()
  120. }
  121. <div id = 'dominantSpeaker'>
  122. <div className = 'dynamic-shadow' />
  123. <img
  124. id = 'dominantSpeakerAvatar'
  125. src = '' />
  126. </div>
  127. <span id = 'remoteConnectionMessage' />
  128. <div id = 'largeVideoWrapper'>
  129. <video
  130. autoPlay = { true }
  131. id = 'largeVideo'
  132. muted = 'true' />
  133. </div>
  134. <span id = 'localConnectionMessage' />
  135. <span
  136. className = 'video-state-indicator moveToCorner'
  137. id = 'videoResolutionLabel'>HD</span>
  138. <span
  139. className
  140. = 'video-state-indicator centeredVideoLabel'
  141. id = 'recordingLabel'>
  142. <span id = 'recordingLabelText' />
  143. <img
  144. className = 'recordingSpinner'
  145. id = 'recordingSpinner'
  146. src = 'images/spin.svg' />
  147. </span>
  148. </div>
  149. <div className = 'filmstrip'>
  150. <div
  151. className = 'filmstrip__videos'
  152. id = 'remoteVideos'>
  153. <span
  154. className = 'videocontainer'
  155. id = 'localVideoContainer'>
  156. <div
  157. className = 'videocontainer__background' />
  158. <span id = 'localVideoWrapper' />
  159. <audio
  160. autoPlay = { true }
  161. id = 'localAudio'
  162. muted = { true } />
  163. <div className = 'videocontainer__toolbar' />
  164. <div
  165. className = 'videocontainer__toptoolbar' />
  166. <div
  167. className
  168. = 'videocontainer__hoverOverlay' />
  169. </span>
  170. <audio
  171. id = 'userJoined'
  172. preload = 'auto'
  173. src = 'sounds/joined.wav' />
  174. <audio
  175. id = 'userLeft'
  176. preload = 'auto'
  177. src = 'sounds/left.wav' />
  178. </div>
  179. </div>
  180. </div>
  181. </div>
  182. );
  183. }
  184. /**
  185. * Method that returns brand watermark element if it is enabled.
  186. *
  187. * @returns {ReactElement|null}
  188. * @private
  189. */
  190. _renderBrandWatermark() {
  191. if (this.state.showBrandWatermark) {
  192. return (
  193. <a
  194. href = { this.state.brandWatermarkLink }
  195. target = '_new'>
  196. <div className = 'watermark rightwatermark' />
  197. </a>
  198. );
  199. }
  200. return null;
  201. }
  202. /**
  203. * Method that returns jitsi watermark element if it is enabled.
  204. *
  205. * @returns {ReactElement|null}
  206. * @private
  207. */
  208. _renderJitsiWatermark() {
  209. if (this.state.showJitsiWatermark) {
  210. return (
  211. <a
  212. href = { this.state.jitsiWatermarkLink }
  213. target = '_new'>
  214. <div className = 'watermark leftwatermark' />
  215. </a>
  216. );
  217. }
  218. return null;
  219. }
  220. /**
  221. * Renders powered by block if it is enabled.
  222. *
  223. * @returns {ReactElement|null}
  224. * @private
  225. */
  226. _renderPoweredBy() {
  227. if (this.state.showPoweredBy) {
  228. return (
  229. <a
  230. className = 'poweredby hide'
  231. href = 'http://jitsi.org'
  232. target = '_new'>
  233. <span data-i18n = 'poweredby' /> jitsi.org
  234. </a>
  235. );
  236. }
  237. return null;
  238. }
  239. }
  240. export default reactReduxConnect()(Conference);