Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

AbstractWelcomePage.js 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import PropTypes from 'prop-types';
  2. import React, { Component } from 'react';
  3. import { appNavigate } from '../../app';
  4. import { isRoomValid } from '../../base/conference';
  5. import { VideoTrack } from '../../base/media';
  6. import { getLocalVideoTrack } from '../../base/tracks';
  7. import { generateRoomWithoutSeparator } from '../roomnameGenerator';
  8. /**
  9. * Base (abstract) class for container component rendering the welcome page.
  10. *
  11. * @abstract
  12. */
  13. export class AbstractWelcomePage extends Component {
  14. /**
  15. * {@code AbstractWelcomePage} component's property types.
  16. *
  17. * @static
  18. */
  19. static propTypes = {
  20. _localVideoTrack: PropTypes.object,
  21. _room: PropTypes.string,
  22. dispatch: PropTypes.func
  23. };
  24. /**
  25. * Initializes a new {@code AbstractWelcomePage} instance.
  26. *
  27. * @param {Object} props - The React {@code Component} props to initialize
  28. * the new {@code AbstractWelcomePage} instance with.
  29. */
  30. constructor(props) {
  31. super(props);
  32. /**
  33. * Save room name into component's local state.
  34. *
  35. * @type {Object}
  36. * @property {number|null} animateTimeoutId - Identifier of the letter
  37. * animation timeout.
  38. * @property {string} generatedRoomname - Automatically generated
  39. * room name.
  40. * @property {string} room - Room name.
  41. * @property {string} roomPlaceholder - Room placeholder
  42. * that's used as a placeholder for input.
  43. * @property {nubmer|null} updateTimeoutId - Identifier of the timeout
  44. * updating the generated room name.
  45. */
  46. this.state = {
  47. animateTimeoutId: null,
  48. generatedRoomname: '',
  49. room: '',
  50. roomPlaceholder: '',
  51. updateTimeoutId: null
  52. };
  53. // Bind event handlers so they are only bound once per instance.
  54. this._animateRoomnameChanging
  55. = this._animateRoomnameChanging.bind(this);
  56. this._onJoin = this._onJoin.bind(this);
  57. this._onRoomChange = this._onRoomChange.bind(this);
  58. this._updateRoomname = this._updateRoomname.bind(this);
  59. }
  60. /**
  61. * This method is executed when component receives new properties.
  62. *
  63. * @inheritdoc
  64. * @param {Object} nextProps - New props component will receive.
  65. */
  66. componentWillReceiveProps(nextProps) {
  67. this.setState({ room: nextProps._room });
  68. }
  69. /**
  70. * This method is executed when method will be unmounted from DOM.
  71. *
  72. * @inheritdoc
  73. */
  74. componentWillUnmount() {
  75. this._clearTimeouts();
  76. }
  77. /**
  78. * Animates the changing of the room name.
  79. *
  80. * @param {string} word - The part of room name that should be added to
  81. * placeholder.
  82. * @private
  83. * @returns {void}
  84. */
  85. _animateRoomnameChanging(word) {
  86. let animateTimeoutId = null;
  87. const roomPlaceholder = this.state.roomPlaceholder + word.substr(0, 1);
  88. if (word.length > 1) {
  89. animateTimeoutId
  90. = setTimeout(
  91. () => {
  92. this._animateRoomnameChanging(
  93. word.substring(1, word.length));
  94. },
  95. 70);
  96. }
  97. this.setState({
  98. animateTimeoutId,
  99. roomPlaceholder
  100. });
  101. }
  102. /**
  103. * Method that clears timeouts for animations and updates of room name.
  104. *
  105. * @private
  106. * @returns {void}
  107. */
  108. _clearTimeouts() {
  109. clearTimeout(this.state.animateTimeoutId);
  110. clearTimeout(this.state.updateTimeoutId);
  111. }
  112. /**
  113. * Determines whether the 'Join' button is (to be) disabled i.e. there's no
  114. * valid room name typed into the respective text input field.
  115. *
  116. * @protected
  117. * @returns {boolean} If the 'Join' button is (to be) disabled, true;
  118. * otherwise, false.
  119. */
  120. _isJoinDisabled() {
  121. return !isRoomValid(this.state.room);
  122. }
  123. /**
  124. * Handles joining. Either by clicking on 'Join' button
  125. * or by pressing 'Enter' in room name input field.
  126. *
  127. * @protected
  128. * @returns {void}
  129. */
  130. _onJoin() {
  131. const room = this.state.room || this.state.generatedRoomname;
  132. room && this.props.dispatch(appNavigate(room));
  133. }
  134. /**
  135. * Handles 'change' event for the room name text input field.
  136. *
  137. * @param {string} value - The text typed into the respective text input
  138. * field.
  139. * @protected
  140. * @returns {void}
  141. */
  142. _onRoomChange(value) {
  143. this.setState({ room: value });
  144. }
  145. /**
  146. * Renders a local video if any.
  147. *
  148. * @protected
  149. * @returns {(ReactElement|null)}
  150. */
  151. _renderLocalVideo() {
  152. return (
  153. <VideoTrack videoTrack = { this.props._localVideoTrack } />
  154. );
  155. }
  156. /**
  157. * Triggers the generation of a new room name and initiates an animation of
  158. * its changing.
  159. *
  160. * @protected
  161. * @returns {void}
  162. */
  163. _updateRoomname() {
  164. const generatedRoomname = generateRoomWithoutSeparator();
  165. const roomPlaceholder = '';
  166. const updateTimeoutId = setTimeout(this._updateRoomname, 10000);
  167. this._clearTimeouts();
  168. this.setState(
  169. {
  170. generatedRoomname,
  171. roomPlaceholder,
  172. updateTimeoutId
  173. },
  174. () => this._animateRoomnameChanging(generatedRoomname));
  175. }
  176. }
  177. /**
  178. * Selects local video track from tracks in state, local participant and room
  179. * and maps them to component props. It seems it's not possible to 'connect'
  180. * base component and then extend from it. So we export this function in order
  181. * to be used in child classes for 'connect'.
  182. *
  183. * @param {Object} state - Redux state.
  184. * @protected
  185. * @returns {{
  186. * _localVideoTrack: (Track|undefined),
  187. * _room: string
  188. * }}
  189. */
  190. export function _mapStateToProps(state) {
  191. const conference = state['features/base/conference'];
  192. const tracks = state['features/base/tracks'];
  193. return {
  194. _localVideoTrack: getLocalVideoTrack(tracks),
  195. _room: conference.room
  196. };
  197. }