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.native.tsx 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /* eslint-disable lines-around-comment */
  2. import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react';
  3. import { useTranslation } from 'react-i18next';
  4. import {
  5. BackHandler,
  6. Platform,
  7. StyleProp,
  8. Text,
  9. TextInput,
  10. TextStyle,
  11. View,
  12. ViewStyle
  13. } from 'react-native';
  14. import { useDispatch, useSelector } from 'react-redux';
  15. // @ts-ignore
  16. import { appNavigate } from '../../app/actions.native';
  17. // @ts-ignore
  18. import { setAudioOnly } from '../../base/audio-only/actions';
  19. // @ts-ignore
  20. import { getConferenceName } from '../../base/conference/functions';
  21. // @ts-ignore
  22. import { connect } from '../../base/connection/actions.native';
  23. import { IconClose } from '../../base/icons/svg/index';
  24. // @ts-ignore
  25. import JitsiScreen from '../../base/modal/components/JitsiScreen';
  26. import { getLocalParticipant } from '../../base/participants/functions';
  27. // @ts-ignore
  28. import { getFieldValue } from '../../base/react';
  29. // @ts-ignore
  30. import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui';
  31. // @ts-ignore
  32. import { updateSettings } from '../../base/settings';
  33. // @ts-ignore
  34. import BaseTheme from '../../base/ui/components/BaseTheme.native';
  35. import Button from '../../base/ui/components/native/Button';
  36. import { BUTTON_TYPES } from '../../base/ui/constants';
  37. import { BrandingImageBackground } from '../../dynamic-branding';
  38. // @ts-ignore
  39. import { LargeVideo } from '../../large-video/components';
  40. // @ts-ignore
  41. import HeaderNavigationButton from '../../mobile/navigation/components/HeaderNavigationButton';
  42. // @ts-ignore
  43. import { navigateRoot } from '../../mobile/navigation/rootNavigationContainerRef';
  44. // @ts-ignore
  45. import { screen } from '../../mobile/navigation/routes';
  46. // @ts-ignore
  47. import AudioMuteButton from '../../toolbox/components/AudioMuteButton';
  48. // @ts-ignore
  49. import VideoMuteButton from '../../toolbox/components/VideoMuteButton';
  50. // @ts-ignore
  51. import { isDisplayNameRequired } from '../functions';
  52. import { PrejoinProps } from '../types';
  53. // @ts-ignore
  54. import styles from './styles';
  55. const Prejoin: React.FC<PrejoinProps> = ({ navigation }: PrejoinProps) => {
  56. const dispatch = useDispatch();
  57. const { t } = useTranslation();
  58. const aspectRatio = useSelector(
  59. (state: any) => state['features/base/responsive-ui']?.aspectRatio
  60. );
  61. const localParticipant = useSelector((state: any) => getLocalParticipant(state));
  62. const isDisplayNameMandatory = useSelector(state => isDisplayNameRequired(state));
  63. const roomName = useSelector(state => getConferenceName(state));
  64. const participantName = localParticipant?.name;
  65. const [ displayName, setDisplayName ]
  66. = useState(participantName || '');
  67. const onChangeDisplayName = useCallback(event => {
  68. const fieldValue = getFieldValue(event);
  69. setDisplayName(fieldValue);
  70. dispatch(updateSettings({
  71. displayName: fieldValue
  72. }));
  73. }, [ displayName ]);
  74. const onJoin = useCallback(() => {
  75. dispatch(connect());
  76. navigateRoot(screen.conference.root);
  77. }, [ dispatch ]);
  78. const onJoinLowBandwidth = useCallback(() => {
  79. dispatch(setAudioOnly(true));
  80. onJoin();
  81. }, [ dispatch ]);
  82. const goBack = useCallback(() => {
  83. dispatch(appNavigate(undefined));
  84. return true;
  85. }, [ dispatch ]);
  86. const headerLeft = useCallback(() => {
  87. if (Platform.OS === 'ios') {
  88. return (
  89. <HeaderNavigationButton
  90. label = { t('dialog.close') }
  91. onPress = { goBack } />
  92. );
  93. }
  94. return (
  95. <HeaderNavigationButton
  96. onPress = { goBack }
  97. src = { IconClose } />
  98. );
  99. }, []);
  100. const { PRIMARY, SECONDARY } = BUTTON_TYPES;
  101. const joinButtonDisabled = !displayName && isDisplayNameMandatory;
  102. useEffect(() => {
  103. BackHandler.addEventListener('hardwareBackPress', goBack);
  104. return () => BackHandler.removeEventListener('hardwareBackPress', goBack);
  105. }, []);
  106. useLayoutEffect(() => {
  107. navigation.setOptions({
  108. headerLeft
  109. });
  110. }, [ navigation ]);
  111. let contentWrapperStyles;
  112. let contentContainerStyles;
  113. let largeVideoContainerStyles;
  114. let toolboxContainerStyles;
  115. if (aspectRatio === ASPECT_RATIO_NARROW) {
  116. contentWrapperStyles = styles.contentWrapper;
  117. contentContainerStyles = styles.contentContainer;
  118. largeVideoContainerStyles = styles.largeVideoContainer;
  119. toolboxContainerStyles = styles.toolboxContainer;
  120. } else {
  121. contentWrapperStyles = styles.contentWrapperWide;
  122. contentContainerStyles = styles.contentContainerWide;
  123. largeVideoContainerStyles = styles.largeVideoContainerWide;
  124. toolboxContainerStyles = styles.toolboxContainerWide;
  125. }
  126. return (
  127. <JitsiScreen
  128. safeAreaInsets = { [ 'left' ] }
  129. style = { contentWrapperStyles }>
  130. <BrandingImageBackground />
  131. <View style = { largeVideoContainerStyles }>
  132. <LargeVideo />
  133. </View>
  134. <View style = { contentContainerStyles }>
  135. <View style = { styles.formWrapper as StyleProp<ViewStyle> }>
  136. <Text style = { styles.preJoinTitle as StyleProp<TextStyle> }>
  137. { t('prejoin.joinMeeting') }
  138. </Text>
  139. <Text
  140. numberOfLines = { 1 }
  141. style = { styles.preJoinRoomName as StyleProp<TextStyle> }>
  142. { roomName }
  143. </Text>
  144. <TextInput
  145. onChangeText = { onChangeDisplayName }
  146. placeholder = { t('dialog.enterDisplayName') }
  147. placeholderTextColor = { BaseTheme.palette.text03 }
  148. style = { styles.field as StyleProp<TextStyle> }
  149. value = { displayName } />
  150. <Button
  151. accessibilityLabel = 'prejoin.joinMeeting'
  152. disabled = { joinButtonDisabled }
  153. labelKey = 'prejoin.joinMeeting'
  154. onClick = { onJoin }
  155. style = { styles.prejoinButton }
  156. type = { PRIMARY } />
  157. <Button
  158. accessibilityLabel = 'prejoin.joinMeetingInLowBandwidthMode'
  159. labelKey = 'prejoin.joinMeetingInLowBandwidthMode'
  160. onClick = { onJoinLowBandwidth }
  161. style = { styles.prejoinButton }
  162. type = { SECONDARY } />
  163. </View>
  164. <View style = { toolboxContainerStyles }>
  165. <AudioMuteButton
  166. styles = { styles.buttonStylesBorderless } />
  167. <VideoMuteButton
  168. styles = { styles.buttonStylesBorderless } />
  169. </View>
  170. </View>
  171. </JitsiScreen>
  172. );
  173. };
  174. export default Prejoin;