-
Notifications
You must be signed in to change notification settings - Fork 88
/
App.tsx
141 lines (131 loc) · 4.09 KB
/
App.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import React, {useContext, useEffect} from 'react';
import {AppLayout} from './screens/AppLayout';
import {useFont} from './shared/hooks/useFont';
import {GlobalContextProvider} from './components/GlobalContextProvider';
import {GlobalContext} from './shared/GlobalContext';
import {useSelector} from '@xstate/react';
import {useTranslation} from 'react-i18next';
import {
APP_EVENTS,
selectIsDecryptError,
selectIsKeyInvalidateError,
selectIsReadError,
selectIsReady,
} from './machines/app';
import {DualMessageOverlay} from './components/DualMessageOverlay';
import {useApp} from './screens/AppController';
import {Alert, AppState} from 'react-native';
import {
configureTelemetry,
getErrorEventData,
sendErrorEvent,
} from './shared/telemetry/TelemetryUtils';
import {TelemetryConstants} from './shared/telemetry/TelemetryConstants';
import {MessageOverlay} from './components/MessageOverlay';
import {NativeModules} from 'react-native';
import {isHardwareKeystoreExists} from './shared/cryptoutil/cryptoUtil';
import i18n from './i18n';
import './shared/flipperConfig';
const {RNSecureKeystoreModule} = NativeModules;
// kludge: this is a bad practice but has been done temporarily to surface
// an occurrence of a bug with minimal residual code changes, this should
// be removed once the bug cause is determined & fixed, ref: INJI-222
const DecryptErrorAlert = (controller, t) => {
const heading = t('errors.decryptionFailed');
const desc = t('errors.decryptionFailed');
const ignoreBtnTxt = t('ignore');
Alert.alert(heading, desc, [
{
text: ignoreBtnTxt,
onPress: () => controller.ignoreDecrypt(),
style: 'cancel',
},
]);
};
const AppLayoutWrapper: React.FC = () => {
const {appService} = useContext(GlobalContext);
const isDecryptError = useSelector(appService, selectIsDecryptError);
const controller = useApp();
const {t} = useTranslation('WelcomeScreen');
useEffect(() => {
if (AppState.currentState === 'active') {
appService.send(APP_EVENTS.ACTIVE());
} else {
appService.send(APP_EVENTS.INACTIVE());
}
}, []);
if (isDecryptError) {
DecryptErrorAlert(controller, t);
}
configureTelemetry();
return <AppLayout />;
};
const AppLoadingWrapper: React.FC = () => {
const {appService} = useContext(GlobalContext);
const isReadError = useSelector(appService, selectIsReadError);
const isKeyInvalidateError = useSelector(
appService,
selectIsKeyInvalidateError,
);
const controller = useApp();
const {t} = useTranslation('WelcomeScreen');
useEffect(() => {
if (isKeyInvalidateError) {
configureTelemetry();
sendErrorEvent(
getErrorEventData(
TelemetryConstants.FlowType.appLogin,
TelemetryConstants.ErrorId.appWasReset,
TelemetryConstants.ErrorMessage.appWasReset,
),
);
}
}, [isKeyInvalidateError]);
return (
<>
<MessageOverlay
isVisible={isKeyInvalidateError}
title={t('errors.invalidateKeyError.title')}
message={t('errors.invalidateKeyError.message')}
onButtonPress={controller.RESET}
buttonText={t('common:ok')}
minHeight={'auto'}
/>
{isReadError ? (
<DualMessageOverlay
isVisible={isReadError}
title={t('failedToReadKeys')}
message={t('retryRead')}
onTryAgain={controller.TRY_AGAIN}
onIgnore={controller.IGNORE}
/>
) : null}
</>
);
};
const AppInitialization: React.FC = () => {
const {appService} = useContext(GlobalContext);
const isReady = useSelector(appService, selectIsReady);
const hasFontsLoaded = useFont();
const {t} = useTranslation('common');
useEffect(() => {
if (isHardwareKeystoreExists) {
RNSecureKeystoreModule.updatePopup(
t('biometricPopup.title'),
t('biometricPopup.description'),
);
}
}, [i18n.language]);
return isReady && hasFontsLoaded ? (
<AppLayoutWrapper />
) : (
<AppLoadingWrapper />
);
};
export default function App() {
return (
<GlobalContextProvider>
<AppInitialization />
</GlobalContextProvider>
);
}