@hexar/biometric-identity-sdk-react-native 1.22.0 → 1.23.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.
|
@@ -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;AAexE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAE1I,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;AA2CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAexE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAE1I,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;AA2CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqiCtD,CAAC;AA4PF,eAAe,aAAa,CAAC"}
|
|
@@ -102,12 +102,20 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
102
102
|
const [guidanceText, setGuidanceText] = (0, react_1.useState)(null);
|
|
103
103
|
const [hasPermission, setHasPermission] = (0, react_1.useState)(false);
|
|
104
104
|
const [isCameraReady, setIsCameraReady] = (0, react_1.useState)(false);
|
|
105
|
+
// Controlled via stopRecording — set to false before calling onComplete so
|
|
106
|
+
// VisionCamera tears down the native session and any in-flight takePhoto()
|
|
107
|
+
// calls fail gracefully instead of crashing with IllegalViewOperationException
|
|
108
|
+
// when the parent unmounts the <Camera> view underneath them.
|
|
109
|
+
const [isCameraActive, setIsCameraActive] = (0, react_1.useState)(true);
|
|
105
110
|
const cameraRef = (0, react_1.useRef)(null);
|
|
106
111
|
const { hasPermission: cameraPermission, requestPermission } = (0, react_native_vision_camera_1.useCameraPermission)();
|
|
107
112
|
// Prefer wide-angle (main) front camera — some Android devices expose
|
|
108
113
|
// multiple front sensors and the default may lack autofocus.
|
|
114
|
+
// Only request wide-angle — ultra-wide opens a multi-physical-camera session
|
|
115
|
+
// that is slow to release, causing CameraViewModule.findCameraView to throw
|
|
116
|
+
// IllegalViewOperationException when the component unmounts after recording.
|
|
109
117
|
const device = (0, react_native_vision_camera_1.useCameraDevice)('front', {
|
|
110
|
-
physicalDevices: ['wide-angle-camera'
|
|
118
|
+
physicalDevices: ['wide-angle-camera'],
|
|
111
119
|
});
|
|
112
120
|
const [deviceReady, setDeviceReady] = (0, react_1.useState)(!!device);
|
|
113
121
|
const fadeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
@@ -307,6 +315,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
307
315
|
setChallengeProgress(0);
|
|
308
316
|
setOverallProgress(0);
|
|
309
317
|
recordingStartTime.current = 0;
|
|
318
|
+
setIsCameraActive(true);
|
|
310
319
|
setPhase('countdown');
|
|
311
320
|
setCountdown(3);
|
|
312
321
|
}, []);
|
|
@@ -380,11 +389,11 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
380
389
|
};
|
|
381
390
|
biometric_identity_sdk_core_1.logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's', 'challenges:', currentCompletedChallenges.length);
|
|
382
391
|
isRecordingRef.current = false;
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
//
|
|
387
|
-
|
|
392
|
+
// Deactivate the camera first so VisionCamera tears down its native
|
|
393
|
+
// session. Any in-flight takePhoto() calls will then fail gracefully
|
|
394
|
+
// rather than crashing with IllegalViewOperationException when the
|
|
395
|
+
// parent unmounts the <Camera> view underneath them.
|
|
396
|
+
setIsCameraActive(false);
|
|
388
397
|
setTimeout(() => onComplete(result), 250);
|
|
389
398
|
}
|
|
390
399
|
catch (error) {
|
|
@@ -536,6 +545,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
536
545
|
sessionId,
|
|
537
546
|
};
|
|
538
547
|
setPhase('processing');
|
|
548
|
+
setIsCameraActive(false);
|
|
539
549
|
setTimeout(() => onComplete(result), 250);
|
|
540
550
|
}
|
|
541
551
|
else {
|
|
@@ -549,6 +559,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
549
559
|
sessionId,
|
|
550
560
|
};
|
|
551
561
|
setPhase('processing');
|
|
562
|
+
setIsCameraActive(false);
|
|
552
563
|
setTimeout(() => onComplete(result), 250);
|
|
553
564
|
}
|
|
554
565
|
}
|
|
@@ -580,6 +591,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
580
591
|
challengesCompleted: currentCompletedChallenges,
|
|
581
592
|
sessionId,
|
|
582
593
|
};
|
|
594
|
+
setIsCameraActive(false);
|
|
583
595
|
setTimeout(() => {
|
|
584
596
|
onComplete(result);
|
|
585
597
|
}, 250);
|
|
@@ -626,6 +638,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
626
638
|
sessionId,
|
|
627
639
|
};
|
|
628
640
|
setPhase('processing');
|
|
641
|
+
setIsCameraActive(false);
|
|
629
642
|
setTimeout(() => onComplete(result), 250);
|
|
630
643
|
}
|
|
631
644
|
}
|
|
@@ -807,7 +820,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
807
820
|
}
|
|
808
821
|
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
809
822
|
react_1.default.createElement(react_native_1.View, { style: styles.cameraContainer },
|
|
810
|
-
react_1.default.createElement(react_native_vision_camera_1.Camera, { ref: cameraRef, style: react_native_1.StyleSheet.absoluteFill, device: device, isActive:
|
|
823
|
+
react_1.default.createElement(react_native_vision_camera_1.Camera, { ref: cameraRef, style: react_native_1.StyleSheet.absoluteFill, device: device, isActive: isCameraActive, video: true, photo: true, audio: false, onInitialized: () => setIsCameraReady(true), onError: (error) => {
|
|
811
824
|
biometric_identity_sdk_core_1.logger.error('Camera hardware error:', error);
|
|
812
825
|
handleRecordingError(error);
|
|
813
826
|
} }),
|
package/package.json
CHANGED
|
@@ -131,12 +131,20 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
131
131
|
const [guidanceText, setGuidanceText] = useState<string | null>(null);
|
|
132
132
|
const [hasPermission, setHasPermission] = useState(false);
|
|
133
133
|
const [isCameraReady, setIsCameraReady] = useState(false);
|
|
134
|
+
// Controlled via stopRecording — set to false before calling onComplete so
|
|
135
|
+
// VisionCamera tears down the native session and any in-flight takePhoto()
|
|
136
|
+
// calls fail gracefully instead of crashing with IllegalViewOperationException
|
|
137
|
+
// when the parent unmounts the <Camera> view underneath them.
|
|
138
|
+
const [isCameraActive, setIsCameraActive] = useState(true);
|
|
134
139
|
const cameraRef = useRef<Camera>(null);
|
|
135
140
|
const { hasPermission: cameraPermission, requestPermission } = useCameraPermission();
|
|
136
141
|
// Prefer wide-angle (main) front camera — some Android devices expose
|
|
137
142
|
// multiple front sensors and the default may lack autofocus.
|
|
143
|
+
// Only request wide-angle — ultra-wide opens a multi-physical-camera session
|
|
144
|
+
// that is slow to release, causing CameraViewModule.findCameraView to throw
|
|
145
|
+
// IllegalViewOperationException when the component unmounts after recording.
|
|
138
146
|
const device = useCameraDevice('front', {
|
|
139
|
-
physicalDevices: ['wide-angle-camera'
|
|
147
|
+
physicalDevices: ['wide-angle-camera'],
|
|
140
148
|
});
|
|
141
149
|
const [deviceReady, setDeviceReady] = useState(!!device);
|
|
142
150
|
|
|
@@ -356,6 +364,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
356
364
|
setChallengeProgress(0);
|
|
357
365
|
setOverallProgress(0);
|
|
358
366
|
recordingStartTime.current = 0;
|
|
367
|
+
setIsCameraActive(true);
|
|
359
368
|
setPhase('countdown');
|
|
360
369
|
setCountdown(3);
|
|
361
370
|
}, []);
|
|
@@ -450,11 +459,11 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
450
459
|
logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's', 'challenges:', currentCompletedChallenges.length);
|
|
451
460
|
|
|
452
461
|
isRecordingRef.current = false;
|
|
453
|
-
//
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
//
|
|
457
|
-
|
|
462
|
+
// Deactivate the camera first so VisionCamera tears down its native
|
|
463
|
+
// session. Any in-flight takePhoto() calls will then fail gracefully
|
|
464
|
+
// rather than crashing with IllegalViewOperationException when the
|
|
465
|
+
// parent unmounts the <Camera> view underneath them.
|
|
466
|
+
setIsCameraActive(false);
|
|
458
467
|
setTimeout(() => onComplete(result), 250);
|
|
459
468
|
} catch (error) {
|
|
460
469
|
logger.error('Error processing video:', error);
|
|
@@ -622,6 +631,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
622
631
|
sessionId,
|
|
623
632
|
};
|
|
624
633
|
setPhase('processing');
|
|
634
|
+
setIsCameraActive(false);
|
|
625
635
|
setTimeout(() => onComplete(result), 250);
|
|
626
636
|
} else {
|
|
627
637
|
logger.info('Stopping recording with frames (fallback):', currentFrames.length);
|
|
@@ -634,6 +644,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
634
644
|
sessionId,
|
|
635
645
|
};
|
|
636
646
|
setPhase('processing');
|
|
647
|
+
setIsCameraActive(false);
|
|
637
648
|
setTimeout(() => onComplete(result), 250);
|
|
638
649
|
}
|
|
639
650
|
}
|
|
@@ -672,6 +683,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
672
683
|
sessionId,
|
|
673
684
|
};
|
|
674
685
|
|
|
686
|
+
setIsCameraActive(false);
|
|
675
687
|
setTimeout(() => {
|
|
676
688
|
onComplete(result);
|
|
677
689
|
}, 250);
|
|
@@ -723,6 +735,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
723
735
|
sessionId,
|
|
724
736
|
};
|
|
725
737
|
setPhase('processing');
|
|
738
|
+
setIsCameraActive(false);
|
|
726
739
|
setTimeout(() => onComplete(result), 250);
|
|
727
740
|
}
|
|
728
741
|
}
|
|
@@ -978,7 +991,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
978
991
|
ref={cameraRef}
|
|
979
992
|
style={StyleSheet.absoluteFill}
|
|
980
993
|
device={device}
|
|
981
|
-
isActive={
|
|
994
|
+
isActive={isCameraActive}
|
|
982
995
|
video={true}
|
|
983
996
|
photo={true}
|
|
984
997
|
audio={false}
|