@trustchex/react-native-sdk 1.374.0 → 1.409.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.
Files changed (137) hide show
  1. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +1 -21
  2. package/android/src/main/java/com/trustchex/reactnativesdk/mlkit/MLKitModule.kt +1 -1
  3. package/android/src/main/java/com/trustchex/reactnativesdk/opencv/OpenCVModule.kt +636 -301
  4. package/ios/Camera/TrustchexCameraView.swift +9 -20
  5. package/ios/MLKit/MLKitModule.swift +1 -1
  6. package/ios/OpenCV/OpenCVHelper.h +0 -7
  7. package/ios/OpenCV/OpenCVHelper.mm +0 -60
  8. package/ios/OpenCV/OpenCVModule.h +0 -4
  9. package/ios/OpenCV/OpenCVModule.mm +440 -358
  10. package/lib/module/Screens/Debug/BarcodeTestScreen.js +308 -0
  11. package/lib/module/Screens/Debug/MRZTestScreen.js +105 -13
  12. package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +49 -29
  13. package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +5 -0
  14. package/lib/module/Screens/Dynamic/IdentityDocumentScanningScreen.js +5 -0
  15. package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +26 -6
  16. package/lib/module/Screens/Dynamic/VideoCallScreen.js +676 -0
  17. package/lib/module/Screens/Static/OTPVerificationScreen.js +6 -0
  18. package/lib/module/Screens/Static/QrCodeScanningScreen.js +7 -1
  19. package/lib/module/Screens/Static/ResultScreen.js +27 -13
  20. package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +51 -51
  21. package/lib/module/Shared/Animations/video-call.json +1 -0
  22. package/lib/module/Shared/Components/DebugNavigationPanel.js +180 -14
  23. package/lib/module/Shared/Components/DebugOverlay.js +541 -0
  24. package/lib/module/Shared/Components/EIDScanner.js +1 -4
  25. package/lib/module/Shared/Components/IdentityDocumentCamera.constants.js +44 -0
  26. package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +270 -0
  27. package/lib/module/Shared/Components/IdentityDocumentCamera.js +702 -1703
  28. package/lib/module/Shared/Components/IdentityDocumentCamera.types.js +3 -0
  29. package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +273 -0
  30. package/lib/module/Shared/Components/NavigationManager.js +15 -3
  31. package/lib/module/Shared/Contexts/AppContext.js +1 -0
  32. package/lib/module/Shared/Libs/SignalingClient.js +128 -0
  33. package/lib/module/Shared/Libs/analytics.utils.js +4 -0
  34. package/lib/module/Shared/Libs/deeplink.utils.js +9 -1
  35. package/lib/module/Shared/Libs/http-client.js +9 -0
  36. package/lib/module/Shared/Libs/promise.utils.js +16 -2
  37. package/lib/module/Shared/Libs/status-bar.utils.js +21 -0
  38. package/lib/module/Shared/Services/DataUploadService.js +294 -0
  39. package/lib/module/Shared/Services/VideoSessionService.js +156 -0
  40. package/lib/module/Shared/Services/WebRTCService.js +510 -0
  41. package/lib/module/Shared/Types/analytics.types.js +2 -0
  42. package/lib/module/Translation/Resources/en.js +20 -0
  43. package/lib/module/Translation/Resources/tr.js +20 -0
  44. package/lib/module/Trustchex.js +10 -0
  45. package/lib/module/version.js +1 -1
  46. package/lib/typescript/src/Screens/Debug/BarcodeTestScreen.d.ts +3 -0
  47. package/lib/typescript/src/Screens/Debug/BarcodeTestScreen.d.ts.map +1 -0
  48. package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -1
  49. package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
  50. package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
  51. package/lib/typescript/src/Screens/Dynamic/IdentityDocumentScanningScreen.d.ts.map +1 -1
  52. package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
  53. package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts +3 -0
  54. package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts.map +1 -0
  55. package/lib/typescript/src/Screens/Static/OTPVerificationScreen.d.ts.map +1 -1
  56. package/lib/typescript/src/Screens/Static/QrCodeScanningScreen.d.ts.map +1 -1
  57. package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
  58. package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
  59. package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -1
  60. package/lib/typescript/src/Shared/Components/DebugOverlay.d.ts +30 -0
  61. package/lib/typescript/src/Shared/Components/DebugOverlay.d.ts.map +1 -0
  62. package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
  63. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.constants.d.ts +35 -0
  64. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.constants.d.ts.map +1 -0
  65. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts +3 -56
  66. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  67. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +88 -0
  68. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -0
  69. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.types.d.ts +116 -0
  70. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.types.d.ts.map +1 -0
  71. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +93 -0
  72. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -0
  73. package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
  74. package/lib/typescript/src/Shared/Contexts/AppContext.d.ts +1 -0
  75. package/lib/typescript/src/Shared/Contexts/AppContext.d.ts.map +1 -1
  76. package/lib/typescript/src/Shared/Libs/SignalingClient.d.ts +24 -0
  77. package/lib/typescript/src/Shared/Libs/SignalingClient.d.ts.map +1 -0
  78. package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -1
  79. package/lib/typescript/src/Shared/Libs/deeplink.utils.d.ts.map +1 -1
  80. package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
  81. package/lib/typescript/src/Shared/Libs/promise.utils.d.ts.map +1 -1
  82. package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts +9 -0
  83. package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts.map +1 -0
  84. package/lib/typescript/src/Shared/Services/DataUploadService.d.ts +25 -0
  85. package/lib/typescript/src/Shared/Services/DataUploadService.d.ts.map +1 -0
  86. package/lib/typescript/src/Shared/Services/VideoSessionService.d.ts +33 -0
  87. package/lib/typescript/src/Shared/Services/VideoSessionService.d.ts.map +1 -0
  88. package/lib/typescript/src/Shared/Services/WebRTCService.d.ts +58 -0
  89. package/lib/typescript/src/Shared/Services/WebRTCService.d.ts.map +1 -0
  90. package/lib/typescript/src/Shared/Types/analytics.types.d.ts +2 -0
  91. package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -1
  92. package/lib/typescript/src/Shared/Types/identificationInfo.d.ts +4 -1
  93. package/lib/typescript/src/Shared/Types/identificationInfo.d.ts.map +1 -1
  94. package/lib/typescript/src/Translation/Resources/en.d.ts +20 -0
  95. package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
  96. package/lib/typescript/src/Translation/Resources/tr.d.ts +20 -0
  97. package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
  98. package/lib/typescript/src/Trustchex.d.ts.map +1 -1
  99. package/lib/typescript/src/version.d.ts +1 -1
  100. package/package.json +29 -2
  101. package/src/Screens/Debug/BarcodeTestScreen.tsx +317 -0
  102. package/src/Screens/Debug/MRZTestScreen.tsx +107 -13
  103. package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +59 -33
  104. package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +6 -0
  105. package/src/Screens/Dynamic/IdentityDocumentScanningScreen.tsx +6 -0
  106. package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +34 -6
  107. package/src/Screens/Dynamic/VideoCallScreen.tsx +764 -0
  108. package/src/Screens/Static/OTPVerificationScreen.tsx +6 -0
  109. package/src/Screens/Static/QrCodeScanningScreen.tsx +7 -1
  110. package/src/Screens/Static/ResultScreen.tsx +58 -23
  111. package/src/Screens/Static/VerificationSessionCheckScreen.tsx +58 -72
  112. package/src/Shared/Animations/video-call.json +1 -0
  113. package/src/Shared/Components/DebugNavigationPanel.tsx +185 -9
  114. package/src/Shared/Components/DebugOverlay.tsx +656 -0
  115. package/src/Shared/Components/EIDScanner.tsx +1 -5
  116. package/src/Shared/Components/IdentityDocumentCamera.constants.ts +44 -0
  117. package/src/Shared/Components/IdentityDocumentCamera.flows.ts +342 -0
  118. package/src/Shared/Components/IdentityDocumentCamera.tsx +1089 -2465
  119. package/src/Shared/Components/IdentityDocumentCamera.types.ts +136 -0
  120. package/src/Shared/Components/IdentityDocumentCamera.utils.ts +364 -0
  121. package/src/Shared/Components/NavigationManager.tsx +14 -1
  122. package/src/Shared/Contexts/AppContext.ts +2 -0
  123. package/src/Shared/Libs/SignalingClient.ts +189 -0
  124. package/src/Shared/Libs/analytics.utils.ts +4 -0
  125. package/src/Shared/Libs/deeplink.utils.ts +12 -1
  126. package/src/Shared/Libs/http-client.ts +10 -0
  127. package/src/Shared/Libs/promise.utils.ts +16 -2
  128. package/src/Shared/Libs/status-bar.utils.ts +19 -0
  129. package/src/Shared/Services/DataUploadService.ts +395 -0
  130. package/src/Shared/Services/VideoSessionService.ts +190 -0
  131. package/src/Shared/Services/WebRTCService.ts +636 -0
  132. package/src/Shared/Types/analytics.types.ts +2 -0
  133. package/src/Shared/Types/identificationInfo.ts +5 -1
  134. package/src/Translation/Resources/en.ts +25 -0
  135. package/src/Translation/Resources/tr.ts +27 -0
  136. package/src/Trustchex.tsx +12 -2
  137. package/src/version.ts +1 -1
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+
3
+ import React, { useState, useRef, useCallback } from 'react';
4
+ import { View, StyleSheet, Text, ScrollView, StatusBar, TouchableOpacity } from 'react-native';
5
+ import { SafeAreaView } from 'react-native-safe-area-context';
6
+ import { TrustchexCamera } from "../../Shared/Components/TrustchexCamera.js";
7
+ import { useKeepAwake } from "../../Shared/Libs/native-keep-awake.utils.js";
8
+
9
+ // ML Kit barcode format constants
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ const BARCODE_FORMAT_NAMES = {
12
+ 1: 'Code 128',
13
+ 2: 'Code 39',
14
+ 4: 'Code 93',
15
+ 8: 'Codabar',
16
+ 16: 'Data Matrix',
17
+ 32: 'EAN-13',
18
+ 64: 'EAN-8',
19
+ 128: 'ITF',
20
+ 256: 'QR Code',
21
+ 512: 'UPC-A',
22
+ 1024: 'UPC-E',
23
+ 2048: 'PDF417',
24
+ 4096: 'Aztec'
25
+ };
26
+ function formatName(format) {
27
+ return BARCODE_FORMAT_NAMES[format] ?? `Format(${format})`;
28
+ }
29
+ const BarcodeTestScreen = () => {
30
+ useKeepAwake();
31
+ const cameraRef = useRef(null);
32
+ const [barcodes, setBarcodes] = useState([]);
33
+ const [history, setHistory] = useState([]);
34
+ const [isPaused, setIsPaused] = useState(false);
35
+ const [cameraLayout, setCameraLayout] = useState({
36
+ width: 1,
37
+ height: 1
38
+ });
39
+ const [frameSize, setFrameSize] = useState({
40
+ width: 1080,
41
+ height: 1920
42
+ });
43
+ const handleCameraLayout = useCallback(e => {
44
+ const {
45
+ width,
46
+ height
47
+ } = e.nativeEvent.layout;
48
+ setCameraLayout({
49
+ width,
50
+ height
51
+ });
52
+ }, []);
53
+ const handleFrame = useCallback(event => {
54
+ if (isPaused) return;
55
+ const frame = event.nativeEvent.frame;
56
+ if (frame.width && frame.height) {
57
+ setFrameSize({
58
+ width: frame.width,
59
+ height: frame.height
60
+ });
61
+ }
62
+ if (frame.barcodes && frame.barcodes.length > 0) {
63
+ setBarcodes(frame.barcodes);
64
+ setHistory(prev => {
65
+ const incoming = frame.barcodes;
66
+ const next = [...prev];
67
+ for (const b of incoming) {
68
+ const alreadyRecent = next.slice(0, 5).some(h => h.rawValue === b.rawValue);
69
+ if (!alreadyRecent) {
70
+ next.unshift({
71
+ rawValue: b.rawValue,
72
+ displayValue: b.displayValue,
73
+ format: b.format,
74
+ timestamp: Date.now()
75
+ });
76
+ }
77
+ }
78
+ return next.slice(0, 30);
79
+ });
80
+ } else {
81
+ setBarcodes([]);
82
+ }
83
+ }, [isPaused]);
84
+ return /*#__PURE__*/_jsxs(View, {
85
+ style: styles.container,
86
+ children: [/*#__PURE__*/_jsx(StatusBar, {
87
+ barStyle: "light-content",
88
+ backgroundColor: "transparent",
89
+ translucent: true
90
+ }), /*#__PURE__*/_jsxs(View, {
91
+ style: styles.cameraWrapper,
92
+ onLayout: handleCameraLayout,
93
+ children: [/*#__PURE__*/_jsx(TrustchexCamera, {
94
+ ref: cameraRef,
95
+ style: StyleSheet.absoluteFill,
96
+ cameraType: "back",
97
+ enableFrameProcessing: true,
98
+ enableFaceDetection: false,
99
+ enableTextRecognition: false,
100
+ enableBarcodeScanning: true,
101
+ includeBase64: false,
102
+ targetFps: 15,
103
+ onFrameAvailable: handleFrame
104
+ }), barcodes.map((b, i) => {
105
+ const bb = b.boundingBox;
106
+ if (!bb) return null;
107
+ const scaleX = cameraLayout.width / frameSize.width;
108
+ const scaleY = cameraLayout.height / frameSize.height;
109
+ const left = bb.left * scaleX;
110
+ const top = bb.top * scaleY;
111
+ const width = (bb.right - bb.left) * scaleX;
112
+ const height = (bb.bottom - bb.top) * scaleY;
113
+ return /*#__PURE__*/_jsx(View, {
114
+ style: [styles.barcodeBoundingBox, {
115
+ left,
116
+ top,
117
+ width,
118
+ height
119
+ }],
120
+ children: /*#__PURE__*/_jsx(View, {
121
+ style: styles.barcodeBoxLabel,
122
+ children: /*#__PURE__*/_jsx(Text, {
123
+ style: styles.barcodeBoxLabelText,
124
+ children: formatName(b.format)
125
+ })
126
+ })
127
+ }, i);
128
+ })]
129
+ }), /*#__PURE__*/_jsx(SafeAreaView, {
130
+ style: styles.panel,
131
+ edges: ['bottom'],
132
+ children: /*#__PURE__*/_jsx(ScrollView, {
133
+ style: styles.scrollView,
134
+ children: /*#__PURE__*/_jsxs(View, {
135
+ style: styles.panelContent,
136
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
137
+ style: styles.pauseButton,
138
+ onPress: () => setIsPaused(!isPaused),
139
+ children: /*#__PURE__*/_jsx(Text, {
140
+ style: styles.pauseButtonText,
141
+ children: isPaused ? 'Resume Processing' : 'Pause Processing'
142
+ })
143
+ }), /*#__PURE__*/_jsx(Text, {
144
+ style: styles.title,
145
+ children: "Barcode Scanner"
146
+ }), /*#__PURE__*/_jsx(Text, {
147
+ style: styles.sectionTitle,
148
+ children: "Live Detections"
149
+ }), barcodes.length === 0 ? /*#__PURE__*/_jsx(Text, {
150
+ style: styles.bodyText,
151
+ children: "No barcode in frame"
152
+ }) : barcodes.map((b, i) => /*#__PURE__*/_jsxs(View, {
153
+ style: styles.barcodeRow,
154
+ children: [/*#__PURE__*/_jsx(View, {
155
+ style: styles.formatBadge,
156
+ children: /*#__PURE__*/_jsx(Text, {
157
+ style: styles.formatBadgeText,
158
+ children: formatName(b.format)
159
+ })
160
+ }), /*#__PURE__*/_jsx(Text, {
161
+ style: styles.barcodeValue,
162
+ children: b.rawValue
163
+ })]
164
+ }, i)), /*#__PURE__*/_jsxs(Text, {
165
+ style: styles.sectionTitle,
166
+ children: ["History (", history.length, ")"]
167
+ }), history.length === 0 ? /*#__PURE__*/_jsx(Text, {
168
+ style: styles.bodyText,
169
+ children: "No barcodes detected yet"
170
+ }) : history.map((entry, i) => /*#__PURE__*/_jsxs(View, {
171
+ style: styles.historyRow,
172
+ children: [/*#__PURE__*/_jsxs(View, {
173
+ style: styles.historyMeta,
174
+ children: [/*#__PURE__*/_jsx(View, {
175
+ style: styles.formatBadge,
176
+ children: /*#__PURE__*/_jsx(Text, {
177
+ style: styles.formatBadgeText,
178
+ children: formatName(entry.format)
179
+ })
180
+ }), /*#__PURE__*/_jsx(Text, {
181
+ style: styles.historyTime,
182
+ children: new Date(entry.timestamp).toLocaleTimeString()
183
+ })]
184
+ }), /*#__PURE__*/_jsx(Text, {
185
+ style: styles.barcodeValue,
186
+ children: entry.rawValue
187
+ })]
188
+ }, i))]
189
+ })
190
+ })
191
+ })]
192
+ });
193
+ };
194
+ const styles = StyleSheet.create({
195
+ container: {
196
+ flex: 1,
197
+ backgroundColor: '#000000'
198
+ },
199
+ cameraWrapper: {
200
+ flex: 2,
201
+ position: 'relative'
202
+ },
203
+ barcodeBoundingBox: {
204
+ position: 'absolute',
205
+ borderWidth: 2,
206
+ borderColor: '#00C853',
207
+ backgroundColor: 'rgba(0, 200, 83, 0.07)'
208
+ },
209
+ barcodeBoxLabel: {
210
+ position: 'absolute',
211
+ top: -14,
212
+ left: 0,
213
+ backgroundColor: '#00C853',
214
+ paddingHorizontal: 4,
215
+ paddingVertical: 1,
216
+ borderRadius: 2
217
+ },
218
+ barcodeBoxLabelText: {
219
+ color: '#000000',
220
+ fontSize: 8,
221
+ fontWeight: 'bold'
222
+ },
223
+ panel: {
224
+ flex: 1,
225
+ backgroundColor: 'rgba(0, 0, 0, 0.95)',
226
+ borderTopWidth: 2,
227
+ borderTopColor: '#00C853'
228
+ },
229
+ scrollView: {
230
+ flex: 1
231
+ },
232
+ panelContent: {
233
+ padding: 10
234
+ },
235
+ pauseButton: {
236
+ alignSelf: 'center',
237
+ borderWidth: 1,
238
+ borderColor: '#00C853',
239
+ borderRadius: 4,
240
+ paddingVertical: 6,
241
+ paddingHorizontal: 12,
242
+ marginBottom: 8
243
+ },
244
+ pauseButtonText: {
245
+ color: '#00C853',
246
+ fontSize: 10,
247
+ fontWeight: 'bold'
248
+ },
249
+ title: {
250
+ color: '#00C853',
251
+ fontSize: 12,
252
+ fontWeight: 'bold',
253
+ marginBottom: 8,
254
+ textAlign: 'center'
255
+ },
256
+ sectionTitle: {
257
+ color: '#00C853',
258
+ fontSize: 10,
259
+ fontWeight: 'bold',
260
+ marginTop: 6,
261
+ marginBottom: 4
262
+ },
263
+ bodyText: {
264
+ color: '#888888',
265
+ fontSize: 9,
266
+ fontFamily: 'monospace'
267
+ },
268
+ barcodeRow: {
269
+ marginBottom: 6
270
+ },
271
+ historyRow: {
272
+ marginBottom: 8,
273
+ borderBottomWidth: 1,
274
+ borderBottomColor: '#333333',
275
+ paddingBottom: 6
276
+ },
277
+ historyMeta: {
278
+ flexDirection: 'row',
279
+ alignItems: 'center',
280
+ marginBottom: 2,
281
+ gap: 6
282
+ },
283
+ formatBadge: {
284
+ backgroundColor: '#00C853',
285
+ borderRadius: 3,
286
+ paddingHorizontal: 5,
287
+ paddingVertical: 2,
288
+ alignSelf: 'flex-start',
289
+ marginBottom: 2
290
+ },
291
+ formatBadgeText: {
292
+ color: '#000000',
293
+ fontSize: 8,
294
+ fontWeight: 'bold'
295
+ },
296
+ barcodeValue: {
297
+ color: '#FFFFFF',
298
+ fontSize: 9,
299
+ fontFamily: 'monospace',
300
+ lineHeight: 14
301
+ },
302
+ historyTime: {
303
+ color: '#888888',
304
+ fontSize: 8,
305
+ fontFamily: 'monospace'
306
+ }
307
+ });
308
+ export default BarcodeTestScreen;
@@ -5,19 +5,60 @@ import { View, StyleSheet, Text, ScrollView, StatusBar, TouchableOpacity } from
5
5
  import { SafeAreaView } from 'react-native-safe-area-context';
