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

Prejoin.tsx 7.5KB

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