@hexar/biometric-identity-sdk-react-native 1.0.11 → 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,CAqyBtD,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,16 +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);
279
- if (!isRecordingRef.current && phase !== 'processing') {
280
- console.log('Video already processed, ignoring duplicate callback');
278
+ if (phase === 'loading' && !video) {
281
279
  return;
282
280
  }
283
281
  try {
284
282
  setPhase('processing');
285
283
  setOverallProgress(100);
286
284
  const actualDuration = Date.now() - recordingStartTime.current;
287
- console.log('Video Processing - Duration:', (actualDuration / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's, Frames:', frames.length);
288
285
  if (actualDuration < minDurationMs) {
289
286
  setPhase('recording');
290
287
  setOverallProgress(0);
@@ -296,15 +293,17 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
296
293
  try {
297
294
  const RNFS = require('react-native-fs');
298
295
  videoBase64 = await RNFS.readFile(video.path, 'base64');
299
- console.log('Video file read successfully, size:', videoBase64.length, 'bytes');
300
296
  }
301
297
  catch (fsError) {
302
- console.warn('Could not read video file, using captured frames:', fsError);
298
+ console.warn('Could not read video file, using captured frames');
303
299
  }
304
300
  }
305
- 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
+ }
306
305
  if (finalFrames.length === 0) {
307
- console.error('No frames available, cannot complete');
306
+ console.error('No frames or video available, cannot complete');
308
307
  setPhase('recording');
309
308
  handleRecordingError(new Error('No video frames captured'));
310
309
  return;
@@ -317,13 +316,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
317
316
  challengesCompleted: completedChallenges,
318
317
  sessionId,
319
318
  };
320
- console.log('Video recording completed successfully:', {
321
- duration: (actualDuration / 1000).toFixed(1) + 's',
322
- frames: result.frames.length,
323
- challenges: `${completedChallenges.length}/${challenges.length}`,
324
- instructionsFollowed: result.instructionsFollowed,
325
- quality: result.qualityScore.toFixed(0) + '%'
326
- });
319
+ console.log('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
327
320
  isRecordingRef.current = false;
328
321
  onComplete(result);
329
322
  }
@@ -336,7 +329,6 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
336
329
  }, [frames, completedChallenges, challenges, sessionId, onComplete, resetAndRetry, handleRecordingError, strings, minDurationMs, phase]);
