@trustchex/react-native-sdk 1.253.0 → 1.266.0
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.
- package/README.md +43 -2
- package/android/src/main/java/com/trustchex/reactnativesdk/DeviceBrightnessModule.kt +66 -0
- package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKPackage.kt +12 -0
- package/ios/DeviceBrightnessModule.h +4 -0
- package/ios/DeviceBrightnessModule.m +27 -0
- package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +25 -0
- package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +19 -0
- package/lib/module/Screens/Dynamic/IdentityDocumentScanningScreen.js +19 -0
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +18 -5
- package/lib/module/Screens/Static/QrCodeScanningScreen.js +10 -2
- package/lib/module/Screens/Static/ResultScreen.js +52 -3
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +41 -2
- package/lib/module/Shared/Components/EIDScanner.js +63 -3
- package/lib/module/Shared/Components/FaceCamera.js +69 -4
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +4 -1
- package/lib/module/Shared/Components/NavigationManager.js +2 -0
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +2 -0
- package/lib/module/Shared/Contexts/AppContext.js +3 -1
- package/lib/module/Shared/Libs/analytics.utils.js +430 -0
- package/lib/module/Shared/Libs/camera.utils.js +58 -2
- package/lib/module/Shared/Libs/deeplink.utils.js +8 -0
- package/lib/module/Shared/Libs/http-client.js +89 -28
- package/lib/module/Shared/Services/AnalyticsService.js +404 -0
- package/lib/module/Shared/Types/analytics.types.js +111 -0
- package/lib/module/Shared/VisionCameraPlugins/BarcodeScanner/hooks/useCameraPermissions.js +1 -0
- package/lib/module/Translation/index.js +5 -0
- package/lib/module/Trustchex.js +47 -4
- package/lib/module/index.js +3 -0
- package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/QrCodeScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts +7 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts +2 -0
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts +98 -0
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/camera.utils.d.ts +19 -1
- package/lib/typescript/src/Shared/Libs/camera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/deeplink.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Services/AnalyticsService.d.ts +86 -0
- package/lib/typescript/src/Shared/Services/AnalyticsService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts +146 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -0
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/hooks/useCameraPermissions.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/Translation/index.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts +1 -0
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +35 -1
- package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +30 -0
- package/src/Screens/Dynamic/IdentityDocumentScanningScreen.tsx +30 -0
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +30 -4
- package/src/Screens/Static/QrCodeScanningScreen.tsx +12 -2
- package/src/Screens/Static/ResultScreen.tsx +79 -4
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +65 -10
- package/src/Shared/Components/EIDScanner.tsx +132 -3
- package/src/Shared/Components/FaceCamera.tsx +77 -2
- package/src/Shared/Components/IdentityDocumentCamera.tsx +4 -4
- package/src/Shared/Components/NavigationManager.tsx +2 -0
- package/src/Shared/Components/QrCodeScannerCamera.tsx +2 -0
- package/src/Shared/Contexts/AppContext.ts +4 -0
- package/src/Shared/Libs/analytics.utils.ts +644 -0
- package/src/Shared/Libs/camera.utils.ts +74 -2
- package/src/Shared/Libs/deeplink.utils.ts +5 -0
- package/src/Shared/Libs/http-client.ts +105 -31
- package/src/Shared/Services/AnalyticsService.ts +470 -0
- package/src/Shared/Types/analytics.types.ts +179 -0
- package/src/Shared/VisionCameraPlugins/BarcodeScanner/hooks/useCameraPermissions.ts +1 -0
- package/src/Translation/Resources/tr.ts +2 -1
- package/src/Translation/index.ts +9 -0
- package/src/Trustchex.tsx +54 -2
- package/src/index.tsx +33 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { Alert, View, Text, Image, StyleSheet } from 'react-native';
|
|
3
3
|
import NFCManager from 'react-native-nfc-manager';
|
|
4
|
+
import DeviceInfo from 'react-native-device-info';
|
|
4
5
|
import { MRZInfo } from '../EIDReader/lds/icao/mrzInfo';
|
|
5
6
|
import { eidReader } from '../EIDReader/eidReader';
|
|
6
7
|
import NativeProgressBar from './NativeProgressBar';
|
|
@@ -11,6 +12,11 @@ import StyledButton from './StyledButton';
|
|
|
11
12
|
import LottieView from 'lottie-react-native';
|
|
12
13
|
import { useKeepAwake } from '../Libs/native-keep-awake.utils';
|
|
13
14
|
import { speakWithDebounce } from '../Libs/tts.utils';
|
|
15
|
+
import {
|
|
16
|
+
trackEIDScanStart,
|
|
17
|
+
trackEIDScanComplete,
|
|
18
|
+
trackEIDScanFailed,
|
|
19
|
+
} from '../Libs/analytics.utils';
|
|
14
20
|
|
|
15
21
|
interface eIDScannerProps {
|
|
16
22
|
documentNumber: string;
|
|
@@ -47,12 +53,58 @@ const EIDScanner = ({
|
|
|
47
53
|
const { t } = useTranslation();
|
|
48
54
|
const appContext = React.useContext(AppContext);
|
|
49
55
|
const [voiceGuidanceMessage, setVoiceGuidanceMessage] = useState<string>();
|
|
56
|
+
const [attemptNumber, setAttemptNumber] = useState<number>(0);
|
|
50
57
|
|
|
51
58
|
const readNFC = useCallback(async () => {
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
const currentAttempt = attemptNumber + 1;
|
|
61
|
+
setAttemptNumber(currentAttempt);
|
|
62
|
+
|
|
52
63
|
setIsScanning(true);
|
|
53
64
|
setIsScanned(false);
|
|
54
65
|
setProgress(0);
|
|
55
66
|
|
|
67
|
+
// Track EID scan start using analytics helper
|
|
68
|
+
const docType =
|
|
69
|
+
(documentType as 'ID' | 'PASSPORT' | 'UNKNOWN') || 'UNKNOWN';
|
|
70
|
+
|
|
71
|
+
// If device doesn't support NFC or NFC is disabled, track and abort early
|
|
72
|
+
if (!hasNfc) {
|
|
73
|
+
await trackEIDScanFailed(
|
|
74
|
+
docType,
|
|
75
|
+
'device_unsupported',
|
|
76
|
+
'Device does not support NFC',
|
|
77
|
+
0,
|
|
78
|
+
currentAttempt,
|
|
79
|
+
DeviceInfo.getModel(),
|
|
80
|
+
DeviceInfo.getSystemVersion()
|
|
81
|
+
).catch(() => {});
|
|
82
|
+
|
|
83
|
+
// Stop scanning - user will see the not-supported UI
|
|
84
|
+
setIsScanning(false);
|
|
85
|
+
setProgress(0);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!isEnabled) {
|
|
90
|
+
await trackEIDScanFailed(
|
|
91
|
+
docType,
|
|
92
|
+
'not_enabled',
|
|
93
|
+
'NFC is disabled on device',
|
|
94
|
+
0,
|
|
95
|
+
currentAttempt,
|
|
96
|
+
DeviceInfo.getModel(),
|
|
97
|
+
DeviceInfo.getSystemVersion()
|
|
98
|
+
).catch(() => {});
|
|
99
|
+
|
|
100
|
+
// Stop scanning - allow the UI to prompt user to enable NFC
|
|
101
|
+
setIsScanning(false);
|
|
102
|
+
setProgress(0);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
await trackEIDScanStart(docType, hasNfc, isEnabled, currentAttempt).catch(()=>{});
|
|
107
|
+
|
|
56
108
|
try {
|
|
57
109
|
if (documentNumber && dateOfBirth && dateOfExpiry) {
|
|
58
110
|
const passportData = await eidReader(
|
|
@@ -64,23 +116,95 @@ const EIDScanner = ({
|
|
|
64
116
|
}
|
|
65
117
|
);
|
|
66
118
|
if (passportData) {
|
|
119
|
+
const scanDuration = Date.now() - startTime;
|
|
67
120
|
setDocumentFaceImage(passportData.faceImage);
|
|
68
121
|
setDocumentMRZInfo(passportData.mrz);
|
|
69
122
|
setDocumentFaceImageMimeType(passportData.mimeType);
|
|
70
123
|
setIsScanned(true);
|
|
124
|
+
|
|
125
|
+
// Track successful EID scan
|
|
126
|
+
await trackEIDScanComplete(docType, scanDuration, currentAttempt).catch(()=>{});
|
|
71
127
|
}
|
|
72
128
|
} else {
|
|
129
|
+
const scanDuration = Date.now() - startTime;
|
|
130
|
+
// MRZ input issue — track as NFC scan failure (unknown error type for NFC-specific stream)
|
|
131
|
+
await trackEIDScanFailed(
|
|
132
|
+
docType,
|
|
133
|
+
'unknown',
|
|
134
|
+
'Invalid MRZ fields',
|
|
135
|
+
scanDuration,
|
|
136
|
+
currentAttempt,
|
|
137
|
+
DeviceInfo.getModel(),
|
|
138
|
+
DeviceInfo.getSystemVersion()
|
|
139
|
+
).catch(() => {});
|
|
73
140
|
Alert.alert(t('general.error'), t('eidScannerScreen.invalidMRZFields'));
|
|
74
141
|
}
|
|
75
142
|
} catch (error) {
|
|
76
|
-
|
|
77
|
-
|
|
143
|
+
const scanDuration = Date.now() - startTime;
|
|
144
|
+
const errorMessage =
|
|
145
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
146
|
+
|
|
147
|
+
// Determine error type
|
|
148
|
+
let errorType:
|
|
149
|
+
| 'device_unsupported'
|
|
150
|
+
| 'not_enabled'
|
|
151
|
+
| 'reading_error'
|
|
152
|
+
| 'user_cancelled'
|
|
153
|
+
| 'timeout'
|
|
154
|
+
| 'unknown' = 'unknown';
|
|
155
|
+
|
|
156
|
+
if (
|
|
157
|
+
errorMessage.includes('cancelled') ||
|
|
158
|
+
errorMessage.includes('cancel')
|
|
159
|
+
) {
|
|
160
|
+
errorType = 'user_cancelled';
|
|
161
|
+
} else if (
|
|
162
|
+
errorMessage.includes('timeout') ||
|
|
163
|
+
errorMessage.includes('time out')
|
|
164
|
+
) {
|
|
165
|
+
errorType = 'timeout';
|
|
166
|
+
} else if (errorMessage.includes('not supported')) {
|
|
167
|
+
errorType = 'device_unsupported';
|
|
168
|
+
} else if (
|
|
169
|
+
errorMessage.includes('not enabled') ||
|
|
170
|
+
errorMessage.includes('disabled')
|
|
171
|
+
) {
|
|
172
|
+
errorType = 'not_enabled';
|
|
173
|
+
} else if (
|
|
174
|
+
errorMessage.includes('read') ||
|
|
175
|
+
errorMessage.includes('communication')
|
|
176
|
+
) {
|
|
177
|
+
errorType = 'reading_error';
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Track EID scan failure with detailed metadata
|
|
181
|
+
await trackEIDScanFailed(
|
|
182
|
+
docType,
|
|
183
|
+
errorType,
|
|
184
|
+
errorMessage,
|
|
185
|
+
scanDuration,
|
|
186
|
+
currentAttempt,
|
|
187
|
+
DeviceInfo.getModel(),
|
|
188
|
+
DeviceInfo.getSystemVersion()
|
|
189
|
+
).catch(() => {});
|
|
190
|
+
|
|
191
|
+
console.debug('NFC scan error:', error);
|
|
192
|
+
// Ignore error - let user retry
|
|
78
193
|
} finally {
|
|
79
194
|
setIsScanning(false);
|
|
80
195
|
setProgress(0);
|
|
81
196
|
setHasGuideShown(false);
|
|
82
197
|
}
|
|
83
|
-
}, [
|
|
198
|
+
}, [
|
|
199
|
+
documentNumber,
|
|
200
|
+
dateOfBirth,
|
|
201
|
+
dateOfExpiry,
|
|
202
|
+
documentType,
|
|
203
|
+
hasNfc,
|
|
204
|
+
isEnabled,
|
|
205
|
+
attemptNumber,
|
|
206
|
+
t,
|
|
207
|
+
]);
|
|
84
208
|
|
|
85
209
|
const getFieldsFromMRZ = useCallback((mrz: MRZInfo) => {
|
|
86
210
|
return {
|
|
@@ -103,8 +227,13 @@ const EIDScanner = ({
|
|
|
103
227
|
setHasNFC(deviceIsSupported);
|
|
104
228
|
isNFCSupported && isNFCSupported(deviceIsSupported);
|
|
105
229
|
|
|
230
|
+
// NFC not supported is a device limitation - not actionable by developers
|
|
231
|
+
|
|
106
232
|
const deviceIsEnabled = await NFCManager.isEnabled();
|
|
107
233
|
setIsEnabled(deviceIsEnabled);
|
|
234
|
+
|
|
235
|
+
// NFC disabled is a user setting - they can enable it in settings
|
|
236
|
+
// Not tracking as it's user-controllable
|
|
108
237
|
};
|
|
109
238
|
|
|
110
239
|
checkIsSupported();
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
Linking,
|
|
10
10
|
Dimensions,
|
|
11
11
|
ActivityIndicator,
|
|
12
|
+
NativeModules,
|
|
12
13
|
} from 'react-native';
|
|
13
14
|
import {
|
|
14
15
|
useCameraDevice,
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
} from '../VisionCameraPlugins/FaceDetector';
|
|
28
29
|
import { Worklets, useSharedValue } from 'react-native-worklets-core';
|
|
29
30
|
import { crop } from '../VisionCameraPlugins/Cropper';
|
|
30
|
-
import {
|
|
31
|
+
import { isCircularRegionBright } from '../Libs/camera.utils';
|
|
31
32
|
import { useTranslation } from 'react-i18next';
|
|
32
33
|
import StyledButton from './StyledButton';
|
|
33
34
|
import { useTheme } from '../Contexts/ThemeContext';
|
|
@@ -39,6 +40,12 @@ export type FaceCameraProps = {
|
|
|
39
40
|
isImageBright: boolean
|
|
40
41
|
) => void;
|
|
41
42
|
onCameraInitialized: (camera: Camera) => void;
|
|
43
|
+
previewRect?: {
|
|
44
|
+
minX: number;
|
|
45
|
+
minY: number;
|
|
46
|
+
width: number;
|
|
47
|
+
height: number;
|
|
48
|
+
};
|
|
42
49
|
};
|
|
43
50
|
|
|
44
51
|
const VIDEO_WIDTH = 1280;
|
|
@@ -50,6 +57,7 @@ const windowHeight = Dimensions.get('window').height;
|
|
|
50
57
|
const FaceCamera = ({
|
|
51
58
|
onFacesDetected,
|
|
52
59
|
onCameraInitialized,
|
|
60
|
+
previewRect,
|
|
53
61
|
}: FaceCameraProps) => {
|
|
54
62
|
useKeepAwake();
|
|
55
63
|
const theme = useTheme();
|
|
@@ -115,10 +123,74 @@ const FaceCamera = ({
|
|
|
115
123
|
};
|
|
116
124
|
}, [device, format, isFocused]);
|
|
117
125
|
|
|
126
|
+
// Set screen brightness to maximum when camera is active
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
const { DeviceBrightness } = NativeModules;
|
|
129
|
+
if (!DeviceBrightness) return;
|
|
130
|
+
|
|
131
|
+
let originalBrightness = -1;
|
|
132
|
+
|
|
133
|
+
const setBrightness = async () => {
|
|
134
|
+
if (isActive) {
|
|
135
|
+
try {
|
|
136
|
+
originalBrightness = await DeviceBrightness.getBrightness();
|
|
137
|
+
await DeviceBrightness.setBrightness(1.0);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.log('Failed to set brightness:', error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
setBrightness();
|
|
145
|
+
|
|
146
|
+
return () => {
|
|
147
|
+
if (originalBrightness >= 0) {
|
|
148
|
+
DeviceBrightness.setBrightness(originalBrightness).catch(() => { });
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}, [isActive]);
|
|
152
|
+
|
|
118
153
|
const handleWorklet = (frame: Frame) => {
|
|
119
154
|
'worklet';
|
|
120
155
|
try {
|
|
121
|
-
|
|
156
|
+
// Calculate brightness based on the circular preview area if provided
|
|
157
|
+
// Otherwise fall back to entire frame brightness
|
|
158
|
+
let isBright = false;
|
|
159
|
+
if (previewRect) {
|
|
160
|
+
// Convert preview rect from screen coordinates to frame coordinates
|
|
161
|
+
const scaleX = frame.width / windowWidth;
|
|
162
|
+
const scaleY = frame.height / windowHeight;
|
|
163
|
+
const frameCircleRect = {
|
|
164
|
+
minX: Math.floor(previewRect.minX * scaleX),
|
|
165
|
+
minY: Math.floor(previewRect.minY * scaleY),
|
|
166
|
+
width: Math.floor(previewRect.width * scaleX),
|
|
167
|
+
height: Math.floor(previewRect.height * scaleY),
|
|
168
|
+
};
|
|
169
|
+
isBright = isCircularRegionBright(frame, frameCircleRect, 60);
|
|
170
|
+
} else {
|
|
171
|
+
// Fallback: check entire frame brightness (use legacy method)
|
|
172
|
+
const buffer = frame.toArrayBuffer();
|
|
173
|
+
const data = new Uint8Array(buffer);
|
|
174
|
+
const width = frame.width;
|
|
175
|
+
const height = frame.height;
|
|
176
|
+
let luminanceSum = 0;
|
|
177
|
+
let pixelCount = 0;
|
|
178
|
+
const centerX = Math.floor(width / 2);
|
|
179
|
+
const centerY = Math.floor(height / 2);
|
|
180
|
+
const halfSizeX = Math.floor(width / 2);
|
|
181
|
+
const halfSizeY = Math.floor(height / 2);
|
|
182
|
+
|
|
183
|
+
for (let y = centerY - halfSizeY; y < centerY + halfSizeY; y++) {
|
|
184
|
+
for (let x = centerX - halfSizeX; x < centerX + halfSizeX; x++) {
|
|
185
|
+
const index = y * width + x;
|
|
186
|
+
if (data[index] !== undefined) {
|
|
187
|
+
luminanceSum += data[index];
|
|
188
|
+
pixelCount++;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
isBright = (luminanceSum / pixelCount) > 60;
|
|
193
|
+
}
|
|
122
194
|
|
|
123
195
|
const image = crop(frame, {
|
|
124
196
|
cropRegion: {
|
|
@@ -172,6 +244,7 @@ const FaceCamera = ({
|
|
|
172
244
|
}
|
|
173
245
|
|
|
174
246
|
if (!cameraPermission.hasPermission) {
|
|
247
|
+
// Camera permission denied by user - their choice, not actionable
|
|
175
248
|
return (
|
|
176
249
|
<View style={styles.permissionContainer}>
|
|
177
250
|
<Text style={styles.permissionText}>
|
|
@@ -190,6 +263,7 @@ const FaceCamera = ({
|
|
|
190
263
|
}
|
|
191
264
|
|
|
192
265
|
if (!microphonePermission.hasPermission) {
|
|
266
|
+
// Microphone permission denied by user - their choice, not actionable
|
|
193
267
|
return (
|
|
194
268
|
<View style={styles.permissionContainer}>
|
|
195
269
|
<Text style={styles.permissionText}>
|
|
@@ -208,6 +282,7 @@ const FaceCamera = ({
|
|
|
208
282
|
}
|
|
209
283
|
|
|
210
284
|
if (device == null) {
|
|
285
|
+
// No camera device - device limitation, not actionable
|
|
211
286
|
return (
|
|
212
287
|
<View style={styles.permissionContainer}>
|
|
213
288
|
<Text style={styles.permissionText}>
|
|
@@ -506,10 +506,10 @@ const IdentityDocumentCamera = ({
|
|
|
506
506
|
face.bounds.x >= width ||
|
|
507
507
|
face.bounds.y >= height
|
|
508
508
|
) {
|
|
509
|
-
console.warn(
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
);
|
|
509
|
+
// console.warn(
|
|
510
|
+
// 'Invalid face bounds detected, skipping face:',
|
|
511
|
+
// face.bounds
|
|
512
|
+
// );
|
|
513
513
|
continue;
|
|
514
514
|
}
|
|
515
515
|
|
|
@@ -15,6 +15,7 @@ import { View, StyleSheet, Alert } from 'react-native';
|
|
|
15
15
|
import { useTranslation } from 'react-i18next';
|
|
16
16
|
import i18n from '../../Translation';
|
|
17
17
|
import StyledButton from './StyledButton';
|
|
18
|
+
import { analyticsService } from '../Services/AnalyticsService';
|
|
18
19
|
|
|
19
20
|
// Simple global navigation lock
|
|
20
21
|
let isNavigating = false;
|
|
@@ -187,6 +188,7 @@ const NavigationManager = forwardRef(
|
|
|
187
188
|
appContext.currentWorkflowStep = undefined;
|
|
188
189
|
appContext.workflowSteps = undefined;
|
|
189
190
|
appContext.isDemoSession = false;
|
|
191
|
+
analyticsService.setDemoSession(false);
|
|
190
192
|
appContext.identificationInfo = {
|
|
191
193
|
sessionId: '',
|
|
192
194
|
identificationId: '',
|
|
@@ -172,6 +172,7 @@ const QrCodeScannerCamera = ({ onQrCodeScanned }: QrCodeScannerCameraProps) => {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
if (!cameraPermission.hasPermission) {
|
|
175
|
+
// Camera permission denied by user - their choice, not actionable
|
|
175
176
|
return (
|
|
176
177
|
<View style={styles.permissionContainer}>
|
|
177
178
|
<Text style={styles.permissionText}>
|
|
@@ -190,6 +191,7 @@ const QrCodeScannerCamera = ({ onQrCodeScanned }: QrCodeScannerCameraProps) => {
|
|
|
190
191
|
}
|
|
191
192
|
|
|
192
193
|
if (device == null) {
|
|
194
|
+
// No camera device - device limitation, not actionable
|
|
193
195
|
return (
|
|
194
196
|
<View style={styles.permissionContainer}>
|
|
195
197
|
<TextView style={styles.permissionText}>
|
|
@@ -19,6 +19,8 @@ export type AppContextType = {
|
|
|
19
19
|
currentWorkflowStep?: WorkflowStep;
|
|
20
20
|
onCompleted?: () => void;
|
|
21
21
|
onError?: (error: string) => void;
|
|
22
|
+
setSessionId?: (id: string) => void;
|
|
23
|
+
setBaseUrl?: (url: string) => void;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export default createContext<AppContextType>({
|
|
@@ -44,4 +46,6 @@ export default createContext<AppContextType>({
|
|
|
44
46
|
currentWorkflowStep: undefined,
|
|
45
47
|
onCompleted: undefined,
|
|
46
48
|
onError: undefined,
|
|
49
|
+
setSessionId: undefined,
|
|
50
|
+
setBaseUrl: undefined,
|
|
47
51
|
});
|