@hexar/biometric-identity-sdk-react-native 1.0.13 → 1.0.15
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/dist/components/BiometricIdentityFlow.d.ts.map +1 -1
- package/dist/components/BiometricIdentityFlow.js +11 -7
- package/dist/components/CameraCapture.d.ts.map +1 -1
- package/dist/components/CameraCapture.js +3 -3
- package/dist/components/VideoRecorder.d.ts.map +1 -1
- package/dist/components/VideoRecorder.js +11 -11
- package/dist/hooks/useBiometricSDK.d.ts.map +1 -1
- package/dist/hooks/useBiometricSDK.js +2 -2
- package/package.json +1 -1
- package/src/components/BiometricIdentityFlow.tsx +12 -7
- package/src/components/CameraCapture.tsx +4 -4
- package/src/components/VideoRecorder.tsx +12 -12
- package/src/hooks/useBiometricSDK.ts +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BiometricIdentityFlow.d.ts","sourceRoot":"","sources":["../../src/components/BiometricIdentityFlow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAChE,OAAO,EAOL,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,cAAc,EAKd,iBAAiB,
|
|
1
|
+
{"version":3,"file":"BiometricIdentityFlow.d.ts","sourceRoot":"","sources":["../../src/components/BiometricIdentityFlow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAChE,OAAO,EAOL,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,cAAc,EAKd,iBAAiB,EAElB,MAAM,oCAAoC,CAAC;AAU5C,MAAM,WAAW,0BAA0B;IACzC,oBAAoB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,OAAO,CAAC,EAAE,SAAS,CAAC;KACrB,CAAC;CACH;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAoTtE,CAAC;AAiOF,eAAe,qBAAqB,CAAC"}
|
|
@@ -69,12 +69,13 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
|
|
|
69
69
|
}, [language]);
|
|
70
70
|
const strings = (0, biometric_identity_sdk_core_1.getStrings)();
|
|
71
71
|
const styles = createStyles(theme);
|
|
72
|
-
// Handle validation result
|
|
72
|
+
// Handle validation result - call callback when RESULT step is reached
|
|
73
73
|
(0, react_1.useEffect)(() => {
|
|
74
|
-
if (state.validationResult) {
|
|
74
|
+
if (state.currentStep === biometric_identity_sdk_core_1.SDKStep.RESULT && state.validationResult) {
|
|
75
|
+
// Call callback automatically when validation completes
|
|
75
76
|
onValidationComplete(state.validationResult);
|
|
76
77
|
}
|
|
77
|
-
}, [state.validationResult, onValidationComplete]);
|
|
78
|
+
}, [state.currentStep, state.validationResult, onValidationComplete]);
|
|
78
79
|
// Handle error
|
|
79
80
|
(0, react_1.useEffect)(() => {
|
|
80
81
|
if (state.error) {
|
|
@@ -94,7 +95,7 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
|
|
|
94
95
|
setCurrentChallenges(challenges);
|
|
95
96
|
}
|
|
96
97
|
catch (error) {
|
|
97
|
-
|
|
98
|
+
biometric_identity_sdk_core_1.logger.warn('Failed to fetch challenges, using defaults');
|
|
98
99
|
setCurrentChallenges(sdk.getDefaultChallenges());
|
|
99
100
|
}
|
|
100
101
|
setIsLoadingChallenges(false);
|
|
@@ -127,12 +128,12 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
|
|
|
127
128
|
challengesCompleted: videoResult.challengesCompleted,
|
|
128
129
|
sessionId: videoResult.sessionId,
|
|
129
130
|
});
|
|
130
|
-
|
|
131
|
+
biometric_identity_sdk_core_1.logger.info('Starting validation...');
|
|
131
132
|
await validateIdentity();
|
|
132
133
|
}
|
|
133
134
|
}
|
|
134
135
|
catch (error) {
|
|
135
|
-
|
|
136
|
+
biometric_identity_sdk_core_1.logger.error('Capture error:', error);
|
|
136
137
|
onError({
|
|
137
138
|
name: 'BiometricError',
|
|
138
139
|
message: error instanceof Error ? error.message : 'Unknown error during capture',
|
|
@@ -175,7 +176,10 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
|
|
|
175
176
|
}
|
|
176
177
|
// Show result
|
|
177
178
|
if (state.currentStep === biometric_identity_sdk_core_1.SDKStep.RESULT && state.validationResult) {
|
|
178
|
-
return (react_1.default.createElement(ResultScreen_1.ResultScreen, { result: state.validationResult, theme: theme, language: language, onClose: () =>
|
|
179
|
+
return (react_1.default.createElement(ResultScreen_1.ResultScreen, { result: state.validationResult, theme: theme, language: language, onClose: () => {
|
|
180
|
+
// Callback already called automatically when RESULT step was reached
|
|
181
|
+
// This onClose is just for UI cleanup/navigation
|
|
182
|
+
} }));
|
|
179
183
|
}
|
|
180
184
|
// Show error
|
|
181
185
|
if (state.currentStep === biometric_identity_sdk_core_1.SDKStep.ERROR && state.error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CameraCapture.d.ts","sourceRoot":"","sources":["../../src/components/CameraCapture.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAY3D,OAAO,EAAE,WAAW,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"CameraCapture.d.ts","sourceRoot":"","sources":["../../src/components/CameraCapture.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAY3D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAIrH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6NtD,CAAC;AA0JF,eAAe,aAAa,CAAC"}
|
|
@@ -81,7 +81,7 @@ const CameraCapture = ({ mode, theme, language, onCapture, onCancel, }) => {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
catch (error) {
|
|
84
|
-
|
|
84
|
+
biometric_identity_sdk_core_1.logger.error('Permission check error:', error);
|
|
85
85
|
setHasPermission(false);
|
|
86
86
|
const errorMsg = typeof strings.errors.cameraPermissionDenied === 'string'
|
|
87
87
|
? strings.errors.cameraPermissionDenied
|
|
@@ -131,14 +131,14 @@ const CameraCapture = ({ mode, theme, language, onCapture, onCancel, }) => {
|
|
|
131
131
|
}
|
|
132
132
|
catch (fetchError) {
|
|
133
133
|
// Final fallback: pass file path (SDK should handle file paths)
|
|
134
|
-
|
|
134
|
+
biometric_identity_sdk_core_1.logger.warn('Could not convert to base64, using file path:', photo.path);
|
|
135
135
|
onCapture(photo.path);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
setIsCapturing(false);
|
|
139
139
|
}
|
|
140
140
|
catch (error) {
|
|
141
|
-
|
|
141
|
+
biometric_identity_sdk_core_1.logger.error('Capture error:', error);
|
|
142
142
|
react_native_1.Alert.alert('Capture Failed', 'Could not capture photo. Please try again.');
|
|
143
143
|
setIsCapturing(false);
|
|
144
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAG1I,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,iCAAiC;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkyBtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
|
|
@@ -144,7 +144,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
catch (error) {
|
|
147
|
-
|
|
147
|
+
biometric_identity_sdk_core_1.logger.error('Permission check error:', error);
|
|
148
148
|
setHasPermission(false);
|
|
149
149
|
react_native_1.Alert.alert('Camera Permission Required', 'Please enable camera access in your device settings to record your face video.');
|
|
150
150
|
}
|
|
@@ -190,7 +190,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
190
190
|
setPhase('countdown');
|
|
191
191
|
}
|
|
192
192
|
catch (error) {
|
|
193
|
-
|
|
193
|
+
biometric_identity_sdk_core_1.logger.error('Failed to fetch challenges:', error);
|
|
194
194
|
// Fallback to default
|
|
195
195
|
setChallenges(DEFAULT_CHALLENGES);
|
|
196
196
|
setPhase('countdown');
|
|
@@ -295,7 +295,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
295
295
|
videoBase64 = await RNFS.readFile(video.path, 'base64');
|
|
296
296
|
}
|
|
297
297
|
catch (fsError) {
|
|
298
|
-
|
|
298
|
+
biometric_identity_sdk_core_1.logger.warn('Could not read video file, using captured frames');
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
let finalFrames = frames.length > 0 ? frames : [];
|
|
@@ -303,7 +303,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
303
303
|
finalFrames = [videoBase64];
|
|
304
304
|
}
|
|
305
305
|
if (finalFrames.length === 0) {
|
|
306
|
-
|
|
306
|
+
biometric_identity_sdk_core_1.logger.error('No frames or video available, cannot complete');
|
|
307
307
|
setPhase('recording');
|
|
308
308
|
handleRecordingError(new Error('No video frames captured'));
|
|
309
309
|
return;
|
|
@@ -316,12 +316,12 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
316
316
|
challengesCompleted: completedChallenges,
|
|
317
317
|
sessionId,
|
|
318
318
|
};
|
|
319
|
-
|
|
319
|
+
biometric_identity_sdk_core_1.logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
|
|
320
320
|
isRecordingRef.current = false;
|
|
321
321
|
onComplete(result);
|
|
322
322
|
}
|
|
323
323
|
catch (error) {
|
|
324
|
-
|
|
324
|
+
biometric_identity_sdk_core_1.logger.error('Error processing video:', error);
|
|
325
325
|
setPhase('recording');
|
|
326
326
|
setOverallProgress(0);
|
|
327
327
|
handleRecordingError(error);
|
|
@@ -381,7 +381,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
381
381
|
await recording.stop();
|
|
382
382
|
}
|
|
383
383
|
catch (error) {
|
|
384
|
-
|
|
384
|
+
biometric_identity_sdk_core_1.logger.error('Error stopping video recording:', error);
|
|
385
385
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
386
386
|
if (actualDuration >= minDurationMs && frames.length > 0) {
|
|
387
387
|
const result = {
|
|
@@ -410,7 +410,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
410
410
|
else {
|
|
411
411
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
412
412
|
if (frames.length === 0 && actualDuration < minDurationMs) {
|
|
413
|
-
|
|
413
|
+
biometric_identity_sdk_core_1.logger.error('No frames and duration too short, cannot complete');
|
|
414
414
|
setPhase('recording');
|
|
415
415
|
react_native_1.Alert.alert(strings.errors.videoTooShort?.title || 'Recording Too Short', strings.errors.videoTooShort?.message || `Video must be at least ${minDurationMs / 1000} seconds. Please try again.`, [{ text: strings.common.retry || 'OK', onPress: resetAndRetry }]);
|
|
416
416
|
return;
|
|
@@ -516,14 +516,14 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
516
516
|
handleVideoComplete(video);
|
|
517
517
|
},
|
|
518
518
|
onRecordingError: (error) => {
|
|
519
|
-
|
|
519
|
+
biometric_identity_sdk_core_1.logger.error('Recording error:', error);
|
|
520
520
|
handleRecordingError(error);
|
|
521
521
|
},
|
|
522
522
|
});
|
|
523
523
|
startFrameCapture();
|
|
524
524
|
}
|
|
525
525
|
catch (error) {
|
|
526
|
-
|
|
526
|
+
biometric_identity_sdk_core_1.logger.warn('Video recording not available, falling back to frame capture');
|
|
527
527
|
startFrameCapture();
|
|
528
528
|
}
|
|
529
529
|
}
|
|
@@ -535,7 +535,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
535
535
|
recordingTimeoutRef.current = setTimeout(() => {
|
|
536
536
|
if (isRecordingRef.current) {
|
|
537
537
|
stopRecording().catch(err => {
|
|
538
|
-
|
|
538
|
+
biometric_identity_sdk_core_1.logger.error('Error stopping recording on safety timeout:', err);
|
|
539
539
|
});
|
|
540
540
|
}
|
|
541
541
|
}, maxDuration);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBiometricSDK.d.ts","sourceRoot":"","sources":["../../src/hooks/useBiometricSDK.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,QAAQ,EACR,WAAW,
|
|
1
|
+
{"version":3,"file":"useBiometricSDK.d.ts","sourceRoot":"","sources":["../../src/hooks/useBiometricSDK.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,QAAQ,EACR,WAAW,EAEZ,MAAM,oCAAoC,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,oBAAoB,CAAC;IAC1B,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,mBAAmB,EAAE,CAAC,SAAS,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC7E,gBAAgB,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,eAAO,MAAM,eAAe,QAAO,qBAuNlC,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -20,7 +20,7 @@ const useBiometricSDK = () => {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
|
-
|
|
23
|
+
biometric_identity_sdk_core_1.logger.error('SDK initialization failed:', error);
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
init();
|
|
@@ -67,7 +67,7 @@ const useBiometricSDK = () => {
|
|
|
67
67
|
return defaultChallenges;
|
|
68
68
|
}
|
|
69
69
|
catch (error) {
|
|
70
|
-
|
|
70
|
+
biometric_identity_sdk_core_1.logger.error('Failed to fetch challenges:', error);
|
|
71
71
|
const defaultChallenges = sdk.getDefaultChallenges().map(c => ({
|
|
72
72
|
action: c.action,
|
|
73
73
|
instruction: c.instruction,
|
package/package.json
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
getStrings,
|
|
23
23
|
setLanguage,
|
|
24
24
|
SupportedLanguage,
|
|
25
|
+
logger,
|
|
25
26
|
} from '@hexar/biometric-identity-sdk-core';
|
|
26
27
|
import type { ChallengeAction } from './VideoRecorder';
|
|
27
28
|
import { useBiometricSDK } from '../hooks/useBiometricSDK';
|
|
@@ -92,12 +93,13 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
92
93
|
const strings = getStrings();
|
|
93
94
|
const styles = createStyles(theme);
|
|
94
95
|
|
|
95
|
-
// Handle validation result
|
|
96
|
+
// Handle validation result - call callback when RESULT step is reached
|
|
96
97
|
useEffect(() => {
|
|
97
|
-
if (state.validationResult) {
|
|
98
|
+
if (state.currentStep === SDKStep.RESULT && state.validationResult) {
|
|
99
|
+
// Call callback automatically when validation completes
|
|
98
100
|
onValidationComplete(state.validationResult);
|
|
99
101
|
}
|
|
100
|
-
}, [state.validationResult, onValidationComplete]);
|
|
102
|
+
}, [state.currentStep, state.validationResult, onValidationComplete]);
|
|
101
103
|
|
|
102
104
|
// Handle error
|
|
103
105
|
useEffect(() => {
|
|
@@ -119,7 +121,7 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
119
121
|
const challenges = await fetchChallenges('active');
|
|
120
122
|
setCurrentChallenges(challenges);
|
|
121
123
|
} catch (error) {
|
|
122
|
-
|
|
124
|
+
logger.warn('Failed to fetch challenges, using defaults');
|
|
123
125
|
setCurrentChallenges(sdk.getDefaultChallenges());
|
|
124
126
|
}
|
|
125
127
|
setIsLoadingChallenges(false);
|
|
@@ -154,11 +156,11 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
154
156
|
sessionId: videoResult.sessionId,
|
|
155
157
|
});
|
|
156
158
|
|
|
157
|
-
|
|
159
|
+
logger.info('Starting validation...');
|
|
158
160
|
await validateIdentity();
|
|
159
161
|
}
|
|
160
162
|
} catch (error) {
|
|
161
|
-
|
|
163
|
+
logger.error('Capture error:', error);
|
|
162
164
|
onError({
|
|
163
165
|
name: 'BiometricError',
|
|
164
166
|
message: error instanceof Error ? error.message : 'Unknown error during capture',
|
|
@@ -250,7 +252,10 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
250
252
|
result={state.validationResult}
|
|
251
253
|
theme={theme}
|
|
252
254
|
language={language}
|
|
253
|
-
onClose={() =>
|
|
255
|
+
onClose={() => {
|
|
256
|
+
// Callback already called automatically when RESULT step was reached
|
|
257
|
+
// This onClose is just for UI cleanup/navigation
|
|
258
|
+
}}
|
|
254
259
|
/>
|
|
255
260
|
);
|
|
256
261
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from 'react-native';
|
|
16
16
|
import { Camera, useCameraDevice, useCameraPermission } from 'react-native-vision-camera';
|
|
17
17
|
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
|
|
18
|
-
import { ThemeConfig, SupportedLanguage, getStrings, setLanguage } from '@hexar/biometric-identity-sdk-core';
|
|
18
|
+
import { ThemeConfig, SupportedLanguage, getStrings, setLanguage, logger } from '@hexar/biometric-identity-sdk-core';
|
|
19
19
|
|
|
20
20
|
const { width, height } = Dimensions.get('window');
|
|
21
21
|
|
|
@@ -74,7 +74,7 @@ export const CameraCapture: React.FC<CameraCaptureProps> = ({
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
} catch (error) {
|
|
77
|
-
|
|
77
|
+
logger.error('Permission check error:', error);
|
|
78
78
|
setHasPermission(false);
|
|
79
79
|
const errorMsg = typeof strings.errors.cameraPermissionDenied === 'string'
|
|
80
80
|
? strings.errors.cameraPermissionDenied
|
|
@@ -129,14 +129,14 @@ export const CameraCapture: React.FC<CameraCaptureProps> = ({
|
|
|
129
129
|
return; // Don't set isCapturing to false here, wait for reader
|
|
130
130
|
} catch (fetchError) {
|
|
131
131
|
// Final fallback: pass file path (SDK should handle file paths)
|
|
132
|
-
|
|
132
|
+
logger.warn('Could not convert to base64, using file path:', photo.path);
|
|
133
133
|
onCapture(photo.path);
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
setIsCapturing(false);
|
|
138
138
|
} catch (error) {
|
|
139
|
-
|
|
139
|
+
logger.error('Capture error:', error);
|
|
140
140
|
Alert.alert('Capture Failed', 'Could not capture photo. Please try again.');
|
|
141
141
|
setIsCapturing(false);
|
|
142
142
|
}
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from 'react-native';
|
|
17
17
|
import { Camera, useCameraDevice, useCameraPermission } from 'react-native-vision-camera';
|
|
18
18
|
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
|
|
19
|
-
import { ThemeConfig, LivenessInstruction, SupportedLanguage, getStrings, setLanguage } from '@hexar/biometric-identity-sdk-core';
|
|
19
|
+
import { ThemeConfig, LivenessInstruction, SupportedLanguage, getStrings, setLanguage, logger } from '@hexar/biometric-identity-sdk-core';
|
|
20
20
|
|
|
21
21
|
// Challenge action configuration (matches backend response)
|
|
22
22
|
export interface ChallengeAction {
|
|
@@ -179,7 +179,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
} catch (error) {
|
|
182
|
-
|
|
182
|
+
logger.error('Permission check error:', error);
|
|
183
183
|
setHasPermission(false);
|
|
184
184
|
Alert.alert(
|
|
185
185
|
'Camera Permission Required',
|
|
@@ -228,7 +228,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
228
228
|
setChallenges(challengeList);
|
|
229
229
|
setPhase('countdown');
|
|
230
230
|
} catch (error) {
|
|
231
|
-
|
|
231
|
+
logger.error('Failed to fetch challenges:', error);
|
|
232
232
|
// Fallback to default
|
|
233
233
|
setChallenges(DEFAULT_CHALLENGES);
|
|
234
234
|
setPhase('countdown');
|
|
@@ -356,7 +356,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
356
356
|
const RNFS = require('react-native-fs');
|
|
357
357
|
videoBase64 = await RNFS.readFile(video.path, 'base64');
|
|
358
358
|
} catch (fsError) {
|
|
359
|
-
|
|
359
|
+
logger.warn('Could not read video file, using captured frames');
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
362
|
|
|
@@ -367,7 +367,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
if (finalFrames.length === 0) {
|
|
370
|
-
|
|
370
|
+
logger.error('No frames or video available, cannot complete');
|
|
371
371
|
setPhase('recording');
|
|
372
372
|
handleRecordingError(new Error('No video frames captured'));
|
|
373
373
|
return;
|
|
@@ -382,12 +382,12 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
382
382
|
sessionId,
|
|
383
383
|
};
|
|
384
384
|
|
|
385
|
-
|
|
385
|
+
logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
|
|
386
386
|
|
|
387
387
|
isRecordingRef.current = false;
|
|
388
388
|
onComplete(result);
|
|
389
389
|
} catch (error) {
|
|
390
|
-
|
|
390
|
+
logger.error('Error processing video:', error);
|
|
391
391
|
setPhase('recording');
|
|
392
392
|
setOverallProgress(0);
|
|
393
393
|
handleRecordingError(error);
|
|
@@ -451,7 +451,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
451
451
|
videoRecordingRef.current = null;
|
|
452
452
|
await recording.stop();
|
|
453
453
|
} catch (error) {
|
|
454
|
-
|
|
454
|
+
logger.error('Error stopping video recording:', error);
|
|
455
455
|
|
|
456
456
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
457
457
|
if (actualDuration >= minDurationMs && frames.length > 0) {
|
|
@@ -480,7 +480,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
480
480
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
481
481
|
|
|
482
482
|
if (frames.length === 0 && actualDuration < minDurationMs) {
|
|
483
|
-
|
|
483
|
+
logger.error('No frames and duration too short, cannot complete');
|
|
484
484
|
setPhase('recording');
|
|
485
485
|
Alert.alert(
|
|
486
486
|
strings.errors.videoTooShort?.title || 'Recording Too Short',
|
|
@@ -608,14 +608,14 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
608
608
|
handleVideoComplete(video);
|
|
609
609
|
},
|
|
610
610
|
onRecordingError: (error: any) => {
|
|
611
|
-
|
|
611
|
+
logger.error('Recording error:', error);
|
|
612
612
|
handleRecordingError(error);
|
|
613
613
|
},
|
|
614
614
|
});
|
|
615
615
|
|
|
616
616
|
startFrameCapture();
|
|
617
617
|
} catch (error) {
|
|
618
|
-
|
|
618
|
+
logger.warn('Video recording not available, falling back to frame capture');
|
|
619
619
|
startFrameCapture();
|
|
620
620
|
}
|
|
621
621
|
} else {
|
|
@@ -628,7 +628,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
628
628
|
recordingTimeoutRef.current = setTimeout(() => {
|
|
629
629
|
if (isRecordingRef.current) {
|
|
630
630
|
stopRecording().catch(err => {
|
|
631
|
-
|
|
631
|
+
logger.error('Error stopping recording on safety timeout:', err);
|
|
632
632
|
});
|
|
633
633
|
}
|
|
634
634
|
}, maxDuration);
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
BiometricIdentitySDK,
|
|
4
4
|
SDKState,
|
|
5
5
|
VideoResult,
|
|
6
|
+
logger,
|
|
6
7
|
} from '@hexar/biometric-identity-sdk-core';
|
|
7
8
|
|
|
8
9
|
export interface ChallengeAction {
|
|
@@ -46,7 +47,7 @@ export const useBiometricSDK = (): UseBiometricSDKResult => {
|
|
|
46
47
|
setState(sdk.getState());
|
|
47
48
|
}
|
|
48
49
|
} catch (error) {
|
|
49
|
-
|
|
50
|
+
logger.error('SDK initialization failed:', error);
|
|
50
51
|
}
|
|
51
52
|
};
|
|
52
53
|
|
|
@@ -101,7 +102,7 @@ export const useBiometricSDK = (): UseBiometricSDKResult => {
|
|
|
101
102
|
setChallenges(defaultChallenges);
|
|
102
103
|
return defaultChallenges;
|
|
103
104
|
} catch (error) {
|
|
104
|
-
|
|
105
|
+
logger.error('Failed to fetch challenges:', error);
|
|
105
106
|
const defaultChallenges: ChallengeAction[] = sdk.getDefaultChallenges().map(c => ({
|
|
106
107
|
action: c.action,
|
|
107
108
|
instruction: c.instruction,
|