agora-appbuilder-core 4.1.7-beta.8 → 4.1.8-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/package.json +1 -1
  2. package/template/_package-lock.json +30671 -5376
  3. package/template/defaultConfig.js +2 -2
  4. package/template/esbuild.rsdk.go +1 -2
  5. package/template/package.json +0 -1
  6. package/template/src/AppWrapper.tsx +30 -35
  7. package/template/src/auth/AuthProvider.tsx +28 -35
  8. package/template/src/auth/IDPAuth.tsx +1 -14
  9. package/template/src/components/Controls.tsx +45 -15
  10. package/template/src/components/common/GenericModal.tsx +143 -0
  11. package/template/src/components/common/GenericPopup.tsx +152 -0
  12. package/template/src/components/common/data-table.tsx +385 -0
  13. package/template/src/components/controls/useControlPermissionMatrix.tsx +6 -7
  14. package/template/src/components/precall/usePreCall.tsx +1 -2
  15. package/template/src/components/stt-transcript/STTTranscriptTable.tsx +295 -0
  16. package/template/src/components/stt-transcript/ViewSTTTranscriptModal.tsx +44 -0
  17. package/template/src/components/stt-transcript/useFetchSTTTranscript.tsx +193 -0
  18. package/template/src/components/useUserPreference.tsx +0 -11
  19. package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -0
  20. package/template/src/logger/AppBuilderLogger.tsx +1 -0
  21. package/template/src/pages/Create.tsx +2 -2
  22. package/template/src/pages/VideoCall.tsx +0 -5
  23. package/template/src/subComponents/LogoutButton.tsx +1 -11
  24. package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +83 -78
  25. package/template/src/utils/common.tsx +79 -1
  26. package/template/src/utils/useCreateRoom.ts +94 -112
  27. package/template/src/utils/useEndCall.ts +16 -3
  28. package/template/src/utils/useGetMeetingPhrase.ts +67 -76
  29. package/template/src/utils/useJoinRoom.ts +0 -3
  30. package/template/src/utils/useMutePSTN.ts +47 -45
  31. package/template/webpack.rsdk.config.js +1 -2
  32. package/template/src/components/GraphQLProvider.tsx +0 -122
@@ -77,8 +77,8 @@ const DefaultConfig = {
77
77
  CHAT_ORG_NAME: '',
78
78
  CHAT_APP_NAME: '',
79
79
  CHAT_URL: '',
80
- CLI_VERSION: '3.1.7-beta.8',
81
- CORE_VERSION: '4.1.7-beta.8',
80
+ CLI_VERSION: '3.1.8-beta.1',
81
+ CORE_VERSION: '4.1.8-beta.1',
82
82
  DISABLE_LANDSCAPE_MODE: false,
83
83
  STT_AUTO_START: false,
84
84
  CLOUD_RECORDING_AUTO_START: false,
@@ -180,8 +180,7 @@ func rsdk(iopath *ioPaths) api.BuildResult {
180
180
  "react",
181
181
  "react-dom",
182
182
  "react-router",
183
- "react-router-dom",
184
- "@apollo/client",
183
+ "react-router-dom",
185
184
  },
186
185
  Define: commonBuildOpts.Define,
187
186
  Inject: commonBuildOpts.Inject,
@@ -48,7 +48,6 @@
48
48
  "url": "https://github.com/AgoraIO-Community/app-builder-core"
49
49
  },