337
330
  const startFrameCapture = (0, react_1.useCallback)(() => {
338
331
  if (cameraRef.current && device) {
339
- console.log('Starting frame capture mode');
340
332
  frameCaptureInterval.current = setInterval(async () => {
341
333
  try {
342
334
  const photo = await cameraRef.current?.takePhoto({
@@ -364,14 +356,12 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
364
356
  }
365
357
  }
366
358
  catch (error) {
367
- console.warn('Frame capture error:', error);
359
+ // Silent frame capture errors
368
360
  }
369
361
  }, 100);
370
362
  }
371
363
  }, [device]);
372
364
  const stopRecording = (0, react_1.useCallback)(async () => {
373
- console.log('stopRecording called, isRecording:', isRecordingRef.current);
374
- // Clear any pending timeouts
375
365
  if (recordingTimeoutRef.current) {
376
366
  clearTimeout(recordingTimeoutRef.current);
377
367
  recordingTimeoutRef.current = null;
@@ -380,27 +370,20 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
380
370
  clearInterval(frameCaptureInterval.current);
381
371
  frameCaptureInterval.current = null;
382
372
  }
383
- // Prevent multiple calls
384
373
  if (!isRecordingRef.current) {
385
- console.log('Recording already stopped, ignoring');
386
374
  return;
387
375
  }
376
+ isRecordingRef.current = false;
388
377
  if (videoRecordingRef.current) {
389
378
  try {
390
- console.log('Stopping video recording, current ref:', !!videoRecordingRef.current);
391
379
  const recording = videoRecordingRef.current;
392
380
  videoRecordingRef.current = null;
393
- isRecordingRef.current = false;
394
381
  await recording.stop();
395
- console.log('Video recording stopped - waiting for onRecordingFinished callback');
396
382
  }
397
383
  catch (error) {
398
384
  console.error('Error stopping video recording:', error);
399
- isRecordingRef.current = false;
400
385
  const actualDuration = Date.now() - recordingStartTime.current;
401
- console.log('Error duration check:', actualDuration, 'minDurationMs:', minDurationMs, 'frames:', frames.length);
402
386
  if (actualDuration >= minDurationMs && frames.length > 0) {
403
- console.log('Video stopped with error, using captured frames');
404
387
  const result = {
405
388
  frames,
406
389
  duration: actualDuration,
@@ -411,45 +394,65 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
411
394
  };
412
395
  onComplete(result);
413
396
  }
397
+ else {
398
+ const result = {
399
+ frames: frames.length > 0 ? frames : [],
400
+ duration: actualDuration,
401
+ instructionsFollowed: completedChallenges.length === challenges.length,
402
+ qualityScore: frames.length > 0 ? Math.min(100, (frames.length / 30) * 100) : 0,
403
+ challengesCompleted: completedChallenges,
404
+ sessionId,
405
+ };
406
+ onComplete(result);
407
+ }
414
408
  }
415
409
  }
416
410
  else {
417
- console.log('No video recording ref, just setting flag to false');
418
- isRecordingRef.current = false;
411
+ const actualDuration = Date.now() - recordingStartTime.current;
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
+ }
418
+ setPhase('processing');
419
+ setOverallProgress(100);
420
+ const result = {
421
+ frames: frames.length > 0 ? frames : [],
422
+ duration: actualDuration,
423
+ instructionsFollowed: completedChallenges.length === challenges.length,
424
+ qualityScore: frames.length > 0 ? Math.min(100, (frames.length / 30) * 100) : 0,
425
+ challengesCompleted: completedChallenges,
426
+ sessionId,
427
+ };
428
+ setTimeout(() => {
429
+ onComplete(result);
430
+ }, 100);
419
431
  }
420
- }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs]);
432
+ }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs, resetAndRetry, strings]);
421
433
  const runChallenge = (0, react_1.useCallback)((index) => {
422
434
  if (index >= challenges.length) {
423
- console.log('All challenges completed, checking duration');
424
435
  setOverallProgress(100);
425
- // Clear the totalDuration timeout since we're handling it manually
426
436
  if (recordingTimeoutRef.current) {
427
437
  clearTimeout(recordingTimeoutRef.current);
428
438
  recordingTimeoutRef.current = null;
429
- console.log('Cleared totalDuration timeout');
430
439
  }
431
440
  if (isRecordingRef.current) {
432
441
  const elapsed = Date.now() - recordingStartTime.current;
433
- console.log('Checking duration - Elapsed:', (elapsed / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's');
434
442
  if (elapsed < minDurationMs) {
435
443
  const remaining = minDurationMs - elapsed;
436
- console.log('Waiting additional', (remaining / 1000).toFixed(1), 's to meet minimum duration');
437
444
  recordingTimeoutRef.current = setTimeout(() => {
438
- console.log('Minimum duration wait completed, stopping recording');
439
445
  if (isRecordingRef.current) {
440
446
  stopRecording();
441
447
  }
442
448
  }, remaining);
443
449
  return;
444
450
  }
445
- console.log('Duration requirement met, stopping immediately');
446
451
  stopRecording();
447
452
  }
448
453
  else {
449
- console.log('Recording already stopped, checking if we can complete');
450
454
  const actualDuration = Date.now() - recordingStartTime.current;
451
455
  if (actualDuration >= minDurationMs && frames.length > 0) {
452
- console.log('Recording already stopped, completing with frames');
453
456
  const result = {
454
457
  frames,
455
458
  duration: actualDuration,
@@ -505,44 +508,31 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
505
508
  setPhase('recording');
506
509
  recordingStartTime.current = Date.now();
507
510
  isRecordingRef.current = true;
508
- console.log('Starting video recording, total duration:', (totalDuration / 1000).toFixed(1), 's');
509
511
  if (cameraRef.current && device) {
510
512
  try {
511
513
  videoRecordingRef.current = await cameraRef.current.startRecording({
512
514
  flash: 'off',
513
515
  onRecordingFinished: (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
- }
516
+ handleVideoComplete(video);
523
517
  },
524
518
  onRecordingError: (error) => {
525
519
  console.error('Recording error:', error);
526
520
  handleRecordingError(error);
527
521
  },
528
522
  });
529
- console.log('Video recording started successfully');
523
+ startFrameCapture();
530
524
  }
531
525
  catch (error) {
532
- console.warn('Video recording not available, falling back to frame capture:', error);
526
+ console.warn('Video recording not available, falling back to frame capture');
533
527
  startFrameCapture();
534
528
  }
535
529
  }
536
530
  else {
537
- console.log('Camera not available, using frame capture');
538
531
  startFrameCapture();
539
532
  }
540
533
  runChallenge(0);
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
534
+ const maxDuration = Math.max(totalDuration, minDurationMs + 2000);
544
535
  recordingTimeoutRef.current = setTimeout(() => {
545
- console.log('Safety timeout reached (max duration), stopping recording');
546
536
  if (isRecordingRef.current) {
547
537
  stopRecording().catch(err => {
548
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.11",
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,10 +329,7 @@ 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);
333
-
334
- if (!isRecordingRef.current && phase !== 'processing') {
335
- console.log('Video already processed, ignoring duplicate callback');
332
+ if (phase === 'loading' && !video) {
336
333
  return;
337
334
  }
338
335
 
@@ -341,7 +338,6 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
341
338
  setOverallProgress(100);
342
339
 
343
340
  const actualDuration = Date.now() - recordingStartTime.current;
344
- console.log('Video Processing - Duration:', (actualDuration / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's, Frames:', frames.length);
345
341
 
346
342
  if (actualDuration < minDurationMs) {
347
343
  setPhase('recording');
@@ -359,16 +355,19 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
359
355
  try {
360
356
  const RNFS = require('react-native-fs');
361
357
  videoBase64 = await RNFS.readFile(video.path, 'base64');
362
- console.log('Video file read successfully, size:', videoBase64.length, 'bytes');
363
358
  } catch (fsError) {
364
- console.warn('Could not read video file, using captured frames:', fsError);
359
+ console.warn('Could not read video file, using captured frames');
365
360
  }
366
361
  }
367
362
 
368
- 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
+ }
369
368
 
370
369
  if (finalFrames.length === 0) {
371
- console.error('No frames available, cannot complete');
370
+ console.error('No frames or video available, cannot complete');
372
371
  setPhase('recording');
373
372
  handleRecordingError(new Error('No video frames captured'));
374
373
  return;
@@ -383,13 +382,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
383
382
  sessionId,
384
383
  };
385
384
 
386
- console.log('Video recording completed successfully:', {
387
- duration: (actualDuration / 1000).toFixed(1) + 's',
388
- frames: result.frames.length,
389
- challenges: `${completedChallenges.length}/${challenges.length}`,
390
- instructionsFollowed: result.instructionsFollowed,
391
- quality: result.qualityScore.toFixed(0) + '%'
392
- });
385
+ console.log('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
393
386
 
394
387
  isRecordingRef.current = false;
395
388
  onComplete(result);
@@ -403,7 +396,6 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
403
396
 
404
397
  const startFrameCapture = useCallback(() => {
405
398
  if (cameraRef.current && device) {
406
- console.log('Starting frame capture mode');
407
399
  frameCaptureInterval.current = setInterval(async () => {
408
400
  try {
409
401
  const photo = await cameraRef.current?.takePhoto({
@@ -430,16 +422,13 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
430
422
  }
431
423
  }
432
424
  } catch (error) {
433
- console.warn('Frame capture error:', error);
425
+ // Silent frame capture errors
434
426
  }
435
427
  }, 100);
436
428
  }
437
429
  }, [device]);
438
430
 
439
431
  const stopRecording = useCallback(async () => {
440
- console.log('stopRecording called, isRecording:', isRecordingRef.current);
441
-
442
- // Clear any pending timeouts
443
432
  if (recordingTimeoutRef.current) {
444
433
  clearTimeout(recordingTimeoutRef.current);
445
434
  recordingTimeoutRef.current = null;
@@ -450,29 +439,22 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
450
439
  frameCaptureInterval.current = null;
451
440
  }
452
441
 
453
- // Prevent multiple calls
454
442
  if (!isRecordingRef.current) {
455
- console.log('Recording already stopped, ignoring');
456
443
  return;
457
444
  }
458
445
 
446
+ isRecordingRef.current = false;
447
+
459
448
  if (videoRecordingRef.current) {
460
449
  try {
461
- console.log('Stopping video recording, current ref:', !!videoRecordingRef.current);
462
450
  const recording = videoRecordingRef.current;
463
451
  videoRecordingRef.current = null;
464
- isRecordingRef.current = false;
465
-
466
452
  await recording.stop();
467
- console.log('Video recording stopped - waiting for onRecordingFinished callback');
468
453
  } catch (error) {
469
454
  console.error('Error stopping video recording:', error);
470
- isRecordingRef.current = false;
471
455
 
472
456
  const actualDuration = Date.now() - recordingStartTime.current;
473
- console.log('Error duration check:', actualDuration, 'minDurationMs:', minDurationMs, 'frames:', frames.length);
474
457
  if (actualDuration >= minDurationMs && frames.length > 0) {
475
- console.log('Video stopped with error, using captured frames');
476
458
  const result: VideoRecordingResult = {
477
459
  frames,
478
460
  duration: actualDuration,
@@ -482,35 +464,65 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
482
464
  sessionId,
483
465
  };
484
466
  onComplete(result);
467
+ } else {
468
+ const result: VideoRecordingResult = {
469
+ frames: frames.length > 0 ? frames : [],
470
+ duration: actualDuration,
471
+ instructionsFollowed: completedChallenges.length === challenges.length,
472
+ qualityScore: frames.length > 0 ? Math.min(100, (frames.length / 30) * 100) : 0,
473
+ challengesCompleted: completedChallenges,
474
+ sessionId,
475
+ };
476
+ onComplete(result);
485
477
  }
486
478
  }
487
479
  } else {
488
- console.log('No video recording ref, just setting flag to false');
489
- isRecordingRef.current = false;
480
+ const actualDuration = Date.now() - recordingStartTime.current;
481
+
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
+
493
+ setPhase('processing');
494
+ setOverallProgress(100);
495
+
496
+ const result: VideoRecordingResult = {
497
+ frames: frames.length > 0 ? frames : [],
498
+ duration: actualDuration,
499
+ instructionsFollowed: completedChallenges.length === challenges.length,
500
+ qualityScore: frames.length > 0 ? Math.min(100, (frames.length / 30) * 100) : 0,
501
+ challengesCompleted: completedChallenges,
502
+ sessionId,
503
+ };
504
+
505
+ setTimeout(() => {
506
+ onComplete(result);
507
+ }, 100);
490
508
  }
491
- }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs]);
509
+ }, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs, resetAndRetry, strings]);
492
510
 
493
511
  const runChallenge = useCallback((index: number) => {
494
512
  if (index >= challenges.length) {
495
- console.log('All challenges completed, checking duration');
496
513
  setOverallProgress(100);
497
514
 
498
- // Clear the totalDuration timeout since we're handling it manually
499
515
  if (recordingTimeoutRef.current) {
500
516
  clearTimeout(recordingTimeoutRef.current);
501
517
  recordingTimeoutRef.current = null;
502
- console.log('Cleared totalDuration timeout');
503
518
  }
504
519
 
505
520
  if (isRecordingRef.current) {
506
521
  const elapsed = Date.now() - recordingStartTime.current;
507
- console.log('Checking duration - Elapsed:', (elapsed / 1000).toFixed(1), 's, Min required:', (minDurationMs / 1000).toFixed(1), 's');
508
522
 
509
523
  if (elapsed < minDurationMs) {
510
524
  const remaining = minDurationMs - elapsed;
511
- console.log('Waiting additional', (remaining / 1000).toFixed(1), 's to meet minimum duration');
512
525
  recordingTimeoutRef.current = setTimeout(() => {
513
- console.log('Minimum duration wait completed, stopping recording');
514
526
  if (isRecordingRef.current) {
515
527
  stopRecording();
516
528
  }
@@ -518,13 +530,10 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
518
530
  return;
519
531
  }
520
532
 
521
- console.log('Duration requirement met, stopping immediately');
522
533
  stopRecording();
523
534
  } else {
524
- console.log('Recording already stopped, checking if we can complete');
525
535
  const actualDuration = Date.now() - recordingStartTime.current;
526
536
  if (actualDuration >= minDurationMs && frames.length > 0) {
527
- console.log('Recording already stopped, completing with frames');
528
537
  const result: VideoRecordingResult = {
529
538
  frames,
530
539
  duration: actualDuration,
@@ -591,44 +600,32 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
591
600
  recordingStartTime.current = Date.now();
592
601
  isRecordingRef.current = true;
593
602
 
594
- console.log('Starting video recording, total duration:', (totalDuration / 1000).toFixed(1), 's');
595
-
596
603
  if (cameraRef.current && device) {
597
604
  try {
598
605
  videoRecordingRef.current = await cameraRef.current.startRecording({
599
606
  flash: 'off',
600
607
  onRecordingFinished: (video: any) => {
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
- }
608
+ handleVideoComplete(video);
609
609
  },
610
610
  onRecordingError: (error: any) => {
611
611
  console.error('Recording error:', error);
612
612
  handleRecordingError(error);
613
613
  },
614
614
  });
615
- console.log('Video recording started successfully');
615
+
616
+ startFrameCapture();
616
617
  } catch (error) {
617
- console.warn('Video recording not available, falling back to frame capture:', error);
618
+ console.warn('Video recording not available, falling back to frame capture');
618
619
  startFrameCapture();
619
620
  }
620
621
  } else {
621
- console.log('Camera not available, using frame capture');
622
622
  startFrameCapture();
623
623
  }
624
624
 
625
625
  runChallenge(0);
626
626
 
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
627
+ const maxDuration = Math.max(totalDuration, minDurationMs + 2000);
630
628
  recordingTimeoutRef.current = setTimeout(() => {
631
- console.log('Safety timeout reached (max duration), stopping recording');
632
629
  if (isRecordingRef.current) {
633
630
  stopRecording().catch(err => {
634
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) {