Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

LobbyScreen.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // @flow
  2. import React from 'react';
  3. import { Text, View, TouchableOpacity, TextInput } from 'react-native';
  4. import { SafeAreaView } from 'react-native-safe-area-context';
  5. import { Avatar } from '../../../base/avatar';
  6. import { translate } from '../../../base/i18n';
  7. import { Icon, IconEdit } from '../../../base/icons';
  8. import JitsiScreen from '../../../base/modal/components/JitsiScreen';
  9. import { LoadingIndicator } from '../../../base/react';
  10. import { connect } from '../../../base/redux';
  11. import AbstractLobbyScreen, { _mapStateToProps } from '../AbstractLobbyScreen';
  12. import styles from './styles';
  13. /**
  14. * Implements a waiting screen that represents the participant being in the lobby.
  15. */
  16. class LobbyScreen extends AbstractLobbyScreen {
  17. /**
  18. * Implements {@code PureComponent#render}.
  19. *
  20. * @inheritdoc
  21. */
  22. render() {
  23. const { _meetingName, t } = this.props;
  24. return (
  25. <JitsiScreen
  26. hasTabNavigator = { false }
  27. style = { styles.contentWrapper }>
  28. <SafeAreaView>
  29. <Text style = { styles.dialogTitle }>
  30. { t(this._getScreenTitleKey()) }
  31. </Text>
  32. <Text style = { styles.secondaryText }>
  33. { _meetingName }
  34. </Text>
  35. { this._renderContent() }
  36. </SafeAreaView>
  37. </JitsiScreen>
  38. );
  39. }
  40. _getScreenTitleKey: () => string;
  41. _onAskToJoin: () => void;
  42. _onCancel: () => boolean;
  43. _onChangeDisplayName: Object => void;
  44. _onChangeEmail: Object => void;
  45. _onChangePassword: Object => void;
  46. _onEnableEdit: () => void;
  47. _onJoinWithPassword: () => void;
  48. _onSwitchToKnockMode: () => void;
  49. _onSwitchToPasswordMode: () => void;
  50. _renderContent: () => React$Element<*>;
  51. /**
  52. * Renders the joining (waiting) fragment of the screen.
  53. *
  54. * @inheritdoc
  55. */
  56. _renderJoining() {
  57. return (
  58. <>
  59. <LoadingIndicator
  60. color = 'black'
  61. style = { styles.loadingIndicator } />
  62. <Text style = { styles.joiningMessage }>
  63. { this.props.t('lobby.joiningMessage') }
  64. </Text>
  65. { this._renderStandardButtons() }
  66. </>
  67. );
  68. }
  69. /**
  70. * Renders the participant form to let the knocking participant enter its details.
  71. *
  72. * @inheritdoc
  73. */
  74. _renderParticipantForm() {
  75. const { t } = this.props;
  76. const { displayName, email } = this.state;
  77. return (
  78. <View style = { styles.formWrapper }>
  79. <Text style = { styles.fieldLabel }>
  80. { t('lobby.nameField') }
  81. </Text>
  82. <TextInput
  83. onChangeText = { this._onChangeDisplayName }
  84. style = { styles.field }
  85. value = { displayName } />
  86. <Text style = { styles.fieldLabel }>
  87. { t('lobby.emailField') }
  88. </Text>
  89. <TextInput
  90. onChangeText = { this._onChangeEmail }
  91. style = { styles.field }
  92. value = { email } />
  93. </View>
  94. );
  95. }
  96. /**
  97. * Renders the participant info fragment when we have all the required details of the user.
  98. *
  99. * @inheritdoc
  100. */
  101. _renderParticipantInfo() {
  102. const { displayName, email } = this.state;
  103. return (
  104. <View style = { styles.participantBox }>
  105. <TouchableOpacity
  106. onPress = { this._onEnableEdit }
  107. style = { styles.editButton }>
  108. <Icon
  109. src = { IconEdit }
  110. style = { styles.editIcon } />
  111. </TouchableOpacity>
  112. <Avatar
  113. participantId = { this.props._participantId }
  114. size = { 64 } />
  115. <Text style = { styles.displayNameText }>
  116. { displayName }
  117. </Text>
  118. { Boolean(email) && <Text style = { styles.secondaryText }>
  119. { email }
  120. </Text> }
  121. </View>
  122. );
  123. }
  124. /**
  125. * Renders the password form to let the participant join by using a password instead of knocking.
  126. *
  127. * @inheritdoc
  128. */
  129. _renderPasswordForm() {
  130. const { _passwordJoinFailed, t } = this.props;
  131. return (
  132. <View style = { styles.formWrapper }>
  133. <Text style = { styles.fieldLabel }>
  134. { this.props.t('lobby.passwordField') }
  135. </Text>
  136. <TextInput
  137. autoCapitalize = 'none'
  138. autoCompleteType = 'off'
  139. onChangeText = { this._onChangePassword }
  140. secureTextEntry = { true }
  141. style = { styles.field }
  142. value = { this.state.password } />
  143. { _passwordJoinFailed && <Text style = { styles.fieldError }>
  144. { t('lobby.invalidPassword') }
  145. </Text> }
  146. </View>
  147. );
  148. }
  149. /**
  150. * Renders the password join button (set).
  151. *
  152. * @inheritdoc
  153. */
  154. _renderPasswordJoinButtons() {
  155. const { t } = this.props;
  156. return (
  157. <>
  158. <TouchableOpacity
  159. disabled = { !this.state.password }
  160. onPress = { this._onJoinWithPassword }
  161. style = { [
  162. styles.button,
  163. styles.primaryButton
  164. ] }>
  165. <Text style = { styles.primaryButtonText }>
  166. { t('lobby.passwordJoinButton') }
  167. </Text>
  168. </TouchableOpacity>
  169. <TouchableOpacity
  170. onPress = { this._onSwitchToKnockMode }
  171. style = { [
  172. styles.button,
  173. styles.secondaryButton
  174. ] }>
  175. <Text>
  176. { t('lobby.backToKnockModeButton') }
  177. </Text>
  178. </TouchableOpacity>
  179. </>
  180. );
  181. }
  182. /**
  183. * Renders the standard button set.
  184. *
  185. * @inheritdoc
  186. */
  187. _renderStandardButtons() {
  188. const { _knocking, _renderPassword, t } = this.props;
  189. return (
  190. <>
  191. { _knocking || <TouchableOpacity
  192. disabled = { !this.state.displayName }
  193. onPress = { this._onAskToJoin }
  194. style = { [
  195. styles.button,
  196. styles.primaryButton
  197. ] }>
  198. <Text style = { styles.primaryButtonText }>
  199. { t('lobby.knockButton') }
  200. </Text>
  201. </TouchableOpacity> }
  202. { _renderPassword && <TouchableOpacity
  203. onPress = { this._onSwitchToPasswordMode }
  204. style = { [
  205. styles.button,
  206. styles.secondaryButton
  207. ] }>
  208. <Text>
  209. { t('lobby.enterPasswordButton') }
  210. </Text>
  211. </TouchableOpacity> }
  212. <TouchableOpacity
  213. onPress = { this._onCancel }
  214. style = { styles.cancelButton }>
  215. <Text>
  216. { t('dialog.Cancel') }
  217. </Text>
  218. </TouchableOpacity>
  219. </>
  220. );
  221. }
  222. }
  223. export default translate(connect(_mapStateToProps)(LobbyScreen));