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

Prejoin.native.tsx 7.3KB

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