6
6
  import { TrustchexCamera } from "../../Shared/Components/TrustchexCamera.js";
7
7
  import mrzUtils from "../../Shared/Libs/mrz.utils.js";
8
+ import { useKeepAwake } from "../../Shared/Libs/native-keep-awake.utils.js";
8
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
10
  const MRZTestScreen = () => {
11
+ useKeepAwake();
10
12
  const cameraRef = useRef(null);
11
13
  const [mrzText, setMrzText] = useState('Waiting for MRZ...');
12
14
  const [mrzRawText, setMrzRawText] = useState('');
13
15
  const [mrzValid, setMrzValid] = useState(false);
14
16
  const [rawHistory, setRawHistory] = useState([]);
15
17
  const [isPaused, setIsPaused] = useState(false);
18
+ const [overlayBlocks, setOverlayBlocks] = useState([]);
19
+ const [cameraLayout, setCameraLayout] = useState({
20
+ width: 1,
21
+ height: 1
22
+ });
23
+ const [frameSize, setFrameSize] = useState({
24
+ width: 1080,
25
+ height: 1920
26
+ });
27
+ const handleCameraLayout = useCallback(e => {
28
+ const {
29
+ width,
30
+ height
31
+ } = e.nativeEvent.layout;
32
+ setCameraLayout({
33
+ width,
34
+ height
35
+ });
36
+ }, []);
16
37
  const handleFrame = useCallback(event => {
17
38
  if (isPaused) {
18
39
  return;
19
40
  }
20
41
  const frame = event.nativeEvent.frame;
42
+ if (frame.width && frame.height) {
43
+ setFrameSize({
44
+ width: frame.width,
45
+ height: frame.height
46
+ });
47
+ }
48
+ if (frame.textBlocks && frame.textBlocks.length > 0) {
49
+ const frameHeight = frame.height;
50
+ const bottomThreshold = frameHeight * 0.5;
51
+ const blocks = frame.textBlocks.map(block => {
52
+ const blockText = block.text || '';
53
+ return {
54
+ ...block,
55
+ isMrz: blockText.includes('<') && blockText.length >= 12 && (block.blockFrame ? block.blockFrame.y > bottomThreshold : false)
56
+ };
57
+ });
58
+ setOverlayBlocks(blocks);
59
+ } else {
60
+ setOverlayBlocks([]);
61
+ }
21
62
  if (frame.resultText) {
22
63
  setRawHistory(prev => {
23
64
  if (prev[0] === frame.resultText) {
@@ -62,17 +103,41 @@ const MRZTestScreen = () => {
62
103
  barStyle: "light-content",
63
104
  backgroundColor: "transparent",
64
105
  translucent: true
65
- }), /*#__PURE__*/_jsx(TrustchexCamera, {
66
- ref: cameraRef,
67
- style: styles.camera,
68
- cameraType: "back",
69
- enableFrameProcessing: true,
70
- enableFaceDetection: false,
71
- enableTextRecognition: true,
72
- enableBarcodeScanning: false,
73
- includeBase64: false,
74
- targetFps: 10,
75
- onFrameAvailable: handleFrame
106
+ }), /*#__PURE__*/_jsxs(View, {
107
+ style: styles.cameraWrapper,
108
+ onLayout: handleCameraLayout,
109
+ children: [/*#__PURE__*/_jsx(TrustchexCamera, {
110
+ ref: cameraRef,
111
+ style: StyleSheet.absoluteFill,
112
+ cameraType: "back",
113
+ enableFrameProcessing: true,
114
+ enableFaceDetection: false,
115
+ enableTextRecognition: true,
116
+ enableBarcodeScanning: false,
117
+ includeBase64: false,
118
+ targetFps: 10,
119
+ onFrameAvailable: handleFrame
120
+ }), overlayBlocks.map((block, i) => {
121
+ const bf = block.blockFrame;
122
+ if (!bf) return null;
123
+ const scaleX = cameraLayout.width / frameSize.width;
124
+ const scaleY = cameraLayout.height / frameSize.height;
125
+ return /*#__PURE__*/_jsx(View, {
126
+ style: [styles.boundingBox, block.isMrz ? styles.boundingBoxMrz : styles.boundingBoxText, {
127
+ left: bf.x * scaleX,
128
+ top: bf.y * scaleY,
129
+ width: bf.width * scaleX,
130
+ height: bf.height * scaleY
131
+ }],
132
+ children: block.isMrz && /*#__PURE__*/_jsx(View, {
133
+ style: styles.blockLabel,
134
+ children: /*#__PURE__*/_jsx(Text, {
135
+ style: styles.blockLabelText,
136
+ children: "MRZ"
137
+ })
138
+ })
139
+ }, i);
140
+ })]
76
141
  }), /*#__PURE__*/_jsx(SafeAreaView, {
77
142
  style: styles.mrzPanel,
78
143
  edges: ['bottom'],
@@ -119,8 +184,35 @@ const styles = StyleSheet.create({
119
184
  flex: 1,
120
185
  backgroundColor: '#000000'
121
186
  },
122
- camera: {
123
- flex: 2
187
+ cameraWrapper: {
188
+ flex: 2,
189
+ position: 'relative'
190
+ },
191
+ boundingBox: {
192
+ position: 'absolute',
193
+ borderWidth: 1.5
194
+ },
195
+ boundingBoxText: {
196
+ borderColor: 'rgba(255, 255, 255, 0.25)'
197
+ },
198
+ boundingBoxMrz: {
199
+ borderColor: '#FFA500',
200
+ borderWidth: 2,
201
+ backgroundColor: 'rgba(255, 165, 0, 0.07)'
202
+ },
203
+ blockLabel: {
204
+ position: 'absolute',
205
+ top: -14,
206
+ left: 0,
207
+ backgroundColor: '#FFA500',
208
+ paddingHorizontal: 4,
209
+ paddingVertical: 1,
210
+ borderRadius: 2
211
+ },
212
+ blockLabelText: {
213
+ color: '#000000',
214
+ fontSize: 8,
215
+ fontWeight: 'bold'
124
216
  },
125
217
  mrzPanel: {
126
218
  flex: 1,
@@ -10,9 +10,12 @@ import { getI18n, useTranslation } from 'react-i18next';
10
10
  import StyledButton from "../../Shared/Components/StyledButton.js";
11
11
  import NativeDeviceInfo from "../../Shared/Libs/native-device-info.utils.js";
12
12
  import { speakWithDebounce } from "../../Shared/Libs/tts.utils.js";
13
+ import { useStatusBarWhiteBackground } from "../../Shared/Libs/status-bar.utils.js";
13
14
  import { trackFunnelStep, useScreenTracking, trackConsentGiven, trackVerificationStart, trackVerificationComplete, trackError } from "../../Shared/Libs/analytics.utils.js";
15
+ import { useKeepAwake } from "../../Shared/Libs/native-keep-awake.utils.js";
14
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
17
  const ContractAcceptanceScreen = () => {
18
+ useKeepAwake();
16
19
  const [isEnabled, setIsEnabled] = useState(false);
17
20
  const [isReady, setIsReady] = useState(false);
18
21
  const appContext = useContext(AppContext);
@@ -27,6 +30,9 @@ const ContractAcceptanceScreen = () => {
27
30
 
28
31
  // Track screen view and exit
29
32
  useScreenTracking('contract_acceptance');
33
+
34
+ // Configure status bar for white background
35
+ useStatusBarWhiteBackground();
30
36
  useEffect(() => {
31
37
  const contracts = appContext.currentWorkflowStep?.data?.contracts;
32
38
  if (!contracts) {
@@ -65,38 +71,49 @@ const ContractAcceptanceScreen = () => {
65
71
  const generateHumanReadableIdentifier = useCallback(async () => {
66
72
  return await NativeDeviceInfo.generateHumanReadableIdentifier();
67
73
  }, []);
74
+
75
+ // Early return if workflow step data is not available (after all hooks)
76
+ if (!appContext.currentWorkflowStep || !appContext.currentWorkflowStep.data) {
77
+ return null;
78
+ }
68
79
  return /*#__PURE__*/_jsxs(SafeAreaView, {
69
80
  style: styles.container,
70
- children: [/*#__PURE__*/_jsx(WebView, {
71
- source: {
72
- uri: contractUrl || ''
73
- },
74
- javaScriptEnabled: true,
75
- domStorageEnabled: false,
76
- scalesPageToFit: false,
77
- scrollEnabled: true,
78
- style: styles.webView,
79
- onError: syntheticEvent => {
80
- const {
81
- nativeEvent
82
- } = syntheticEvent;
83
- trackError('CONTRACT_WEBVIEW_ERROR', nativeEvent.description || 'Failed to load contract', 'contract_acceptance', 'medium', {
84
- recoverable: true,
85
- userAction: 'load_contract'
86
- });
87
- },
88
- onLoadEnd: event => {
89
- if (event.nativeEvent.url === contractUrl) {
90
- setIsReady(true);
81
+ children: [/*#__PURE__*/_jsx(View, {
82
+ style: [styles.webViewContainer, {
83
+ paddingHorizontal: Math.max(insets.left, insets.right),
84
+ paddingTop: insets.top
85
+ }],
86
+ children: /*#__PURE__*/_jsx(WebView, {
87
+ source: {
88
+ uri: contractUrl || ''
89
+ },
90
+ javaScriptEnabled: true,
91
+ domStorageEnabled: false,
92
+ scalesPageToFit: false,
93
+ scrollEnabled: true,
94
+ style: styles.webView,
95
+ onError: syntheticEvent => {
96
+ const {
97
+ nativeEvent
98
+ } = syntheticEvent;
99
+ trackError('CONTRACT_WEBVIEW_ERROR', nativeEvent.description || 'Failed to load contract', 'contract_acceptance', 'medium', {
100
+ recoverable: true,
101
+ userAction: 'load_contract'
102
+ });
103
+ },
104
+ onLoadEnd: event => {
105
+ if (event.nativeEvent.url === contractUrl) {
106
+ setIsReady(true);
91
107
 
92
- // Track contract acceptance started
93
- trackVerificationStart('CONTRACT_ACCEPTANCE');
94
- if (appContext.currentWorkflowStep?.data?.voiceGuidanceActive) {
95
- speakWithDebounce(t('termsOfUseAndDataPrivacyScreen.footerText'));
108
+ // Track contract acceptance started
109
+ trackVerificationStart('CONTRACT_ACCEPTANCE');
110
+ if (appContext.currentWorkflowStep?.data?.voiceGuidanceActive) {
111
+ speakWithDebounce(t('termsOfUseAndDataPrivacyScreen.footerText'));
112
+ }
96
113
  }
97
- }
98
- },
99
- onScroll: hasReachedEnd
114
+ },
115
+ onScroll: hasReachedEnd
116
+ })
100
117
  }), /*#__PURE__*/_jsxs(View, {
101
118
  style: [styles.footer, {
102
119
  paddingBottom: insets.bottom
@@ -153,10 +170,13 @@ const styles = StyleSheet.create({
153
170
  container: {
154
171
  flex: 1
155
172
  },
173
+ webViewContainer: {
174
+ flex: 1,
175
+ width: '100%'
176
+ },
156
177
  webView: {
157
178
  flex: 1,
158
179
  width: '100%',
159
- height: '100%',
160
180
  resizeMode: 'contain'
161
181
  },
162
182
  footer: {
@@ -9,8 +9,10 @@ import AppContext from "../../Shared/Contexts/AppContext.js";
9
9
  import IdentityDocumentCamera from "../../Shared/Components/IdentityDocumentCamera.js";
10
10
  import { useTranslation } from 'react-i18next';
11
11
  import { trackFunnelStep, useScreenTracking, trackVerificationStart, trackVerificationComplete } from "../../Shared/Libs/analytics.utils.js";
12
+ import { useKeepAwake } from "../../Shared/Libs/native-keep-awake.utils.js";
12
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
14
  const IdentityDocumentEIDScanningScreen = () => {
15
+ useKeepAwake();
14
16
  const appContext = useContext(AppContext);
15
17
  const navigationManagerRef = React.useRef(null);
16
18
  const insets = useSafeAreaInsets();
@@ -55,6 +57,9 @@ const IdentityDocumentEIDScanningScreen = () => {
55
57
  setAllowedDocumentTypes(appContext.currentWorkflowStep?.data?.allowedDocumentTypes ?? null);
56
58
  setAllowedCountries(appContext.currentWorkflowStep?.data?.allowedCountries ?? null);
57
59
  }, [appContext.currentWorkflowStep]);
60
+ if (!appContext.currentWorkflowStep) {
61
+ return null;
62
+ }
58
63
  return /*#__PURE__*/_jsxs(SafeAreaView, {
59
64
  style: styles.safeAreaContainer,
60
65
  children: [documentNumber && dateOfBirth && dateOfExpiry ? /*#__PURE__*/_jsx(View, {
@@ -8,8 +8,10 @@ import AppContext from "../../Shared/Contexts/AppContext.js";
8
8
  import NavigationManager from "../../Shared/Components/NavigationManager.js";
9
9
  import { useTranslation } from 'react-i18next';
10
10
  import { trackFunnelStep, useScreenTracking, trackVerificationStart, trackVerificationComplete } from "../../Shared/Libs/analytics.utils.js";
11
+ import { useKeepAwake } from "../../Shared/Libs/native-keep-awake.utils.js";
11
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
13
  const IdentityDocumentScanningScreen = () => {
14
+ useKeepAwake();
13
15
  const [idFrontSideData, setIDFrontSideData] = useState(null);
14
16
  const [idBackSideData, setIDBackSideData] = useState(null);
15
17
  const [passportData, setPassportData] = useState();
@@ -83,6 +85,9 @@ const IdentityDocumentScanningScreen = () => {
83
85
  setAllowedDocumentTypes(appContext.currentWorkflowStep?.data?.allowedDocumentTypes ?? null);
84
86
  setAllowedCountries(appContext.currentWorkflowStep?.data?.allowedCountries ?? null);
85
87
  }, [appContext.currentWorkflowStep]);
88
+ if (!appContext.currentWorkflowStep) {
89
+ return null;
90
+ }
86
91
  return /*#__PURE__*/_jsxs(SafeAreaView, {
87
92
  style: styles.container,
88
93
  children: [/*#__PURE__*/_jsx(IdentityDocumentCamera, {