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.tsx 7.2KB

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