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

Prejoin.native.tsx 7.2KB

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