@hexar/biometric-identity-sdk-react-native 1.0.12 → 1.0.13

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":"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,EAClB,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,CAiUtE,CAAC;AAiOF,eAAe,qBAAqB,CAAC"}
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,EAClB,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,CAgTtE,CAAC;AAiOF,eAAe,qBAAqB,CAAC"}
@@ -109,28 +109,16 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
109
109
  * Handle capture completion
110
110
  */
111
111
  const handleCaptureComplete = (0, react_1.useCallback)(async (data) => {
112
- console.log('handleCaptureComplete called, cameraMode:', cameraMode);
113
112
  setShowCamera(false);
114
113
  try {
115
114
  if (cameraMode === 'front') {
116
- console.log('Uploading front ID');
117
115
  await uploadFrontID(data);
118
- console.log('Front ID uploaded successfully');
119
116
  }
120
117
  else if (cameraMode === 'back') {
121
- console.log('Uploading back ID');
122
118
  await uploadBackID(data);
123
- console.log('Back ID uploaded successfully');
124
119
  }
125
120
  else if (cameraMode === 'video') {
126
- console.log('Processing video recording result');
127
- // Handle video recording result
128
121
  const videoResult = data;
129
- console.log('Storing video recording:', {
130
- frames: videoResult.frames.length,
131
- duration: videoResult.duration,
132
- challengesCompleted: videoResult.challengesCompleted.length
133
- });
134
122
  await storeVideoRecording({
135
123
  frames: videoResult.frames,
136
124
  duration: videoResult.duration,
@@ -139,10 +127,8 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
139
127
  challengesCompleted: videoResult.challengesCompleted,
140
128
  sessionId: videoResult.sessionId,
141
129
  });
142
- console.log('Video recording stored, starting validation...');
143
- // Automatically start validation after video
144
- const result = await validateIdentity();
145
- console.log('Validation complete, result:', result);
130
+ console.log('Starting validation...');
131
+ await validateIdentity();
146
132
  }
147
133
  }
148
134
  catch (error) {
@@ -185,12 +171,10 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
185
171
  }
186
172
  // Show validation progress
187
173
  if (state.currentStep === biometric_identity_sdk_core_1.SDKStep.VALIDATING) {
188
- console.log('Rendering ValidationProgress, progress:', state.progress);
189
174
  return (react_1.default.createElement(ValidationProgress_1.ValidationProgress, { progress: state.progress, theme: theme, language: language }));
190
175
  }
191
176
  // Show result
192
177
  if (state.currentStep === biometric_identity_sdk_core_1.SDKStep.RESULT && state.validationResult) {
193
- console.log('Rendering ResultScreen, result:', state.validationResult);
194
178
  return (react_1.default.createElement(ResultScreen_1.ResultScreen, { result: state.validationResult, theme: theme, language: language, onClose: () => onValidationComplete(state.validationResult) }));
195
179
  }
196
180
  // Show error
@@ -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,CA80BtD,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,CAkyBtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
@@ -275,18 +275,13 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
275
275
  react_native_1.Alert.alert('Recording Error', 'Failed to record video. Please try again.', [{ text: 'OK', onPress: onCancel }]);
276
276
  }, [onCancel]);
