@sanctum-key/react-native-sdk 1.0.35 → 1.0.37

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanctum-key/react-native-sdk",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "Sanctum Key React Native SDK",
5
5
  "main": "build/src/index.js",
6
6
  "types": "build/src/index.d.ts",
@@ -1 +1 @@
1
- {"version":3,"file":"IDCardCapture.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/IDCardCapture.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAIpE,OAAO,EAAE,iBAAiB,EAAoI,MAAM,uBAAuB,CAAC;AAsB5L,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAyoCtD,CAAC"}
1
+ {"version":3,"file":"IDCardCapture.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/IDCardCapture.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAIpE,OAAO,EAAE,iBAAiB,EAAoI,MAAM,uBAAuB,CAAC;AAsB5L,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA2lCtD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useMemo, useRef, useState } from 'react';
2
- import { View, Text, StyleSheet, Image, ScrollView, Platform, ActivityIndicator, TouchableOpacity, useWindowDimensions, Alert } from 'react-native';
2
+ import { View, Text, StyleSheet, Image, ScrollView, Platform, ActivityIndicator, TouchableOpacity, useWindowDimensions } from 'react-native';
3
3
  import { showAlert } from '../../utils/platformAlert';
4
4
  import { EnhancedCameraView } from '../EnhancedCameraView';
5
5
  import { GovernmentDocumentTypeShorted, GovernmentDocumentTypeBackend } from '../../types/KYC.types';
@@ -484,9 +484,7 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
484
484
  return;
485
485
  if (result.success && result.path) {
486
486
  setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
487
- const safeCapturePath = Platform.OS === 'ios' && !result.path.startsWith('file://')
488
- ? `file://${result.path}`
489
- : result.path;
487
+ const safeCapturePath = Platform.OS === 'ios' && !result.path.startsWith('file://') ? `file://${result.path}` : result.path;
490
488
  let templatePath = capturedImages[currentSide]?.templatePath || '';
491
489
  let templateBbox;
492
490
  let templateResponse;
@@ -495,18 +493,15 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
495
493
  return;
496
494
  }
497
495
  const issuingSubdivision = selectedDocumentType.region !== 'root' ? selectedDocumentType.region : undefined;
498
- // 🚨 WATCHDOG TIMER: If the iOS network drops and doesn't throw, this guarantees the UI unlocks after 20 seconds.
496
+ // Subtle timeout handling without blocking pop-ups
499
497
  const watchdog = setTimeout(() => {
500
498
  if (isAnalyzingRef.current) {
501
499
  setSilentCaptureResult((prev) => ({
502
500
  ...prev,
503
501
  isAnalyzing: false,
504
502
  success: false,
505
- error: state.currentLanguage === 'en' ? 'Connection timeout. Please try again.' : 'Délai de connexion dépassé. Veuillez réessayer.'
503
+ error: state.currentLanguage === 'en' ? 'Taking longer than expected. Hold steady.' : 'Traitement long. Veuillez rester immobile.'
506
504
  }));
507
- Alert.alert(state.currentLanguage === 'en' ? "Timeout" : "Délai dépassé", state.currentLanguage === 'en'
508
- ? "The request took too long. Please verify your network and try again."
509
- : "La requête a pris trop de temps. Veuillez vérifier votre connexion et réessayer.");
510
505
  }
511
506
  }, 20000);
512
507
  try {
@@ -543,10 +538,7 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
543
538
  const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || 'TD1';
544
539
  verificationRes = await frontVerification({
545
540
  path: safeCapturePath,
546
- regionMapping: {
547
- authMethod: matchedAuthMethod ? [matchedAuthMethod] : [],
548
- mrzTypes: mrzType ? [mrzType] : []
549
- },
541
+ regionMapping: { authMethod: matchedAuthMethod ? [matchedAuthMethod] : [], mrzTypes: mrzType ? [mrzType] : [] },
550
542
  selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '',
551
543
  code: countryData?.code || '',
552
544
  currentSide,
@@ -563,10 +555,7 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
563
555
  const frontTemplatePath = capturedImages['front']?.templatePath || '';
564
556
  verificationRes = await backVerification({
565
557
  path: safeCapturePath,
566
- regionMapping: {
567
- authMethod: matchedBackAuthMethod ? [matchedBackAuthMethod] : [],
568
- mrzTypes: backMrzType ? [backMrzType] : []
569
- },
558
+ regionMapping: { authMethod: matchedBackAuthMethod ? [matchedBackAuthMethod] : [], mrzTypes: backMrzType ? [backMrzType] : [] },
570
559
  selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '',
571
560
  code: countryData?.code || '',
572
561
  currentSide,
@@ -629,34 +618,28 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
629
618
  }
630
619
  catch (error) {
631
620
  clearTimeout(watchdog);
632
- console.log("Backend Verification Error:", error);
633
- const isNetworkError = !error.response ||
634
- error.message === 'Network Error' ||
635
- error.code === 'ECONNABORTED' ||
636
- error.message?.includes('Network');
637
- let userFriendlyMessage = 'Verification failed. Please try again.';
621
+ const isNetworkError = !error.response || error.message === 'Network Error' || error.code === 'ECONNABORTED' || error.message?.includes('Network');
622
+ // Keep UI errors extremely brief and actionable
623
+ let hintMessage = '';
638
624
  if (isNetworkError) {
639
- userFriendlyMessage = state.currentLanguage === 'en'
640
- ? 'Cannot connect to verification server. Please check your internet connection.'
641
- : 'Impossible de se connecter au serveur de vérification. Veuillez vérifier votre connexion internet.';
642
- Alert.alert(state.currentLanguage === 'en' ? "Connection Failed" : "Échec de connexion", userFriendlyMessage);
625
+ hintMessage = state.currentLanguage === 'en' ? 'Poor connection. Retrying...' : 'Connexion faible. Nouvelle tentative...';
643
626
  }
644
627
  else {
645
628
  const rawMessage = (error?.message || '').toLowerCase();
646
629
  if (rawMessage.includes('impossible') || rawMessage.includes('unreadable')) {
647
- userFriendlyMessage = 'Document unreadable. Please hold the camera steady in good light.';
630
+ hintMessage = state.currentLanguage === 'en' ? 'Move to better lighting.' : 'Améliorez l\'éclairage.';
648
631
  }
649
632
  else if (rawMessage.includes('country mismatch') || rawMessage.includes('pays sélectionné')) {
650
- userFriendlyMessage = 'The document does not match your selected country.';
633
+ hintMessage = state.currentLanguage === 'en' ? 'Wrong document type.' : 'Mauvais type de document.';
651
634
  }
652
635
  else if (rawMessage.includes('card_not_fully_in_frame')) {
653
- userFriendlyMessage = 'Move closer to the document and ensure all corners are visible.';
636
+ hintMessage = state.currentLanguage === 'en' ? 'Move closer.' : 'Rapprochez-vous.';
654
637
  }
655
638
  else if (rawMessage.includes('ne correspond pas au recto')) {
656
- userFriendlyMessage = 'The back of the document does not match the front. You must scan the same ID.';
639
+ hintMessage = state.currentLanguage === 'en' ? 'Scan the same ID.' : 'Scannez la même pièce.';
657
640
  }
658
641
  }
659
- setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: userFriendlyMessage }));
642
+ setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: hintMessage }));
660
643
  }
