Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

Prejoin.tsx 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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 { PREJOIN_PAGE_HIDE_DISPLAY_NAME } from '../../../base/flags/constants';
  21. import { getFeatureFlag } from '../../../base/flags/functions';
  22. import { IconCloseLarge } from '../../../base/icons/svg';
  23. // @ts-ignore
  24. import JitsiScreen from '../../../base/modal/components/JitsiScreen';
  25. import { getLocalParticipant } from '../../../base/participants/functions';
  26. import { getFieldValue } from '../../../base/react/functions';
  27. import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
  28. import { updateSettings } from '../../../base/settings/actions';
  29. import Button from '../../../base/ui/components/native/Button';
  30. import Input from '../../../base/ui/components/native/Input';
  31. import { BUTTON_TYPES } from '../../../base/ui/constants.native';
  32. import BrandingImageBackground from '../../../dynamic-branding/components/native/BrandingImageBackground';
  33. // @ts-ignore
  34. import LargeVideo from '../../../large-video/components/LargeVideo.native';
  35. // @ts-ignore
  36. import HeaderNavigationButton from '../../../mobile/navigation/components/HeaderNavigationButton';
  37. // @ts-ignore
  38. import { navigateRoot } from '../../../mobile/navigation/rootNavigationContainerRef';
  39. // @ts-ignore
  40. import { screen } from '../../../mobile/navigation/routes';
  41. // @ts-ignore
  42. import AudioMuteButton from '../../../toolbox/components/AudioMuteButton';
  43. // @ts-ignore
  44. import VideoMuteButton from '../../../toolbox/components/VideoMuteButton';
  45. import { isDisplayNameRequired } from '../../functions';
  46. import { IPrejoinProps } from '../../types';
  47. // @ts-ignore
  48. import { preJoinStyles as styles } from './styles';
  49. const Prejoin: React.FC<IPrejoinProps> = ({ navigation }: IPrejoinProps) => {
  50. const dispatch = useDispatch();
  51. const isFocused = useIsFocused();
  52. const { t } = useTranslation();
  53. const aspectRatio = useSelector(
  54. (state: IReduxState) => state['features/base/responsive-ui']?.aspectRatio
  55. );
  56. const localParticipant = useSelector((state: IReduxState) => getLocalParticipant(state));
  57. const isDisplayNameMandatory = useSelector((state: IReduxState) => isDisplayNameRequired(state));
  58. const isDisplayNameVisible
  59. = useSelector((state: IReduxState) => !getFeatureFlag(state, PREJOIN_PAGE_HIDE_DISPLAY_NAME, false));
  60. const roomName = useSelector((state: IReduxState) => getConferenceName(state));
  61. const participantName = localParticipant?.name;
  62. const [ displayName, setDisplayName ]
  63. = useState(participantName || '');
  64. const [ isJoining, setIsJoining ]
  65. = useState(false);
  66. const onChangeDisplayName = useCallback(event => {
  67. const fieldValue = getFieldValue(event);
  68. setDisplayName(fieldValue);
  69. dispatch(updateSettings({
  70. displayName: fieldValue
  71. }));
  72. }, [ displayName ]);
  73. const onJoin = useCallback(() => {
  74. setIsJoining(true);
  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 = () => {
  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 = { IconCloseLarge } />
  98. );
  99. };
  100. const { PRIMARY, TERTIARY } = 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. headerTitle: t('prejoin.joinMeeting')
  110. });
  111. }, [ navigation ]);
  112. let contentWrapperStyles;
  113. let contentContainerStyles;
  114. let largeVideoContainerStyles;
  115. if (aspectRatio === ASPECT_RATIO_NARROW) {
  116. contentWrapperStyles = styles.contentWrapper;
  117. contentContainerStyles = styles.contentContainer;
  118. largeVideoContainerStyles = styles.largeVideoContainer;
  119. } else {
  120. contentWrapperStyles = styles.contentWrapperWide;
  121. contentContainerStyles = styles.contentContainerWide;
  122. largeVideoContainerStyles = styles.largeVideoContainerWide;
  123. }
  124. return (
  125. <JitsiScreen
  126. addBottomPadding = { false }
  127. safeAreaInsets = { [ 'right' ] }
  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. {/* @ts-ignore */}
  141. <LargeVideo />
  142. </View>
  143. }
  144. <View style = { contentContainerStyles }>
  145. <View style = { styles.toolboxContainer }>
  146. <AudioMuteButton
  147. // @ts-ignore
  148. styles = { styles.buttonStylesBorderless } />
  149. <VideoMuteButton
  150. // @ts-ignore
  151. styles = { styles.buttonStylesBorderless } />
  152. </View>
  153. {
  154. isDisplayNameVisible
  155. && <Input
  156. // @ts-ignore
  157. customStyles = {{ input: styles.customInput }}
  158. onChange = { onChangeDisplayName }
  159. placeholder = { t('dialog.enterDisplayName') }
  160. value = { displayName } />
  161. }
  162. <Button
  163. accessibilityLabel = 'prejoin.joinMeeting'
  164. disabled = { joinButtonDisabled }
  165. labelKey = 'prejoin.joinMeeting'
  166. // @ts-ignore
  167. onClick = { !isJoining && onJoin }
  168. style = { styles.joinButton }
  169. type = { PRIMARY } />
  170. <Button
  171. accessibilityLabel = 'prejoin.joinMeetingInLowBandwidthMode'
  172. disabled = { joinButtonDisabled }
  173. labelKey = 'prejoin.joinMeetingInLowBandwidthMode'
  174. onClick = { onJoinLowBandwidth }
  175. style = { styles.joinButton }
  176. type = { TERTIARY } />
  177. </View>
  178. </JitsiScreen>
  179. );
  180. };
  181. export default Prejoin;