50
50
  "dependencies": {
51
- "@apollo/client": "3.8.1",
52
51
  "@datadog/browser-logs": "^5.15.0",
53
52
  "@datadog/mobile-react-native": "^2.3.2",
54
53
  "@gorhom/bottom-sheet": "4.4.7",
@@ -13,7 +13,6 @@ import React, {useContext} from 'react';
13
13
  import {Router} from './components/Router';
14
14
  import Navigation from './components/Navigation';
15
15
  import {StorageProvider} from './components/StorageContext';
16
- import GraphQLProvider from './components/GraphQLProvider';
17
16
  import {SessionProvider} from './components/SessionContext';
18
17
  import {
19
18
  ImageBackground,
@@ -89,40 +88,36 @@ const AppWrapper = (props: AppWrapperProps) => {
89
88
  {$config.DISABLE_LANDSCAPE_MODE && <BlockUI />}
90
89
  <StorageProvider>
91
90
  <LanguageProvider>
92
- <GraphQLProvider>
93
- <Router
94
- /*@ts-ignore Router will be memory Router in sdk*/
95
- initialEntries={[
96
- //@ts-ignore
97
- isSDK && SdkJoinState.phrase
98
- ? //@ts-ignore
99
- `/${SdkJoinState.phrase}`
100
- : '',
101
- ]}>
102
- <ToastProvider>
103
- <ToastContext.Consumer>
104
- {({isActionSheetVisible}) => {
105
- return !isActionSheetVisible ? (
106
- <ToastComponent />
107
- ) : null;
108
- }}
109
- </ToastContext.Consumer>
110
- <AuthProvider>
111
- <SessionProvider>
112
- <ColorConfigure>
113
- <DimensionProvider>
114
- <ErrorProvider>
115
- <Error />
116
- <Navigation />
117
- {props.children}
118
- </ErrorProvider>
119
- </DimensionProvider>
120
- </ColorConfigure>
121
- </SessionProvider>
122
- </AuthProvider>
123
- </ToastProvider>
124
- </Router>
125
- </GraphQLProvider>
91
+ <Router
92
+ /*@ts-ignore Router will be memory Router in sdk*/
93
+ initialEntries={[
94
+ //@ts-ignore
95
+ isSDK && SdkJoinState.phrase
96
+ ? //@ts-ignore
97
+ `/${SdkJoinState.phrase}`
98
+ : '',
99
+ ]}>
100
+ <ToastProvider>
101
+ <ToastContext.Consumer>
102
+ {({isActionSheetVisible}) => {
103
+ return !isActionSheetVisible ? <ToastComponent /> : null;
104
+ }}
105
+ </ToastContext.Consumer>
106
+ <AuthProvider>
107
+ <SessionProvider>
108
+ <ColorConfigure>
109
+ <DimensionProvider>
110
+ <ErrorProvider>
111
+ <Error />
112
+ <Navigation />
113
+ {props.children}
114
+ </ErrorProvider>
115
+ </DimensionProvider>
116
+ </ColorConfigure>
117
+ </SessionProvider>
118
+ </AuthProvider>
119
+ </ToastProvider>
120
+ </Router>
126
121
  </LanguageProvider>
127
122
  </StorageProvider>
128
123
  </SafeAreaView>
@@ -8,7 +8,6 @@ import React, {
8
8
  useRef,
9
9
  } from 'react';
10
10
  import {useHistory, useLocation} from '../components/Router';
11
- import {gql, useApolloClient} from '@apollo/client';
12
11
  import {useIDPAuth} from './useIDPAuth';
13
12
  import Loading from '../subComponents/Loading';
14
13
  import useTokenAuth from './useTokenAuth';
@@ -45,14 +44,7 @@ import LocalEventEmitter, {
45
44
  LocalEventsEnum,
46
45
  } from '../rtm-events-api/LocalEvents';
47
46
 
48
- export const GET_USER = gql`
49
- query getUser {
50
- getUser {
51
- name
52
- email
53
- }
54
- }
55
- `;
47
+ const GET_USER_URL = `${$config.BACKEND_ENDPOINT}/v1/user/details`;
56
48
 
57
49
  type AuthProviderProps = {
58
50
  enableAuth?: boolean;
@@ -87,7 +79,6 @@ const AuthProvider = (props: AuthProviderProps) => {
87
79
  const history = useHistory();
88
80
  const location = useLocation();
89
81
  // client
90
- const apolloClient = useApolloClient();
91
82
  const {isRecordingBot} = useIsRecordingBot();
92
83
  const indexesOf = (arr, item) =>
93
84
  arr.reduce((acc, v, i) => (v === item && acc.push(i), acc), []);
@@ -324,44 +315,47 @@ const AuthProvider = (props: AuthProviderProps) => {
324
315
  async function getUserDetails() {
325
316
  const requestId = getUniqueID();
326
317
  const startReqTs = Date.now();
318
+ //fetch user details
319
+ logger.log(
320
+ LogSource.NetworkRest,
321
+ 'user_details',
322
+ 'API fetching user_details, to check if user is authenticated',
323
+ {
324
+ requestId,
325
+ startReqTs,
326
+ },
327
+ );
328
+ const token = store?.token;
327
329
  try {
328
- //fetch user details
329
- logger.log(
330
- LogSource.NetworkRest,
331
- 'user_details',
332
- 'API fetching user_details, to check if user is authenticated',
333
- {
334
- requestId,
335
- startReqTs,
336
- },
337
- );
338
- const token = store?.token;
339
- const res = await apolloClient.query({
340
- query: GET_USER,
341
- fetchPolicy: 'network-only',
342
- context: {
343
- headers: {
344
- 'X-Request-Id': requestId,
345
- 'X-Session-Id': logger.getSessionId(),
346
- ...(token && {
347
- authorization: token ? `Bearer ${token}` : '',
348
- }),
349
- },
330
+ const res = await fetch(`${GET_USER_URL}`, {
331
+ method: 'POST',
332
+ headers: {
333
+ 'Content-Type': 'application/json',
334
+ 'X-Request-Id': requestId,
335
+ 'X-Session-Id': logger.getSessionId(),
336
+ ...(token && {
337
+ authorization: token ? `Bearer ${token}` : '',
338
+ }),
350
339
  },
351
340
  });
341
+ const response = await res.json();
342
+ if (response?.error) {
343
+ throw response?.error;
344
+ }
352
345
  const endRequestTs = Date.now();
353
346
  logger.log(
354
347
  LogSource.NetworkRest,
355
348
  'user_details',
356
349
  'API user_details query succesful. User is authenticated',
357
350
  {
358
- responseData: res,
351
+ responseData: response,
359
352
  startReqTs,
360
353
  endRequestTs,
361
354
  latency: endRequestTs - startReqTs,
362
355
  requestId,
363
356
  },
364
357
  );
358
+ setLoading(false);
365
359
  } catch (error) {
366
360
  const endRequestTs = Date.now();
367
361
  logger.log(
@@ -376,9 +370,8 @@ const AuthProvider = (props: AuthProviderProps) => {
376
370
  requestId,
377
371
  },
378
372
  );
379
- throw new Error(error);
380
- } finally {
381
373
  setLoading(false);
374
+ throw new Error(error);
382
375
  }
383
376
  }
384
377
 
@@ -1,8 +1,7 @@
1
1
  import React, {useEffect} from 'react';
2
- import {GET_USER, useAuth} from './AuthProvider';
2
+ import {useAuth} from './AuthProvider';
3
3
  import {useHistory, useParams} from '../components/Router';
4
4
  import Loading from '../subComponents/Loading';
5
- import {useApolloClient} from '@apollo/client';
6
5
  import Toast from '../../react-native-toast-message';
7
6
  import {getParamFromURL} from '../utils/common';
8
7
  import useTokenAuth from './useTokenAuth';
@@ -20,20 +19,8 @@ export const IDPAuth = () => {
20
19
  const history = useHistory();
21
20
  const {token: returnTo}: {token: string} = useParams();
22
21
  //token used as returnTo and webToken is sent on the token query param
23
- const apolloClient = useApolloClient();
24
22
  const {enableTokenAuth} = useTokenAuth();
25
23
 
26
- async function getUserDetails() {
27
- try {
28
- await apolloClient.query({
29
- query: GET_USER,
30
- fetchPolicy: 'network-only',
31
- });
32
- } catch (error) {
33
- throw error;
34
- }
35
- }
36
-
37
24
  useEffect(() => {
38
25
  const token = getParamFromURL(history.location.search, 'token');
39
26
  if (token) {
@@ -103,6 +103,7 @@ import {
103
103
  toolbarItemTranscriptText,
104
104
  toolbarItemVirtualBackgroundText,
105
105
  toolbarItemWhiteboardText,
106
+ toolbarItemManageTranscriptText,
106
107
  } from '../language/default-labels/videoCallScreenLabels';
107
108
  import {LogSource, logger} from '../logger/AppBuilderLogger';
108
109
  import {useModal} from '../utils/useModal';
@@ -115,6 +116,7 @@ import {
115
116
  InviteToolbarItem,
116
117
  ScreenshareToolbarItem,
117
118
  } from './controls/toolbar-items';
119
+ import ViewSTTTranscriptModal from './stt-transcript/ViewSTTTranscriptModal';
118
120
 
119
121
  export const useToggleWhiteboard = () => {
120
122
  const {
@@ -276,6 +278,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
276
278
  const viewRecordingsLabel = useString<boolean>(
277
279
  toolbarItemViewRecordingText,
278
280
  )();
281
+ const viewSTTLabel = useString<boolean>(toolbarItemManageTranscriptText)();
279
282
  const moreButtonLabel = useString(toolbarItemMoreText)();
280
283
  const virtualBackgroundLabel = useString(toolbarItemVirtualBackgroundText)();
281
284
  const chatLabel = useString(toolbarItemChatText)();
@@ -293,6 +296,11 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
293
296
  setModalOpen: setVRModalOpen,
294
297
  toggle: toggleVRModal,
295
298
  } = useModal();
299
+ const {
300
+ modalOpen: isSTTTranscriptModalOpen,
301
+ setModalOpen: setSTTTranscriptModalOpen,
302
+ toggle: toggleSTTTranscriptModal,
303
+ } = useModal();
296
304
  const moreBtnRef = useRef(null);
297
305
  const {width: globalWidth, height: globalHeight} = useWindowDimensions();
298
306
  const layouts = useLayoutsData();
@@ -330,7 +338,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
330
338
 
331
339
  const {isNoiseSupressionEnabled, setNoiseSupression} = useNoiseSupression();
332
340
 
333
- //AINS
341
+ //0. AINS
334
342
  if ($config.ENABLE_NOISE_CANCELLATION) {
335
343
  actionMenuitems.push({
336
344
  componentName: 'noise-cancellation',
@@ -354,7 +362,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
354
362
  }
355
363
  //AINS
356
364
 
357
- //virtual background
365
+ //1. virtual background
358
366
  const {isVBActive, setIsVBActive} = useVB();
359
367
 
360
368
  const toggleVB = () => {
@@ -385,7 +393,6 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
385
393
  //virtual background
386
394
 
387
395
  //whiteboard start
388
-
389
396
  const {
390
397
  whiteboardRoomState,
391
398
  whiteboardActive,
@@ -472,8 +479,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
472
479
  ? true
473
480
  : false;
474
481
 
475
- //whiteboard ends
476
-
482
+ // 2. whiteboard ends
477
483
  if (isHost && $config.ENABLE_WHITEBOARD && isWebInternal()) {
478
484
  actionMenuitems.push({
479
485
  componentName: 'whiteboard',
@@ -515,8 +521,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
515
521
  });
516
522
  }
517
523
 
518
- // host can see stt options and attendee can view only when stt is enabled by a host in the channel
519
-
524
+ // 3. host can see stt options and attendee can view only when stt is enabled by a host in the channel
520
525
  if ($config.ENABLE_STT && $config.ENABLE_CAPTION) {
521
526
  actionMenuitems.push({
522
527
  componentName: 'caption',
@@ -546,7 +551,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
546
551
  }
547
552
  },
548
553
  });
549
-
554
+ // 4. Meeting transcript
550
555
  if ($config.ENABLE_MEETING_TRANSCRIPT) {
551
556
  actionMenuitems.push({
552
557
  componentName: 'transcript',
@@ -583,8 +588,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
583
588
  }
584
589
  }
585
590
 
586
- // view recordings
587
-
591
+ // 5. view recordings
588
592
  if (isHost && $config.CLOUD_RECORDING && isWeb()) {
589
593
  actionMenuitems.push({
590
594
  componentName: 'view-recordings',
@@ -599,7 +603,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
599
603
  });
600
604
  }
601
605
 
602
- // Particpants
606
+ // 6. Particpants
603
607
  const canAccessParticipants =
604
608
  useControlPermissionMatrix('participantControl');
605
609
  if (canAccessParticipants) {
@@ -619,7 +623,8 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
619
623
  },
620
624
  });
621
625
  }
622
- // Chat
626
+
627
+ // 7. Chat
623
628
  const canAccessChat = useControlPermissionMatrix('chatControl');
624
629
  if (canAccessChat) {
625
630
  //disable chat button when BE sends error on chat
@@ -669,7 +674,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
669
674
  });
670
675
  }
671
676
 
672
- // Screenshare
677
+ // 8. Screenshare
673
678
  const canAccessScreenshare = useControlPermissionMatrix('screenshareControl');
674
679
  if (canAccessScreenshare) {
675
680
  if (
@@ -706,6 +711,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
706
711
  }
707
712
  }
708
713
 
714
+ // 9. Recording
709
715
  if (isHost && $config.CLOUD_RECORDING) {
710
716
  actionMenuitems.push({
711
717
  hide: w => {
@@ -733,6 +739,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
733
739
  });
734
740
  }
735
741
 
742
+ // 10. layout
736
743
  actionMenuitems.push({
737
744
  hide: w => {
738
745
  return w >= BREAKPOINTS.lg ? true : false;
@@ -767,7 +774,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
767
774
  ),
768
775
  });
769
776
 
770
- // Invite
777
+ // 11. Invite
771
778
  const canAccessInvite = useControlPermissionMatrix('inviteControl');
772
779
  if (canAccessInvite) {
773
780
  actionMenuitems.push({
@@ -787,7 +794,7 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
787
794
  });
788
795
  }
789
796
 
790
- // Settings
797
+ // 12.Settings
791
798
  const canAccessSettings = useControlPermissionMatrix('settingsControl');
792
799
  if (canAccessSettings) {
793
800
  actionMenuitems.push({
@@ -807,6 +814,24 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
807
814
  });
808
815
  }
809
816
 
817
+ // 13. Transcripts to download
818
+ const canAccessAllTranscripts =
819
+ useControlPermissionMatrix('viewAllTranscripts');
820
+
821
+ if (canAccessAllTranscripts) {
822
+ actionMenuitems.push({
823
+ componentName: 'view-all-transcripts',
824
+ order: 13,
825
+ icon: 'transcript',
826
+ iconColor: $config.SECONDARY_ACTION_COLOR,
827
+ textColor: $config.FONT_COLOR,
828
+ title: viewSTTLabel,
829
+ onPress: () => {
830
+ toggleSTTTranscriptModal();
831
+ },
832
+ });
833
+ }
834
+
810
835
  useEffect(() => {
811
836
  if (isHovered) {
812
837
  setActionMenuVisible(true);
@@ -953,6 +978,11 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
953
978
  )}
954
979
  </>
955
980
  )}
981
+ {canAccessAllTranscripts && isSTTTranscriptModalOpen ? (
982
+ <ViewSTTTranscriptModal setModalOpen={setSTTTranscriptModalOpen} />
983
+ ) : (
984
+ <></>
985
+ )}
956
986
  <ActionMenu
957
987
  containerStyle={globalWidth < 720 ? {width: 180} : {width: 260}}
958
988
  hoverMode={true}
@@ -0,0 +1,143 @@
1
+ import {
2
+ StyleSheet,
3
+ Text,
4
+ View,
5
+ Modal,
6
+ TouchableWithoutFeedback,
7
+ ModalProps,
8
+ ViewStyle,
9
+ } from 'react-native';
10
+ import React from 'react';
11
+ import IconButton from '../../atoms/IconButton';
12
+ import ThemeConfig from '../../theme';
13
+ import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
14
+ import {isMobileUA, useIsDesktop} from '../../utils/common';
15
+
16
+ interface GenericModalProps extends ModalProps {
17
+ title?: string;
18
+ cancelable?: boolean;
19
+ showCloseIcon?: boolean;
20
+ contentContainerStyle?: ViewStyle;
21
+ }
22
+ const GenericModal = (props: GenericModalProps) => {
23
+ const {
24
+ visible,
25
+ onRequestClose,
26
+ title,
27
+ children,
28
+ cancelable = false,
29
+ showCloseIcon = true,
30
+ contentContainerStyle = {},
31
+ ...modalProps
32
+ } = props;
33
+
34
+ const isDesktop = useIsDesktop()('popup');
35
+
36
+ // Fallback Handle close
37
+ const handleClose = () => {
38
+ onRequestClose?.(undefined);
39
+ };
40
+
41
+ return (
42
+ <Modal
43
+ animationType="none"
44
+ transparent={true}
45
+ visible={visible}
46
+ onRequestClose={handleClose}>
47
+ <View style={[styles.centeredView, isDesktop && styles.desktopAlign]}>
48
+ <TouchableWithoutFeedback
49
+ onPress={() => {
50
+ cancelable && handleClose();
51
+ }}>
52
+ <View style={styles.backDrop} />
53
+ </TouchableWithoutFeedback>
54
+ <View style={[styles.modalView, contentContainerStyle]}>
55
+ <View style={styles.header}>
56
+ <Text style={styles.title}>{title}</Text>
57
+ {showCloseIcon && (
58
+ <View>
59
+ <IconButton
60
+ hoverEffect={true}
61
+ hoverEffectStyle={{
62
+ backgroundColor: $config.ICON_BG_COLOR,
63
+ borderRadius: 20,
64
+ }}
65
+ iconProps={{
66
+ iconType: 'plain',
67
+ iconContainerStyle: {
68
+ padding: isMobileUA() ? 0 : 5,
69
+ },
70
+ name: 'close',
71
+ tintColor: $config.SECONDARY_ACTION_COLOR,
72
+ }}
73
+ onPress={handleClose}
74
+ />
75
+ </View>
76
+ )}
77
+ </View>
78
+ {children}
79
+ </View>
80
+ </View>
81
+ </Modal>
82
+ );
83
+ };
84
+
85
+ export default GenericModal;
86
+
87
+ const styles = StyleSheet.create({
88
+ centeredView: {
89
+ flex: 1,
90
+ position: 'relative',
91
+ justifyContent: 'center',
92
+ alignItems: 'center',
93
+ paddingHorizontal: 20,
94
+ },
95
+ desktopAlign: {
96
+ alignItems: 'center',
97
+ },
98
+ modalView: {
99
+ backgroundColor: $config.CARD_LAYER_1_COLOR,
100
+ borderWidth: 1,
101
+ borderColor: $config.CARD_LAYER_3_COLOR,
102
+ borderRadius: ThemeConfig.BorderRadius.large,
103
+ shadowColor: $config.HARD_CODED_BLACK_COLOR,
104
+ shadowOffset: {
105
+ width: 0,
106
+ height: 2,
107
+ },
108
+ shadowOpacity: 0.1,
109
+ shadowRadius: 4,
110
+ elevation: 5,
111
+ maxWidth: 680,
112
+ minWidth: 340,
113
+ height: 620,
114
+ maxHeight: 620,
115
+ zIndex: 2,
116
+ },
117
+ backDrop: {
118
+ zIndex: 1,
119
+ position: 'absolute',
120
+ top: 0,
121
+ bottom: 0,
122
+ left: 0,
123
+ right: 0,
124
+ backgroundColor:
125
+ $config.HARD_CODED_BLACK_COLOR + hexadecimalTransparency['60%'],
126
+ },
127
+ header: {
128
+ flexDirection: 'row',
129
+ justifyContent: 'space-between',
130
+ alignItems: 'flex-start',
131
+ paddingVertical: 12,
132
+ paddingHorizontal: 20,
133
+ width: '100%',
134
+ },
135
+ title: {
136
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.high,
137
+ fontFamily: ThemeConfig.FontFamily.sansPro,
138
+ fontSize: ThemeConfig.FontSize.xLarge,
139
+ lineHeight: 32,
140
+ fontWeight: '500',
141
+ alignSelf: 'center',
142
+ },
143
+ });