661
644
  }
662
645
  };
@@ -671,34 +654,18 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
671
654
  }, [scanPhase, pendingCAImage, silentCaptureResult.barcode]);
672
655
  const handleError = (event) => {
673
656
  logger.error("Camera Error:", event);
674
- // Normalize the error to lowercase for easy checking
675
657
  const errString = `${event.message} ${event.name} ${event.code}`.toLowerCase();
676
- let friendlyMessage = state.currentLanguage === 'en'
677
- ? 'An unknown camera error occurred.'
678
- : 'Une erreur de caméra inconnue est survenue.';
679
- // 1. Detect Hardware Lock (Camera in use by Zoom, Teams, or another app)
680
- if (errString.includes('notreadableerror') ||
681
- errString.includes('trackstarterror') ||
682
- errString.includes('in use') ||
683
- errString.includes('concurrent') ||
684
- errString.includes('camera unavailable')) {
685
- friendlyMessage = state.currentLanguage === 'en'
686
- ? 'Your camera is currently being used by another application (like Zoom or Teams). Please close the other app and try again.'
687
- : 'Votre caméra est actuellement utilisée par une autre application. Veuillez fermer l\'autre application et réessayer.';
658
+ let friendlyMessage = state.currentLanguage === 'en' ? 'Camera error.' : 'Erreur de caméra.';
659
+ if (errString.includes('notreadableerror') || errString.includes('trackstarterror') || errString.includes('in use') || errString.includes('concurrent') || errString.includes('camera unavailable')) {
660
+ friendlyMessage = state.currentLanguage === 'en' ? 'Camera is in use by another app.' : 'Caméra utilisée par une autre application.';
688
661
  }
689
- // 2. Detect Permission Denied
690
662
  else if (errString.includes('notallowederror') || errString.includes('permission')) {
691
- friendlyMessage = state.currentLanguage === 'en'
692
- ? 'Camera permission denied. Please allow camera access in your settings to proceed.'
693
- : 'Autorisation de la caméra refusée. Veuillez autoriser l\'accès dans vos paramètres.';
663
+ friendlyMessage = state.currentLanguage === 'en' ? 'Allow camera access in settings.' : 'Autorisez l\'accès à la caméra.';
694
664
  }
695
- // 3. Detect No Camera Found
696
665
  else if (errString.includes('notfounderror') || errString.includes('no camera')) {
697
- friendlyMessage = state.currentLanguage === 'en'
698
- ? 'No camera detected on this device.'
699
- : 'Aucune caméra détectée sur cet appareil.';
666
+ friendlyMessage = state.currentLanguage === 'en' ? 'No camera detected.' : 'Aucune caméra détectée.';
700
667
  }
701
- showAlert(state.currentLanguage === 'en' ? 'Camera Error' : 'Erreur de Caméra', friendlyMessage);
668
+ showAlert(state.currentLanguage === 'en' ? 'Camera Error' : 'Erreur', friendlyMessage);
702
669
  setShowCamera(false);
703
670
  setIsProcessingCapture(false);
704
671
  };