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.

Prejoin.js 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // @flow
  2. import React, { Component } from 'react';
  3. import InlineDialog from '@atlaskit/inline-dialog';
  4. import {
  5. joinConference as joinConferenceAction,
  6. joinConferenceWithoutAudio as joinConferenceWithoutAudioAction,
  7. setSkipPrejoin as setSkipPrejoinAction,
  8. setJoinByPhoneDialogVisiblity as setJoinByPhoneDialogVisiblityAction
  9. } from '../actions';
  10. import { getRoomName } from '../../base/conference';
  11. import { Icon, IconPhone, IconVolumeOff } from '../../base/icons';
  12. import { translate } from '../../base/i18n';
  13. import { connect } from '../../base/redux';
  14. import { getDisplayName, updateSettings } from '../../base/settings';
  15. import ActionButton from './buttons/ActionButton';
  16. import {
  17. areJoinByPhoneButtonsVisible,
  18. isDeviceStatusVisible,
  19. isJoinByPhoneDialogVisible
  20. } from '../functions';
  21. import { isGuest } from '../../invite';
  22. import CopyMeetingUrl from './preview/CopyMeetingUrl';
  23. import DeviceStatus from './preview/DeviceStatus';
  24. import ParticipantName from './preview/ParticipantName';
  25. import Preview from './preview/Preview';
  26. import { VideoSettingsButton, AudioSettingsButton } from '../../toolbox';
  27. type Props = {
  28. /**
  29. * Flag signaling if the device status is visible or not.
  30. */
  31. deviceStatusVisible: boolean,
  32. /**
  33. * Flag signaling if a user is logged in or not.
  34. */
  35. isAnonymousUser: boolean,
  36. /**
  37. * Joins the current meeting.
  38. */
  39. joinConference: Function,
  40. /**
  41. * Joins the current meeting without audio.
  42. */
  43. joinConferenceWithoutAudio: Function,
  44. /**
  45. * The name of the user that is about to join.
  46. */
  47. name: string,
  48. /**
  49. * Updates settings.
  50. */
  51. updateSettings: Function,
  52. /**
  53. * The name of the meeting that is about to be joined.
  54. */
  55. roomName: string,
  56. /**
  57. * Sets visibility of the prejoin page for the next sessions.
  58. */
  59. setSkipPrejoin: Function,
  60. /**
  61. * Sets visibility of the 'JoinByPhoneDialog'.
  62. */
  63. setJoinByPhoneDialogVisiblity: Function,
  64. /**
  65. * If 'JoinByPhoneDialog' is visible or not.
  66. */
  67. showDialog: boolean,
  68. /**
  69. * If join by phone buttons should be visible.
  70. */
  71. hasJoinByPhoneButtons: boolean,
  72. /**
  73. * Used for translation.
  74. */
  75. t: Function,
  76. };
  77. type State = {
  78. /**
  79. * Flag controlling the visibility of the 'join by phone' buttons.
  80. */
  81. showJoinByPhoneButtons: boolean
  82. }
  83. /**
  84. * This component is displayed before joining a meeting.
  85. */
  86. class Prejoin extends Component<Props, State> {
  87. /**
  88. * Initializes a new {@code Prejoin} instance.
  89. *
  90. * @inheritdoc
  91. */
  92. constructor(props) {
  93. super(props);
  94. this.state = {
  95. showJoinByPhoneButtons: false
  96. };
  97. this._showDialog = this._showDialog.bind(this);
  98. this._onCheckboxChange = this._onCheckboxChange.bind(this);
  99. this._onDropdownClose = this._onDropdownClose.bind(this);
  100. this._onOptionsClick = this._onOptionsClick.bind(this);
  101. this._setName = this._setName.bind(this);
  102. }
  103. _onCheckboxChange: () => void;
  104. /**
  105. * Handler for the checkbox.
  106. *
  107. * @param {Object} e - The synthetic event.
  108. * @returns {void}
  109. */
  110. _onCheckboxChange(e) {
  111. this.props.setSkipPrejoin(e.target.checked);
  112. }
  113. _onDropdownClose: () => void;
  114. /**
  115. * Closes the dropdown.
  116. *
  117. * @returns {void}
  118. */
  119. _onDropdownClose() {
  120. this.setState({
  121. showJoinByPhoneButtons: false
  122. });
  123. }
  124. _onOptionsClick: () => void;
  125. /**
  126. * Displays the join by phone buttons dropdown.
  127. *
  128. * @param {Object} e - The synthetic event.
  129. * @returns {void}
  130. */
  131. _onOptionsClick(e) {
  132. e.stopPropagation();
  133. this.setState({
  134. showJoinByPhoneButtons: !this.state.showJoinByPhoneButtons
  135. });
  136. }
  137. _setName: () => void;
  138. /**
  139. * Sets the guest participant name.
  140. *
  141. * @param {string} displayName - Participant name.
  142. * @returns {void}
  143. */
  144. _setName(displayName) {
  145. this.props.updateSettings({
  146. displayName
  147. });
  148. }
  149. _showDialog: () => void;
  150. /**
  151. * Displays the dialog for joining a meeting by phone.
  152. *
  153. * @returns {undefined}
  154. */
  155. _showDialog() {
  156. this.props.setJoinByPhoneDialogVisiblity(true);
  157. }
  158. /**
  159. * Implements React's {@link Component#render()}.
  160. *
  161. * @inheritdoc
  162. * @returns {ReactElement}
  163. */
  164. render() {
  165. const {
  166. deviceStatusVisible,
  167. isAnonymousUser,
  168. joinConference,
  169. joinConferenceWithoutAudio,
  170. name,
  171. hasJoinByPhoneButtons,
  172. t
  173. } = this.props;
  174. const { _onCheckboxChange, _onDropdownClose, _onOptionsClick, _setName, _showDialog } = this;
  175. const { showJoinByPhoneButtons } = this.state;
  176. return (
  177. <div className = 'prejoin-full-page'>
  178. <Preview name = { name } />
  179. <div className = 'prejoin-input-area-container'>
  180. <div className = 'prejoin-input-area'>
  181. <div className = 'prejoin-title'>
  182. {t('prejoin.joinMeeting')}
  183. </div>
  184. <CopyMeetingUrl />
  185. <ParticipantName
  186. isEditable = { isAnonymousUser }
  187. joinConference = { joinConference }
  188. setName = { _setName }
  189. value = { name } />
  190. <div className = 'prejoin-preview-dropdown-container'>
  191. <InlineDialog
  192. content = { <div className = 'prejoin-preview-dropdown-btns'>
  193. <div
  194. className = 'prejoin-preview-dropdown-btn'
  195. onClick = { joinConferenceWithoutAudio }>
  196. <Icon
  197. className = 'prejoin-preview-dropdown-icon'
  198. size = { 24 }
  199. src = { IconVolumeOff } />
  200. { t('prejoin.joinWithoutAudio') }
  201. </div>
  202. <div
  203. className = 'prejoin-preview-dropdown-btn'
  204. onClick = { _showDialog }>
  205. <Icon
  206. className = 'prejoin-preview-dropdown-icon'
  207. size = { 24 }
  208. src = { IconPhone } />
  209. { t('prejoin.joinAudioByPhone') }
  210. </div>
  211. </div> }
  212. isOpen = { showJoinByPhoneButtons }
  213. onClose = { _onDropdownClose }>
  214. <ActionButton
  215. hasOptions = { hasJoinByPhoneButtons }
  216. onClick = { joinConference }
  217. onOptionsClick = { _onOptionsClick }
  218. type = 'primary'>
  219. { t('prejoin.joinMeeting') }
  220. </ActionButton>
  221. </InlineDialog>
  222. </div>
  223. <div className = 'prejoin-preview-btn-container'>
  224. <AudioSettingsButton visible = { true } />
  225. <VideoSettingsButton visible = { true } />
  226. </div>
  227. </div>
  228. <div className = 'prejoin-checkbox-container'>
  229. <input
  230. className = 'prejoin-checkbox'
  231. onChange = { _onCheckboxChange }
  232. type = 'checkbox' />
  233. <span>{t('prejoin.doNotShow')}</span>
  234. </div>
  235. </div>
  236. { deviceStatusVisible && <DeviceStatus /> }
  237. </div>
  238. );
  239. }
  240. }
  241. /**
  242. * Maps (parts of) the redux state to the React {@code Component} props.
  243. *
  244. * @param {Object} state - The redux state.
  245. * @returns {Object}
  246. */
  247. function mapStateToProps(state): Object {
  248. return {
  249. isAnonymousUser: isGuest(state),
  250. deviceStatusVisible: isDeviceStatusVisible(state),
  251. name: getDisplayName(state),
  252. roomName: getRoomName(state),
  253. showDialog: isJoinByPhoneDialogVisible(state),
  254. hasJoinByPhoneButtons: areJoinByPhoneButtonsVisible(state)
  255. };
  256. }
  257. const mapDispatchToProps = {
  258. joinConferenceWithoutAudio: joinConferenceWithoutAudioAction,
  259. joinConference: joinConferenceAction,
  260. setJoinByPhoneDialogVisiblity: setJoinByPhoneDialogVisiblityAction,
  261. setSkipPrejoin: setSkipPrejoinAction,
  262. updateSettings
  263. };
  264. export default connect(mapStateToProps, mapDispatchToProps)(translate(Prejoin));