@hexar/biometric-identity-sdk-react-native 1.21.0 → 1.22.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,CAwhCtD,CAAC;AA4PF,eAAe,aAAa,CAAC"}
|
|
@@ -101,6 +101,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
101
101
|
const framesRef = (0, react_1.useRef)([]);
|
|
102
102
|
const [guidanceText, setGuidanceText] = (0, react_1.useState)(null);
|
|
103
103
|
const [hasPermission, setHasPermission] = (0, react_1.useState)(false);
|
|
104
|
+
const [isCameraReady, setIsCameraReady] = (0, react_1.useState)(false);
|
|
104
105
|
const cameraRef = (0, react_1.useRef)(null);
|
|
105
106
|
const { hasPermission: cameraPermission, requestPermission } = (0, react_native_vision_camera_1.useCameraPermission)();
|
|
106
107
|
// Prefer wide-angle (main) front camera — some Android devices expose
|
|
@@ -233,7 +234,11 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
233
234
|
initChallenges();
|
|
234
235
|
}, [propChallenges, instructions, onFetchChallenges, smartMode, duration, language]);
|
|
235
236
|
(0, react_1.useEffect)(() => {
|
|
236
|
-
|
|
237
|
+
// Don't start countdown until the native camera session is ready.
|
|
238
|
+
// On Motorola and other slow-to-initialize Android OEMs, isActive becoming
|
|
239
|
+
// true before the native view is registered causes IllegalViewOperationException
|
|
240
|
+
// inside CameraViewModule.findCameraView. We wait for onInitialized to fire.
|
|
241
|
+
if (phase !== 'countdown' || !isCameraReady)
|
|
237
242
|
return;
|
|
238
243
|
// Trigger focus at the start of countdown so the camera has ~3s to lock focus
|
|
239
244
|
if (countdown === 3)
|
|
@@ -257,7 +262,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
257
262
|
else {
|
|
258
263
|
startRecording();
|
|
259
264
|
}
|
|
260
|
-
}, [countdown, phase]);
|
|
265
|
+
}, [countdown, phase, isCameraReady]);
|
|
261
266
|
(0, react_1.useEffect)(() => {
|
|
262
267
|
if (phase === 'recording') {
|
|
263
268
|
react_native_1.Animated.loop(react_native_1.Animated.sequence([
|
|
@@ -309,6 +314,19 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
309
314
|
setPhase('loading');
|
|
310
315
|
react_native_1.Alert.alert('Recording Error', 'Failed to record video. Please try again.', [{ text: 'OK', onPress: onCancel }]);
|
|
311
316
|
}, [onCancel]);
|
|
317
|
+
// Safety timeout: if the camera session never fires onInitialized within
|
|
318
|
+
// 10 seconds, treat it as a hardware failure and send the user back.
|
|
319
|
+
(0, react_1.useEffect)(() => {
|
|
320
|
+
if (isCameraReady)
|
|
321
|
+
return;
|
|
322
|
+
const timeout = setTimeout(() => {
|
|
323
|
+
if (!isCameraReady) {
|
|
324
|
+
biometric_identity_sdk_core_1.logger.error('Camera onInitialized timed out — hardware may be unavailable');
|
|
325
|
+
handleRecordingError(new Error('Camera initialization timed out'));
|
|
326
|
+
}
|
|
327
|
+
}, 10000);
|
|
328
|
+
return () => clearTimeout(timeout);
|
|
329
|
+
}, [isCameraReady, handleRecordingError]);
|
|
312
330
|
const handleVideoComplete = (0, react_1.useCallback)(async (video) => {
|
|
313
331
|
if (phase === 'loading' && !video) {
|
|
314
332
|
return;
|
|
@@ -789,7 +807,10 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
789
807
|
}
|
|
790
808
|
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
791
809
|
react_1.default.createElement(react_native_1.View, { style: styles.cameraContainer },
|
|
792
|
-
react_1.default.createElement(react_native_vision_camera_1.Camera, { ref: cameraRef, style: react_native_1.StyleSheet.absoluteFill, device: device, isActive:
|
|
810
|
+
react_1.default.createElement(react_native_vision_camera_1.Camera, { ref: cameraRef, style: react_native_1.StyleSheet.absoluteFill, device: device, isActive: true, video: true, photo: true, audio: false, onInitialized: () => setIsCameraReady(true), onError: (error) => {
|
|
811
|
+
biometric_identity_sdk_core_1.logger.error('Camera hardware error:', error);
|
|
812
|
+
handleRecordingError(error);
|
|
813
|
+
} }),
|
|
793
814
|
react_1.default.createElement(react_native_1.View, { style: styles.overlay },
|
|
794
815
|
react_1.default.createElement(react_native_1.View, { style: [
|
|
795
816
|
styles.faceOval,
|
package/package.json
CHANGED
|
@@ -130,6 +130,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
130
130
|
const framesRef = useRef<string[]>([]);
|
|
131
131
|
const [guidanceText, setGuidanceText] = useState<string | null>(null);
|
|
132
132
|
const [hasPermission, setHasPermission] = useState(false);
|
|
133
|
+
const [isCameraReady, setIsCameraReady] = useState(false);
|
|
133
134
|
const cameraRef = useRef<Camera>(null);
|
|
134
135
|
const { hasPermission: cameraPermission, requestPermission } = useCameraPermission();
|
|
135
136
|
// Prefer wide-angle (main) front camera — some Android devices expose
|
|
@@ -274,7 +275,11 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
274
275
|
}, [propChallenges, instructions, onFetchChallenges, smartMode, duration, language]);
|
|
275
276
|
|
|
276
277
|
useEffect(() => {
|
|
277
|
-
|
|
278
|
+
// Don't start countdown until the native camera session is ready.
|
|
279
|
+
// On Motorola and other slow-to-initialize Android OEMs, isActive becoming
|
|
280
|
+
// true before the native view is registered causes IllegalViewOperationException
|
|
281
|
+
// inside CameraViewModule.findCameraView. We wait for onInitialized to fire.
|
|
282
|
+
if (phase !== 'countdown' || !isCameraReady) return;
|
|
278
283
|
|
|
279
284
|
// Trigger focus at the start of countdown so the camera has ~3s to lock focus
|
|
280
285
|
if (countdown === 3) triggerFocus();
|
|
@@ -298,7 +303,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
298
303
|
} else {
|
|
299
304
|
startRecording();
|
|
300
305
|
}
|
|
301
|
-
}, [countdown, phase]);
|
|
306
|
+
}, [countdown, phase, isCameraReady]);
|
|
302
307
|
|
|
303
308
|
useEffect(() => {
|
|
304
309
|
if (phase === 'recording') {
|
|
@@ -364,6 +369,19 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
364
369
|
);
|
|
365
370
|
}, [onCancel]);
|
|
366
371
|
|
|
372
|
+
// Safety timeout: if the camera session never fires onInitialized within
|
|
373
|
+
// 10 seconds, treat it as a hardware failure and send the user back.
|
|
374
|
+
useEffect(() => {
|
|
375
|
+
if (isCameraReady) return;
|
|
376
|
+
const timeout = setTimeout(() => {
|
|
377
|
+
if (!isCameraReady) {
|
|
378
|
+
logger.error('Camera onInitialized timed out — hardware may be unavailable');
|
|
379
|
+
handleRecordingError(new Error('Camera initialization timed out'));
|
|
380
|
+
}
|
|
381
|
+
}, 10000);
|
|
382
|
+
return () => clearTimeout(timeout);
|
|
383
|
+
}, [isCameraReady, handleRecordingError]);
|
|
384
|
+
|
|
367
385
|
const handleVideoComplete = useCallback(async (video: any) => {
|
|
368
386
|
if (phase === 'loading' && !video) {
|
|
369
387
|
return;
|
|
@@ -960,10 +978,15 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
960
978
|
ref={cameraRef}
|
|
961
979
|
style={StyleSheet.absoluteFill}
|
|
962
980
|
device={device}
|
|
963
|
-
isActive={
|
|
981
|
+
isActive={true}
|
|
964
982
|
video={true}
|
|
965
983
|
photo={true}
|
|
966
984
|
audio={false}
|
|
985
|
+
onInitialized={() => setIsCameraReady(true)}
|
|
986
|
+
onError={(error) => {
|
|
987
|
+
logger.error('Camera hardware error:', error);
|
|
988
|
+
handleRecordingError(error);
|
|
989
|
+
}}
|
|
967
990
|
/>
|
|
968
991
|
|
|
969
992
|
{/* Face Oval Overlay */}
|