@trustchex/react-native-sdk 1.409.0 → 1.464.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/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKModule.kt +2 -8
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +59 -1
- package/ios/Camera/TrustchexCameraView.swift +9 -1
- package/lib/module/Screens/Debug/NFCScanTestScreen.js +635 -0
- package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +1 -4
- package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +17 -4
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +102 -23
- package/lib/module/Screens/Dynamic/VerbalConsentScreen.js +1079 -0
- package/lib/module/Screens/Dynamic/VideoCallScreen.js +3 -1
- package/lib/module/Screens/Static/ResultScreen.js +128 -22
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +8 -0
- package/lib/module/Shared/Animations/recording.json +1 -0
- package/lib/module/Shared/Components/DebugNavigationPanel.js +69 -71
- package/lib/module/Shared/Components/EIDScanner.js +212 -108
- package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +5 -3
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +53 -36
- package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +13 -4
- package/lib/module/Shared/Components/NavigationManager.js +24 -16
- package/lib/module/Shared/EIDReader/aesSecureMessagingWrapper.js +51 -0
- package/lib/module/Shared/EIDReader/apduLevelPACECapable.js +3 -0
- package/lib/module/Shared/EIDReader/bacKey.js +16 -2
- package/lib/module/Shared/EIDReader/eidReader.js +354 -13
- package/lib/module/Shared/EIDReader/eidService.js +25 -1
- package/lib/module/Shared/EIDReader/nfcManagerCardService.js +4 -7
- package/lib/module/Shared/EIDReader/paceInfo.js +85 -0
- package/lib/module/Shared/EIDReader/paceKeySpec.js +51 -0
- package/lib/module/Shared/EIDReader/protocol/paceAPDUSender.js +100 -0
- package/lib/module/Shared/EIDReader/protocol/paceProtocol.js +655 -0
- package/lib/module/Shared/EIDReader/protocol/paceResult.js +37 -0
- package/lib/module/Shared/EIDReader/secureMessagingWrapper.js +27 -4
- package/lib/module/Shared/EIDReader/smartcards/commandAPDU.js +2 -1
- package/lib/module/Shared/EIDReader/tlv/tlv.helpers.js +1 -1
- package/lib/module/Shared/EIDReader/tlv/tlv.utils.js +6 -3
- package/lib/module/Shared/EIDReader/utils/aesCrypto.utils.js +189 -0
- package/lib/module/Shared/Libs/analytics.utils.js +4 -0
- package/lib/module/Shared/Libs/contains.js +1 -40
- package/lib/module/Shared/Libs/country-display.utils.js +34 -0
- package/lib/module/Shared/Libs/demo.utils.js +8 -0
- package/lib/module/Shared/Libs/mrz.utils.js +3 -2
- package/lib/module/Shared/Libs/status-bar.utils.js +4 -2
- package/lib/module/Shared/Types/analytics.types.js +2 -0
- package/lib/module/Translation/Resources/en.js +41 -2
- package/lib/module/Translation/Resources/tr.js +41 -2
- package/lib/module/Trustchex.js +54 -20
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts.map +1 -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/LivenessDetectionScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.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/DebugNavigationPanel.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +5 -0
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts +18 -0
- package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts +23 -0
- package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts +6 -0
- package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts +9 -0
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/nfcManagerCardService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts +50 -0
- package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts +30 -0
- package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts +17 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts +105 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts +24 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts +15 -0
- package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/smartcards/commandAPDU.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/tlv/tlv.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts +39 -0
- package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/contains.d.ts +0 -7
- package/lib/typescript/src/Shared/Libs/contains.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts +2 -0
- package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts +2 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Types/identificationInfo.d.ts +10 -1
- package/lib/typescript/src/Shared/Types/identificationInfo.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +40 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +40 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +7 -4
- package/src/Screens/Debug/NFCScanTestScreen.tsx +692 -0
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +1 -4
- package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +21 -4
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +124 -23
- package/src/Screens/Dynamic/VerbalConsentScreen.tsx +1401 -0
- package/src/Screens/Dynamic/VideoCallScreen.tsx +3 -1
- package/src/Screens/Static/ResultScreen.tsx +183 -31
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +9 -0
- package/src/Shared/Animations/recording.json +1 -0
- package/src/Shared/Components/DebugNavigationPanel.tsx +73 -48
- package/src/Shared/Components/EIDScanner.tsx +222 -111
- package/src/Shared/Components/IdentityDocumentCamera.flows.ts +7 -4
- package/src/Shared/Components/IdentityDocumentCamera.tsx +199 -184
- package/src/Shared/Components/IdentityDocumentCamera.utils.ts +13 -4
- package/src/Shared/Components/NavigationManager.tsx +27 -18
- package/src/Shared/EIDReader/aesSecureMessagingWrapper.ts +69 -0
- package/src/Shared/EIDReader/apduLevelPACECapable.ts +34 -0
- package/src/Shared/EIDReader/bacKey.ts +24 -8
- package/src/Shared/EIDReader/eidReader.ts +398 -12
- package/src/Shared/EIDReader/eidService.ts +49 -1
- package/src/Shared/EIDReader/nfcManagerCardService.ts +4 -6
- package/src/Shared/EIDReader/paceInfo.ts +159 -0
- package/src/Shared/EIDReader/paceKeySpec.ts +56 -0
- package/src/Shared/EIDReader/protocol/paceAPDUSender.ts +163 -0
- package/src/Shared/EIDReader/protocol/paceProtocol.ts +946 -0
- package/src/Shared/EIDReader/protocol/paceResult.ts +62 -0
- package/src/Shared/EIDReader/secureMessagingWrapper.ts +28 -10
- package/src/Shared/EIDReader/smartcards/commandAPDU.ts +2 -1
- package/src/Shared/EIDReader/tlv/tlv.helpers.ts +1 -1
- package/src/Shared/EIDReader/tlv/tlv.utils.ts +8 -5
- package/src/Shared/EIDReader/utils/aesCrypto.utils.ts +217 -0
- package/src/Shared/Libs/analytics.utils.ts +4 -0
- package/src/Shared/Libs/contains.ts +0 -53
- package/src/Shared/Libs/country-display.utils.ts +55 -0
- package/src/Shared/Libs/crypto.utils.ts +2 -2
- package/src/Shared/Libs/demo.utils.ts +10 -0
- package/src/Shared/Libs/http-client.ts +12 -4
- package/src/Shared/Libs/mrz.utils.ts +3 -2
- package/src/Shared/Libs/status-bar.utils.ts +4 -2
- package/src/Shared/Services/VideoSessionService.ts +1 -1
- package/src/Shared/Types/analytics.types.ts +2 -0
- package/src/Shared/Types/identificationInfo.ts +11 -0
- package/src/Translation/Resources/en.ts +63 -3
- package/src/Translation/Resources/tr.ts +62 -3
- package/src/Trustchex.tsx +53 -17
- package/src/version.ts +1 -1
|
@@ -30,10 +30,27 @@ const IdentityDocumentEIDScanningScreen = () => {
|
|
|
30
30
|
useState<DocumentScannedData | null>(null);
|
|
31
31
|
const [passportData, setPassportData] =
|
|
32
32
|
useState<DocumentScannedData | null>();
|
|
33
|
-
const [documentNumber, setDocumentNumber] = useState<string>(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const [documentNumber, setDocumentNumber] = useState<string | undefined>(
|
|
34
|
+
() => {
|
|
35
|
+
const mrzFields =
|
|
36
|
+
appContext.identificationInfo.scannedDocument?.mrzFields;
|
|
37
|
+
return mrzFields?.documentNumber ?? undefined;
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
const [dateOfBirth, setDateOfBirth] = useState<string | undefined>(() => {
|
|
41
|
+
const mrzFields = appContext.identificationInfo.scannedDocument?.mrzFields;
|
|
42
|
+
return mrzFields?.birthDate ?? undefined;
|
|
43
|
+
});
|
|
44
|
+
const [dateOfExpiry, setDateOfExpiry] = useState<string | undefined>(() => {
|
|
45
|
+
const mrzFields = appContext.identificationInfo.scannedDocument?.mrzFields;
|
|
46
|
+
return mrzFields?.expirationDate ?? undefined;
|
|
47
|
+
});
|
|
48
|
+
const [documentType, setDocumentType] = useState<string | undefined>(() => {
|
|
49
|
+
const dc =
|
|
50
|
+
appContext.identificationInfo.scannedDocument?.mrzFields?.documentCode;
|
|
51
|
+
if (!dc) return undefined;
|
|
52
|
+
return dc === 'I' ? 'ID' : dc === 'P' ? 'PASSPORT' : 'UNKNOWN';
|
|
53
|
+
});
|
|
37
54
|
const [isNFCSupported, setIsNFCSupported] = useState<boolean>(false);
|
|
38
55
|
const { t } = useTranslation();
|
|
39
56
|
const [allowedDocumentTypes, setAllowedDocumentTypes] = useState<
|
|
@@ -9,10 +9,13 @@ import React, {
|
|
|
9
9
|
useRef,
|
|
10
10
|
} from 'react';
|
|
11
11
|
import {
|
|
12
|
+
Animated,
|
|
13
|
+
Easing,
|
|
12
14
|
StyleSheet,
|
|
13
15
|
Text,
|
|
14
16
|
View,
|
|
15
17
|
Dimensions,
|
|
18
|
+
Platform,
|
|
16
19
|
Vibration,
|
|
17
20
|
StatusBar,
|
|
18
21
|
} from 'react-native';
|
|
@@ -27,7 +30,7 @@ import NavigationManager, {
|
|
|
27
30
|
type NavigationManagerRef,
|
|
28
31
|
} from '../../Shared/Components/NavigationManager';
|
|
29
32
|
import AppContext from '../../Shared/Contexts/AppContext';
|
|
30
|
-
import {
|
|
33
|
+
import { type Rect } from '../../Shared/Libs/contains';
|
|
31
34
|
import { useTranslation } from 'react-i18next';
|
|
32
35
|
import StyledButton from '../../Shared/Components/StyledButton';
|
|
33
36
|
import LottieView from 'lottie-react-native';
|
|
@@ -43,7 +46,7 @@ import { useKeepAwake } from '../../Shared/Libs/native-keep-awake.utils';
|
|
|
43
46
|
|
|
44
47
|
const { width: windowWidth, height: windowHeight } = Dimensions.get('window');
|
|
45
48
|
|
|
46
|
-
const PREVIEW_SIZE = windowWidth * 0.
|
|
49
|
+
const PREVIEW_SIZE = windowWidth * 0.95;
|
|
47
50
|
const PREVIEW_RECT: Rect = {
|
|
48
51
|
minX: (windowWidth - PREVIEW_SIZE) / 2,
|
|
49
52
|
minY: (windowHeight - PREVIEW_SIZE) / 2,
|
|
@@ -96,10 +99,36 @@ const LivenessDetectionScreen = () => {
|
|
|
96
99
|
const [isRecording, setIsRecording] = useState(false);
|
|
97
100
|
const insets = useSafeAreaInsets();
|
|
98
101
|
const referenceFaceTrackingId = useRef<number | null>(null);
|
|
102
|
+
const recordingDotOpacity = useRef(new Animated.Value(1)).current;
|
|
99
103
|
|
|
100
104
|
// Track screen view and exit
|
|
101
105
|
useScreenTracking('liveness_detection');
|
|
102
106
|
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (isRecording) {
|
|
109
|
+
const pulse = Animated.loop(
|
|
110
|
+
Animated.sequence([
|
|
111
|
+
Animated.timing(recordingDotOpacity, {
|
|
112
|
+
toValue: 0.2,
|
|
113
|
+
duration: 600,
|
|
114
|
+
easing: Easing.inOut(Easing.ease),
|
|
115
|
+
useNativeDriver: true,
|
|
116
|
+
}),
|
|
117
|
+
Animated.timing(recordingDotOpacity, {
|
|
118
|
+
toValue: 1,
|
|
119
|
+
duration: 600,
|
|
120
|
+
easing: Easing.inOut(Easing.ease),
|
|
121
|
+
useNativeDriver: true,
|
|
122
|
+
}),
|
|
123
|
+
])
|
|
124
|
+
);
|
|
125
|
+
pulse.start();
|
|
126
|
+
return () => pulse.stop();
|
|
127
|
+
} else {
|
|
128
|
+
recordingDotOpacity.setValue(1);
|
|
129
|
+
}
|
|
130
|
+
}, [isRecording, recordingDotOpacity]);
|
|
131
|
+
|
|
103
132
|
// Configure status bar for white background
|
|
104
133
|
useStatusBarWhiteBackground();
|
|
105
134
|
|
|
@@ -167,7 +196,9 @@ const LivenessDetectionScreen = () => {
|
|
|
167
196
|
} else {
|
|
168
197
|
// Guide screen with white background - use dark icons
|
|
169
198
|
StatusBar.setBarStyle('dark-content', true);
|
|
170
|
-
|
|
199
|
+
if (Platform.OS === 'android') {
|
|
200
|
+
StatusBar.setBackgroundColor('#ffffff', true);
|
|
201
|
+
}
|
|
171
202
|
}
|
|
172
203
|
}, [hasGuideShown]);
|
|
173
204
|
|
|
@@ -289,6 +320,14 @@ const LivenessDetectionScreen = () => {
|
|
|
289
320
|
return leftOpen >= 0.8 && rightOpen >= 0.8;
|
|
290
321
|
};
|
|
291
322
|
|
|
323
|
+
const areEyesVisible = (face: Face) => {
|
|
324
|
+
// Relaxed check: eyes just need to be detected (not fully closed).
|
|
325
|
+
// Smiling naturally causes squinting, so a lower threshold is used.
|
|
326
|
+
const leftOpen = face.leftEyeOpenProbability ?? 0;
|
|
327
|
+
const rightOpen = face.rightEyeOpenProbability ?? 0;
|
|
328
|
+
return leftOpen >= 0.3 && rightOpen >= 0.3;
|
|
329
|
+
};
|
|
330
|
+
|
|
292
331
|
const instructionReducer = (
|
|
293
332
|
state: StateType,
|
|
294
333
|
action: PossibleActions
|
|
@@ -526,26 +565,42 @@ const LivenessDetectionScreen = () => {
|
|
|
526
565
|
);
|
|
527
566
|
}
|
|
528
567
|
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
|
|
568
|
+
// Map the on-screen circle into frame coordinates.
|
|
569
|
+
// Camera uses FILL_CENTER / resizeAspectFill (cover): uniform scale filling
|
|
570
|
+
// the view, cropping overflow symmetrically.
|
|
571
|
+
const coverScale = Math.max(
|
|
572
|
+
windowWidth / frameWidth,
|
|
573
|
+
windowHeight / frameHeight
|
|
574
|
+
);
|
|
575
|
+
const offsetX = (frameWidth - windowWidth / coverScale) / 2;
|
|
576
|
+
const offsetY = (frameHeight - windowHeight / coverScale) / 2;
|
|
532
577
|
const previewRectInFrame: Rect = {
|
|
533
|
-
minX:
|
|
534
|
-
minY:
|
|
535
|
-
width:
|
|
536
|
-
height:
|
|
578
|
+
minX: PREVIEW_RECT.minX / coverScale + offsetX,
|
|
579
|
+
minY: PREVIEW_RECT.minY / coverScale + offsetY,
|
|
580
|
+
width: PREVIEW_RECT.width / coverScale,
|
|
581
|
+
height: PREVIEW_RECT.height / coverScale,
|
|
537
582
|
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
583
|
+
const previewSizeInFrame = PREVIEW_RECT.width / coverScale;
|
|
584
|
+
|
|
585
|
+
// Check containment using face center + yaw-stable core radius.
|
|
586
|
+
// When the head turns (yaw), the bounding box grows wider but height stays
|
|
587
|
+
// constant — so min(width, height)/2 gives a stable size that doesn't
|
|
588
|
+
// falsely trigger an outside-circle reset during TURN_HEAD_LEFT/RIGHT.
|
|
589
|
+
const faceCenterX = face.bounds.x + face.bounds.width / 2;
|
|
590
|
+
const faceCenterY = face.bounds.y + face.bounds.height / 2;
|
|
591
|
+
const faceCoreRadius = Math.max(
|
|
592
|
+
0,
|
|
593
|
+
Math.min(face.bounds.width, face.bounds.height) / 2 -
|
|
594
|
+
PREVIEW_EDGE_OFFSET / 2
|
|
595
|
+
);
|
|
596
|
+
const circleCX = previewRectInFrame.minX + previewRectInFrame.width / 2;
|
|
597
|
+
const circleCY = previewRectInFrame.minY + previewRectInFrame.height / 2;
|
|
598
|
+
const circleR = previewSizeInFrame / 2;
|
|
599
|
+
const faceDx = faceCenterX - circleCX;
|
|
600
|
+
const faceDy = faceCenterY - circleCY;
|
|
601
|
+
const previewContainsFace =
|
|
602
|
+
faceDx * faceDx + faceDy * faceDy <=
|
|
603
|
+
(circleR - faceCoreRadius) * (circleR - faceCoreRadius);
|
|
549
604
|
const multipleFacesDetected = faces.length > 1;
|
|
550
605
|
|
|
551
606
|
if (!isImageBright) {
|
|
@@ -694,11 +749,12 @@ const LivenessDetectionScreen = () => {
|
|
|
694
749
|
instructions.SMILE.minAngle < face.pitchAngle &&
|
|
695
750
|
face.pitchAngle < instructions.SMILE.maxAngle;
|
|
696
751
|
|
|
697
|
-
// Check if smiling with sufficient probability AND looking at camera AND eyes
|
|
752
|
+
// Check if smiling with sufficient probability AND looking at camera AND eyes visible
|
|
753
|
+
// Use relaxed eye check — smiling naturally causes squinting
|
|
698
754
|
if (
|
|
699
755
|
smilingProb >= instructions.SMILE.minProbability &&
|
|
700
756
|
isFacingCamera &&
|
|
701
|
-
|
|
757
|
+
areEyesVisible(face)
|
|
702
758
|
) {
|
|
703
759
|
instructions.SMILE.photo = image;
|
|
704
760
|
dispatch({ type: 'NEXT_INSTRUCTION', payload: 'SMILE' });
|
|
@@ -890,6 +946,24 @@ const LivenessDetectionScreen = () => {
|
|
|
890
946
|
mask="url(#hole-mask)"
|
|
891
947
|
/>
|
|
892
948
|
</Svg>
|
|
949
|
+
{isRecording && (
|
|
950
|
+
<View
|
|
951
|
+
style={[
|
|
952
|
+
styles.recordingIndicatorContainer,
|
|
953
|
+
{ top: PREVIEW_RECT.minY - 40 },
|
|
954
|
+
]}
|
|
955
|
+
>
|
|
956
|
+
<View style={styles.recordingIndicator}>
|
|
957
|
+
<Animated.View
|
|
958
|
+
style={[
|
|
959
|
+
styles.recordingDot,
|
|
960
|
+
{ opacity: recordingDotOpacity },
|
|
961
|
+
]}
|
|
962
|
+
/>
|
|
963
|
+
<Text style={styles.recordingText}>REC</Text>
|
|
964
|
+
</View>
|
|
965
|
+
</View>
|
|
966
|
+
)}
|
|
893
967
|
<View
|
|
894
968
|
style={[
|
|
895
969
|
styles.instructionsContainerBottom,
|
|
@@ -1014,6 +1088,33 @@ const styles = StyleSheet.create({
|
|
|
1014
1088
|
width: '100%',
|
|
1015
1089
|
zIndex: 1,
|
|
1016
1090
|
},
|
|
1091
|
+
recordingIndicatorContainer: {
|
|
1092
|
+
position: 'absolute',
|
|
1093
|
+
width: '100%',
|
|
1094
|
+
alignItems: 'center',
|
|
1095
|
+
zIndex: 2,
|
|
1096
|
+
},
|
|
1097
|
+
recordingIndicator: {
|
|
1098
|
+
flexDirection: 'row',
|
|
1099
|
+
alignItems: 'center',
|
|
1100
|
+
gap: 8,
|
|
1101
|
+
backgroundColor: 'rgba(0, 0, 0, 0.6)',
|
|
1102
|
+
paddingVertical: 6,
|
|
1103
|
+
paddingHorizontal: 14,
|
|
1104
|
+
borderRadius: 20,
|
|
1105
|
+
},
|
|
1106
|
+
recordingDot: {
|
|
1107
|
+
width: 10,
|
|
1108
|
+
height: 10,
|
|
1109
|
+
borderRadius: 5,
|
|
1110
|
+
backgroundColor: '#ef4444',
|
|
1111
|
+
},
|
|
1112
|
+
recordingText: {
|
|
1113
|
+
color: '#ffffff',
|
|
1114
|
+
fontSize: 14,
|
|
1115
|
+
fontWeight: '700',
|
|
1116
|
+
letterSpacing: 1,
|
|
1117
|
+
},
|
|
1017
1118
|
guide: {
|
|
1018
1119
|
flex: 1,
|
|
1019
1120
|
display: 'flex',
|