@sanctum-key/react-native-sdk 1.0.6 → 1.0.7
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.
- package/README.md +3 -3
- package/android/build/.transforms/{f62cb96b2d1f78ca96ab35932dd530dc → c9d62bb333688ab562f51958998d5a48}/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/generated/source/buildConfig/debug/kyc/{transfergratis → SanctumKey}/com/BuildConfig.java +2 -2
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +1 -1
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +1 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +2 -2
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/kyc/SanctumKey/com/BuildConfig.class +0 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +1 -1
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +1 -1
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -1
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +1 -1
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$1$5$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$1$5$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$View$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule.class → SanctumKey/com/SanctumKeySdkModule.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkView.class → SanctumKey/com/SanctumKeySdkView.class} +0 -0
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/kyc/transfergratis/com/TransfergratisSdkModule.kt +6 -6
- package/android/src/main/java/kyc/transfergratis/com/TransfergratisSdkView.kt +2 -2
- package/build/package.json +9 -7
- package/build/src/App.d.ts +2 -2
- package/build/src/App.d.ts.map +1 -1
- package/build/src/App.js +2 -2
- package/build/src/App.js.map +1 -1
- package/build/src/{TransfergratisSdk.types.d.ts → SanctumKeySdk.types.d.ts} +3 -3
- package/build/src/SanctumKeySdk.types.d.ts.map +1 -0
- package/build/src/SanctumKeySdk.types.js +2 -0
- package/build/src/SanctumKeySdk.types.js.map +1 -0
- package/build/src/{TransfergratisSdkModule.d.ts → SanctumKeySdkModule.d.ts} +4 -4
- package/build/src/SanctumKeySdkModule.d.ts.map +1 -0
- package/build/src/{TransfergratisSdkModule.js → SanctumKeySdkModule.js} +2 -2
- package/build/src/SanctumKeySdkModule.js.map +1 -0
- package/build/src/{TransfergratisSdkModule.web.d.ts → SanctumKeySdkModule.web.d.ts} +4 -4
- package/build/src/SanctumKeySdkModule.web.d.ts.map +1 -0
- package/build/src/{TransfergratisSdkModule.web.js → SanctumKeySdkModule.web.js} +3 -3
- package/build/src/SanctumKeySdkModule.web.js.map +1 -0
- package/build/src/SanctumKeySdkView.d.ts +4 -0
- package/build/src/SanctumKeySdkView.d.ts.map +1 -0
- package/build/src/SanctumKeySdkView.js +7 -0
- package/build/src/SanctumKeySdkView.js.map +1 -0
- package/build/src/SanctumKeySdkView.web.d.ts +4 -0
- package/build/src/SanctumKeySdkView.web.d.ts.map +1 -0
- package/build/src/{TransfergratisSdkView.web.js → SanctumKeySdkView.web.js} +2 -2
- package/build/src/SanctumKeySdkView.web.js.map +1 -0
- package/build/src/api/axios.js +2 -2
- package/build/src/api/axios.js.map +1 -1
- package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.js +66 -338
- package/build/src/components/EnhancedCameraView.js.map +1 -1
- package/build/src/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/EmailVerificationTemplate.js +93 -15
- package/build/src/components/KYCElements/EmailVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +167 -695
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js +269 -40
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/SelfieCapture.d.ts +1 -1
- package/build/src/components/KYCElements/SelfieCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/SelfieCapture.js +130 -192
- package/build/src/components/KYCElements/SelfieCapture.js.map +1 -1
- package/build/src/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/SelfieCaptureTemplate.js +131 -433
- package/build/src/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/src/components/NativeCameraView.js +1 -1
- package/build/src/components/NativeCameraView.js.map +1 -1
- package/build/src/components/OverLay/IdCard.d.ts +3 -2
- package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/src/components/OverLay/IdCard.js +149 -141
- package/build/src/components/OverLay/IdCard.js.map +1 -1
- package/build/src/components/OverLay/SelfieOverlay.d.ts +2 -1
- package/build/src/components/OverLay/SelfieOverlay.d.ts.map +1 -1
- package/build/src/components/OverLay/SelfieOverlay.js +37 -95
- package/build/src/components/OverLay/SelfieOverlay.js.map +1 -1
- package/build/src/components/OverLay/type.d.ts +1 -0
- package/build/src/components/OverLay/type.d.ts.map +1 -1
- package/build/src/components/OverLay/type.js.map +1 -1
- package/build/src/components/Svgs/scanningLine.d.ts +2 -1
- package/build/src/components/Svgs/scanningLine.d.ts.map +1 -1
- package/build/src/components/Svgs/scanningLine.js +55 -51
- package/build/src/components/Svgs/scanningLine.js.map +1 -1
- package/build/src/config/KYCConfig.js +1 -1
- package/build/src/config/KYCConfig.js.map +1 -1
- package/build/src/config/allowedDomains.js +6 -6
- package/build/src/config/allowedDomains.js.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js +37 -38
- package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/src/index.d.ts +3 -3
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +3 -3
- package/build/src/index.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts +0 -5
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +114 -116
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +11 -1
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +101 -38
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/modules/camera/NativeCameraModule.js +17 -17
- package/build/src/modules/camera/NativeCameraModule.js.map +1 -1
- package/expo-module.config.json +2 -2
- package/ios/TransfergratisSdk.podspec +2 -2
- package/ios/TransfergratisSdkModule.swift +12 -12
- package/package.json +9 -7
- package/src/App.tsx +2 -2
- package/src/{TransfergratisSdk.types.ts → SanctumKeySdk.types.ts} +2 -2
- package/src/{TransfergratisSdkModule.ts → SanctumKeySdkModule.ts} +3 -3
- package/src/{TransfergratisSdkModule.web.ts → SanctumKeySdkModule.web.ts} +3 -3
- package/src/SanctumKeySdkView.tsx +11 -0
- package/src/{TransfergratisSdkView.web.tsx → SanctumKeySdkView.web.tsx} +2 -2
- package/src/api/axios.ts +2 -2
- package/src/components/EnhancedCameraView.tsx +81 -400
- package/src/components/KYCElements/EmailVerificationTemplate.tsx +115 -26
- package/src/components/KYCElements/IDCardCapture.tsx +228 -868
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +328 -60
- package/src/components/KYCElements/SelfieCapture.tsx +184 -213
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +330 -662
- package/src/components/NativeCameraView.tsx +1 -1
- package/src/components/OverLay/IdCard.tsx +218 -217
- package/src/components/OverLay/SelfieOverlay.tsx +56 -134
- package/src/components/OverLay/type.ts +1 -0
- package/src/components/Svgs/scanningLine.tsx +71 -72
- package/src/config/KYCConfig.ts +1 -1
- package/src/config/allowedDomains.ts +6 -6
- package/src/hooks/useTemplateKYCFlow.tsx +45 -39
- package/src/i18n/README.md +1 -1
- package/src/index.ts +3 -3
- package/src/modules/api/CardAuthentification.ts +202 -200
- package/src/modules/api/KYCService.ts +168 -53
- package/src/modules/camera/NativeCameraModule.ts +17 -17
- package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$1$5$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$1$5$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$View$1.class +0 -0
- package/build/src/TransfergratisSdk.types.d.ts.map +0 -1
- package/build/src/TransfergratisSdk.types.js +0 -2
- package/build/src/TransfergratisSdk.types.js.map +0 -1
- package/build/src/TransfergratisSdkModule.d.ts.map +0 -1
- package/build/src/TransfergratisSdkModule.js.map +0 -1
- package/build/src/TransfergratisSdkModule.web.d.ts.map +0 -1
- package/build/src/TransfergratisSdkModule.web.js.map +0 -1
- package/build/src/TransfergratisSdkView.d.ts +0 -4
- package/build/src/TransfergratisSdkView.d.ts.map +0 -1
- package/build/src/TransfergratisSdkView.js +0 -7
- package/build/src/TransfergratisSdkView.js.map +0 -1
- package/build/src/TransfergratisSdkView.web.d.ts +0 -4
- package/build/src/TransfergratisSdkView.web.d.ts.map +0 -1
- package/build/src/TransfergratisSdkView.web.js.map +0 -1
- package/src/TransfergratisSdkView.tsx +0 -11
- /package/android/build/.transforms/{532c0e65d82f446633d0a7dab2772198 → ab90740579f5bd05b27b4343ada2d1c9}/results.bin +0 -0
- /package/android/build/.transforms/{532c0e65d82f446633d0a7dab2772198 → ab90740579f5bd05b27b4343ada2d1c9}/transformed/classes/classes_dex/classes.dex +0 -0
- /package/android/build/.transforms/{f62cb96b2d1f78ca96ab35932dd530dc → c9d62bb333688ab562f51958998d5a48}/results.bin +0 -0
- /package/android/build/{intermediates/javac/debug/compileDebugJavaWithJavac/classes/kyc/transfergratis/com/BuildConfig.class → tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/BuildConfig.class.uniqueId0} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { View, Text, StyleSheet, Image, ScrollView, Platform,
|
|
2
|
+
import { View, Text, StyleSheet, Image, ScrollView, Platform, ActivityIndicator } 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';
|
|
@@ -11,140 +11,71 @@ import { removeDuplicates } from '../../utils/remove-duplicate';
|
|
|
11
11
|
import { backVerification, checkTemplateType, frontVerification } from '../../modules/api/CardAuthentification';
|
|
12
12
|
import { getDocumentTypeInfo } from '../../utils/get-document-type-info';
|
|
13
13
|
import pathToBase64 from '../../utils/pathToBase64';
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
import { isMobileWeb } from '../../utils/deviceDetection';
|
|
17
|
-
import { logger } from '../../utils/logger';
|
|
18
|
-
export const IDCardCapture = ({ component, value = {}, onValueChange, error, language = 'en', }) => {
|
|
14
|
+
import { cropByObb, cropImageWithBBoxWithTolerance, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from '../../utils/cropByObb';
|
|
15
|
+
export const IDCardCapture = ({ component, value = {}, onValueChange, error, language = 'en' }) => {
|
|
19
16
|
const { t, locale } = useI18n();
|
|
20
17
|
const [showCamera, setShowCamera] = useState(false);
|
|
21
18
|
const [capturedImages, setCapturedImages] = useState(value || {});
|
|
22
|
-
// const [cropImageUri, setCropImageUri] = useState<string>('');
|
|
23
19
|
const [currentSide, setCurrentSide] = useState('front');
|
|
24
20
|
const [bboxBySide, setBboxBySide] = useState({});
|
|
25
21
|
const [silentCaptureResult, setSilentCaptureResult] = useState({ success: false, isAnalyzing: false });
|
|
26
|
-
const [
|
|
27
|
-
|
|
22
|
+
const [isProcessingCapture, setIsProcessingCapture] = useState(false);
|
|
23
|
+
const [processingImagePath, setProcessingImagePath] = useState(null);
|
|
28
24
|
const documentTypeMapping = {
|
|
29
|
-
'nationalId': 'national_id',
|
|
30
|
-
'
|
|
31
|
-
'driversLicense': 'drivers_licence',
|
|
32
|
-
'residencePermit': 'permanent_residence',
|
|
33
|
-
'healthInsuranceCard': 'health_insurance_card',
|
|
25
|
+
'nationalId': 'national_id', 'passport': 'passport', 'driversLicense': 'drivers_licence',
|
|
26
|
+
'residencePermit': 'permanent_residence', 'healthInsuranceCard': 'health_insurance_card',
|
|
34
27
|
};
|
|
35
|
-
// const [imageNaturalSize, setImageNaturalSize] = useState<{ width: number; height: number } | null>(null);
|
|
36
28
|
const { actions, state, env } = useTemplateKYCFlowContext();
|
|
37
29
|
const getLocalizedText = (text) => {
|
|
38
|
-
|
|
39
|
-
if (text && typeof text[currentSide] === 'object' && text[currentSide][locale]) {
|
|
30
|
+
if (text && typeof text[currentSide] === 'object' && text[currentSide][locale])
|
|
40
31
|
return text[currentSide][locale] || '';
|
|
41
|
-
}
|
|
42
32
|
return "";
|
|
43
33
|
};
|
|
44
|
-
// Récupérer les données depuis le composant country_selection
|
|
45
34
|
const countrySelectionData = useMemo(() => {
|
|
46
35
|
const countrySelectionComponent = state.template.components.find(c => c.type === 'country_selection');
|
|
47
|
-
|
|
48
|
-
return state.componentData[countrySelectionComponent.id];
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
36
|
+
return countrySelectionComponent ? state.componentData[countrySelectionComponent.id] : null;
|
|
51
37
|
}, [state.template.components, state.componentData]);
|
|
52
|
-
// Extraire selectedDocumentType depuis countrySelectionData
|
|
53
38
|
const selectedDocumentType = useMemo(() => {
|
|
54
39
|
if (!countrySelectionData?.documentType)
|
|
55
40
|
return null;
|
|
56
41
|
const backendDocType = countrySelectionData.documentType;
|
|
57
42
|
const mappedType = documentTypeMapping[backendDocType] || backendDocType;
|
|
58
|
-
|
|
59
|
-
return { type: mappedType, region };
|
|
43
|
+
return { type: mappedType, region: countrySelectionData.region || 'root' };
|
|
60
44
|
}, [countrySelectionData, documentTypeMapping]);
|
|
61
|
-
|
|
62
|
-
const countryData = useMemo(() => {
|
|
63
|
-
return countrySelectionData;
|
|
64
|
-
}, [countrySelectionData]);
|
|
65
|
-
// console.log();
|
|
66
|
-
// Synchroniser capturedImages avec value quand les données sont chargées (ex: reprise de session)
|
|
45
|
+
const countryData = useMemo(() => countrySelectionData, [countrySelectionData]);
|
|
67
46
|
useEffect(() => {
|
|
68
47
|
if (value && Object.keys(value).length > 0) {
|
|
69
|
-
|
|
70
|
-
const valueChanged = JSON.stringify(value) !== JSON.stringify(capturedImages);
|
|
71
|
-
if (valueChanged) {
|
|
72
|
-
logger.log("Updating capturedImages from value:", Object.keys(value));
|
|
73
|
-
logger.log("Value data sample:", truncateFields(value));
|
|
48
|
+
if (JSON.stringify(value) !== JSON.stringify(capturedImages)) {
|
|
74
49
|
const updatedImages = value;
|
|
75
50
|
setCapturedImages(updatedImages);
|
|
76
|
-
// Si on a des images chargées, mettre à jour silentCaptureResult pour l'affichage
|
|
77
51
|
Object.keys(updatedImages).forEach((side) => {
|
|
78
52
|
const imageData = updatedImages[side];
|
|
79
53
|
if (imageData?.dir) {
|
|
80
54
|
setSilentCaptureResult(prev => ({
|
|
81
|
-
...prev,
|
|
82
|
-
path: imageData.dir,
|
|
83
|
-
success: true,
|
|
84
|
-
isAnalyzing: false,
|
|
85
|
-
mrz: imageData.mrz || '',
|
|
86
|
-
templatePath: imageData.templatePath || '',
|
|
55
|
+
...prev, path: imageData.dir, success: true, isAnalyzing: false, mrz: imageData.mrz || '', templatePath: imageData.templatePath || '',
|
|
87
56
|
}));
|
|
88
57
|
}
|
|
89
58
|
});
|
|
90
59
|
}
|
|
91
60
|
}
|
|
92
61
|
}, [value]);
|
|
93
|
-
useEffect(() => {
|
|
94
|
-
logger.log("cropImageUri", JSON.stringify(truncateFields({ box: silentCaptureResult }), null, 2));
|
|
95
|
-
if (capturedImages[currentSide]?.dir && silentCaptureResult?.bbox) {
|
|
96
|
-
cropImageWithBBox(capturedImages[currentSide].dir, silentCaptureResult.bbox)?.then((uri) => {
|
|
97
|
-
// setCropImageUri(uri);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}, [capturedImages[currentSide]?.dir, silentCaptureResult?.bbox]);
|
|
101
62
|
const cameraConfig = useMemo(() => {
|
|
102
63
|
const instructions = selectedDocumentType
|
|
103
64
|
? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr)
|
|
104
65
|
: getLocalizedText(component.instructions);
|
|
105
66
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
flashMode: 'auto',
|
|
109
|
-
cameraType: 'back',
|
|
110
|
-
autoFocus: 'on',
|
|
111
|
-
whiteBalance: 'auto',
|
|
112
|
-
allowRetake: true,
|
|
113
|
-
maxRetakes: 3,
|
|
114
|
-
overlay: {
|
|
115
|
-
showGuide: true,
|
|
116
|
-
guideText: instructions,
|
|
117
|
-
bbox: {
|
|
118
|
-
xMin: 20,
|
|
119
|
-
yMin: 140,
|
|
120
|
-
xMax: 370,
|
|
121
|
-
yMax: 340,
|
|
122
|
-
borderColor: '#2DBD60',
|
|
123
|
-
borderWidth: 3,
|
|
124
|
-
cornerRadius: 8
|
|
125
|
-
}
|
|
126
|
-
}
|
|
67
|
+
cameraType: 'back', flashMode: 'auto',
|
|
68
|
+
overlay: { guideText: instructions, bbox: { xMin: 15, yMin: 20, xMax: 85, yMax: 70, borderColor: '#2DBD60', borderWidth: 3, cornerRadius: 8 } }
|
|
127
69
|
};
|
|
128
70
|
}, [selectedDocumentType, locale, component.instructions]);
|
|
129
71
|
const retakePicture = (sideToRetake) => {
|
|
130
|
-
//
|
|
72
|
+
// Completely wipe all processing states to prevent leakage
|
|
73
|
+
setIsProcessingCapture(false);
|
|
74
|
+
setProcessingImagePath(null);
|
|
75
|
+
setSilentCaptureResult({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '', mrz: '', bbox: undefined });
|
|
131
76
|
setShowCamera(true);
|
|
132
77
|
actions.showCustomStepper(false);
|
|
133
|
-
|
|
134
|
-
setCapturedImages((prev) => {
|
|
135
|
-
const newState = { ...prev };
|
|
136
|
-
delete newState[sideToRetake];
|
|
137
|
-
return newState;
|
|
138
|
-
});
|
|
139
|
-
setSilentCaptureResult({
|
|
140
|
-
path: '',
|
|
141
|
-
success: false,
|
|
142
|
-
isAnalyzing: false,
|
|
143
|
-
error: '',
|
|
144
|
-
templatePath: '',
|
|
145
|
-
mrz: '',
|
|
146
|
-
bbox: undefined,
|
|
147
|
-
});
|
|
78
|
+
setCapturedImages((prev) => { const newState = { ...prev }; delete newState[sideToRetake]; return newState; });
|
|
148
79
|
if (value) {
|
|
149
80
|
const newValue = { ...value };
|
|
150
81
|
delete newValue[sideToRetake];
|
|
@@ -152,9 +83,8 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
152
83
|
}
|
|
153
84
|
};
|
|
154
85
|
const getCurrentSideVerification = (currentSide) => {
|
|
155
|
-
if (!selectedDocumentType || !countryData?.regionMapping)
|
|
86
|
+
if (!selectedDocumentType || !countryData?.regionMapping)
|
|
156
87
|
return { authMethod: [], mrzTypes: [], regionMapping: null, key: 'root' };
|
|
157
|
-
}
|
|
158
88
|
const regionMapping = countryData.regionMapping[selectedDocumentType.type];
|
|
159
89
|
const authMethod = [];
|
|
160
90
|
const mrzTypes = [];
|
|
@@ -163,25 +93,20 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
163
93
|
regionMapping[key].forEach((item) => {
|
|
164
94
|
if (item[currentSide]) {
|
|
165
95
|
authMethod.push(item[currentSide]);
|
|
166
|
-
if (item?.mrz_type)
|
|
96
|
+
if (item?.mrz_type)
|
|
167
97
|
mrzTypes.push(item?.mrz_type);
|
|
168
|
-
}
|
|
169
98
|
}
|
|
170
99
|
});
|
|
171
100
|
}
|
|
172
|
-
|
|
173
|
-
return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping: regionMapping, key: key };
|
|
101
|
+
return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping, key };
|
|
174
102
|
};
|
|
175
103
|
const getCorrespondingMrzType = (templatePath, mapping, selectedDocumentType = "root") => {
|
|
176
104
|
if (!mapping || !mapping[selectedDocumentType])
|
|
177
105
|
return null;
|
|
178
|
-
// Extraire le nom du fichier depuis le template_path
|
|
179
106
|
const fileName = templatePath.split("/").pop()?.replace(".jpg", "").replace(".png", "");
|
|
180
107
|
if (!fileName)
|
|
181
108
|
return null;
|
|
182
|
-
|
|
183
|
-
const pyName = `${fileName}.py`; // ex: cameroon_id_back_3_1.py
|
|
184
|
-
// Chercher dans la liste
|
|
109
|
+
const pyName = `${fileName}.py`;
|
|
185
110
|
const found = mapping[selectedDocumentType].find((item) => item.py_file === pyName);
|
|
186
111
|
return found?.mrz_type || null;
|
|
187
112
|
};
|
|
@@ -195,10 +120,52 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
195
120
|
const found = mapping[selectedDocumentType].find((item) => item.py_file === pyName);
|
|
196
121
|
return found?.[side] || null;
|
|
197
122
|
};
|
|
198
|
-
const
|
|
199
|
-
if (
|
|
123
|
+
const autoCapture = async (capturePath, verified) => {
|
|
124
|
+
if (isProcessingCapture)
|
|
200
125
|
return;
|
|
126
|
+
setIsProcessingCapture(true);
|
|
127
|
+
setProcessingImagePath(capturePath);
|
|
128
|
+
try {
|
|
129
|
+
let imagePathForUpload = capturePath;
|
|
130
|
+
if (verified.bbox) {
|
|
131
|
+
try {
|
|
132
|
+
imagePathForUpload = await cropImageWithBBoxWithTolerance(capturePath, verified.bbox, 0.15);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
imagePathForUpload = capturePath;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const base64 = await pathToBase64(imagePathForUpload);
|
|
139
|
+
const newImages = {
|
|
140
|
+
...capturedImages,
|
|
141
|
+
[currentSide]: { dir: imagePathForUpload, file: base64, mrz: verified.mrz || "", templatePath: verified.templatePath },
|
|
142
|
+
};
|
|
143
|
+
setCapturedImages(newImages);
|
|
144
|
+
if (verified.country && verified.documentType) {
|
|
145
|
+
onValueChange({
|
|
146
|
+
...newImages,
|
|
147
|
+
country: verified.country,
|
|
148
|
+
documentType: GovernmentDocumentTypeBackend[verified.documentType] || '',
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
setShowCamera(false);
|
|
153
|
+
actions.showCustomStepper(true);
|
|
154
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false }));
|
|
155
|
+
setIsProcessingCapture(false);
|
|
156
|
+
setProcessingImagePath(null);
|
|
157
|
+
}, 600);
|
|
201
158
|
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
showAlert('Error', e?.message || 'Impossible de capturer la photo');
|
|
161
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false }));
|
|
162
|
+
setIsProcessingCapture(false);
|
|
163
|
+
setProcessingImagePath(null);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const handleSilentCapture = async (result) => {
|
|
167
|
+
if (silentCaptureResult.isAnalyzing || isProcessingCapture)
|
|
168
|
+
return;
|
|
202
169
|
if (result.success && result.path) {
|
|
203
170
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
|
|
204
171
|
let templatePath = silentCaptureResult.templatePath || '';
|
|
@@ -209,336 +176,120 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
209
176
|
return;
|
|
210
177
|
}
|
|
211
178
|
const regionMappings = getCurrentSideVerification(currentSide);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
logger.log("checkTemplateType - BEFORE call", {
|
|
216
|
-
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
217
|
-
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
218
|
-
docTypeToSend: selectedDocumentType?.type
|
|
219
|
-
});
|
|
179
|
+
try {
|
|
180
|
+
if (templatePath.length === 0) {
|
|
220
181
|
const templateType = await checkTemplateType({ path: result.path || '', docType: selectedDocumentType?.type, docRegion: countryData?.code || "", postfix: currentSide }, env);
|
|
221
182
|
templateResponse = templateType;
|
|
222
|
-
if (templateType.template_path)
|
|
183
|
+
if (templateType.template_path)
|
|
223
184
|
templatePath = templateType.template_path;
|
|
224
|
-
logger.log("templatePath", templatePath);
|
|
225
|
-
setSilentCaptureResult((prev) => ({ ...prev, templatePath: templatePath }));
|
|
226
|
-
}
|
|
227
185
|
if (templateType.card_obb) {
|
|
228
186
|
const obbConfidence = getObbConfidence(templateType.card_obb);
|
|
229
187
|
if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
230
|
-
setSilentCaptureResult((prev) => ({
|
|
231
|
-
...prev,
|
|
232
|
-
isAnalyzing: false,
|
|
233
|
-
success: false,
|
|
234
|
-
error: t('kyc.idCardCapture.cardNotFullyInFrame'),
|
|
235
|
-
}));
|
|
188
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: t('kyc.idCardCapture.cardNotFullyInFrame') }));
|
|
236
189
|
return;
|
|
237
190
|
}
|
|
238
|
-
let bbox;
|
|
239
191
|
try {
|
|
240
|
-
const crop = await cropByObb(result
|
|
241
|
-
|
|
242
|
-
templateBbox = bbox;
|
|
192
|
+
const crop = await cropByObb(result.path, templateType.card_obb);
|
|
193
|
+
templateBbox = crop.bbox;
|
|
243
194
|
}
|
|
244
195
|
catch { }
|
|
245
196
|
}
|
|
246
197
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: e?.message || 'Erreur de vérification du template' }));
|
|
250
|
-
return; // Return early if checkTemplateType fails
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
logger.log("templatePath before verification", templatePath, "currentSide", currentSide);
|
|
254
|
-
if (currentSide === 'front') {
|
|
255
|
-
logger.log("frontVerification - BEFORE call", {
|
|
256
|
-
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
257
|
-
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
258
|
-
docTypeToSend: selectedDocumentType?.type
|
|
259
|
-
});
|
|
260
|
-
logger.log("Calling frontVerification", { templatePath, selectedDocumentType: selectedDocumentType?.type, regionMappings });
|
|
261
|
-
console.log("About to call frontVerification", typeof frontVerification);
|
|
262
|
-
try {
|
|
198
|
+
let verificationRes;
|
|
199
|
+
if (currentSide === 'front') {
|
|
263
200
|
const matchedAuthMethod = getCorrespondingAuthMethod(templatePath, regionMappings.regionMapping, regionMappings.key || '', 'front');
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const authMethod = matchedAuthMethod
|
|
267
|
-
? regionMappings.authMethod.filter((method) => method === matchedAuthMethod)
|
|
268
|
-
: regionMappings.authMethod.filter((method) => method !== 'MRZ' && method !== '2D_barcode');
|
|
269
|
-
console.log("mrzType calculated", mrzType);
|
|
270
|
-
const verificationParams = {
|
|
271
|
-
path: result.path,
|
|
272
|
-
regionMapping: {
|
|
273
|
-
authMethod,
|
|
274
|
-
mrzTypes: regionMappings.mrzTypes,
|
|
275
|
-
},
|
|
276
|
-
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '',
|
|
277
|
-
code: countryData?.code || '',
|
|
278
|
-
currentSide: currentSide,
|
|
279
|
-
templatePath: templatePath,
|
|
280
|
-
mrzType: mrzType,
|
|
281
|
-
};
|
|
282
|
-
console.log("frontVerification params", verificationParams);
|
|
283
|
-
console.log("About to call frontVerification function");
|
|
284
|
-
const promise = frontVerification(verificationParams, env);
|
|
285
|
-
console.log("frontVerification promise created", promise);
|
|
286
|
-
promise.then((res) => {
|
|
287
|
-
logger.log("front verification result", truncateFields(res));
|
|
288
|
-
const bbox = res?.bbox || templateBbox;
|
|
289
|
-
setSilentCaptureResult((prev) => ({
|
|
290
|
-
...prev,
|
|
291
|
-
path: result.path,
|
|
292
|
-
templatePath: templatePath,
|
|
293
|
-
bbox: bbox,
|
|
294
|
-
success: true,
|
|
295
|
-
mrz: res?.mrz ? JSON.stringify(res.mrz) : "",
|
|
296
|
-
isAnalyzing: false,
|
|
297
|
-
country: countryData?.code,
|
|
298
|
-
documentType: selectedDocumentType.type,
|
|
299
|
-
}));
|
|
300
|
-
// Stocker le bbox pour ce côté
|
|
301
|
-
if (bbox && typeof bbox === 'object') {
|
|
302
|
-
setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
|
|
303
|
-
}
|
|
304
|
-
}).catch((e) => {
|
|
305
|
-
}).catch((e) => {
|
|
306
|
-
console.log("error front verification", e);
|
|
307
|
-
logger.log("error front verification", truncateFields(e));
|
|
308
|
-
const isCardNotFullyInFrame = e?.message === 'CARD_NOT_FULLY_IN_FRAME' ||
|
|
309
|
-
e?.message?.includes('entirement') ||
|
|
310
|
-
e?.message?.includes('fully in frame');
|
|
311
|
-
const errorMessage = isCardNotFullyInFrame
|
|
312
|
-
? t('kyc.idCardCapture.cardNotFullyInFrame')
|
|
313
|
-
: (e?.message || 'Erreur de détection du MRZ');
|
|
314
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: errorMessage }));
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
catch (error) {
|
|
318
|
-
console.log("Error setting up frontVerification call", error);
|
|
319
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: error?.message || 'Erreur lors de la configuration de la vérification' }));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
const backRegionMappings = getCurrentSideVerification(currentSide);
|
|
324
|
-
logger.log("Calling backVerification", { templatePath, selectedDocumentType: selectedDocumentType.type, backRegionMappings });
|
|
325
|
-
const matchedBackAuthMethod = getCorrespondingAuthMethod(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '', 'back');
|
|
326
|
-
const backMrzType = getCorrespondingMrzType(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '') || '';
|
|
327
|
-
backVerification({
|
|
328
|
-
path: result.path,
|
|
329
|
-
regionMapping: {
|
|
330
|
-
authMethod: matchedBackAuthMethod
|
|
331
|
-
? backRegionMappings.authMethod.filter((method) => method === matchedBackAuthMethod)
|
|
332
|
-
: backRegionMappings.authMethod.filter((method) => method !== 'MRZ' && method !== '2D_barcode'),
|
|
333
|
-
mrzTypes: backRegionMappings.mrzTypes,
|
|
334
|
-
},
|
|
335
|
-
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '',
|
|
336
|
-
code: countryData?.code || '',
|
|
337
|
-
currentSide: currentSide,
|
|
338
|
-
templatePath: templatePath,
|
|
339
|
-
mrzType: backMrzType,
|
|
340
|
-
templateResponse,
|
|
341
|
-
}, env).then((res) => {
|
|
342
|
-
logger.log("back verification result", truncateFields(res));
|
|
343
|
-
const bbox = res?.bbox || templateBbox;
|
|
344
|
-
setSilentCaptureResult((prev) => ({
|
|
345
|
-
...prev,
|
|
346
|
-
path: result.path,
|
|
347
|
-
bbox: bbox,
|
|
348
|
-
success: true,
|
|
349
|
-
mrz: res?.mrz ? JSON.stringify(res.mrz) : "",
|
|
350
|
-
isAnalyzing: false,
|
|
351
|
-
country: countryData?.code,
|
|
352
|
-
documentType: selectedDocumentType.type,
|
|
353
|
-
}));
|
|
354
|
-
// Stocker le bbox pour ce côté
|
|
355
|
-
if (bbox && typeof bbox === 'object') {
|
|
356
|
-
setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
|
|
357
|
-
}
|
|
358
|
-
}).catch((e) => {
|
|
359
|
-
logger.log("error back verification", truncateFields(e));
|
|
360
|
-
const isCardNotFullyInFrame = e?.message === 'CARD_NOT_FULLY_IN_FRAME' ||
|
|
361
|
-
e?.message?.includes('entirement') ||
|
|
362
|
-
e?.message?.includes('fully in frame');
|
|
363
|
-
const errorMessage = isCardNotFullyInFrame
|
|
364
|
-
? t('kyc.idCardCapture.cardNotFullyInFrame')
|
|
365
|
-
: (e?.message || 'Erreur de détection du MRZ');
|
|
366
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: errorMessage }));
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
const handleCapture = async (result) => {
|
|
372
|
-
if (silentCaptureResult.path) {
|
|
373
|
-
let imagePathForUpload = silentCaptureResult.path;
|
|
374
|
-
if (silentCaptureResult.bbox) {
|
|
375
|
-
try {
|
|
376
|
-
imagePathForUpload = await cropImageWithBBoxWithTolerance(silentCaptureResult.path, silentCaptureResult.bbox, 0.05);
|
|
201
|
+
const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
202
|
+
verificationRes = await frontVerification({ path: result.path, regionMapping: { authMethod: matchedAuthMethod ? [matchedAuthMethod] : regionMappings.authMethod, mrzTypes: regionMappings.mrzTypes }, selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '', code: countryData?.code || '', currentSide, templatePath, mrzType }, env);
|
|
377
203
|
}
|
|
378
|
-
|
|
379
|
-
|
|
204
|
+
else {
|
|
205
|
+
const matchedBackAuthMethod = getCorrespondingAuthMethod(templatePath, regionMappings.regionMapping, regionMappings.key || '', 'back');
|
|
206
|
+
const backMrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
207
|
+
verificationRes = await backVerification({ path: result.path, regionMapping: { authMethod: matchedBackAuthMethod ? [matchedBackAuthMethod] : regionMappings.authMethod, mrzTypes: regionMappings.mrzTypes }, selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '', code: countryData?.code || '', currentSide, templatePath, mrzType: backMrzType, templateResponse }, env);
|
|
380
208
|
}
|
|
209
|
+
const bbox = verificationRes?.bbox || templateBbox;
|
|
210
|
+
const mrz = verificationRes?.mrz ? JSON.stringify(verificationRes.mrz) : "";
|
|
211
|
+
const verifiedResult = { path: result.path, templatePath, bbox, success: true, mrz, isAnalyzing: false, country: countryData?.code, documentType: selectedDocumentType.type };
|
|
212
|
+
setSilentCaptureResult(verifiedResult);
|
|
213
|
+
if (bbox)
|
|
214
|
+
setBboxBySide(prev => ({ ...prev, [currentSide]: bbox }));
|
|
215
|
+
await autoCapture(result.path, verifiedResult);
|
|
381
216
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
...
|
|
386
|
-
[currentSide]: {
|
|
387
|
-
dir: imagePathForUpload, // <--- CHANGED THIS LINE
|
|
388
|
-
file: base64,
|
|
389
|
-
mrz: silentCaptureResult.mrz || "",
|
|
390
|
-
templatePath: silentCaptureResult.templatePath
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
setCapturedImages(newImages);
|
|
394
|
-
if (silentCaptureResult.country && silentCaptureResult.documentType) {
|
|
395
|
-
onValueChange({
|
|
396
|
-
...newImages,
|
|
397
|
-
country: silentCaptureResult.country,
|
|
398
|
-
documentType: GovernmentDocumentTypeBackend[silentCaptureResult.documentType] || '',
|
|
399
|
-
});
|
|
217
|
+
catch (error) {
|
|
218
|
+
const isCardNotFullyInFrame = error?.message === 'CARD_NOT_FULLY_IN_FRAME' || error?.message?.includes('entirement');
|
|
219
|
+
const errorMessage = isCardNotFullyInFrame ? t('kyc.idCardCapture.cardNotFullyInFrame') : (error?.message || 'Erreur de détection');
|
|
220
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: errorMessage }));
|
|
400
221
|
}
|
|
401
|
-
setShowCamera(false);
|
|
402
|
-
actions.showCustomStepper(true);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
showAlert('Erreur', result.error || 'Impossible de prendre la photo');
|
|
406
222
|
}
|
|
407
223
|
};
|
|
408
224
|
const handleError = (event) => {
|
|
409
225
|
showAlert('Erreur', event.message);
|
|
410
226
|
setShowCamera(false);
|
|
227
|
+
setIsProcessingCapture(false);
|
|
411
228
|
};
|
|
412
|
-
useEffect(() => {
|
|
413
|
-
actions.showCustomStepper(!showCamera);
|
|
414
|
-
}, [showCamera]);
|
|
415
|
-
// Cross-device polling logic
|
|
416
|
-
useEffect(() => {
|
|
417
|
-
if (!showQRModal || !state.session.session_id)
|
|
418
|
-
return;
|
|
419
|
-
const pollInterval = setInterval(async () => {
|
|
420
|
-
try {
|
|
421
|
-
const result = await kycService.getVerificationResult(state.session.session_id);
|
|
422
|
-
const sessionData = result[state.session.session_id]?.data;
|
|
423
|
-
if (sessionData) {
|
|
424
|
-
// Check if verification is completed or if we have ID card data
|
|
425
|
-
// Since the requirement is "verification restarts", we might look for overall completion
|
|
426
|
-
// or we could check if user_data is populated.
|
|
427
|
-
// For now, let's assume if status is not PENDING/INITIALIZED it might be done.
|
|
428
|
-
// Or simplier: if the mobile flow completes, the session status updates.
|
|
429
|
-
logger.log('Polling result:', truncateFields(sessionData));
|
|
430
|
-
if (sessionData.verification_status === 'completed' || sessionData.verification_status === 'approved' || sessionData.verification_status === 'review') {
|
|
431
|
-
clearInterval(pollInterval);
|
|
432
|
-
setShowQRModal(false);
|
|
433
|
-
actions.submitVerification(); // Or handleComplete
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
catch (error) {
|
|
438
|
-
console.error('Polling error:', error);
|
|
439
|
-
}
|
|
440
|
-
}, 5000);
|
|
441
|
-
return () => clearInterval(pollInterval);
|
|
442
|
-
}, [showQRModal, state.session.session_id, actions]);
|
|
443
|
-
const getQrCodeUrl = () => {
|
|
444
|
-
// Only available on web platform
|
|
445
|
-
if (Platform.OS !== 'web')
|
|
446
|
-
return '';
|
|
447
|
-
if (typeof window === 'undefined' || !window.location || !window.location.href)
|
|
448
|
-
return '';
|
|
449
|
-
try {
|
|
450
|
-
const currentUrl = new URL(window.location.href);
|
|
451
|
-
if (!currentUrl.searchParams.has('kyc_id') && state.session.session_id) {
|
|
452
|
-
currentUrl.searchParams.set('kyc_id', state.session.session_id);
|
|
453
|
-
}
|
|
454
|
-
currentUrl.searchParams.set('component_index', String(state.currentComponentIndex));
|
|
455
|
-
if (countrySelectionData?.code) {
|
|
456
|
-
currentUrl.searchParams.set('country', countrySelectionData.code);
|
|
457
|
-
if (countrySelectionData.documentType)
|
|
458
|
-
currentUrl.searchParams.set('document_type', countrySelectionData.documentType);
|
|
459
|
-
if (countrySelectionData.region)
|
|
460
|
-
currentUrl.searchParams.set('region', countrySelectionData.region);
|
|
461
|
-
}
|
|
462
|
-
return `https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${encodeURIComponent(currentUrl.toString())}`;
|
|
463
|
-
}
|
|
464
|
-
catch (error) {
|
|
465
|
-
console.warn('Error generating QR code URL:', error);
|
|
466
|
-
return '';
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
// En reprise sur un autre appareil: afficher un chargement tant que les données de session ne sont pas restaurées
|
|
470
|
-
const isResumingSession = Boolean(state.session.session_id && state.currentComponentIndex > 0);
|
|
471
|
-
const sessionDataRestored = state.session.sessionDataRestored !== false;
|
|
472
|
-
if (isResumingSession && !sessionDataRestored && (!countrySelectionData || !selectedDocumentType)) {
|
|
473
|
-
return (<View style={styles.root}>
|
|
474
|
-
<View style={[styles.container, { justifyContent: 'center', alignItems: 'center' }]}>
|
|
475
|
-
<ActivityIndicator size="large" color="#2DBD60"/>
|
|
476
|
-
<Text style={[styles.description, { marginTop: 16 }]}>
|
|
477
|
-
{state.currentLanguage === 'en' ? 'Loading your session...' : 'Chargement de votre session...'}
|
|
478
|
-
</Text>
|
|
479
|
-
</View>
|
|
480
|
-
</View>);
|
|
481
|
-
}
|
|
482
|
-
// Vérifier si les données sont disponibles, sinon afficher un message d'erreur
|
|
229
|
+
useEffect(() => { actions.showCustomStepper(!showCamera); }, [showCamera]);
|
|
483
230
|
if (!countrySelectionData || !selectedDocumentType) {
|
|
484
231
|
return (<View style={styles.root}>
|
|
485
232
|
<View style={styles.container}>
|
|
486
233
|
<Text style={styles.title}>{getLocalizedText(component.labels)}</Text>
|
|
487
234
|
<Text style={styles.description}>
|
|
488
|
-
{state.currentLanguage === "en"
|
|
489
|
-
? "Please complete the country and document selection first."
|
|
490
|
-
: "Veuillez d'abord compléter la sélection du pays et du document."}
|
|
235
|
+
{state.currentLanguage === "en" ? "Please complete the country and document selection first." : "Veuillez d'abord compléter la sélection du pays et du document."}
|
|
491
236
|
</Text>
|
|
492
|
-
{error && (<Text style={styles.errorText}>{error}</Text>)}
|
|
493
237
|
</View>
|
|
494
238
|
</View>);
|
|
495
239
|
}
|
|
240
|
+
// --- CAMERA RENDER ---
|
|
496
241
|
if (showCamera) {
|
|
242
|
+
const isBusy = isProcessingCapture;
|
|
497
243
|
return (<View style={styles.cameraContainer}>
|
|
498
|
-
<EnhancedCameraView
|
|
244
|
+
<EnhancedCameraView key={currentSide} // 🚨 BUG FIX: Forces the camera instance to completely reset when switching sides
|
|
245
|
+
showCamera={true} isProcessing={isBusy} cameraType={cameraConfig.cameraType} style={styles.camera} onError={handleError} onSilentCapture={handleSilentCapture} silentCaptureResult={silentCaptureResult} overlayComponent={<>
|
|
246
|
+
{!isBusy && silentCaptureResult.isAnalyzing && (<View style={styles.topAnalyzingPillContainer}>
|
|
247
|
+
<View style={styles.topAnalyzingPill}>
|
|
248
|
+
<ActivityIndicator size="small" color="white"/>
|
|
249
|
+
<Text style={styles.analyzingPillText}>
|
|
250
|
+
{state.currentLanguage === 'en' ? 'Scanning...' : 'Analyse...'}
|
|
251
|
+
</Text>
|
|
252
|
+
</View>
|
|
253
|
+
</View>)}
|
|
254
|
+
|
|
255
|
+
{isBusy && (<View style={StyleSheet.absoluteFillObject}>
|
|
256
|
+
{processingImagePath && (<Image source={{ uri: processingImagePath.startsWith('file://') ? processingImagePath : `file://${processingImagePath}` }} style={StyleSheet.absoluteFillObject} resizeMode="cover"/>)}
|
|
257
|
+
<View style={styles.processingOverlay}>
|
|
258
|
+
<ActivityIndicator size="large" color="#2DBD60"/>
|
|
259
|
+
<Text style={styles.processingText}>
|
|
260
|
+
{state.currentLanguage === 'en' ? 'Perfect!\nProcessing Document...' : 'Parfait!\nTraitement du document...'}
|
|
261
|
+
</Text>
|
|
262
|
+
</View>
|
|
263
|
+
</View>)}
|
|
264
|
+
|
|
265
|
+
<IdCardOverlay xMin={cameraConfig.overlay.bbox.xMin} yMin={cameraConfig.overlay.bbox.yMin} xMax={cameraConfig.overlay.bbox.xMax} yMax={cameraConfig.overlay.bbox.yMax} instructions={cameraConfig.overlay.guideText} cornerOpacity={cameraConfig.overlay.bbox.cornerRadius || 0} isSuccess={silentCaptureResult.success} language={state.currentLanguage} stepperProps={{
|
|
499
266
|
back: () => {
|
|
500
267
|
if (currentSide === 'back') {
|
|
501
268
|
setCurrentSide('front');
|
|
502
269
|
setShowCamera(false);
|
|
503
|
-
//
|
|
270
|
+
// 🚨 Clean up any residual state when going backwards
|
|
271
|
+
setIsProcessingCapture(false);
|
|
272
|
+
setProcessingImagePath(null);
|
|
504
273
|
if (capturedImages['front']?.dir) {
|
|
505
|
-
// Restaurer l'état de capture du front pour afficher l'image
|
|
506
274
|
const frontImage = capturedImages['front'];
|
|
507
|
-
|
|
508
|
-
setSilentCaptureResult((prev) => ({
|
|
509
|
-
path: frontImage.dir,
|
|
510
|
-
success: true,
|
|
511
|
-
isAnalyzing: false,
|
|
512
|
-
error: '',
|
|
513
|
-
mrz: frontImage.mrz || '',
|
|
514
|
-
templatePath: frontImage.templatePath || '',
|
|
515
|
-
country: silentCaptureResult.country,
|
|
516
|
-
documentType: silentCaptureResult.documentType,
|
|
517
|
-
bbox: frontBbox // Restaurer le bbox pour recalculer le cropImageUri
|
|
518
|
-
}));
|
|
275
|
+
setSilentCaptureResult((prev) => ({ ...prev, path: frontImage.dir, success: true, isAnalyzing: false, error: '', mrz: frontImage.mrz || '', templatePath: frontImage.templatePath || '', bbox: bboxBySide['front'] }));
|
|
519
276
|
}
|
|
520
277
|
else {
|
|
521
|
-
|
|
522
|
-
setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
|
|
278
|
+
setSilentCaptureResult((prev) => ({ ...prev, path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
|
|
523
279
|
}
|
|
524
280
|
}
|
|
525
281
|
else {
|
|
526
|
-
// Retour au composant précédent (country_selection)
|
|
527
282
|
actions.previousComponent();
|
|
528
283
|
}
|
|
529
284
|
},
|
|
530
285
|
selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
|
|
531
|
-
step: state.currentComponentIndex + 1,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
}}/>}/>
|
|
286
|
+
step: state.currentComponentIndex + 1, totalSteps: state.template.components.length, side: currentSide,
|
|
287
|
+
}}/>
|
|
288
|
+
</>}/>
|
|
535
289
|
|
|
536
|
-
{silentCaptureResult.error ? (<View style={styles.floatingErrorBanner}>
|
|
537
|
-
<Text style={styles.floatingErrorText}>
|
|
538
|
-
{silentCaptureResult.error}
|
|
539
|
-
</Text>
|
|
290
|
+
{silentCaptureResult.error && !isBusy ? (<View style={styles.floatingErrorBanner}>
|
|
291
|
+
<Text style={styles.floatingErrorText}>{silentCaptureResult.error}</Text>
|
|
540
292
|
</View>) : null}
|
|
541
|
-
|
|
542
293
|
</View>);
|
|
543
294
|
}
|
|
544
295
|
return (<View style={styles.root}>
|
|
@@ -551,349 +302,70 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
551
302
|
<Text style={{ fontSize: 14, color: '#666', textAlign: 'center', marginBottom: 16, lineHeight: 22 }}>
|
|
552
303
|
{getLocalizedText(component.instructions)}
|
|
553
304
|
</Text>
|
|
554
|
-
|
|
555
305
|
<View style={{ alignItems: 'center', justifyContent: 'center', flexDirection: "column", gap: 16 }}>
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
shadowOffset: { width: 0, height: 2 },
|
|
563
|
-
shadowOpacity: 0.2,
|
|
564
|
-
shadowRadius: 4,
|
|
565
|
-
elevation: 4
|
|
566
|
-
}}>
|
|
567
|
-
<Text style={{ color: 'white', fontWeight: 'bold', textAlign: 'center', fontSize: 16 }}>
|
|
568
|
-
{state.currentLanguage === "en"
|
|
569
|
-
? "Move the document closer to the camera."
|
|
570
|
-
: "Veuillez rapprocher le document de la caméra."}
|
|
571
|
-
</Text>
|
|
572
|
-
</View>)}
|
|
306
|
+
|
|
307
|
+
{silentCaptureResult?.error === 'TOO_FAR_AWAY' && (<View style={styles.warningBanner}>
|
|
308
|
+
<Text style={styles.warningText}>
|
|
309
|
+
{state.currentLanguage === "en" ? "Move the document closer to the camera and place it on a flat surface." : "Veuillez rapprocher le document de la caméra et le poser à plat."}
|
|
310
|
+
</Text>
|
|
311
|
+
</View>)}
|
|
573
312
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
height: 200,
|
|
577
|
-
borderRadius: 12,
|
|
578
|
-
padding: 1,
|
|
579
|
-
overflow: 'hidden',
|
|
580
|
-
shadowColor: '#000',
|
|
581
|
-
shadowOffset: { width: 0, height: 4 },
|
|
582
|
-
shadowOpacity: 0.18,
|
|
583
|
-
shadowRadius: 8,
|
|
584
|
-
elevation: 8,
|
|
585
|
-
backgroundColor: '#000',
|
|
586
|
-
}}>
|
|
587
|
-
{capturedImages[currentSide]?.dir ? (<Image source={{ uri: capturedImages[currentSide].dir }} style={{
|
|
588
|
-
width: '100%',
|
|
589
|
-
height: '100%',
|
|
590
|
-
borderRadius: 12,
|
|
591
|
-
resizeMode: 'contain',
|
|
592
|
-
}}/>) : silentCaptureResult.path ? (<Image source={{ uri: silentCaptureResult.path }} style={{
|
|
593
|
-
width: '100%',
|
|
594
|
-
height: '100%',
|
|
595
|
-
borderRadius: 12,
|
|
596
|
-
resizeMode: 'contain',
|
|
597
|
-
}}/>) : null}
|
|
313
|
+
<View style={styles.imagePreviewWrapper}>
|
|
314
|
+
{capturedImages[currentSide]?.dir ? (<Image source={{ uri: capturedImages[currentSide].dir }} style={styles.previewImage}/>) : silentCaptureResult.path ? (<Image source={{ uri: silentCaptureResult.path }} style={styles.previewImage}/>) : null}
|
|
598
315
|
</View>
|
|
599
|
-
|
|
600
|
-
{!capturedImages[currentSide]?.dir && (<Button title={state.currentLanguage === "en" ? "
|
|
601
|
-
|
|
602
|
-
actions.showCustomStepper(false);
|
|
603
|
-
}} variant="primary" size="large" fullWidth/>)}
|
|
604
|
-
{/* retake button si une image a été capturée */}
|
|
316
|
+
|
|
317
|
+
{!capturedImages[currentSide]?.dir && (<Button title={state.currentLanguage === "en" ? "Start Scanning" : "Commencer la numérisation"} onPress={() => { setShowCamera(true); actions.showCustomStepper(false); }} variant="primary" size="large" fullWidth/>)}
|
|
318
|
+
|
|
605
319
|
{capturedImages[currentSide]?.dir && (<>
|
|
606
|
-
<Button title={t('kyc.idCardCapture.retakeButton')} onPress={() =>
|
|
607
|
-
retakePicture(currentSide);
|
|
608
|
-
}} variant="outline" size="medium" fullWidth/>
|
|
320
|
+
<Button title={t('kyc.idCardCapture.retakeButton')} onPress={() => retakePicture(currentSide)} variant="outline" size="medium" fullWidth/>
|
|
609
321
|
<Button title={t('common.next')} onPress={() => {
|
|
610
322
|
if (!selectedDocumentType) {
|
|
611
323
|
showAlert('Error', 'Document type not selected');
|
|
612
324
|
return;
|
|
613
325
|
}
|
|
326
|
+
// 🚨 BUG FIX: Clear all state before moving forward
|
|
614
327
|
if (currentSide === 'back' || selectedDocumentType.type === 'passport') {
|
|
615
328
|
actions.nextComponent();
|
|
616
|
-
return;
|
|
617
329
|
}
|
|
618
330
|
else {
|
|
619
331
|
setShowCamera(true);
|
|
620
332
|
setCurrentSide('back');
|
|
621
|
-
setSilentCaptureResult(
|
|
622
|
-
|
|
333
|
+
setSilentCaptureResult({ success: false, isAnalyzing: false, path: '', error: '' });
|
|
334
|
+
setIsProcessingCapture(false);
|
|
335
|
+
setProcessingImagePath(null);
|
|
623
336
|
}
|
|
624
337
|
}} variant="primary" size="large" fullWidth/>
|
|
625
338
|
</>)}
|
|
626
339
|
</View>
|
|
627
340
|
</View>
|
|
628
341
|
</ScrollView>
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
{error && (<Text style={styles.errorText}>{error}</Text>)}
|
|
633
|
-
|
|
634
|
-
{/* Cross-Device / Continue on Phone Button (Web Only) */}
|
|
635
|
-
{Platform.OS === 'web' && !isMobileWeb() && !capturedImages[currentSide]?.dir && (<Button title={t('kyc.idCardCapture.continueOnPhone')} onPress={() => { setShowQRModal(true); }}/>)}
|
|
636
|
-
|
|
637
|
-
{/* QR Code Modal - Web Only */}
|
|
638
|
-
{Platform.OS === 'web' && (<Modal visible={showQRModal} transparent={true} animationType="fade" onRequestClose={() => setShowQRModal(false)}>
|
|
639
|
-
<View style={styles.modalOverlay}>
|
|
640
|
-
<View style={styles.modalContent}>
|
|
641
|
-
<Text style={styles.modalTitle}>
|
|
642
|
-
{t('kyc.idCardCapture.continueOnMobile')}
|
|
643
|
-
</Text>
|
|
644
|
-
<Text style={styles.modalDescription}>
|
|
645
|
-
{t('kyc.idCardCapture.scanQrCode')}
|
|
646
|
-
</Text>
|
|
647
|
-
|
|
648
|
-
{showQRModal && getQrCodeUrl() ? (<Image source={{ uri: getQrCodeUrl() }} style={styles.qrCodeImage}/>) : null}
|
|
649
|
-
|
|
650
|
-
<TouchableOpacity style={styles.closeButton} onPress={() => setShowQRModal(false)}>
|
|
651
|
-
<Text style={styles.closeButtonText}>
|
|
652
|
-
{t('common.close')}
|
|
653
|
-
</Text>
|
|
654
|
-
</TouchableOpacity>
|
|
655
|
-
</View>
|
|
656
|
-
</View>
|
|
657
|
-
</Modal>)}
|
|
658
|
-
|
|
659
342
|
</View>
|
|
660
343
|
</View>);
|
|
661
344
|
};
|
|
662
345
|
const styles = StyleSheet.create({
|
|
663
|
-
root: {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
},
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
},
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
width: '100%',
|
|
685
|
-
height: '100%',
|
|
686
|
-
},
|
|
687
|
-
previewContainer: {
|
|
688
|
-
width: '95%',
|
|
689
|
-
backgroundColor: 'white',
|
|
690
|
-
margin: 10,
|
|
691
|
-
borderRadius: 10,
|
|
692
|
-
paddingVertical: 16,
|
|
693
|
-
paddingHorizontal: 16,
|
|
694
|
-
},
|
|
695
|
-
previewItemContainer: {
|
|
696
|
-
// marginBottom: 24,
|
|
697
|
-
},
|
|
698
|
-
title: {
|
|
699
|
-
fontSize: 24,
|
|
700
|
-
fontWeight: 'bold',
|
|
701
|
-
color: '#333',
|
|
702
|
-
marginBottom: 8,
|
|
703
|
-
textAlign: 'center',
|
|
704
|
-
},
|
|
705
|
-
subtitle: {
|
|
706
|
-
fontSize: 18,
|
|
707
|
-
color: '#666',
|
|
708
|
-
textAlign: 'center',
|
|
709
|
-
marginBottom: 16,
|
|
710
|
-
},
|
|
711
|
-
sideInfo: {
|
|
712
|
-
fontSize: 14,
|
|
713
|
-
color: '#888',
|
|
714
|
-
textAlign: 'center',
|
|
715
|
-
marginBottom: 16,
|
|
716
|
-
fontStyle: 'italic',
|
|
717
|
-
},
|
|
718
|
-
description: {
|
|
719
|
-
fontSize: 16,
|
|
720
|
-
color: '#666',
|
|
721
|
-
textAlign: 'center',
|
|
722
|
-
marginBottom: 24,
|
|
723
|
-
lineHeight: 22,
|
|
724
|
-
},
|
|
725
|
-
sidesContainer: {
|
|
726
|
-
flex: 1,
|
|
727
|
-
},
|
|
728
|
-
sideContainer: {
|
|
729
|
-
marginBottom: 24,
|
|
730
|
-
},
|
|
731
|
-
sideTitle: {
|
|
732
|
-
fontSize: 25,
|
|
733
|
-
fontWeight: 'bold',
|
|
734
|
-
color: '#000',
|
|
735
|
-
marginBottom: 12,
|
|
736
|
-
textAlign: 'center',
|
|
737
|
-
},
|
|
738
|
-
captureButton: {
|
|
739
|
-
borderWidth: 2,
|
|
740
|
-
borderColor: '#2DBD60',
|
|
741
|
-
borderStyle: 'dashed',
|
|
742
|
-
borderRadius: 12,
|
|
743
|
-
padding: 32,
|
|
744
|
-
alignItems: 'center',
|
|
745
|
-
backgroundColor: '#f0f9f0',
|
|
746
|
-
},
|
|
747
|
-
captureIcon: {
|
|
748
|
-
fontSize: 48,
|
|
749
|
-
marginBottom: 16,
|
|
750
|
-
},
|
|
751
|
-
captureText: {
|
|
752
|
-
fontSize: 16,
|
|
753
|
-
color: '#2DBD60',
|
|
754
|
-
fontWeight: '600',
|
|
755
|
-
},
|
|
756
|
-
capturedImageContainer: {
|
|
757
|
-
position: 'relative',
|
|
758
|
-
},
|
|
759
|
-
capturedImage: {
|
|
760
|
-
width: '100%',
|
|
761
|
-
height: 200,
|
|
762
|
-
borderRadius: 12,
|
|
763
|
-
resizeMode: 'contain',
|
|
764
|
-
backgroundColor: '#f0f0f0',
|
|
765
|
-
},
|
|
766
|
-
retakeButton: {
|
|
767
|
-
position: 'absolute',
|
|
768
|
-
top: 8,
|
|
769
|
-
right: 8,
|
|
770
|
-
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
771
|
-
paddingHorizontal: 12,
|
|
772
|
-
paddingVertical: 6,
|
|
773
|
-
borderRadius: 6,
|
|
774
|
-
},
|
|
775
|
-
retakeButtonText: {
|
|
776
|
-
color: 'white',
|
|
777
|
-
fontSize: 12,
|
|
778
|
-
fontWeight: '600',
|
|
779
|
-
},
|
|
346
|
+
root: { flex: 1, maxWidth: 760, width: '100%' },
|
|
347
|
+
container: { backgroundColor: 'white', margin: 10, borderRadius: 10, paddingVertical: 16, paddingHorizontal: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.35, shadowRadius: 4.84, elevation: 10 },
|
|
348
|
+
cameraContainer: { flex: 1, width: '100%', height: '100%' },
|
|
349
|
+
previewContainer: { width: '95%', backgroundColor: 'white', margin: 10, borderRadius: 10, paddingVertical: 16, paddingHorizontal: 16 },
|
|
350
|
+
previewItemContainer: {},
|
|
351
|
+
title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center' },
|
|
352
|
+
description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 24, lineHeight: 22 },
|
|
353
|
+
sideContainer: { marginBottom: 24 },
|
|
354
|
+
sideTitle: { fontSize: 25, fontWeight: 'bold', color: '#000', marginBottom: 12, textAlign: 'center' },
|
|
355
|
+
imagePreviewWrapper: { width: '100%', height: 200, borderRadius: 12, padding: 1, overflow: 'hidden', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.18, shadowRadius: 8, elevation: 8, backgroundColor: '#000' },
|
|
356
|
+
previewImage: { width: '100%', height: '100%', borderRadius: 12, resizeMode: 'contain' },
|
|
357
|
+
floatingErrorBanner: { position: 'absolute', top: 60, left: '10%', right: '10%', backgroundColor: 'rgba(220, 38, 38, 0.95)', paddingVertical: 12, paddingHorizontal: 16, borderRadius: 8, alignItems: 'center', justifyContent: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 5, elevation: 8, zIndex: 100 },
|
|
358
|
+
floatingErrorText: { color: 'white', fontSize: 14, fontWeight: '700', textAlign: 'center' },
|
|
359
|
+
processingOverlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.6)', justifyContent: 'center', alignItems: 'center', zIndex: 9999 },
|
|
360
|
+
processingText: { color: '#FFF', fontSize: 18, fontWeight: 'bold', marginTop: 16, textAlign: 'center' },
|
|
361
|
+
warningBanner: { backgroundColor: '#FF9500', padding: 12, borderRadius: 8, width: '100%', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4, elevation: 4 },
|
|
362
|
+
warningText: { color: 'white', fontWeight: 'bold', textAlign: 'center', fontSize: 16 },
|
|
363
|
+
errorText: { color: '#dc2626', fontSize: 14, marginTop: 8, textAlign: 'center' },
|
|
364
|
+
topAnalyzingPillContainer: { position: 'absolute', top: Platform.OS === 'android' ? 60 : 50, left: 0, right: 0, alignItems: 'center', zIndex: 100 },
|
|
365
|
+
topAnalyzingPill: { flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.6)', paddingVertical: 8, paddingHorizontal: 16, borderRadius: 20, gap: 8 },
|
|
366
|
+
analyzingPillText: { color: 'white', fontSize: 14, fontWeight: 'bold' },
|
|
780
367
|
camera: {
|
|
781
368
|
flex: 1,
|
|
782
369
|
},
|
|
783
|
-
completionContainer: {
|
|
784
|
-
marginTop: 24,
|
|
785
|
-
alignItems: 'center',
|
|
786
|
-
},
|
|
787
|
-
completionText: {
|
|
788
|
-
fontSize: 16,
|
|
789
|
-
color: '#2DBD60',
|
|
790
|
-
fontWeight: '600',
|
|
791
|
-
marginBottom: 16,
|
|
792
|
-
},
|
|
793
|
-
primaryButton: {
|
|
794
|
-
paddingHorizontal: 32,
|
|
795
|
-
paddingVertical: 16,
|
|
796
|
-
borderRadius: 8,
|
|
797
|
-
// minWidth: 120,
|
|
798
|
-
alignItems: 'center',
|
|
799
|
-
backgroundColor: '#2DBD60',
|
|
800
|
-
},
|
|
801
|
-
primaryButtonText: {
|
|
802
|
-
color: 'white',
|
|
803
|
-
fontWeight: '600',
|
|
804
|
-
fontSize: 16,
|
|
805
|
-
},
|
|
806
|
-
errorText: {
|
|
807
|
-
color: '#dc2626',
|
|
808
|
-
fontSize: 14,
|
|
809
|
-
marginTop: 8,
|
|
810
|
-
textAlign: 'center',
|
|
811
|
-
},
|
|
812
|
-
crossDeviceButton: {
|
|
813
|
-
marginTop: 16,
|
|
814
|
-
padding: 12,
|
|
815
|
-
alignItems: 'center',
|
|
816
|
-
borderWidth: 1,
|
|
817
|
-
borderColor: '#2DBD60',
|
|
818
|
-
borderRadius: 8,
|
|
819
|
-
backgroundColor: '#f0f9f0',
|
|
820
|
-
},
|
|
821
|
-
crossDeviceText: {
|
|
822
|
-
color: '#2DBD60',
|
|
823
|
-
fontSize: 16,
|
|
824
|
-
fontWeight: '600',
|
|
825
|
-
},
|
|
826
|
-
modalOverlay: {
|
|
827
|
-
flex: 1,
|
|
828
|
-
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
829
|
-
justifyContent: 'center',
|
|
830
|
-
alignItems: 'center',
|
|
831
|
-
},
|
|
832
|
-
modalContent: {
|
|
833
|
-
backgroundColor: 'white',
|
|
834
|
-
borderRadius: 16,
|
|
835
|
-
padding: 24,
|
|
836
|
-
alignItems: 'center',
|
|
837
|
-
width: '90%',
|
|
838
|
-
maxWidth: 340,
|
|
839
|
-
shadowColor: '#000',
|
|
840
|
-
shadowOffset: { width: 0, height: 2 },
|
|
841
|
-
shadowOpacity: 0.25,
|
|
842
|
-
shadowRadius: 4,
|
|
843
|
-
elevation: 5,
|
|
844
|
-
},
|
|
845
|
-
modalTitle: {
|
|
846
|
-
fontSize: 20,
|
|
847
|
-
fontWeight: 'bold',
|
|
848
|
-
marginBottom: 12,
|
|
849
|
-
color: '#333',
|
|
850
|
-
},
|
|
851
|
-
modalDescription: {
|
|
852
|
-
fontSize: 16,
|
|
853
|
-
color: '#666',
|
|
854
|
-
textAlign: 'center',
|
|
855
|
-
marginBottom: 20,
|
|
856
|
-
lineHeight: 22,
|
|
857
|
-
},
|
|
858
|
-
qrCodeImage: {
|
|
859
|
-
width: 200,
|
|
860
|
-
height: 200,
|
|
861
|
-
marginBottom: 20,
|
|
862
|
-
},
|
|
863
|
-
closeButton: {
|
|
864
|
-
paddingVertical: 10,
|
|
865
|
-
paddingHorizontal: 20,
|
|
866
|
-
backgroundColor: '#f5f5f5',
|
|
867
|
-
borderRadius: 8,
|
|
868
|
-
},
|
|
869
|
-
closeButtonText: {
|
|
870
|
-
fontSize: 16,
|
|
871
|
-
color: '#666',
|
|
872
|
-
fontWeight: '600',
|
|
873
|
-
},
|
|
874
|
-
floatingErrorBanner: {
|
|
875
|
-
position: 'absolute',
|
|
876
|
-
top: 60, // Pushes it down slightly from the very top of the screen
|
|
877
|
-
left: '10%',
|
|
878
|
-
right: '10%',
|
|
879
|
-
backgroundColor: 'rgba(220, 38, 38, 0.95)', // Bright red
|
|
880
|
-
paddingVertical: 12,
|
|
881
|
-
paddingHorizontal: 16,
|
|
882
|
-
borderRadius: 8,
|
|
883
|
-
alignItems: 'center',
|
|
884
|
-
justifyContent: 'center',
|
|
885
|
-
shadowColor: '#000',
|
|
886
|
-
shadowOffset: { width: 0, height: 4 },
|
|
887
|
-
shadowOpacity: 0.3,
|
|
888
|
-
shadowRadius: 5,
|
|
889
|
-
elevation: 8,
|
|
890
|
-
zIndex: 100,
|
|
891
|
-
},
|
|
892
|
-
floatingErrorText: {
|
|
893
|
-
color: 'white',
|
|
894
|
-
fontSize: 14,
|
|
895
|
-
fontWeight: '700',
|
|
896
|
-
textAlign: 'center',
|
|
897
|
-
},
|
|
898
370
|
});
|
|
899
371
|
//# sourceMappingURL=IDCardCapture.js.map
|