@hexar/biometric-identity-sdk-react-native 1.0.10 → 1.0.11

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;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAA2B,MAAM,oCAAoC,CAAC;AAGlI,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,CA8vBtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
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,EAA2B,MAAM,oCAAoC,CAAC;AAGlI,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,CAqyBtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
@@ -116,6 +116,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
116
116
  const frameCaptureInterval = (0, react_1.useRef)(null);
117
117
  const videoRecordingRef = (0, react_1.useRef)(null);
118
118
  const isRecordingRef = (0, react_1.useRef)(false);
119
+ const recordingTimeoutRef = (0, react_1.useRef)(null);
119
120
  const minDurationMs = 8000;
120
121
  const totalDuration = duration || Math.max(minDurationMs, challenges.reduce((sum, c) => sum + c.duration_ms, 0) + 2000);
121
122
  // Check camera permissions
@@ -369,14 +370,24 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
369
370
  }
370
371
  }, [device]);
371
372
  const stopRecording = (0, react_1.useCallback)(async () => {
372
- console.log('Stopping recording...');
373
+ console.log('stopRecording called, isRecording:', isRecordingRef.current);
374
+ // Clear any pending timeouts
375
+ if (recordingTimeoutRef.current) {
376
+ clearTimeout(recordingTimeoutRef.current);
377
+ recordingTimeoutRef.current = null;
378
+ }
373
379
  if (frameCaptureInterval.current) {
374
380
  clearInterval(frameCaptureInterval.current);
375
381
  frameCaptureInterval.current = null;
376
382
  }
383
+ // Prevent multiple calls
384
+ if (!isRecordingRef.current) {
385
+ console.log('Recording already stopped, ignoring');
386
+ return;
387
+ }
377
388
  if (videoRecordingRef.current) {
378
389
  try {
379
- console.log('Stopping video recording');
390
+ console.log('Stopping video recording, current ref:', !!videoRecordingRef.current);
380
391
  const recording = videoRecordingRef.current;
381
392
  videoRecordingRef.current = null;
382
393
  isRecordingRef.current = false;
@@ -387,6 +398,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
387
398
  console.error('Error stopping video recording:', error);
388
399
  isRecordingRef.current = false;
389
400
  const actualDuration = Date.now() - recordingStartTime.current;
401
+ console.log('Error duration check:', actualDuration, 'minDurationMs:', minDurationMs, 'frames:', frames.length);
390
402
  if (actualDuration >= minDurationMs && frames.length > 0) {
391
403
  console.log('Video stopped with error, using captured frames');
392
404
  const result = {
@@ -402,29 +414,39 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
402
414
  }
403
415
  }
404
416
  else {
417
+ console.log('No video recording ref, just setting flag to false');
405
418
  isRecordingRef.current = false;
406
419
  }
407
420
  }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs]);
408
421
  const runChallenge = (0, react_1.useCallback)((index) => {
409
422
  if (index >= challenges.length) {
410
- console.log('All challenges completed, stopping recording');
423
+ console.log('All challenges completed, checking duration');
411
424
  setOverallProgress(100);
425
+ // Clear the totalDuration timeout since we're handling it manually
426
+ if (recordingTimeoutRef.current) {
427
+ clearTimeout(recordingTimeoutRef.current);
428
+ recordingTimeoutRef.current = null;
429
+ console.log('Cleared totalDuration timeout');
430
+ }
412
431
  if (isRecordingRef.current) {
413
432
  const elapsed = Date.now() - recordingStartTime.current;
414
433
  console.log('Checking duration - Elapsed:', (elapsed / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's');
415
434
  if (elapsed < minDurationMs) {
416
435
  const remaining = minDurationMs - elapsed;
417
436
  console.log('Waiting additional', (remaining / 1000).toFixed(1), 's to meet minimum duration');
418
- setTimeout(() => {
437
+ recordingTimeoutRef.current = setTimeout(() => {
438
+ console.log('Minimum duration wait completed, stopping recording');
419
439
  if (isRecordingRef.current) {
420
440
  stopRecording();
421
441
  }
422
442
  }, remaining);
423
443
  return;
424
444
  }
445
+ console.log('Duration requirement met, stopping immediately');
425
446
  stopRecording();
426
447
  }
427
448
  else {
449
+ console.log('Recording already stopped, checking if we can complete');
428
450
  const actualDuration = Date.now() - recordingStartTime.current;
429
451
  if (actualDuration >= minDurationMs && frames.length > 0) {
430
452
  console.log('Recording already stopped, completing with frames');
@@ -489,8 +511,15 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
489
511
  videoRecordingRef.current = await cameraRef.current.startRecording({
490
512
  flash: 'off',
491
513
  onRecordingFinished: (video) => {
492
- console.log('Video recording finished callback called, path:', video?.path || 'N/A');
493
- handleVideoComplete(video);
514
+ console.log('Video recording finished callback called, path:', video?.path || 'N/A', 'phase:', phase);
515
+ // Ensure we're in the right state to process
516
+ if (phase === 'recording' || phase === 'processing') {
517
+ handleVideoComplete(video);
518
+ }
519
+ else {
520
+ console.warn('Received onRecordingFinished but phase is', phase, '- calling handleVideoComplete anyway');
521
+ handleVideoComplete(video);
522
+ }
494
523
  },
495
524
  onRecordingError: (error) => {
496
525
  console.error('Recording error:', error);
@@ -509,16 +538,24 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
509
538
  startFrameCapture();
510
539
  }
511
540
  runChallenge(0);
512
- const timeoutId = setTimeout(() => {
513
- console.log('Recording timeout reached, stopping recording');
541
+ // Set a safety timeout that's longer than totalDuration to ensure we stop eventually
542
+ // This will be cleared if challenges complete early
543
+ const maxDuration = Math.max(totalDuration, minDurationMs + 2000); // Add 2s buffer
544
+ recordingTimeoutRef.current = setTimeout(() => {
545
+ console.log('Safety timeout reached (max duration), stopping recording');
514
546
  if (isRecordingRef.current) {
515
547
  stopRecording().catch(err => {
516
- console.error('Error stopping recording on timeout:', err);
548
+ console.error('Error stopping recording on safety timeout:', err);
517
549
  });
518
550
  }
519
- }, totalDuration);
520
- return () => clearTimeout(timeoutId);
521
- }, [device, totalDuration, handleVideoComplete, handleRecordingError, runChallenge, stopRecording, startFrameCapture]);
551
+ }, maxDuration);
552
+ return () => {
553
+ if (recordingTimeoutRef.current) {
554
+ clearTimeout(recordingTimeoutRef.current);
555
+ recordingTimeoutRef.current = null;
556
+ }
557
+ };
558
+ }, [device, totalDuration, minDurationMs, handleVideoComplete, handleRecordingError, runChallenge, stopRecording, startFrameCapture]);
522
559
  // Current challenge
523
560
  const currentChallenge = challenges[currentChallengeIndex];
524
561
  // Get direction arrow for the current challenge
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexar/biometric-identity-sdk-react-native",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "React Native wrapper for Biometric Identity SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -147,6 +147,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
147
147
  const frameCaptureInterval = useRef<NodeJS.Timeout | null>(null);
148
148
  const videoRecordingRef = useRef<any>(null);
149
149
  const isRecordingRef = useRef<boolean>(false);
150
+ const recordingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
150
151
  const minDurationMs = 8000;
151
152
  const totalDuration = duration || Math.max(
152
153
  minDurationMs,
@@ -436,16 +437,28 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
436
437
  }, [device]);
437
438
 
438
439
  const stopRecording = useCallback(async () => {
439
- console.log('Stopping recording...');
440
+ console.log('stopRecording called, isRecording:', isRecordingRef.current);
441
+
442
+ // Clear any pending timeouts
443
+ if (recordingTimeoutRef.current) {
444
+ clearTimeout(recordingTimeoutRef.current);
445
+ recordingTimeoutRef.current = null;
446
+ }
440
447
 
441
448
  if (frameCaptureInterval.current) {
442
449
  clearInterval(frameCaptureInterval.current);
443
450
  frameCaptureInterval.current = null;
444
451
  }
445
452
 
453
+ // Prevent multiple calls
454
+ if (!isRecordingRef.current) {
455
+ console.log('Recording already stopped, ignoring');
456
+ return;
457
+ }
458
+
446
459
  if (videoRecordingRef.current) {
447
460
  try {
448
- console.log('Stopping video recording');
461
+ console.log('Stopping video recording, current ref:', !!videoRecordingRef.current);
449
462
  const recording = videoRecordingRef.current;
450
463
  videoRecordingRef.current = null;
451
464
  isRecordingRef.current = false;
@@ -457,6 +470,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
457
470
  isRecordingRef.current = false;
458
471
 
459
472
  const actualDuration = Date.now() - recordingStartTime.current;
473
+ console.log('Error duration check:', actualDuration, 'minDurationMs:', minDurationMs, 'frames:', frames.length);
460
474
  if (actualDuration >= minDurationMs && frames.length > 0) {
461
475
  console.log('Video stopped with error, using captured frames');
462
476
  const result: VideoRecordingResult = {
@@ -471,15 +485,23 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
471
485
  }
472
486
  }
473
487
  } else {
488
+ console.log('No video recording ref, just setting flag to false');
474
489
  isRecordingRef.current = false;
475
490
  }
476
491
  }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs]);
477
492
 
478
493
  const runChallenge = useCallback((index: number) => {
479
494
  if (index >= challenges.length) {
480
- console.log('All challenges completed, stopping recording');
495
+ console.log('All challenges completed, checking duration');
481
496
  setOverallProgress(100);
482
497
 
498
+ // Clear the totalDuration timeout since we're handling it manually
499
+ if (recordingTimeoutRef.current) {
500
+ clearTimeout(recordingTimeoutRef.current);
501
+ recordingTimeoutRef.current = null;
502
+ console.log('Cleared totalDuration timeout');
503
+ }
504
+
483
505
  if (isRecordingRef.current) {
484
506
  const elapsed = Date.now() - recordingStartTime.current;
485
507
  console.log('Checking duration - Elapsed:', (elapsed / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's');
@@ -487,7 +509,8 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
487
509
  if (elapsed < minDurationMs) {
488
510
  const remaining = minDurationMs - elapsed;
489
511
  console.log('Waiting additional', (remaining / 1000).toFixed(1), 's to meet minimum duration');
490
- setTimeout(() => {
512
+ recordingTimeoutRef.current = setTimeout(() => {
513
+ console.log('Minimum duration wait completed, stopping recording');
491
514
  if (isRecordingRef.current) {
492
515
  stopRecording();
493
516
  }
@@ -495,8 +518,10 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
495
518
  return;
496
519
  }
497
520
 
521
+ console.log('Duration requirement met, stopping immediately');
498
522
  stopRecording();
499
523
  } else {
524
+ console.log('Recording already stopped, checking if we can complete');
500
525
  const actualDuration = Date.now() - recordingStartTime.current;
501
526
  if (actualDuration >= minDurationMs && frames.length > 0) {
502
527
  console.log('Recording already stopped, completing with frames');
@@ -573,8 +598,14 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
573
598
  videoRecordingRef.current = await cameraRef.current.startRecording({
574
599
  flash: 'off',
575
600
  onRecordingFinished: (video: any) => {
576
- console.log('Video recording finished callback called, path:', video?.path || 'N/A');
577
- handleVideoComplete(video);
601
+ console.log('Video recording finished callback called, path:', video?.path || 'N/A', 'phase:', phase);
602
+ // Ensure we're in the right state to process
603
+ if (phase === 'recording' || phase === 'processing') {
604
+ handleVideoComplete(video);
605
+ } else {
606
+ console.warn('Received onRecordingFinished but phase is', phase, '- calling handleVideoComplete anyway');
607
+ handleVideoComplete(video);
608
+ }
578
609
  },
579
610
  onRecordingError: (error: any) => {
580
611
  console.error('Recording error:', error);
@@ -593,17 +624,25 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
593
624
 
594
625
  runChallenge(0);
595
626
 
596
- const timeoutId = setTimeout(() => {
597
- console.log('Recording timeout reached, stopping recording');
627
+ // Set a safety timeout that's longer than totalDuration to ensure we stop eventually
628
+ // This will be cleared if challenges complete early
629
+ const maxDuration = Math.max(totalDuration, minDurationMs + 2000); // Add 2s buffer
630
+ recordingTimeoutRef.current = setTimeout(() => {
631
+ console.log('Safety timeout reached (max duration), stopping recording');
598
632
  if (isRecordingRef.current) {
599
633
  stopRecording().catch(err => {
600
- console.error('Error stopping recording on timeout:', err);
634
+ console.error('Error stopping recording on safety timeout:', err);
601
635
  });
602
636
  }
603
- }, totalDuration);
637
+ }, maxDuration);
604
638
 
605
- return () => clearTimeout(timeoutId);
606
- }, [device, totalDuration, handleVideoComplete, handleRecordingError, runChallenge, stopRecording, startFrameCapture]);
639
+ return () => {
640
+ if (recordingTimeoutRef.current) {
641
+ clearTimeout(recordingTimeoutRef.current);
642
+ recordingTimeoutRef.current = null;
643
+ }
644
+ };
645
+ }, [device, totalDuration, minDurationMs, handleVideoComplete, handleRecordingError, runChallenge, stopRecording, startFrameCapture]);
607
646
 
608
647
  // Current challenge
609
648
  const currentChallenge = challenges[currentChallengeIndex];