@trustchex/react-native-sdk 1.360.0 → 1.362.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/TrustchexSDK.podspec +3 -1
- package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKPackage.kt +0 -13
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraManager.kt +0 -8
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +59 -39
- package/android/src/main/java/com/trustchex/reactnativesdk/opencv/OpenCVModule.kt +94 -13
- package/ios/Camera/TrustchexCameraManager.m +0 -2
- package/ios/Camera/TrustchexCameraManager.swift +0 -7
- package/ios/Camera/TrustchexCameraView.swift +16 -47
- package/ios/OpenCV/OpenCVHelper.h +17 -0
- package/ios/OpenCV/OpenCVHelper.mm +128 -0
- package/ios/OpenCV/OpenCVModule.h +6 -0
- package/ios/OpenCV/OpenCVModule.mm +141 -0
- package/ios/TrustchexSDK-Bridging-Header.h +8 -0
- package/lib/module/Screens/Debug/MRZTestScreen.js +175 -0
- package/lib/module/Shared/Components/DebugNavigationPanel.js +4 -0
- package/lib/module/Shared/Components/EIDScanner.js +0 -78
- package/lib/module/Shared/Components/FaceCamera.js +6 -3
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +199 -153
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +0 -3
- package/lib/module/Shared/Config/camera-enhancement.config.js +11 -12
- package/lib/module/Shared/Libs/mrz.utils.js +265 -0
- package/lib/module/Trustchex.js +4 -0
- package/lib/module/index.js +1 -0
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Components/DebugNavigationPanel.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.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts +3 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts +0 -19
- package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Config/camera-enhancement.config.d.ts +10 -10
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +18 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +2 -1
- package/src/Screens/Debug/MRZTestScreen.tsx +209 -0
- package/src/Shared/Components/DebugNavigationPanel.tsx +5 -0
- package/src/Shared/Components/EIDScanner.tsx +0 -53
- package/src/Shared/Components/FaceCamera.tsx +6 -3
- package/src/Shared/Components/IdentityDocumentCamera.tsx +246 -149
- package/src/Shared/Components/QrCodeScannerCamera.tsx +0 -9
- package/src/Shared/Components/TrustchexCamera.tsx +0 -20
- package/src/Shared/Config/camera-enhancement.config.ts +6 -6
- package/src/Shared/Libs/mrz.utils.ts +289 -1
- package/src/Trustchex.tsx +5 -0
- package/src/index.tsx +3 -0
- package/src/version.ts +1 -1
- package/android/src/main/java/com/trustchex/reactnativesdk/mrz/MRZValidationModule.kt +0 -785
- package/android/src/main/java/com/trustchex/reactnativesdk/mrz/MRZValidator.kt +0 -419
- package/ios/MRZValidation.m +0 -39
- package/ios/MRZValidation.swift +0 -802
- package/ios/MRZValidator.swift +0 -466
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import React, { useState, useRef, useCallback } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Text,
|
|
6
|
+
ScrollView,
|
|
7
|
+
StatusBar,
|
|
8
|
+
TouchableOpacity,
|
|
9
|
+
type NativeSyntheticEvent,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
12
|
+
import {
|
|
13
|
+
TrustchexCamera,
|
|
14
|
+
type TrustchexCameraHandle,
|
|
15
|
+
type Frame,
|
|
16
|
+
} from '../../Shared/Components/TrustchexCamera';
|
|
17
|
+
import mrzUtils from '../../Shared/Libs/mrz.utils';
|
|
18
|
+
|
|
19
|
+
const MRZTestScreen = () => {
|
|
20
|
+
const cameraRef = useRef<TrustchexCameraHandle>(null);
|
|
21
|
+
const [mrzText, setMrzText] = useState<string>('Waiting for MRZ...');
|
|
22
|
+
const [mrzRawText, setMrzRawText] = useState<string>('');
|
|
23
|
+
const [mrzValid, setMrzValid] = useState<boolean>(false);
|
|
24
|
+
const [rawHistory, setRawHistory] = useState<string[]>([]);
|
|
25
|
+
const [isPaused, setIsPaused] = useState<boolean>(false);
|
|
26
|
+
|
|
27
|
+
const handleFrame = useCallback(
|
|
28
|
+
(event: NativeSyntheticEvent<{ frame: Frame }>) => {
|
|
29
|
+
if (isPaused) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const frame = event.nativeEvent.frame;
|
|
34
|
+
|
|
35
|
+
if (frame.resultText) {
|
|
36
|
+
setRawHistory((prev) => {
|
|
37
|
+
if (prev[0] === frame.resultText) {
|
|
38
|
+
return prev;
|
|
39
|
+
}
|
|
40
|
+
const next = [frame.resultText, ...prev];
|
|
41
|
+
return next.slice(0, 20);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (frame.resultText && frame.resultText.includes('<')) {
|
|
46
|
+
// Extract MRZ-only text from detected blocks
|
|
47
|
+
let mrzOnlyText = '';
|
|
48
|
+
if (frame.textBlocks && frame.textBlocks.length > 0) {
|
|
49
|
+
// Filter blocks that look like MRZ (contain < and are in bottom half of frame)
|
|
50
|
+
const frameHeight = frame.height;
|
|
51
|
+
const bottomThreshold = frameHeight * 0.5;
|
|
52
|
+
|
|
53
|
+
const mrzBlocks = frame.textBlocks.filter((block) => {
|
|
54
|
+
const blockText = block.text || '';
|
|
55
|
+
const hasFillers = blockText.includes('<');
|
|
56
|
+
const isInBottomArea = block.blockFrame
|
|
57
|
+
? block.blockFrame.y > bottomThreshold
|
|
58
|
+
: false;
|
|
59
|
+
const isLongEnough = blockText.length >= 12;
|
|
60
|
+
return hasFillers && isInBottomArea && isLongEnough;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (mrzBlocks.length > 0) {
|
|
64
|
+
mrzOnlyText = mrzBlocks.map((b) => b.text).join('\n');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Fallback to full text if no MRZ blocks detected
|
|
69
|
+
if (!mrzOnlyText) {
|
|
70
|
+
mrzOnlyText = frame.resultText;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const fixedMrz = mrzUtils.fixMRZ(mrzOnlyText);
|
|
74
|
+
setMrzRawText(mrzOnlyText);
|
|
75
|
+
setMrzText(fixedMrz);
|
|
76
|
+
setMrzValid(mrzUtils.validateMRZWithCorrections(fixedMrz).valid);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
[isPaused]
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<View style={styles.container}>
|
|
84
|
+
<StatusBar
|
|
85
|
+
barStyle="light-content"
|
|
86
|
+
backgroundColor="transparent"
|
|
87
|
+
translucent
|
|
88
|
+
/>
|
|
89
|
+
<TrustchexCamera
|
|
90
|
+
ref={cameraRef}
|
|
91
|
+
style={styles.camera}
|
|
92
|
+
cameraType="back"
|
|
93
|
+
enableFrameProcessing={true}
|
|
94
|
+
enableFaceDetection={false}
|
|
95
|
+
enableTextRecognition={true}
|
|
96
|
+
enableBarcodeScanning={false}
|
|
97
|
+
includeBase64={false}
|
|
98
|
+
targetFps={10}
|
|
99
|
+
onFrameAvailable={handleFrame}
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
<SafeAreaView style={styles.mrzPanel} edges={['bottom']}>
|
|
103
|
+
<ScrollView style={styles.scrollView}>
|
|
104
|
+
<View style={styles.panelContent}>
|
|
105
|
+
<TouchableOpacity
|
|
106
|
+
style={styles.pauseButton}
|
|
107
|
+
onPress={() => setIsPaused(!isPaused)}
|
|
108
|
+
>
|
|
109
|
+
<Text style={styles.pauseButtonText}>
|
|
110
|
+
{isPaused ? 'Resume Processing' : 'Pause Processing'}
|
|
111
|
+
</Text>
|
|
112
|
+
</TouchableOpacity>
|
|
113
|
+
<Text style={styles.title}>MRZ Text Read</Text>
|
|
114
|
+
<Text style={styles.sectionTitle}>MRZ Raw Text</Text>
|
|
115
|
+
<Text style={styles.mrzText}>
|
|
116
|
+
{mrzRawText
|
|
117
|
+
? mrzRawText
|
|
118
|
+
.split('\n')
|
|
119
|
+
.map(
|
|
120
|
+
(line, i) =>
|
|
121
|
+
`Line ${i + 1}: ${line} (${line.length} chars)`
|
|
122
|
+
)
|
|
123
|
+
.join('\n')
|
|
124
|
+
: 'No MRZ raw text'}
|
|
125
|
+
</Text>
|
|
126
|
+
<Text style={styles.sectionTitle}>MRZ Corrected Text</Text>
|
|
127
|
+
<Text style={[styles.mrzText, mrzValid ? styles.mrzValid : null]}>
|
|
128
|
+
{mrzText
|
|
129
|
+
.split('\n')
|
|
130
|
+
.map(
|
|
131
|
+
(line, i) => `Line ${i + 1}: ${line} (${line.length} chars)`
|
|
132
|
+
)
|
|
133
|
+
.join('\n')}
|
|
134
|
+
</Text>
|
|
135
|
+
<Text style={styles.sectionTitle}>Raw Text History</Text>
|
|
136
|
+
<Text style={styles.mrzText}>
|
|
137
|
+
{rawHistory.length > 0
|
|
138
|
+
? rawHistory
|
|
139
|
+
.map((text, i) => `#${i + 1}: ${text.replace(/\n/g, ' ')}`)
|
|
140
|
+
.join('\n')
|
|
141
|
+
: 'No history'}
|
|
142
|
+
</Text>
|
|
143
|
+
</View>
|
|
144
|
+
</ScrollView>
|
|
145
|
+
</SafeAreaView>
|
|
146
|
+
</View>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const styles = StyleSheet.create({
|
|
151
|
+
container: {
|
|
152
|
+
flex: 1,
|
|
153
|
+
backgroundColor: '#000000',
|
|
154
|
+
},
|
|
155
|
+
camera: {
|
|
156
|
+
flex: 2,
|
|
157
|
+
},
|
|
158
|
+
mrzPanel: {
|
|
159
|
+
flex: 1,
|
|
160
|
+
backgroundColor: 'rgba(0, 0, 0, 0.95)',
|
|
161
|
+
borderTopWidth: 2,
|
|
162
|
+
borderTopColor: '#FFA500',
|
|
163
|
+
},
|
|
164
|
+
scrollView: {
|
|
165
|
+
flex: 1,
|
|
166
|
+
},
|
|
167
|
+
panelContent: {
|
|
168
|
+
padding: 10,
|
|
169
|
+
},
|
|
170
|
+
pauseButton: {
|
|
171
|
+
alignSelf: 'center',
|
|
172
|
+
borderWidth: 1,
|
|
173
|
+
borderColor: '#FFA500',
|
|
174
|
+
borderRadius: 4,
|
|
175
|
+
paddingVertical: 6,
|
|
176
|
+
paddingHorizontal: 12,
|
|
177
|
+
marginBottom: 8,
|
|
178
|
+
},
|
|
179
|
+
pauseButtonText: {
|
|
180
|
+
color: '#FFA500',
|
|
181
|
+
fontSize: 10,
|
|
182
|
+
fontWeight: 'bold',
|
|
183
|
+
},
|
|
184
|
+
title: {
|
|
185
|
+
color: '#FFA500',
|
|
186
|
+
fontSize: 12,
|
|
187
|
+
fontWeight: 'bold',
|
|
188
|
+
marginBottom: 8,
|
|
189
|
+
textAlign: 'center',
|
|
190
|
+
},
|
|
191
|
+
sectionTitle: {
|
|
192
|
+
color: '#FFA500',
|
|
193
|
+
fontSize: 10,
|
|
194
|
+
fontWeight: 'bold',
|
|
195
|
+
marginTop: 6,
|
|
196
|
+
marginBottom: 4,
|
|
197
|
+
},
|
|
198
|
+
mrzText: {
|
|
199
|
+
color: '#FFFFFF',
|
|
200
|
+
fontSize: 9,
|
|
201
|
+
fontFamily: 'monospace',
|
|
202
|
+
lineHeight: 16,
|
|
203
|
+
},
|
|
204
|
+
mrzValid: {
|
|
205
|
+
color: '#00C853',
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
export default MRZTestScreen;
|
|
@@ -13,7 +13,6 @@ import StyledButton from './StyledButton';
|
|
|
13
13
|
import LottieView from 'lottie-react-native';
|
|
14
14
|
import { useKeepAwake } from '../Libs/native-keep-awake.utils';
|
|
15
15
|
import { speak, resetLastMessage } from '../Libs/tts.utils';
|
|
16
|
-
import { isDebugEnabled } from '../Libs/debug.utils';
|
|
17
16
|
import {
|
|
18
17
|
trackEIDScanStart,
|
|
19
18
|
trackEIDScanComplete,
|
|
@@ -618,58 +617,6 @@ const EIDScanner = ({
|
|
|
618
617
|
</StyledButton>
|
|
619
618
|
</View>
|
|
620
619
|
)}
|
|
621
|
-
|
|
622
|
-
{isDebugEnabled() && (
|
|
623
|
-
<View
|
|
624
|
-
style={{
|
|
625
|
-
position: 'absolute',
|
|
626
|
-
top: insets.top + 10,
|
|
627
|
-
right: 10,
|
|
628
|
-
backgroundColor: 'rgba(0, 0, 0, 0.85)',
|
|
629
|
-
padding: 10,
|
|
630
|
-
borderRadius: 8,
|
|
631
|
-
borderWidth: 1,
|
|
632
|
-
borderColor: '#FF6B6B',
|
|
633
|
-
maxWidth: 200,
|
|
634
|
-
zIndex: 1001,
|
|
635
|
-
}}
|
|
636
|
-
>
|
|
637
|
-
<Text
|
|
638
|
-
style={{
|
|
639
|
-
color: '#FF6B6B',
|
|
640
|
-
fontSize: 11,
|
|
641
|
-
fontWeight: 'bold',
|
|
642
|
-
marginBottom: 6,
|
|
643
|
-
}}
|
|
644
|
-
>
|
|
645
|
-
🐛 DEBUG MODE
|
|
646
|
-
</Text>
|
|
647
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
648
|
-
{`NFC: ${hasNfc ? '✓' : '✗'}`}
|
|
649
|
-
</Text>
|
|
650
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
651
|
-
{`Enabled: ${isEnabled ? '✓' : '✗'}`}
|
|
652
|
-
</Text>
|
|
653
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
654
|
-
{`Scanning: ${isScanning ? '✓' : '○'}`}
|
|
655
|
-
</Text>
|
|
656
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
657
|
-
{`Scanned: ${isScanned ? '✓' : '○'}`}
|
|
658
|
-
</Text>
|
|
659
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
660
|
-
{`Progress: ${Math.round(progress)}%`}
|
|
661
|
-
</Text>
|
|
662
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
663
|
-
{`Face Image: ${documentFaceImage ? '✓' : '✗'}`}
|
|
664
|
-
</Text>
|
|
665
|
-
<Text style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}>
|
|
666
|
-
{`MRZ Info: ${documentMRZInfo ? '✓' : '✗'}`}
|
|
667
|
-
</Text>
|
|
668
|
-
<Text style={{ color: '#88D8B0', fontSize: 9 }}>
|
|
669
|
-
{`Doc Type: ${documentType}`}
|
|
670
|
-
</Text>
|
|
671
|
-
</View>
|
|
672
|
-
)}
|
|
673
620
|
</>
|
|
674
621
|
)}
|
|
675
622
|
</View>
|
|
@@ -26,9 +26,9 @@ import { Dimensions } from 'react-native';
|
|
|
26
26
|
|
|
27
27
|
const { width: windowWidth, height: windowHeight } = Dimensions.get('window');
|
|
28
28
|
const { OpenCVModule } = NativeModules;
|
|
29
|
-
const MIN_BRIGHTNESS_THRESHOLD =
|
|
29
|
+
const MIN_BRIGHTNESS_THRESHOLD = 60;
|
|
30
30
|
const BLUR_VARIANCE_THRESHOLD = 60;
|
|
31
|
-
const REGION_BRIGHTNESS_THRESHOLD =
|
|
31
|
+
const REGION_BRIGHTNESS_THRESHOLD = 50;
|
|
32
32
|
|
|
33
33
|
export type Face = {
|
|
34
34
|
bounds: {
|
|
@@ -222,7 +222,7 @@ const FaceCamera = ({
|
|
|
222
222
|
const isBright = avgBrightness >= MIN_BRIGHTNESS_THRESHOLD;
|
|
223
223
|
|
|
224
224
|
// Check brightness in the region of interest (circular preview area)
|
|
225
|
-
let isRegionBright =
|
|
225
|
+
let isRegionBright = false;
|
|
226
226
|
if (previewRect && base64Image && OpenCVModule) {
|
|
227
227
|
try {
|
|
228
228
|
// Scale preview rect from screen coordinates to frame coordinates
|
|
@@ -243,7 +243,10 @@ const FaceCamera = ({
|
|
|
243
243
|
);
|
|
244
244
|
} catch (error) {
|
|
245
245
|
debugWarn('FaceCamera', 'Region brightness check failed:', error);
|
|
246
|
+
isRegionBright = isBright;
|
|
246
247
|
}
|
|
248
|
+
} else {
|
|
249
|
+
isRegionBright = isBright;
|
|
247
250
|
}
|
|
248
251
|
|
|
249
252
|
// Check for blur using OpenCV Laplacian variance
|