277
277
  const handleVideoComplete = (0, react_1.useCallback)(async (video) => {
278
- console.log('handleVideoComplete called with video:', video?.path, 'current phase:', phase, 'isRecording:', isRecordingRef.current);
279
- // Don't process if we're already done (result screen or error)
280
278
  if (phase === 'loading' && !video) {
281
- console.log('Video completion in loading phase with no video, ignoring');
282
279
  return;
283
280
  }
284
281
  try {
285
- console.log('Setting phase to processing');
286
282
  setPhase('processing');
287
283
  setOverallProgress(100);
288
284
  const actualDuration = Date.now() - recordingStartTime.current;
289
- console.log('Video Processing - Duration:', (actualDuration / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's, Frames:', frames.length);
290
285
  if (actualDuration < minDurationMs) {
291
286
  setPhase('recording');
292
287
  setOverallProgress(0);
@@ -298,15 +293,17 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
298
293
  try {
299
294
  const RNFS = require('react-native-fs');
300
295
  videoBase64 = await RNFS.readFile(video.path, 'base64');
301
- console.log('Video file read successfully, size:', videoBase64.length, 'bytes');
302
296
  }
303
297
  catch (fsError) {
304
- console.warn('Could not read video file, using captured frames:', fsError);
298
+ console.warn('Could not read video file, using captured frames');
305
299
  }
306
300
  }
307
- const finalFrames = frames.length > 0 ? frames : (videoBase64 ? [videoBase64] : []);
301
+ let finalFrames = frames.length > 0 ? frames : [];
302
+ if (finalFrames.length === 0 && videoBase64) {
303
+ finalFrames = [videoBase64];
304
+ }
308
305
  if (finalFrames.length === 0) {
309
- console.error('No frames available, cannot complete');
306
+ console.error('No frames or video available, cannot complete');
310
307
  setPhase('recording');
311
308
  handleRecordingError(new Error('No video frames captured'));
312
309
  return;
@@ -319,13 +316,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
319
316
  challengesCompleted: completedChallenges,
320
317
  sessionId,
321
318
  };
322
- console.log('Video recording completed successfully:', {
323
- duration: (actualDuration / 1000).toFixed(1) + 's',
324
- frames: result.frames.length,
325
- challenges: `${completedChallenges.length}/${challenges.length}`,
326
- instructionsFollowed: result.instructionsFollowed,
327
- quality: result.qualityScore.toFixed(0) + '%'
328
- });
319
+ console.log('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
329
320
  isRecordingRef.current = false;
330
321
  onComplete(result);
331
322
  }
@@ -338,7 +329,6 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
338
329
  }, [frames, completedChallenges, challenges, sessionId, onComplete, resetAndRetry, handleRecordingError, strings, minDurationMs, phase]);
339
330
  const startFrameCapture = (0, react_1.useCallback)(() => {
340
331
  if (cameraRef.current && device) {
341
- console.log('Starting frame capture mode');
342
332
  frameCaptureInterval.current = setInterval(async () => {
343
333
  try {
344
334
  const photo = await cameraRef.current?.takePhoto({
@@ -366,14 +356,12 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
366
356
  }
367
357
  }
368
358
  catch (error) {
369
- console.warn('Frame capture error:', error);
359
+ // Silent frame capture errors
370
360
  }
371
361
  }, 100);
372
362
  }
373
363
  }, [device]);
374
364
  const stopRecording = (0, react_1.useCallback)(async () => {
375
- console.log('stopRecording called, isRecording:', isRecordingRef.current, 'hasVideoRef:', !!videoRecordingRef.current);
376
- // Clear any pending timeouts
377
365
  if (recordingTimeoutRef.current) {
378
366
  clearTimeout(recordingTimeoutRef.current);
379
367
  recordingTimeoutRef.current = null;
@@ -382,28 +370,20 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
382
370
  clearInterval(frameCaptureInterval.current);
383
371
  frameCaptureInterval.current = null;
384
372
  }
385
- // Prevent multiple calls
386
373
  if (!isRecordingRef.current) {
387
- console.log('Recording already stopped, ignoring');
388
374
  return;
389
375
  }
390
- // Mark as not recording first to prevent re-entry
391
376
  isRecordingRef.current = false;
392
377
  if (videoRecordingRef.current) {
393
378
  try {
394
- console.log('Stopping video recording, current ref exists');
395
379
  const recording = videoRecordingRef.current;
396
380
  videoRecordingRef.current = null;
397
381
  await recording.stop();
398
- console.log('Video recording stopped - waiting for onRecordingFinished callback');
399
- // onRecordingFinished callback will handle completion
400
382
  }
401
383
  catch (error) {
402
384
  console.error('Error stopping video recording:', error);
403
385
  const actualDuration = Date.now() - recordingStartTime.current;
404
- console.log('Error duration check:', actualDuration, 'minDurationMs:', minDurationMs, 'frames:', frames.length);
405
386
  if (actualDuration >= minDurationMs && frames.length > 0) {
406
- console.log('Video stopped with error, using captured frames');
407
387
  const result = {
408
388
  frames,
409
389
  duration: actualDuration,
@@ -415,8 +395,6 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
415
395
  onComplete(result);
416
396
  }
417
397
  else {
418
- // Even if we don't have enough frames, try to complete with what we have
419
- console.log('Completing with available data despite error');
420
398
  const result = {
421
399
  frames: frames.length > 0 ? frames : [],
422
400
  duration: actualDuration,
@@ -430,12 +408,15 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
430
408
  }
431
409
  }
432
410
  else {
433
- console.log('No video recording ref - completing with captured frames');
434
411
  const actualDuration = Date.now() - recordingStartTime.current;
435
- // Set phase to processing immediately
412
+ if (frames.length === 0 && actualDuration < minDurationMs) {
413
+ console.error('No frames and duration too short, cannot complete');
414
+ setPhase('recording');
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
+ return;
417
+ }
436
418
  setPhase('processing');
437
419
  setOverallProgress(100);
438
- // Complete with frames we have
439
420
  const result = {
440
421
  frames: frames.length > 0 ? frames : [],
441
422
  duration: actualDuration,
@@ -444,49 +425,34 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
444
425
  challengesCompleted: completedChallenges,
445
426
  sessionId,
446
427
  };
447
- console.log('Completing without video ref:', {
448
- frames: result.frames.length,
449
- duration: (actualDuration / 1000).toFixed(1) + 's',
450
- challenges: completedChallenges.length
451
- });
452
- // Small delay to ensure UI updates
453
428
  setTimeout(() => {
454
429
  onComplete(result);
455
430
  }, 100);
456
431
  }
457
- }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs]);
432
+ }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs, resetAndRetry, strings]);
458
433
  const runChallenge = (0, react_1.useCallback)((index) => {
459
434
  if (index >= challenges.length) {
460
- console.log('All challenges completed, checking duration');
461
435
  setOverallProgress(100);
462
- // Clear the totalDuration timeout since we're handling it manually
463
436
  if (recordingTimeoutRef.current) {
464
437
  clearTimeout(recordingTimeoutRef.current);
465
438
  recordingTimeoutRef.current = null;
466
- console.log('Cleared totalDuration timeout');
467
439
  }
468
440
  if (isRecordingRef.current) {
469
441
  const elapsed = Date.now() - recordingStartTime.current;
470
- console.log('Checking duration - Elapsed:', (elapsed / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's');
471
442
  if (elapsed < minDurationMs) {
472
443
  const remaining = minDurationMs - elapsed;
473
- console.log('Waiting additional', (remaining / 1000).toFixed(1), 's to meet minimum duration');
474
444
  recordingTimeoutRef.current = setTimeout(() => {
475
- console.log('Minimum duration wait completed, stopping recording');
476
445
  if (isRecordingRef.current) {
477
446
  stopRecording();
478
447
  }
479
448
  }, remaining);
480
449
  return;
481
450
  }
482
- console.log('Duration requirement met, stopping immediately');
483
451
  stopRecording();
484
452
  }
485
453
  else {
486
- console.log('Recording already stopped, checking if we can complete');
487
454
  const actualDuration = Date.now() - recordingStartTime.current;
488
455
  if (actualDuration >= minDurationMs && frames.length > 0) {
489
- console.log('Recording already stopped, completing with frames');
490
456
  const result = {
491
457
  frames,
492
458
  duration: actualDuration,
@@ -542,44 +508,31 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
542
508
  setPhase('recording');
543
509
  recordingStartTime.current = Date.now();
544
510
  isRecordingRef.current = true;
545
- console.log('Starting video recording, total duration:', (totalDuration / 1000).toFixed(1), 's');
546
511
  if (cameraRef.current && device) {
547
512
  try {
548
513
  videoRecordingRef.current = await cameraRef.current.startRecording({
549
514
  flash: 'off',
550
515
  onRecordingFinished: (video) => {
551
- console.log('Video recording finished callback called, path:', video?.path || 'N/A', 'phase:', phase);
552
- // Ensure we're in the right state to process
553
- if (phase === 'recording' || phase === 'processing') {
554
- handleVideoComplete(video);
555
- }
556
- else {
557
- console.warn('Received onRecordingFinished but phase is', phase, '- calling handleVideoComplete anyway');
558
- handleVideoComplete(video);
559
- }
516
+ handleVideoComplete(video);
560
517
  },
561
518
  onRecordingError: (error) => {
562
519
  console.error('Recording error:', error);
563
520
  handleRecordingError(error);
564
521
  },
565
522
  });
566
- console.log('Video recording started successfully');
523
+ startFrameCapture();
567
524
  }
568
525
  catch (error) {
569
- console.warn('Video recording not available, falling back to frame capture:', error);
526
+ console.warn('Video recording not available, falling back to frame capture');
570
527
  startFrameCapture();
571
528
  }
572
529
  }
573
530
  else {
574
- console.log('Camera not available, using frame capture');
575
531
  startFrameCapture();
576
532
  }
577
533
  runChallenge(0);
578
- // Set a safety timeout that's longer than totalDuration to ensure we stop eventually
579
- // This will be cleared if challenges complete early
580
- const maxDuration = Math.max(totalDuration, minDurationMs + 2000); // Add 2s buffer
534
+ const maxDuration = Math.max(totalDuration, minDurationMs + 2000);
581
535
  recordingTimeoutRef.current = setTimeout(() => {
582
- console.log('Safety timeout reached (max duration), stopping recording');
583
536
  if (isRecordingRef.current) {
584
537
  stopRecording().catch(err => {
585
538
  console.error('Error stopping recording on safety timeout:', err);
@@ -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,EACZ,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,qBA+NlC,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"useBiometricSDK.d.ts","sourceRoot":"","sources":["../../src/hooks/useBiometricSDK.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACZ,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"}
@@ -137,24 +137,17 @@ const useBiometricSDK = () => {
137
137
  * Validate identity with all collected data
138
138
  */
139
139
  const validateIdentity = (0, react_1.useCallback)(async () => {
140
- console.log('validateIdentity called, current state:', sdk.getState().currentStep);
141
- // Update state immediately to show validation screen
142
140
  setState(sdk.getState());
143
- // Poll state during validation to catch intermediate updates
144
141
  const pollInterval = setInterval(() => {
145
142
  if (isMounted.current) {
146
- const currentState = sdk.getState();
147
- setState(currentState);
148
- console.log('State polled - step:', currentState.currentStep, 'progress:', currentState.progress);
143
+ setState(sdk.getState());
149
144
  }
150
145
  }, 200);
151
146
  try {
152
147
  const result = await sdk.validateIdentity();
153
148
  clearInterval(pollInterval);
154
149
  if (isMounted.current) {
155
- const finalState = sdk.getState();
156
- setState(finalState);
157
- console.log('Validation complete, final state:', finalState.currentStep, 'result:', result);
150
+ setState(sdk.getState());
158
151
  }
159
152
  return result;
160
153
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexar/biometric-identity-sdk-react-native",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "React Native wrapper for Biometric Identity SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -135,29 +135,16 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
135
135
  * Handle capture completion
136
136
  */
137
137
  const handleCaptureComplete = useCallback(async (data: any) => {
138
- console.log('handleCaptureComplete called, cameraMode:', cameraMode);
139
138
  setShowCamera(false);
140
139
 
141
140
  try {
142
141
  if (cameraMode === 'front') {
143
- console.log('Uploading front ID');
144
142
  await uploadFrontID(data);
145
- console.log('Front ID uploaded successfully');
146
143
  } else if (cameraMode === 'back') {
147
- console.log('Uploading back ID');
148
144
  await uploadBackID(data);
149
- console.log('Back ID uploaded successfully');
150
145
  } else if (cameraMode === 'video') {
151
- console.log('Processing video recording result');
152
- // Handle video recording result
153
146
  const videoResult: VideoRecordingResult = data;
154
147
 
155
- console.log('Storing video recording:', {
156
- frames: videoResult.frames.length,
157
- duration: videoResult.duration,
158
- challengesCompleted: videoResult.challengesCompleted.length
159
- });
160
-
161
148
  await storeVideoRecording({
162
149
  frames: videoResult.frames,
163
150
  duration: videoResult.duration,
@@ -167,10 +154,8 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
167
154
  sessionId: videoResult.sessionId,
168
155
  });
169
156
 
170
- console.log('Video recording stored, starting validation...');
171
- // Automatically start validation after video
172
- const result = await validateIdentity();
173
- console.log('Validation complete, result:', result);
157
+ console.log('Starting validation...');
158
+ await validateIdentity();
174
159
  }
175
160
  } catch (error) {
176
161
  console.error('Capture error:', error);
@@ -249,7 +234,6 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
249
234
 
250
235
  // Show validation progress
251
236
  if (state.currentStep === SDKStep.VALIDATING) {
252
- console.log('Rendering ValidationProgress, progress:', state.progress);
253
237
  return (
254
238
  <ValidationProgress
255
239
  progress={state.progress}
@@ -261,7 +245,6 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
261
245
 
262
246
  // Show result
263
247
  if (state.currentStep === SDKStep.RESULT && state.validationResult) {
264
- console.log('Rendering ResultScreen, result:', state.validationResult);
265
248
  return (
266
249
  <ResultScreen
267
250
  result={state.validationResult}
@@ -329,21 +329,15 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
329
329
  }, [onCancel]);
330
330
 
331
331
  const handleVideoComplete = useCallback(async (video: any) => {
332
- console.log('handleVideoComplete called with video:', video?.path, 'current phase:', phase, 'isRecording:', isRecordingRef.current);
333
-
334
- // Don't process if we're already done (result screen or error)
335
332
  if (phase === 'loading' && !video) {
336
- console.log('Video completion in loading phase with no video, ignoring');
337
333
  return;
338
334
  }
339
335
 
340
336
  try {
341
- console.log('Setting phase to processing');
342
337
  setPhase('processing');
343
338
  setOverallProgress(100);
344
339
 
345
340
  const actualDuration = Date.now() - recordingStartTime.current;
346
- console.log('Video Processing - Duration:', (actualDuration / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's, Frames:', frames.length);
347
341
 
348
342
  if (actualDuration < minDurationMs) {
349
343
  setPhase('recording');
@@ -361,16 +355,19 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
361
355
  try {
362
356
  const RNFS = require('react-native-fs');
363
357
  videoBase64 = await RNFS.readFile(video.path, 'base64');
364
- console.log('Video file read successfully, size:', videoBase64.length, 'bytes');
365
358
  } catch (fsError) {
366
- console.warn('Could not read video file, using captured frames:', fsError);
359
+ console.warn('Could not read video file, using captured frames');
367
360
  }
368
361
  }
369
362
 
370
- const finalFrames = frames.length > 0 ? frames : (videoBase64 ? [videoBase64] : []);
363
+ let finalFrames = frames.length > 0 ? frames : [];
364
+
365
+ if (finalFrames.length === 0 && videoBase64) {
366
+ finalFrames = [videoBase64];
367
+ }
371
368
 
372
369
  if (finalFrames.length === 0) {
373
- console.error('No frames available, cannot complete');
370
+ console.error('No frames or video available, cannot complete');
374
371
  setPhase('recording');
375
372
  handleRecordingError(new Error('No video frames captured'));
376
373
  return;
@@ -385,13 +382,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
385
382
  sessionId,
386
383
  };
387
384
 
388
- console.log('Video recording completed successfully:', {
389
- duration: (actualDuration / 1000).toFixed(1) + 's',
390
- frames: result.frames.length,
391
- challenges: `${completedChallenges.length}/${challenges.length}`,
392
- instructionsFollowed: result.instructionsFollowed,
393
- quality: result.qualityScore.toFixed(0) + '%'
394
- });
385
+ console.log('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
395
386
 
396
387
  isRecordingRef.current = false;
397
388
  onComplete(result);
@@ -405,7 +396,6 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
405
396
 
406
397
  const startFrameCapture = useCallback(() => {
407
398
  if (cameraRef.current && device) {
408
- console.log('Starting frame capture mode');
409
399
  frameCaptureInterval.current = setInterval(async () => {
410
400
  try {
411
401
  const photo = await cameraRef.current?.takePhoto({
@@ -432,16 +422,13 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
432
422
  }
433
423
  }
434
424
  } catch (error) {
435
- console.warn('Frame capture error:', error);
425
+ // Silent frame capture errors
436
426
  }
437
427
  }, 100);
438
428
  }
439
429
  }, [device]);
440
430
 
441
431
  const stopRecording = useCallback(async () => {
442
- console.log('stopRecording called, isRecording:', isRecordingRef.current, 'hasVideoRef:', !!videoRecordingRef.current);
443
-
444
- // Clear any pending timeouts
445
432
  if (recordingTimeoutRef.current) {
446
433
  clearTimeout(recordingTimeoutRef.current);
447
434
  recordingTimeoutRef.current = null;
@@ -452,31 +439,22 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
452
439
  frameCaptureInterval.current = null;
453
440
  }
454
441
 
455
- // Prevent multiple calls
456
442
  if (!isRecordingRef.current) {
457
- console.log('Recording already stopped, ignoring');
458
443
  return;
459
444
  }
460
445
 
461
- // Mark as not recording first to prevent re-entry
462
446
  isRecordingRef.current = false;
463
447
 
464
448
  if (videoRecordingRef.current) {
465
449
  try {
466
- console.log('Stopping video recording, current ref exists');
467
450
  const recording = videoRecordingRef.current;
468
451
  videoRecordingRef.current = null;
469
-
470
452
  await recording.stop();
471
- console.log('Video recording stopped - waiting for onRecordingFinished callback');
472
- // onRecordingFinished callback will handle completion
473
453
  } catch (error) {
474
454
  console.error('Error stopping video recording:', error);
475
455
 
476
456
  const actualDuration = Date.now() - recordingStartTime.current;
477
- console.log('Error duration check:', actualDuration, 'minDurationMs:', minDurationMs, 'frames:', frames.length);
478
457
  if (actualDuration >= minDurationMs && frames.length > 0) {
479
- console.log('Video stopped with error, using captured frames');
480
458
  const result: VideoRecordingResult = {
481
459
  frames,
482
460
  duration: actualDuration,
@@ -487,8 +465,6 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
487
465
  };
488
466
  onComplete(result);
489
467
  } else {
490
- // Even if we don't have enough frames, try to complete with what we have
491
- console.log('Completing with available data despite error');
492
468
  const result: VideoRecordingResult = {
493
469
  frames: frames.length > 0 ? frames : [],
494
470
  duration: actualDuration,
@@ -501,14 +477,22 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
501
477
  }
502
478
  }
503
479
  } else {
504
- console.log('No video recording ref - completing with captured frames');
505
480
  const actualDuration = Date.now() - recordingStartTime.current;
506
481
 
507
- // Set phase to processing immediately
482
+ if (frames.length === 0 && actualDuration < minDurationMs) {
483
+ console.error('No frames and duration too short, cannot complete');
484
+ setPhase('recording');
485
+ Alert.alert(
486
+ strings.errors.videoTooShort?.title || 'Recording Too Short',
487
+ strings.errors.videoTooShort?.message || `Video must be at least ${minDurationMs / 1000} seconds. Please try again.`,
488
+ [{ text: strings.common.retry || 'OK', onPress: resetAndRetry }]
489
+ );
490
+ return;
491
+ }
492
+
508
493
  setPhase('processing');
509
494
  setOverallProgress(100);
510
495
 
511
- // Complete with frames we have
512
496
  const result: VideoRecordingResult = {
513
497
  frames: frames.length > 0 ? frames : [],
514
498
  duration: actualDuration,
@@ -518,40 +502,27 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
518
502
  sessionId,
519
503
  };
520
504
 
521
- console.log('Completing without video ref:', {
522
- frames: result.frames.length,
523
- duration: (actualDuration / 1000).toFixed(1) + 's',
524
- challenges: completedChallenges.length
525
- });
526
-
527
- // Small delay to ensure UI updates
528
505
  setTimeout(() => {
529
506
  onComplete(result);
530
507
  }, 100);
531
508
  }
532
- }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs]);
509
+ }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs, resetAndRetry, strings]);
533
510
 
534
511
  const runChallenge = useCallback((index: number) => {
535
512
  if (index >= challenges.length) {
536
- console.log('All challenges completed, checking duration');
537
513
  setOverallProgress(100);
538
514
 
539
- // Clear the totalDuration timeout since we're handling it manually
540
515
  if (recordingTimeoutRef.current) {
541
516
  clearTimeout(recordingTimeoutRef.current);
542
517
  recordingTimeoutRef.current = null;
543
- console.log('Cleared totalDuration timeout');
544
518
  }
545
519
 
546
520
  if (isRecordingRef.current) {
547
521
  const elapsed = Date.now() - recordingStartTime.current;
548
- console.log('Checking duration - Elapsed:', (elapsed / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's');
549
522
 
550
523
  if (elapsed < minDurationMs) {
551
524
  const remaining = minDurationMs - elapsed;
552
- console.log('Waiting additional', (remaining / 1000).toFixed(1), 's to meet minimum duration');
553
525
  recordingTimeoutRef.current = setTimeout(() => {
554
- console.log('Minimum duration wait completed, stopping recording');
555
526
  if (isRecordingRef.current) {
556
527
  stopRecording();
557
528
  }
@@ -559,13 +530,10 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
559
530
  return;
560
531
  }
561
532
 
562
- console.log('Duration requirement met, stopping immediately');
563
533
  stopRecording();
564
534
  } else {
565
- console.log('Recording already stopped, checking if we can complete');
566
535
  const actualDuration = Date.now() - recordingStartTime.current;
567
536
  if (actualDuration >= minDurationMs && frames.length > 0) {
568
- console.log('Recording already stopped, completing with frames');
569
537
  const result: VideoRecordingResult = {
570
538
  frames,
571
539
  duration: actualDuration,
@@ -632,44 +600,32 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
632
600
  recordingStartTime.current = Date.now();
633
601
  isRecordingRef.current = true;
634
602
 
635
- console.log('Starting video recording, total duration:', (totalDuration / 1000).toFixed(1), 's');
636
-
637
603
  if (cameraRef.current && device) {
638
604
  try {
639
605
  videoRecordingRef.current = await cameraRef.current.startRecording({
640
606
  flash: 'off',
641
607
  onRecordingFinished: (video: any) => {
642
- console.log('Video recording finished callback called, path:', video?.path || 'N/A', 'phase:', phase);
643
- // Ensure we're in the right state to process
644
- if (phase === 'recording' || phase === 'processing') {
645
- handleVideoComplete(video);
646
- } else {
647
- console.warn('Received onRecordingFinished but phase is', phase, '- calling handleVideoComplete anyway');
648
- handleVideoComplete(video);
649
- }
608
+ handleVideoComplete(video);
650
609
  },
651
610
  onRecordingError: (error: any) => {
652
611
  console.error('Recording error:', error);
653
612
  handleRecordingError(error);
654
613
  },
655
614
  });
656
- console.log('Video recording started successfully');
615
+
616
+ startFrameCapture();
657
617
  } catch (error) {
658
- console.warn('Video recording not available, falling back to frame capture:', error);
618
+ console.warn('Video recording not available, falling back to frame capture');
659
619
  startFrameCapture();
660
620
  }
661
621
  } else {
662
- console.log('Camera not available, using frame capture');
663
622
  startFrameCapture();
664
623
  }
665
624
 
666
625
  runChallenge(0);
667
626
 
668
- // Set a safety timeout that's longer than totalDuration to ensure we stop eventually
669
- // This will be cleared if challenges complete early
670
- const maxDuration = Math.max(totalDuration, minDurationMs + 2000); // Add 2s buffer
627
+ const maxDuration = Math.max(totalDuration, minDurationMs + 2000);
671
628
  recordingTimeoutRef.current = setTimeout(() => {
672
- console.log('Safety timeout reached (max duration), stopping recording');
673
629
  if (isRecordingRef.current) {
674
630
  stopRecording().catch(err => {
675
631
  console.error('Error stopping recording on safety timeout:', err);
@@ -192,17 +192,11 @@ export const useBiometricSDK = (): UseBiometricSDKResult => {
192
192
  * Validate identity with all collected data
193
193
  */
194
194
  const validateIdentity = useCallback(async () => {
195
- console.log('validateIdentity called, current state:', sdk.getState().currentStep);
196
-
197
- // Update state immediately to show validation screen
198
195
  setState(sdk.getState());
199
196
 
200
- // Poll state during validation to catch intermediate updates
201
197
  const pollInterval = setInterval(() => {
202
198
  if (isMounted.current) {
203
- const currentState = sdk.getState();
204
- setState(currentState);
205
- console.log('State polled - step:', currentState.currentStep, 'progress:', currentState.progress);
199
+ setState(sdk.getState());
206
200
  }
207
201
  }, 200);
208
202
 
@@ -211,9 +205,7 @@ export const useBiometricSDK = (): UseBiometricSDKResult => {
211
205
  clearInterval(pollInterval);
212
206
 
213
207
  if (isMounted.current) {
214
- const finalState = sdk.getState();
215
- setState(finalState);
216
- console.log('Validation complete, final state:', finalState.currentStep, 'result:', result);
208
+ setState(sdk.getState());
217
209
  }
218
210
  return result;
219
211
  } catch (error) {