@sanctum-key/react-native-sdk 1.0.53 → 1.0.54

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.
Files changed (124) hide show
  1. package/README.md +7 -2
  2. package/android/build/.transforms/3db9b15041d4285a820fc84462995ea1/results.bin +1 -0
  3. package/android/build/.transforms/3db9b15041d4285a820fc84462995ea1/transformed/classes/classes_dex/classes.dex +0 -0
  4. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  5. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  6. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  7. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  8. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  9. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  10. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  11. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  12. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  13. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  14. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  15. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  16. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  17. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  18. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  19. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  20. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  21. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  22. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  23. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  24. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  25. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  26. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  27. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  28. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  29. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  30. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  31. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  32. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  33. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  34. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  35. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  36. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  41. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  42. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  43. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  44. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  45. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  46. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  47. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  48. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  49. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  50. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  51. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  52. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  53. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  54. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  55. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  56. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  57. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/SanctumKeySdkModule$BarcodeRegion.class +0 -0
  58. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/SanctumKeySdkModule$Companion.class +0 -0
  59. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$1$5$1.class → SanctumKeySdkModule$definition$1$6$1.class} +0 -0
  60. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$1$5$2.class → SanctumKeySdkModule$definition$1$6$2.class} +0 -0
  61. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunction$1.class} +0 -0
  62. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunction$2.class} +0 -0
  63. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunction$3.class} +0 -0
  64. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunction$4.class} +0 -0
  65. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunction$5.class} +0 -0
  66. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunction$6.class} +0 -0
  67. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$1.class} +0 -0
  68. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$2.class} +0 -0
  69. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$3.class +0 -0
  70. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$4.class +0 -0
  71. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$5.class} +0 -0
  72. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$6.class +0 -0
  73. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class → SanctumKeySdkModule$definition$lambda$16$$inlined$AsyncFunctionWithPromise$7.class} +0 -0
  74. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$$inlined$View$1.class → SanctumKeySdkModule$definition$lambda$16$$inlined$View$1.class} +0 -0
  75. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class → SanctumKeySdkModule$definition$lambda$16$lambda$15$$inlined$Prop$1.class} +0 -0
  76. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/{SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class → SanctumKeySdkModule$definition$lambda$16$lambda$15$$inlined$Prop$2.class} +0 -0
  77. package/android/build/tmp/kotlin-classes/debug/kyc/sanctumkey/com/SanctumKeySdkModule.class +0 -0
  78. package/android/build.gradle +7 -0
  79. package/android/src/main/java/kyc/sanctumkey/com/SanctumKeySdkModule.kt +428 -1
  80. package/build/package.json +1 -1
  81. package/build/src/SanctumKeySdkModule.d.ts +1 -0
  82. package/build/src/SanctumKeySdkModule.d.ts.map +1 -1
  83. package/build/src/SanctumKeySdkModule.js.map +1 -1
  84. package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
  85. package/build/src/components/EnhancedCameraView.js +50 -41
  86. package/build/src/components/EnhancedCameraView.js.map +1 -1
  87. package/build/src/components/EnhancedCameraView.web.d.ts +2 -0
  88. package/build/src/components/EnhancedCameraView.web.d.ts.map +1 -1
  89. package/build/src/components/EnhancedCameraView.web.js +11 -6
  90. package/build/src/components/EnhancedCameraView.web.js.map +1 -1
  91. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  92. package/build/src/components/KYCElements/IDCardCapture.js +499 -78
  93. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  94. package/build/src/components/TemplateKYCExample.d.ts.map +1 -1
  95. package/build/src/components/TemplateKYCExample.js +3 -9
  96. package/build/src/components/TemplateKYCExample.js.map +1 -1
  97. package/build/src/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  98. package/build/src/components/TemplateKYCFlowRefactored.js +0 -2
  99. package/build/src/components/TemplateKYCFlowRefactored.js.map +1 -1
  100. package/build/src/components/WebBarcodeScanner.d.ts +2 -0
  101. package/build/src/components/WebBarcodeScanner.d.ts.map +1 -1
  102. package/build/src/components/WebBarcodeScanner.js +99 -85
  103. package/build/src/components/WebBarcodeScanner.js.map +1 -1
  104. package/build/src/modules/api/KYCService.d.ts +1 -0
  105. package/build/src/modules/api/KYCService.d.ts.map +1 -1
  106. package/build/src/modules/api/KYCService.js +1 -1
  107. package/build/src/modules/api/KYCService.js.map +1 -1
  108. package/build/src/modules/api/types.d.ts +1 -0
  109. package/build/src/modules/api/types.d.ts.map +1 -1
  110. package/build/src/modules/api/types.js.map +1 -1
  111. package/package.json +1 -1
  112. package/plugin/build/withVisionCamera.d.ts +1 -0
  113. package/plugin/build/withVisionCamera.js +13 -1
  114. package/plugin/src/withVisionCamera.js +18 -2
  115. package/plugin/src/withVisionCamera.ts +19 -2
  116. package/src/SanctumKeySdkModule.ts +1 -0
  117. package/src/components/EnhancedCameraView.tsx +52 -41
  118. package/src/components/EnhancedCameraView.web.tsx +15 -5
  119. package/src/components/KYCElements/IDCardCapture.tsx +552 -75
  120. package/src/components/TemplateKYCExample.tsx +6 -14
  121. package/src/components/TemplateKYCFlowRefactored.tsx +0 -2
  122. package/src/components/WebBarcodeScanner.tsx +147 -198
  123. package/src/modules/api/KYCService.ts +3 -3
  124. package/src/modules/api/types.ts +1 -0
@@ -4,12 +4,14 @@ import { Camera, useCameraDevice, useCodeScanner } from 'react-native-vision-cam
4
4
  import VisionCameraModule from '../modules/camera/VisionCameraModule';
5
5
  import { useI18n } from '../hooks/useI18n';
6
6
  import { WebBarcodeScanner } from './WebBarcodeScanner';
7
- export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType = 'front', style, onError, onSilentCapture, silentCaptureResult, isProcessing = false, overlayComponent, isScanningBarcode = false, onBarcodeScanned, barcodeTypes }) => {
7
+ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType = 'front', style, onError, onSilentCapture, silentCaptureResult, isProcessing = false, overlayComponent, captureStabilizationDelayMs = 4000, isScanningBarcode = false, onBarcodeScanned, barcodeTypes }) => {
8
8
  const { t } = useI18n();
9
9
  const camera = useRef(null);
10
10
  const webVideoRef = useRef(null);
11
11
  const isCapturingRef = useRef(false);
12
12
  const isProcessingRef = useRef(isProcessing);
13
+ const isScanningBarcodeRef = useRef(isScanningBarcode);
14
+ const onBarcodeScannedRef = useRef(onBarcodeScanned);
13
15
  // Ref-tracked isAnalyzing so captureSilentPhoto always reads the latest
14
16
  // value — the prop-based closure goes stale on iOS between renders.
15
17
  const isAnalyzingRef = useRef(silentCaptureResult?.isAnalyzing ?? false);
@@ -18,12 +20,17 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
18
20
  const [isInitialized, setIsInitialized] = useState(false);
19
21
  const [refreshCamera] = useState(false);
20
22
  const [isVideoFound, setIsVideoFound] = useState(false);
21
- const scannedBarcodeRef = useRef(null);
23
+ const scannedBarcodeRef = useRef({ value: null, emittedAt: 0 });
22
24
  const containerRef = useRef(null);
23
25
  const [appState, setAppState] = useState(AppState.currentState);
24
26
  const device = useCameraDevice(cameraType);
25
27
  useEffect(() => { isProcessingRef.current = isProcessing; }, [isProcessing]);
28
+ useEffect(() => { isScanningBarcodeRef.current = isScanningBarcode; }, [isScanningBarcode]);
29
+ useEffect(() => { onBarcodeScannedRef.current = onBarcodeScanned; }, [onBarcodeScanned]);
26
30
  useEffect(() => { isAnalyzingRef.current = silentCaptureResult?.isAnalyzing ?? false; }, [silentCaptureResult?.isAnalyzing]);
31
+ useEffect(() => {
32
+ scannedBarcodeRef.current = { value: null, emittedAt: 0 };
33
+ }, [isScanningBarcode]);
27
34
  useEffect(() => {
28
35
  const subscription = AppState.addEventListener('change', nextAppState => {
29
36
  setAppState(nextAppState);
@@ -68,7 +75,12 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
68
75
  if (showCamera)
69
76
  checkPermissions();
70
77
  }, [showCamera, refreshCamera]);
71
- const onInitialized = useCallback(() => setIsInitialized(true), []);
78
+ const onInitialized = useCallback(() => {
79
+ setIsInitialized(true);
80
+ if (isScanningBarcodeRef.current) {
81
+ console.log('📷 Barcode camera initialized');
82
+ }
83
+ }, []);
72
84
  const onCameraError = useCallback((error) => {
73
85
  console.warn("🎥 [Vision Camera Error Caught]:", error);
74
86
  onError?.({
@@ -80,11 +92,15 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
80
92
  const codeScanner = useCodeScanner({
81
93
  codeTypes: barcodeTypes || ['pdf-417', 'qr', 'code-128', 'code-39'],
82
94
  onCodeScanned: (codes) => {
83
- if (!isProcessingRef.current && isScanningBarcode) {
95
+ if (!isProcessingRef.current && isScanningBarcodeRef.current) {
84
96
  for (const code of codes) {
85
- if (code.value && scannedBarcodeRef.current !== code.value) {
86
- scannedBarcodeRef.current = code.value;
87
- onBarcodeScanned?.(code.value);
97
+ if (!code.value)
98
+ continue;
99
+ const now = Date.now();
100
+ const previous = scannedBarcodeRef.current;
101
+ if (previous.value !== code.value || now - previous.emittedAt > 1500) {
102
+ scannedBarcodeRef.current = { value: code.value, emittedAt: now };
103
+ onBarcodeScannedRef.current?.(code.value);
88
104
  break;
89
105
  }
90
106
  }
@@ -101,8 +117,8 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
101
117
  // Web handles its own stream via WebBarcodeScanner; do not run native camera methods on web.
102
118
  if (Platform.OS === 'web')
103
119
  return;
104
- // We intentionally ignore `isInitialized`. If AVFoundation (iOS) or CameraX (Android)
105
- // aren't ready, the try/catch will handle it gracefully.
120
+ // The scheduling effect waits for camera initialization and a positioning
121
+ // grace period before this function can run.
106
122
  if (!camera.current || isProcessingRef.current || isCapturingRef.current)
107
123
  return;
108
124
  if (isAnalyzingRef.current)
@@ -112,8 +128,14 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
112
128
  const photo = await camera.current.takePhoto({
113
129
  enableShutterSound: false,
114
130
  flash: 'off',
115
- // iOS requires aggressive compression to prevent RAM crashes during interval captures
116
- ...(Platform.OS === 'ios' ? { photoCodec: 'jpeg', qualityPrioritization: 'speed' } : {})
131
+ ...(Platform.OS === 'ios'
132
+ ? {
133
+ photoCodec: 'jpeg',
134
+ // Barcode stills are decoded off the live path, so preserve the
135
+ // fine PDF417 modules instead of favoring capture speed.
136
+ qualityPrioritization: isScanningBarcodeRef.current ? 'quality' : 'balanced',
137
+ }
138
+ : {})
117
139
  });
118
140
  // 3. CROSS-PLATFORM PATH NORMALIZATION
119
141
  let finalPath = photo.path;
@@ -134,7 +156,7 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
134
156
  onSilentCaptureRef.current?.({
135
157
  success: captureSuccess,
136
158
  path: finalPath,
137
- barcode: scannedBarcodeRef.current
159
+ barcode: scannedBarcodeRef.current.value
138
160
  });
139
161
  }
140
162
  catch (error) {
@@ -147,44 +169,26 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
147
169
  }, []); // <-- EMPTY ARRAY GUARANTEES STABILITY
148
170
  // 5. THE UNBREAKABLE INTERVAL
149
171
  useEffect(() => {
150
- // If we shouldn't scan, or if web (web handles its own stream), abort.
151
- // We intentionally don't require `isInitialized` here, the try/catch inside
152
- // captureSilentPhoto handles unready cameras gracefully without breaking the loop.
153
- if (!showCamera || isProcessing || Platform.OS === 'web')
154
- return;
155
- let active = true;
156
- let id;
157
- const timer = setTimeout(() => {
158
- if (!active)
159
- return;
160
- const intervalDelay = isScanningBarcode ? 3000 : 1500;
161
- id = setInterval(captureSilentPhoto, intervalDelay);
162
- }, 1500);
163
- return () => {
164
- active = false;
165
- clearTimeout(timer);
166
- if (id)
167
- clearInterval(id);
168
- };
169
- }, [showCamera, isProcessing, isScanningBarcode, captureSilentPhoto]);
170
- useEffect(() => {
171
- if (!showCamera || !isInitialized || isProcessing)
172
+ // Give autofocus/exposure and the user time to settle before the first
173
+ // automatic capture. A remount creates a fresh grace period for each side.
174
+ if (!showCamera || !isInitialized || isProcessing || Platform.OS === 'web')
172
175
  return;
173
176
  let active = true;
174
177
  let id;
175
178
  const timer = setTimeout(() => {
176
179
  if (!active)
177
180
  return;
178
- const intervalDelay = isScanningBarcode ? 3000 : 1500;
181
+ captureSilentPhoto();
182
+ const intervalDelay = isScanningBarcode ? 4500 : 3000;
179
183
  id = setInterval(captureSilentPhoto, intervalDelay);
180
- }, 1500);
184
+ }, Math.max(0, captureStabilizationDelayMs));
181
185
  return () => {
182
186
  active = false;
183
187
  clearTimeout(timer);
184
188
  if (id)
185
189
  clearInterval(id);
186
190
  };
187
- }, [showCamera, isInitialized, isProcessing, captureSilentPhoto, isScanningBarcode]);
191
+ }, [showCamera, isInitialized, isProcessing, isScanningBarcode, captureStabilizationDelayMs, captureSilentPhoto]);
188
192
  useEffect(() => {
189
193
  if (Platform.OS !== 'web' || !showCamera)
190
194
  return;
@@ -209,8 +213,8 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
209
213
  return () => clearTimeout(timeoutId);
210
214
  }, [showCamera]);
211
215
  const handleWebBarcodeScanned = useCallback((value) => {
212
- if (!isProcessingRef.current && value !== scannedBarcodeRef.current) {
213
- scannedBarcodeRef.current = value;
216
+ if (!isProcessingRef.current && value !== scannedBarcodeRef.current.value) {
217
+ scannedBarcodeRef.current = { value, emittedAt: Date.now() };
214
218
  onBarcodeScanned?.(value);
215
219
  }
216
220
  }, [onBarcodeScanned]);
@@ -236,8 +240,13 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
236
240
  if (!device || !showCamera)
237
241
  return <View style={[styles.container, style]}/>;
238
242
  return (<View ref={containerRef} style={[styles.container, style]}>
239
- <Camera ref={camera} style={StyleSheet.absoluteFill} device={device} resizeMode="cover" isActive={showCamera && !isProcessing && appState === 'active'} photo={true} video={false} audio={false} onInitialized={onInitialized} onError={onCameraError} codeScanner={Platform.OS !== 'web' && isScanningBarcode ? codeScanner : undefined}/>
240
- {Platform.OS === 'web' && isScanningBarcode && isVideoFound && (<WebBarcodeScanner videoRef={webVideoRef} onBarcodeScanned={handleWebBarcodeScanned} active={!isProcessingRef.current}/>)}
243
+ <Camera ref={camera} style={StyleSheet.absoluteFill} device={device} resizeMode="cover" isActive={showCamera && !isProcessing && appState === 'active'} photo={true} photoQualityBalance={isScanningBarcode ? 'quality' : 'balanced'} video={false} audio={false} onInitialized={onInitialized} onError={onCameraError}
244
+ // Some Android camera levels cannot configure Preview + ImageCapture +
245
+ // ImageAnalysis together and fail with invalid-output-configuration.
246
+ // Android barcodes use the bundled full-resolution ML Kit/ZXing still
247
+ // decoder; iOS can retain Vision Camera's low-latency live scanner.
248
+ codeScanner={Platform.OS === 'ios' && isScanningBarcode ? codeScanner : undefined}/>
249
+ {Platform.OS === 'web' && isScanningBarcode && isVideoFound && (<WebBarcodeScanner videoRef={webVideoRef} onBarcodeScanned={handleWebBarcodeScanned} formats={barcodeTypes} active={!isProcessingRef.current}/>)}
241
250
  {overlayComponent}
242
251
  </View>);
243
252
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EnhancedCameraView.js","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { View, StyleSheet, Text, Platform, AppState, AppStateStatus } from 'react-native';\nimport { Camera, CodeType, useCameraDevice, useCodeScanner } from 'react-native-vision-camera';\nimport VisionCameraModule from '../modules/camera/VisionCameraModule';\nimport { useI18n } from '../hooks/useI18n';\nimport { EnhancedCameraViewProps } from './OverLay/type';\nimport { WebBarcodeScanner } from './WebBarcodeScanner';\n\nexport interface ExtendedCameraProps extends Omit<EnhancedCameraViewProps, 'onError'> {\n isScanningBarcode?: boolean;\n onBarcodeScanned?: (data: string) => void;\n barcodeTypes?: CodeType[];\n onError?: (error: { message: string; name?: string; code?: string }) => void; \n}\n\nexport const EnhancedCameraView: React.FC<ExtendedCameraProps> = ({\n showCamera,\n cameraType: initialCameraType = 'front',\n style,\n onError,\n onSilentCapture,\n silentCaptureResult,\n isProcessing = false,\n overlayComponent,\n isScanningBarcode = false,\n onBarcodeScanned,\n barcodeTypes\n}) => {\n const { t } = useI18n();\n const camera = useRef<Camera>(null);\n const webVideoRef = useRef<HTMLVideoElement | null>(null);\n \n const isCapturingRef = useRef(false);\n const isProcessingRef = useRef(isProcessing);\n // Ref-tracked isAnalyzing so captureSilentPhoto always reads the latest\n // value — the prop-based closure goes stale on iOS between renders.\n const isAnalyzingRef = useRef(silentCaptureResult?.isAnalyzing ?? false);\n \n const [cameraType] = useState<'front' | 'back'>(initialCameraType);\n const [hasPermission, setHasPermission] = useState<boolean | null>(null);\n const [isInitialized, setIsInitialized] = useState(false);\n const [refreshCamera] = useState(false);\n \n const [isVideoFound, setIsVideoFound] = useState(false);\n const scannedBarcodeRef = useRef<string | null>(null);\n const containerRef = useRef<any>(null);\n\n const [appState, setAppState] = useState<AppStateStatus>(AppState.currentState);\n\n const device = useCameraDevice(cameraType);\n\n useEffect(() => { isProcessingRef.current = isProcessing; }, [isProcessing]);\n useEffect(() => { isAnalyzingRef.current = silentCaptureResult?.isAnalyzing ?? false; }, [silentCaptureResult?.isAnalyzing]);\n\n useEffect(() => {\n const subscription = AppState.addEventListener('change', nextAppState => {\n setAppState(nextAppState);\n });\n return () => {\n subscription.remove();\n };\n }, []);\n\n const checkPermissions = async () => {\n try {\n // getCameraPermissionStatus is synchronous — no await\n const cameraStatus = Camera.getCameraPermissionStatus();\n\n if (cameraStatus === 'granted') {\n setHasPermission(true);\n return;\n }\n\n if (cameraStatus === 'not-determined') {\n const result = await Camera.requestCameraPermission();\n if (result === 'granted') {\n setHasPermission(true);\n return;\n }\n }\n\n // 'denied' or 'restricted' — user must enable in Settings\n setHasPermission(false);\n onError?.({\n message: t('camera.permissionRequired'),\n name: 'NotAllowedError',\n code: 'permission-denied'\n });\n } catch (e: any) {\n setHasPermission(false);\n onError?.({\n message: e.message || t('camera.errorOccurred'),\n name: e.name || 'UnknownError',\n code: e.code || 'unknown'\n });\n }\n };\n\n useEffect(() => {\n if (showCamera) checkPermissions();\n }, [showCamera, refreshCamera]);\n\n const onInitialized = useCallback(() => setIsInitialized(true), []);\n\n const onCameraError = useCallback((error: any) => {\n console.warn(\"🎥 [Vision Camera Error Caught]:\", error);\n onError?.({ \n message: error.message || t('camera.errorOccurred'),\n code: error.code, // Contains specific RNVC codes (e.g., 'session/camera-in-use')\n name: error.name // Contains Web standard names (e.g., 'NotReadableError')\n });\n }, [onError, t]);\n\n const codeScanner = useCodeScanner({\n codeTypes: barcodeTypes || ['pdf-417', 'qr', 'code-128', 'code-39'],\n onCodeScanned: (codes) => {\n if (!isProcessingRef.current && isScanningBarcode) {\n for (const code of codes) {\n if (code.value && scannedBarcodeRef.current !== code.value) {\n scannedBarcodeRef.current = code.value;\n onBarcodeScanned?.(code.value);\n break;\n }\n }\n }\n }\n });\n\n // 1. ISOLATE THE CALLBACK: This breaks the dependency death spiral for all platforms.\n const onSilentCaptureRef = useRef(onSilentCapture);\n useEffect(() => {\n onSilentCaptureRef.current = onSilentCapture;\n }, [onSilentCapture]);\n\n // 2. THE CAPTURE FUNCTION: Zero dependencies. Immune to re-renders.\n const captureSilentPhoto = useCallback(async () => {\n // Web handles its own stream via WebBarcodeScanner; do not run native camera methods on web.\n if (Platform.OS === 'web') return; \n \n // We intentionally ignore `isInitialized`. If AVFoundation (iOS) or CameraX (Android) \n // aren't ready, the try/catch will handle it gracefully.\n if (!camera.current || isProcessingRef.current || isCapturingRef.current) return;\n if (isAnalyzingRef.current) return;\n\n try {\n isCapturingRef.current = true;\n \n const photo = await camera.current.takePhoto({\n enableShutterSound: false,\n flash: 'off',\n // iOS requires aggressive compression to prevent RAM crashes during interval captures\n ...(Platform.OS === 'ios' ? { photoCodec: 'jpeg', qualityPrioritization: 'speed' } : {})\n });\n\n // 3. CROSS-PLATFORM PATH NORMALIZATION\n let finalPath = photo.path;\n let captureSuccess = true;\n\n // 4. DEFENSIVE NATIVE MODULE EXECUTION\n if (VisionCameraModule && VisionCameraModule.processPhotoResult) {\n try {\n const moduleResult = await VisionCameraModule.processPhotoResult(photo);\n if (moduleResult) {\n captureSuccess = moduleResult.success ?? true;\n finalPath = moduleResult.path || photo.path;\n }\n } catch (nativeError) {\n console.warn(\"⚠️ Native module failed, falling back to raw device path\");\n }\n }\n\n onSilentCaptureRef.current?.({\n success: captureSuccess,\n path: finalPath,\n barcode: scannedBarcodeRef.current\n });\n \n } catch (error: any) {\n // 📸 Silent fail: The camera is busy, focusing, or warming up. Just wait for the next tick.\n console.log(`📸 Frame dropped (${Platform.OS}):`, error?.message);\n } finally {\n isCapturingRef.current = false;\n }\n }, []); // <-- EMPTY ARRAY GUARANTEES STABILITY\n\n // 5. THE UNBREAKABLE INTERVAL\n useEffect(() => {\n // If we shouldn't scan, or if web (web handles its own stream), abort.\n // We intentionally don't require `isInitialized` here, the try/catch inside \n // captureSilentPhoto handles unready cameras gracefully without breaking the loop.\n if (!showCamera || isProcessing || Platform.OS === 'web') return; \n\n let active = true;\n let id: ReturnType<typeof setInterval>;\n\n const timer = setTimeout(() => {\n if (!active) return;\n const intervalDelay = isScanningBarcode ? 3000 : 1500;\n id = setInterval(captureSilentPhoto, intervalDelay);\n }, 1500);\n\n return () => {\n active = false;\n clearTimeout(timer);\n if (id) clearInterval(id);\n };\n }, [showCamera, isProcessing, isScanningBarcode, captureSilentPhoto]);\n\n\n useEffect(() => {\n if (!showCamera || !isInitialized || isProcessing) return;\n let active = true;\n let id: ReturnType<typeof setInterval>;\n \n const timer = setTimeout(() => {\n if (!active) return;\n const intervalDelay = isScanningBarcode ? 3000 : 1500;\n id = setInterval(captureSilentPhoto, intervalDelay);\n }, 1500);\n\n return () => {\n active = false;\n clearTimeout(timer);\n if (id) clearInterval(id);\n };\n }, [showCamera, isInitialized, isProcessing, captureSilentPhoto, isScanningBarcode]);\n\n useEffect(() => {\n if (Platform.OS !== 'web' || !showCamera) return;\n \n let timeoutId: ReturnType<typeof setTimeout>;\n \n const findVideo = () => {\n let video: HTMLVideoElement | null = null;\n if (containerRef.current?.querySelector) {\n video = containerRef.current.querySelector('video');\n }\n if (!video) {\n video = document.querySelector('video');\n }\n \n if (video) {\n webVideoRef.current = video;\n setIsVideoFound(true);\n } else {\n timeoutId = setTimeout(findVideo, 500);\n }\n };\n \n findVideo();\n return () => clearTimeout(timeoutId);\n }, [showCamera]);\n\n const handleWebBarcodeScanned = useCallback((value: string) => {\n if (!isProcessingRef.current && value !== scannedBarcodeRef.current) {\n scannedBarcodeRef.current = value;\n onBarcodeScanned?.(value);\n }\n }, [onBarcodeScanned]);\n\n if (hasPermission === null) return <View style={[styles.container, style]} />;\n \n if (hasPermission === false) return (\n <View style={[styles.container, style]}>\n <Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>\n </View>\n );\n\n if (!device && showCamera) {\n // We delay the missing device error slightly to account for the camera mounting delay\n setTimeout(() => {\n if (!device) {\n onError?.({ \n message: \"No camera detected\", \n name: \"NotFoundError\", \n code: \"device/not-found\" \n });\n }\n }, 1000);\n return <View style={[styles.container, style]} />;\n }\n\n if (!device || !showCamera) return <View style={[styles.container, style]} />;\n\n return (\n <View ref={containerRef} style={[styles.container, style]}>\n <Camera\n ref={camera}\n style={StyleSheet.absoluteFill}\n device={device}\n resizeMode=\"cover\"\n isActive={showCamera && !isProcessing && appState === 'active'}\n photo={true}\n video={false}\n audio={false}\n onInitialized={onInitialized}\n onError={onCameraError}\n codeScanner={Platform.OS !== 'web' && isScanningBarcode ? codeScanner : undefined}\n />\n {Platform.OS === 'web' && isScanningBarcode && isVideoFound && (\n <WebBarcodeScanner\n videoRef={webVideoRef as React.RefObject<HTMLVideoElement>}\n onBarcodeScanned={handleWebBarcodeScanned}\n active={!isProcessingRef.current}\n />\n )}\n {overlayComponent}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, backgroundColor: 'black' },\n permissionMessage: { color: 'white', textAlign: 'center', margin: 20, fontSize: 16 },\n});"]}
1
+ {"version":3,"file":"EnhancedCameraView.js","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAkB,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAY,eAAe,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC/F,OAAO,kBAAkB,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AASxD,MAAM,CAAC,MAAM,kBAAkB,GAAkC,CAAC,EAChE,UAAU,EACV,UAAU,EAAE,iBAAiB,GAAG,OAAO,EACvC,KAAK,EACL,OAAO,EACP,eAAe,EACf,mBAAmB,EACnB,YAAY,GAAG,KAAK,EACpB,gBAAgB,EAChB,2BAA2B,GAAG,IAAI,EAClC,iBAAiB,GAAG,KAAK,EACzB,gBAAgB,EAChB,YAAY,EACb,EAAE,EAAE;IACH,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,MAAM,CAAS,IAAI,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,MAAM,CAA0B,IAAI,CAAC,CAAC;IAE1D,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACvD,MAAM,mBAAmB,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACrD,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,cAAc,GAAG,MAAM,CAAC,mBAAmB,EAAE,WAAW,IAAI,KAAK,CAAC,CAAC;IAEzE,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAmB,iBAAiB,CAAC,CAAC;IACnE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAiB,IAAI,CAAC,CAAC;IACzE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,iBAAiB,GAAG,MAAM,CAA8C,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7G,MAAM,YAAY,GAAG,MAAM,CAAM,IAAI,CAAC,CAAC;IAEvC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAiB,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEhF,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAE3C,SAAS,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7E,SAAS,CAAC,GAAG,EAAE,GAAG,oBAAoB,CAAC,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC5F,SAAS,CAAC,GAAG,EAAE,GAAG,mBAAmB,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACzF,SAAS,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,OAAO,GAAG,mBAAmB,EAAE,WAAW,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC,CAAC;IAE7H,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC5D,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,YAAY,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE;YACtE,WAAW,CAAC,YAAY,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC;YACH,sDAAsD;YACtD,MAAM,YAAY,GAAG,MAAM,CAAC,yBAAyB,EAAE,CAAC;YAExD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC/B,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvB,OAAO;YACT,CAAC;YAED,IAAI,YAAY,KAAK,gBAAgB,EAAE,CAAC;gBACtC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,uBAAuB,EAAE,CAAC;gBACtD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBACzB,gBAAgB,CAAC,IAAI,CAAC,CAAC;oBACvB,OAAO;gBACT,CAAC;YACH,CAAC;YAED,0DAA0D;YAC1D,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO,EAAE,CAAC;gBACR,OAAO,EAAE,CAAC,CAAC,2BAA2B,CAAC;gBACvC,IAAI,EAAE,iBAAiB;gBACvB,IAAI,EAAE,mBAAmB;aAC1B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO,EAAE,CAAC;gBACR,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,sBAAsB,CAAC;gBAC/C,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,cAAc;gBAC9B,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU;YAAE,gBAAgB,EAAE,CAAC;IACrC,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;IAEhC,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;QACrC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,oBAAoB,CAAC,OAAO,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,KAAU,EAAE,EAAE;QAC/C,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,sBAAsB,CAAC;YACnD,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,+DAA+D;YACjF,IAAI,EAAE,KAAK,CAAC,IAAI,CAAE,yDAAyD;SAC5E,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAEjB,MAAM,WAAW,GAAG,cAAc,CAAC;QACjC,SAAS,EAAE,YAAY,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC;QACnE,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;YACvB,IAAI,CAAC,eAAe,CAAC,OAAO,IAAI,oBAAoB,CAAC,OAAO,EAAE,CAAC;gBAC7D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,KAAK;wBAAE,SAAS;oBAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC;oBAC3C,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG,QAAQ,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC;wBACrE,iBAAiB,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;wBAClE,mBAAmB,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBAC1C,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,sFAAsF;IACtF,MAAM,kBAAkB,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;IACnD,SAAS,CAAC,GAAG,EAAE;QACb,kBAAkB,CAAC,OAAO,GAAG,eAAe,CAAC;IAC/C,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,oEAAoE;IACpE,MAAM,kBAAkB,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAChD,6FAA6F;QAC7F,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK;YAAE,OAAO;QAElC,0EAA0E;QAC1E,6CAA6C;QAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,eAAe,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO;YAAE,OAAO;QACjF,IAAI,cAAc,CAAC,OAAO;YAAE,OAAO;QAEnC,IAAI,CAAC;YACH,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;YAE9B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;gBAC3C,kBAAkB,EAAE,KAAK;gBACzB,KAAK,EAAE,KAAK;gBACZ,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,KAAK;oBACvB,CAAC,CAAC;wBACE,UAAU,EAAE,MAAe;wBAC3B,gEAAgE;wBAChE,yDAAyD;wBACzD,qBAAqB,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,SAAkB,CAAC,CAAC,CAAC,UAAmB;qBAC/F;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;YAEH,uCAAuC;YACvC,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;YAC3B,IAAI,cAAc,GAAG,IAAI,CAAC;YAE1B,uCAAuC;YACvC,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;gBAChE,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;oBACxE,IAAI,YAAY,EAAE,CAAC;wBACjB,cAAc,GAAG,YAAY,CAAC,OAAO,IAAI,IAAI,CAAC;wBAC9C,SAAS,GAAG,YAAY,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;oBAC9C,CAAC;gBACH,CAAC;gBAAC,OAAO,WAAW,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;gBAC3E,CAAC;YACH,CAAC;YAED,kBAAkB,CAAC,OAAO,EAAE,CAAC;gBAC3B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK;aACzC,CAAC,CAAC;QAEL,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,4FAA4F;YAC5F,OAAO,CAAC,GAAG,CAAC,qBAAqB,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QACpE,CAAC;gBAAS,CAAC;YACT,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC;QACjC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,uCAAuC;IAE/C,8BAA8B;IAC9B,SAAS,CAAC,GAAG,EAAE;QACb,uEAAuE;QACvE,2EAA2E;QAC3E,IAAI,CAAC,UAAU,IAAI,CAAC,aAAa,IAAI,YAAY,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK;YAAE,OAAO;QAEnF,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,EAAkC,CAAC;QAEvC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,kBAAkB,EAAE,CAAC;YACrB,MAAM,aAAa,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACtD,EAAE,GAAG,WAAW,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;QACtD,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC,CAAC;QAE7C,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,KAAK,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,EAAE;gBAAE,aAAa,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAElH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,UAAU;YAAE,OAAO;QAEjD,IAAI,SAAwC,CAAC;QAE7C,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,IAAI,KAAK,GAA4B,IAAI,CAAC;YAC1C,IAAI,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,CAAC;gBACxC,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAC1C,CAAC;YAED,IAAI,KAAK,EAAE,CAAC;gBACV,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC;gBAC5B,eAAe,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC;QAEF,SAAS,EAAE,CAAC;QACZ,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,MAAM,uBAAuB,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,EAAE;QAC5D,IAAI,CAAC,eAAe,CAAC,OAAO,IAAI,KAAK,KAAK,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1E,iBAAiB,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC7D,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEvB,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAG,CAAC;IAE9E,IAAI,aAAa,KAAK,KAAK;QAAE,OAAO,CAClC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACrC;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,EAAE,IAAI,CAC/E;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;IAEF,IAAI,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAC1B,sFAAsF;QACtF,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,EAAE,CAAC;oBACR,OAAO,EAAE,oBAAoB;oBAC7B,IAAI,EAAE,eAAe;oBACrB,IAAI,EAAE,kBAAkB;iBACzB,CAAC,CAAC;YACL,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAG,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAG,CAAC;IAE9E,OAAO,CACL,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACxD;MAAA,CAAC,MAAM,CACL,GAAG,CAAC,CAAC,MAAM,CAAC,CACZ,KAAK,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAC/B,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,UAAU,CAAC,OAAO,CAClB,QAAQ,CAAC,CAAC,UAAU,IAAI,CAAC,YAAY,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAC/D,KAAK,CAAC,CAAC,IAAI,CAAC,CACZ,mBAAmB,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAChE,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,OAAO,CAAC,CAAC,aAAa,CAAC;IACvB,uEAAuE;IACvE,qEAAqE;IACrE,sEAAsE;IACtE,oEAAoE;IACpE,WAAW,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,iBAAiB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAEpF;MAAA,CAAC,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,iBAAiB,IAAI,YAAY,IAAI,CAC7D,CAAC,iBAAiB,CAChB,QAAQ,CAAC,CAAC,WAAgD,CAAC,CAC3D,gBAAgB,CAAC,CAAC,uBAAuB,CAAC,CAC1C,OAAO,CAAC,CAAC,YAAY,CAAC,CACtB,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,EACjC,CACH,CACD;MAAA,CAAC,gBAAgB,CACnB;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,OAAO,EAAE;IAChD,iBAAiB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;CACrF,CAAC,CAAC","sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { View, StyleSheet, Text, Platform, AppState, AppStateStatus } from 'react-native';\nimport { Camera, CodeType, useCameraDevice, useCodeScanner } from 'react-native-vision-camera';\nimport VisionCameraModule from '../modules/camera/VisionCameraModule';\nimport { useI18n } from '../hooks/useI18n';\nimport { EnhancedCameraViewProps } from './OverLay/type';\nimport { WebBarcodeScanner } from './WebBarcodeScanner';\n\nexport interface ExtendedCameraProps extends Omit<EnhancedCameraViewProps, 'onError'> {\n isScanningBarcode?: boolean;\n onBarcodeScanned?: (data: string) => void;\n barcodeTypes?: CodeType[];\n onError?: (error: { message: string; name?: string; code?: string }) => void; \n}\n\nexport const EnhancedCameraView: React.FC<ExtendedCameraProps> = ({\n showCamera,\n cameraType: initialCameraType = 'front',\n style,\n onError,\n onSilentCapture,\n silentCaptureResult,\n isProcessing = false,\n overlayComponent,\n captureStabilizationDelayMs = 4000,\n isScanningBarcode = false,\n onBarcodeScanned,\n barcodeTypes\n}) => {\n const { t } = useI18n();\n const camera = useRef<Camera>(null);\n const webVideoRef = useRef<HTMLVideoElement | null>(null);\n \n const isCapturingRef = useRef(false);\n const isProcessingRef = useRef(isProcessing);\n const isScanningBarcodeRef = useRef(isScanningBarcode);\n const onBarcodeScannedRef = useRef(onBarcodeScanned);\n // Ref-tracked isAnalyzing so captureSilentPhoto always reads the latest\n // value — the prop-based closure goes stale on iOS between renders.\n const isAnalyzingRef = useRef(silentCaptureResult?.isAnalyzing ?? false);\n \n const [cameraType] = useState<'front' | 'back'>(initialCameraType);\n const [hasPermission, setHasPermission] = useState<boolean | null>(null);\n const [isInitialized, setIsInitialized] = useState(false);\n const [refreshCamera] = useState(false);\n \n const [isVideoFound, setIsVideoFound] = useState(false);\n const scannedBarcodeRef = useRef<{ value: string | null; emittedAt: number }>({ value: null, emittedAt: 0 });\n const containerRef = useRef<any>(null);\n\n const [appState, setAppState] = useState<AppStateStatus>(AppState.currentState);\n\n const device = useCameraDevice(cameraType);\n\n useEffect(() => { isProcessingRef.current = isProcessing; }, [isProcessing]);\n useEffect(() => { isScanningBarcodeRef.current = isScanningBarcode; }, [isScanningBarcode]);\n useEffect(() => { onBarcodeScannedRef.current = onBarcodeScanned; }, [onBarcodeScanned]);\n useEffect(() => { isAnalyzingRef.current = silentCaptureResult?.isAnalyzing ?? false; }, [silentCaptureResult?.isAnalyzing]);\n\n useEffect(() => {\n scannedBarcodeRef.current = { value: null, emittedAt: 0 };\n }, [isScanningBarcode]);\n\n useEffect(() => {\n const subscription = AppState.addEventListener('change', nextAppState => {\n setAppState(nextAppState);\n });\n return () => {\n subscription.remove();\n };\n }, []);\n\n const checkPermissions = async () => {\n try {\n // getCameraPermissionStatus is synchronous — no await\n const cameraStatus = Camera.getCameraPermissionStatus();\n\n if (cameraStatus === 'granted') {\n setHasPermission(true);\n return;\n }\n\n if (cameraStatus === 'not-determined') {\n const result = await Camera.requestCameraPermission();\n if (result === 'granted') {\n setHasPermission(true);\n return;\n }\n }\n\n // 'denied' or 'restricted' — user must enable in Settings\n setHasPermission(false);\n onError?.({\n message: t('camera.permissionRequired'),\n name: 'NotAllowedError',\n code: 'permission-denied'\n });\n } catch (e: any) {\n setHasPermission(false);\n onError?.({\n message: e.message || t('camera.errorOccurred'),\n name: e.name || 'UnknownError',\n code: e.code || 'unknown'\n });\n }\n };\n\n useEffect(() => {\n if (showCamera) checkPermissions();\n }, [showCamera, refreshCamera]);\n\n const onInitialized = useCallback(() => {\n setIsInitialized(true);\n if (isScanningBarcodeRef.current) {\n console.log('📷 Barcode camera initialized');\n }\n }, []);\n\n const onCameraError = useCallback((error: any) => {\n console.warn(\"🎥 [Vision Camera Error Caught]:\", error);\n onError?.({ \n message: error.message || t('camera.errorOccurred'),\n code: error.code, // Contains specific RNVC codes (e.g., 'session/camera-in-use')\n name: error.name // Contains Web standard names (e.g., 'NotReadableError')\n });\n }, [onError, t]);\n\n const codeScanner = useCodeScanner({\n codeTypes: barcodeTypes || ['pdf-417', 'qr', 'code-128', 'code-39'],\n onCodeScanned: (codes) => {\n if (!isProcessingRef.current && isScanningBarcodeRef.current) {\n for (const code of codes) {\n if (!code.value) continue;\n\n const now = Date.now();\n const previous = scannedBarcodeRef.current;\n if (previous.value !== code.value || now - previous.emittedAt > 1500) {\n scannedBarcodeRef.current = { value: code.value, emittedAt: now };\n onBarcodeScannedRef.current?.(code.value);\n break;\n }\n }\n }\n }\n });\n\n // 1. ISOLATE THE CALLBACK: This breaks the dependency death spiral for all platforms.\n const onSilentCaptureRef = useRef(onSilentCapture);\n useEffect(() => {\n onSilentCaptureRef.current = onSilentCapture;\n }, [onSilentCapture]);\n\n // 2. THE CAPTURE FUNCTION: Zero dependencies. Immune to re-renders.\n const captureSilentPhoto = useCallback(async () => {\n // Web handles its own stream via WebBarcodeScanner; do not run native camera methods on web.\n if (Platform.OS === 'web') return; \n \n // The scheduling effect waits for camera initialization and a positioning\n // grace period before this function can run.\n if (!camera.current || isProcessingRef.current || isCapturingRef.current) return;\n if (isAnalyzingRef.current) return;\n\n try {\n isCapturingRef.current = true;\n \n const photo = await camera.current.takePhoto({\n enableShutterSound: false,\n flash: 'off',\n ...(Platform.OS === 'ios'\n ? {\n photoCodec: 'jpeg' as const,\n // Barcode stills are decoded off the live path, so preserve the\n // fine PDF417 modules instead of favoring capture speed.\n qualityPrioritization: isScanningBarcodeRef.current ? 'quality' as const : 'balanced' as const,\n }\n : {})\n });\n\n // 3. CROSS-PLATFORM PATH NORMALIZATION\n let finalPath = photo.path;\n let captureSuccess = true;\n\n // 4. DEFENSIVE NATIVE MODULE EXECUTION\n if (VisionCameraModule && VisionCameraModule.processPhotoResult) {\n try {\n const moduleResult = await VisionCameraModule.processPhotoResult(photo);\n if (moduleResult) {\n captureSuccess = moduleResult.success ?? true;\n finalPath = moduleResult.path || photo.path;\n }\n } catch (nativeError) {\n console.warn(\"⚠️ Native module failed, falling back to raw device path\");\n }\n }\n\n onSilentCaptureRef.current?.({\n success: captureSuccess,\n path: finalPath,\n barcode: scannedBarcodeRef.current.value\n });\n \n } catch (error: any) {\n // 📸 Silent fail: The camera is busy, focusing, or warming up. Just wait for the next tick.\n console.log(`📸 Frame dropped (${Platform.OS}):`, error?.message);\n } finally {\n isCapturingRef.current = false;\n }\n }, []); // <-- EMPTY ARRAY GUARANTEES STABILITY\n\n // 5. THE UNBREAKABLE INTERVAL\n useEffect(() => {\n // Give autofocus/exposure and the user time to settle before the first\n // automatic capture. A remount creates a fresh grace period for each side.\n if (!showCamera || !isInitialized || isProcessing || Platform.OS === 'web') return;\n\n let active = true;\n let id: ReturnType<typeof setInterval>;\n\n const timer = setTimeout(() => {\n if (!active) return;\n captureSilentPhoto();\n const intervalDelay = isScanningBarcode ? 4500 : 3000;\n id = setInterval(captureSilentPhoto, intervalDelay);\n }, Math.max(0, captureStabilizationDelayMs));\n\n return () => {\n active = false;\n clearTimeout(timer);\n if (id) clearInterval(id);\n };\n }, [showCamera, isInitialized, isProcessing, isScanningBarcode, captureStabilizationDelayMs, captureSilentPhoto]);\n\n useEffect(() => {\n if (Platform.OS !== 'web' || !showCamera) return;\n \n let timeoutId: ReturnType<typeof setTimeout>;\n \n const findVideo = () => {\n let video: HTMLVideoElement | null = null;\n if (containerRef.current?.querySelector) {\n video = containerRef.current.querySelector('video');\n }\n if (!video) {\n video = document.querySelector('video');\n }\n \n if (video) {\n webVideoRef.current = video;\n setIsVideoFound(true);\n } else {\n timeoutId = setTimeout(findVideo, 500);\n }\n };\n \n findVideo();\n return () => clearTimeout(timeoutId);\n }, [showCamera]);\n\n const handleWebBarcodeScanned = useCallback((value: string) => {\n if (!isProcessingRef.current && value !== scannedBarcodeRef.current.value) {\n scannedBarcodeRef.current = { value, emittedAt: Date.now() };\n onBarcodeScanned?.(value);\n }\n }, [onBarcodeScanned]);\n\n if (hasPermission === null) return <View style={[styles.container, style]} />;\n \n if (hasPermission === false) return (\n <View style={[styles.container, style]}>\n <Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>\n </View>\n );\n\n if (!device && showCamera) {\n // We delay the missing device error slightly to account for the camera mounting delay\n setTimeout(() => {\n if (!device) {\n onError?.({ \n message: \"No camera detected\", \n name: \"NotFoundError\", \n code: \"device/not-found\" \n });\n }\n }, 1000);\n return <View style={[styles.container, style]} />;\n }\n\n if (!device || !showCamera) return <View style={[styles.container, style]} />;\n\n return (\n <View ref={containerRef} style={[styles.container, style]}>\n <Camera\n ref={camera}\n style={StyleSheet.absoluteFill}\n device={device}\n resizeMode=\"cover\"\n isActive={showCamera && !isProcessing && appState === 'active'}\n photo={true}\n photoQualityBalance={isScanningBarcode ? 'quality' : 'balanced'}\n video={false}\n audio={false}\n onInitialized={onInitialized}\n onError={onCameraError}\n // Some Android camera levels cannot configure Preview + ImageCapture +\n // ImageAnalysis together and fail with invalid-output-configuration.\n // Android barcodes use the bundled full-resolution ML Kit/ZXing still\n // decoder; iOS can retain Vision Camera's low-latency live scanner.\n codeScanner={Platform.OS === 'ios' && isScanningBarcode ? codeScanner : undefined}\n />\n {Platform.OS === 'web' && isScanningBarcode && isVideoFound && (\n <WebBarcodeScanner\n videoRef={webVideoRef as React.RefObject<HTMLVideoElement>}\n onBarcodeScanned={handleWebBarcodeScanned}\n formats={barcodeTypes}\n active={!isProcessingRef.current}\n />\n )}\n {overlayComponent}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, backgroundColor: 'black' },\n permissionMessage: { color: 'white', textAlign: 'center', margin: 20, fontSize: 16 },\n});\n"]}
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import { EnhancedCameraViewProps } from './OverLay/type';
3
+ import type { CodeType } from 'react-native-vision-camera';
3
4
  export interface ExtendedCameraProps extends EnhancedCameraViewProps {
4
5
  isScanningBarcode?: boolean;
5
6
  onBarcodeScanned?: (data: string) => void;
7
+ barcodeTypes?: CodeType[];
6
8
  }
7
9
  export declare const EnhancedCameraView: React.FC<ExtendedCameraProps>;
8
10
  //# sourceMappingURL=EnhancedCameraView.web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EnhancedCameraView.web.d.ts","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAMzD,MAAM,WAAW,mBAAoB,SAAQ,uBAAuB;IAClE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgU5D,CAAC"}
1
+ {"version":3,"file":"EnhancedCameraView.web.d.ts","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAK3D,MAAM,WAAW,mBAAoB,SAAQ,uBAAuB;IAClE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAwU5D,CAAC"}
@@ -3,9 +3,9 @@ import { View, StyleSheet, TouchableOpacity, Text, Platform } from 'react-native
3
3
  import { useI18n } from '../hooks/useI18n';
4
4
  // 🚨 Import the WebBarcodeScanner we built earlier
5
5
  import { WebBarcodeScanner } from './WebBarcodeScanner';
6
- export const EnhancedCameraView = ({ instructions = 'Position yourself in the frame and tap the capture button', showCamera, cameraType: initialCameraType = 'front', style, onCapture, onError, onClose, enableFlash = false, enableHdr = false, quality = 'high', showCaptureButton = true, showSwitchCamera = true, overlayComponent, bbox, canFlip = true, enableVideo = false, isRecording = false, onVideoRecordingStart, onVideoRecordingStop, videoDuration = 10, onSilentCapture, silentCaptureResult, captureStabilizationDelayMs = 2500,
6
+ export const EnhancedCameraView = ({ instructions = 'Position yourself in the frame and tap the capture button', showCamera, cameraType: initialCameraType = 'front', style, onCapture, onError, onClose, enableFlash = false, enableHdr = false, quality = 'high', showCaptureButton = true, showSwitchCamera = true, overlayComponent, bbox, canFlip = true, enableVideo = false, isRecording = false, onVideoRecordingStart, onVideoRecordingStop, videoDuration = 10, onSilentCapture, silentCaptureResult, captureStabilizationDelayMs = 4000,
7
7
  // 🚨 New props for barcode support
8
- isScanningBarcode = false, onBarcodeScanned, }) => {
8
+ isScanningBarcode = false, onBarcodeScanned, barcodeTypes, }) => {
9
9
  const { t } = useI18n();
10
10
  // Platform check
11
11
  if (Platform.OS !== 'web') {
@@ -24,10 +24,13 @@ isScanningBarcode = false, onBarcodeScanned, }) => {
24
24
  // const [recordedChunks, setRecordedChunks] = useState<Blob[]>([]);
25
25
  // 🚨 New Refs for Barcode Logic
26
26
  const isProcessingRef = useRef(silentCaptureResult?.isAnalyzing || false);
27
- const scannedBarcodeRef = useRef(null);
27
+ const scannedBarcodeRef = useRef({ value: null, emittedAt: 0 });
28
28
  useEffect(() => {
29
29
  isProcessingRef.current = silentCaptureResult?.isAnalyzing || false;
30
30
  }, [silentCaptureResult?.isAnalyzing]);
31
+ useEffect(() => {
32
+ scannedBarcodeRef.current = { value: null, emittedAt: 0 };
33
+ }, [isScanningBarcode]);
31
34
  useEffect(() => {
32
35
  if (showCamera) {
33
36
  checkPermissions();
@@ -183,8 +186,10 @@ isScanningBarcode = false, onBarcodeScanned, }) => {
183
186
  // 🚨 Memoized Callback for Barcode Decoding
184
187
  const handleWebBarcodeScanned = useCallback((value) => {
185
188
  console.log(`🎉 [WEB SCANNER] SUCCESS! Decoded value:`, value);
186
- if (!isProcessingRef.current && value !== scannedBarcodeRef.current) {
187
- scannedBarcodeRef.current = value;
189
+ const now = Date.now();
190
+ const previous = scannedBarcodeRef.current;
191
+ if (!isProcessingRef.current && (value !== previous.value || now - previous.emittedAt > 1500)) {
192
+ scannedBarcodeRef.current = { value, emittedAt: now };
188
193
  onBarcodeScanned?.(value);
189
194
  }
190
195
  }, [onBarcodeScanned]);
@@ -226,7 +231,7 @@ isScanningBarcode = false, onBarcodeScanned, }) => {
226
231
  top: '-9999px',
227
232
  }}/>
228
233
 
229
- {isScanningBarcode && isInitialized && (<WebBarcodeScanner videoRef={videoRef} onBarcodeScanned={handleWebBarcodeScanned}
234
+ {isScanningBarcode && isInitialized && (<WebBarcodeScanner videoRef={videoRef} onBarcodeScanned={handleWebBarcodeScanned} formats={barcodeTypes}
230
235
  // Use silentCaptureResult.isAnalyzing (state) not the ref so
231
236
  // React re-renders with the correct active value
232
237
  active={isScanningBarcode && isInitialized && !(silentCaptureResult?.isAnalyzing ?? false)}/>)}
@@ -1 +1 @@
1
- {"version":3,"file":"EnhancedCameraView.web.js","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { View, StyleSheet, TouchableOpacity, Text, Platform } from 'react-native';\nimport { EnhancedCameraViewProps } from './OverLay/type';\nimport { useI18n } from '../hooks/useI18n';\n// 🚨 Import the WebBarcodeScanner we built earlier\nimport { WebBarcodeScanner } from './WebBarcodeScanner';\n\n// Add the specific properties needed for barcode scanning to the existing props\nexport interface ExtendedCameraProps extends EnhancedCameraViewProps {\n isScanningBarcode?: boolean;\n onBarcodeScanned?: (data: string) => void;\n}\n\nexport const EnhancedCameraView: React.FC<ExtendedCameraProps> = ({\n instructions = 'Position yourself in the frame and tap the capture button',\n showCamera,\n cameraType: initialCameraType = 'front',\n style,\n onCapture,\n onError,\n onClose,\n enableFlash = false,\n enableHdr = false,\n quality = 'high',\n showCaptureButton = true,\n showSwitchCamera = true,\n overlayComponent,\n bbox,\n canFlip = true,\n enableVideo = false,\n isRecording = false,\n onVideoRecordingStart,\n onVideoRecordingStop,\n videoDuration = 10,\n onSilentCapture,\n silentCaptureResult,\n captureStabilizationDelayMs = 2500,\n // 🚨 New props for barcode support\n isScanningBarcode = false,\n onBarcodeScanned,\n}) => {\n const { t } = useI18n();\n\n // Platform check\n if (Platform.OS !== 'web') {\n console.warn('EnhancedCameraView.web.tsx should only be used on web platform');\n return null;\n }\n\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n const [cameraType, setCameraType] = useState<'front' | 'back'>(initialCameraType);\n const [hasPermission, setHasPermission] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n // const [flash, setFlash] = useState<'off' | 'on' | 'auto'>('off');\n const [stream, setStream] = useState<MediaStream | null>(null);\n // const [isRecordingVideo, setIsRecordingVideo] = useState(false);\n // const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);\n // const [recordedChunks, setRecordedChunks] = useState<Blob[]>([]);\n\n // 🚨 New Refs for Barcode Logic\n const isProcessingRef = useRef(silentCaptureResult?.isAnalyzing || false);\n const scannedBarcodeRef = useRef<string | null>(null);\n\n useEffect(() => {\n isProcessingRef.current = silentCaptureResult?.isAnalyzing || false;\n }, [silentCaptureResult?.isAnalyzing]);\n\n useEffect(() => {\n if (showCamera) {\n checkPermissions();\n }\n }, [showCamera]);\n\n useEffect(() => {\n return () => {\n if (stream) {\n stream.getTracks().forEach(track => track.stop());\n }\n };\n }, [stream]);\n\n const getVideoConstraints = useCallback((): MediaTrackConstraints => {\n const isHigh = quality === 'high';\n const isMedium = quality === 'medium';\n return {\n facingMode: cameraType === 'front' ? 'user' : 'environment',\n width: {\n min: isHigh ? 1280 : isMedium ? 960 : 640,\n ideal: isHigh ? 2560 : isMedium ? 1280 : 640,\n },\n height: {\n min: isHigh ? 720 : isMedium ? 540 : 480,\n ideal: isHigh ? 1440 : isMedium ? 720 : 480,\n },\n };\n }, [cameraType, quality]);\n\n const checkPermissions = async () => {\n try {\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n onError?.({ message: 'Camera not supported in this browser' });\n return;\n }\n const tempStream = await navigator.mediaDevices.getUserMedia({\n video: getVideoConstraints(),\n audio: enableVideo,\n });\n tempStream.getTracks().forEach(track => track.stop());\n setHasPermission(true);\n await startCamera();\n } catch (error) {\n console.error('Error checking permissions:', error);\n onError?.({ message: 'Camera permissions not granted' });\n }\n };\n\n const startCamera = async () => {\n try {\n if (stream) {\n stream.getTracks().forEach(track => track.stop());\n }\n const constraints: MediaStreamConstraints = {\n video: getVideoConstraints(),\n audio: enableVideo,\n };\n let newStream: MediaStream;\n try {\n newStream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (err) {\n const name = err instanceof Error ? err.name : '';\n if (name === 'OverconstrainedError') {\n const fallbackConstraints: MediaStreamConstraints = {\n video: {\n facingMode: cameraType === 'front' ? 'user' : 'environment',\n width: { ideal: quality === 'high' ? 2560 : quality === 'medium' ? 1280 : 640 },\n height: { ideal: quality === 'high' ? 1440 : quality === 'medium' ? 720 : 480 },\n },\n audio: enableVideo,\n };\n newStream = await navigator.mediaDevices.getUserMedia(fallbackConstraints);\n } else {\n throw err;\n }\n }\n setStream(newStream);\n if (videoRef.current) {\n videoRef.current.srcObject = newStream;\n // 🚨 CRUCIAL FIX: Wait for the video to actually have metadata before saying it's initialized\n videoRef.current.onloadedmetadata = () => {\n console.log('✅ [WEB ENGINE] Camera stream loaded metadata. Initializing.');\n setIsInitialized(true);\n };\n }\n } catch (error) {\n console.error('Error starting camera:', error);\n onError?.({ message: 'Failed to start camera' });\n }\n };\n\n // const capturePhoto = useCallback(async () => {\n // try {\n // onCapture && onCapture({ success: true });\n // } catch (error) {\n // console.error('Error taking photo:', error);\n // onCapture?.({\n // success: false,\n // error: error instanceof Error ? error.message : 'Failed to capture photo',\n // });\n // }\n // }, [isInitialized, onCapture, onError]);\n\n const captureSilentPhoto = useCallback(async () => {\n try {\n // During barcode phase, we still need to take a photo to give\n // handleSilentCapture the image path for pendingCAImage.\n // IDCardCapture gates further processing via scanPhase state.\n if (!videoRef.current || !canvasRef.current || !isInitialized) {\n return; // Fail silently, no need to throw errors in a loop\n }\n const video = videoRef.current;\n const canvas = canvasRef.current;\n const context = canvas.getContext('2d');\n if (!context) {\n return;\n }\n canvas.width = video.videoWidth;\n canvas.height = video.videoHeight;\n if (cameraType === 'front') {\n context.save();\n context.translate(canvas.width, 0);\n context.scale(-1, 1);\n context.drawImage(video, 0, 0);\n context.restore();\n } else {\n context.drawImage(video, 0, 0);\n }\n const imageDataUrl = canvas.toDataURL('image/jpeg', 0.95);\n onSilentCapture?.({ success: true, path: imageDataUrl, barcode: null });\n } catch (error) {\n console.error('Error taking silent photo:', error);\n }\n }, [isInitialized, cameraType, onSilentCapture, isScanningBarcode]);\n\n useEffect(() => {\n if (!showCamera || !isInitialized || silentCaptureResult?.success) {\n return;\n }\n const delayMs = Math.max(0, captureStabilizationDelayMs);\n const intervalMs = 5000;\n let intervalId: ReturnType<typeof setInterval> | null = null;\n const timeoutId = setTimeout(() => {\n captureSilentPhoto();\n intervalId = setInterval(captureSilentPhoto, intervalMs);\n }, delayMs);\n return () => {\n clearTimeout(timeoutId);\n if (intervalId) clearInterval(intervalId);\n };\n }, [showCamera, isInitialized, captureStabilizationDelayMs, captureSilentPhoto, silentCaptureResult?.success]);\n\n // 🚨 Memoized Callback for Barcode Decoding\n const handleWebBarcodeScanned = useCallback((value: string) => {\n console.log(`🎉 [WEB SCANNER] SUCCESS! Decoded value:`, value);\n if (!isProcessingRef.current && value !== scannedBarcodeRef.current) {\n scannedBarcodeRef.current = value;\n onBarcodeScanned?.(value);\n }\n }, [onBarcodeScanned]);\n\n // Video recording logic...\n // const startVideoRecording = useCallback(async () => {\n // /* ... Keep original logic ... */\n // }, [isInitialized, stream, videoDuration, onVideoRecordingStart, onVideoRecordingStop, onError]);\n\n // const stopVideoRecording = useCallback(async () => {\n // /* ... Keep original logic ... */\n // }, [mediaRecorder, onError]);\n\n const switchCamera = useCallback(async () => {\n setCameraType(current => current === 'front' ? 'back' : 'front');\n await startCamera();\n }, [cameraType]);\n\n // const toggleFlash = useCallback(() => {\n // /* ... Keep original logic ... */\n // }, []);\n\n if (!hasPermission) {\n return (\n <View style={[styles.container, style]}>\n <Text style={styles.permissionMessage}>\n Camera permission required. Please grant permission to continue.\n </Text>\n </View>\n );\n }\n\n if (!showCamera) {\n return <View style={[styles.container, style]} />;\n }\n\n return (\n <View style={[styles.container, style]}>\n <video\n ref={videoRef}\n style={{\n position: 'absolute',\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n transform: cameraType === 'front' ? 'scaleX(-1)' : undefined,\n }}\n autoPlay\n playsInline\n muted\n />\n <canvas\n ref={canvasRef}\n style={{\n position: 'absolute',\n left: '-9999px',\n top: '-9999px',\n }}\n />\n\n {isScanningBarcode && isInitialized && (\n <WebBarcodeScanner\n videoRef={videoRef}\n onBarcodeScanned={handleWebBarcodeScanned}\n // Use silentCaptureResult.isAnalyzing (state) not the ref so\n // React re-renders with the correct active value\n active={isScanningBarcode && isInitialized && !(silentCaptureResult?.isAnalyzing ?? false)}\n />\n )}\n\n {overlayComponent}\n\n {bbox && (\n <View style={styles.bboxOverlay}>\n <View\n style={[\n styles.bbox,\n {\n left: `${bbox.xMin}%`,\n top: `${bbox.yMin}%`,\n width: `${bbox.xMax - bbox.xMin}%`,\n height: `${bbox.yMax - bbox.yMin}%`,\n borderColor: bbox.borderColor || '#2DBD60',\n borderWidth: bbox.borderWidth || 3,\n borderRadius: bbox.cornerRadius || 8,\n },\n ]}\n />\n </View>\n )}\n\n {silentCaptureResult?.isAnalyzing && (\n <View style={styles.analyzingContainer}>\n <Text style={styles.analyzingText}>{t('camera.analyzing')}</Text>\n </View>\n )}\n\n <View style={styles.controlsContainer}>\n {showSwitchCamera && canFlip && (\n <TouchableOpacity style={styles.controlButton} onPress={switchCamera}>\n <Text style={styles.controlButtonText}>🔄</Text>\n </TouchableOpacity>\n )}\n </View>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n // ... Keep all your original styles exactly as they are\n container: { flex: 1, backgroundColor: 'black' },\n instructionsOverlay: { position: 'absolute', top: 60, left: 20, right: 20, backgroundColor: 'rgba(0, 0, 0, 0.7)', padding: 15, borderRadius: 10, zIndex: 1 },\n instructions: { color: 'white', fontSize: 16, textAlign: 'center', fontWeight: '500' },\n closeButton: { position: 'absolute', top: 50, right: 20, backgroundColor: 'rgba(0, 0, 0, 0.7)', width: 40, height: 40, borderRadius: 20, justifyContent: 'center', alignItems: 'center', zIndex: 2 },\n closeButtonText: { color: 'white', fontSize: 20, fontWeight: 'bold' },\n controlsContainer: { position: 'absolute', bottom: 40, left: 0, right: 0, flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', paddingHorizontal: 40, zIndex: 1 },\n controlButton: { backgroundColor: 'rgba(0, 0, 0, 0.7)', width: 50, height: 50, borderRadius: 25, justifyContent: 'center', alignItems: 'center' },\n controlButtonText: { fontSize: 24 },\n captureButton: { backgroundColor: 'rgba(255, 255, 255, 0.3)', width: 80, height: 80, borderRadius: 40, justifyContent: 'center', alignItems: 'center', borderWidth: 3, borderColor: 'white' },\n captureButtonInner: { backgroundColor: 'white', width: 60, height: 60, borderRadius: 30 },\n captureButtonDisabled: { backgroundColor: 'rgba(255, 255, 255, 0.5)' },\n recordingButton: { backgroundColor: 'rgba(255, 59, 48, 0.3)', borderColor: '#FF3B30' },\n recordingButtonInner: { backgroundColor: '#FF3B30' },\n permissionMessage: { color: 'white', fontSize: 16, textAlign: 'center', margin: 20 },\n errorMessage: { color: 'red', fontSize: 16, textAlign: 'center', margin: 20 },\n bboxOverlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, pointerEvents: 'none' },\n bbox: { position: 'absolute', borderStyle: 'solid', backgroundColor: 'transparent' },\n analyzingContainer: { position: 'absolute', bottom: 100, alignSelf: 'center', backgroundColor: 'rgba(0, 0, 0, 0.7)', padding: 10, borderRadius: 10, zIndex: 1000 },\n analyzingText: { color: 'white', fontSize: 16, fontWeight: 'bold' },\n});"]}
1
+ {"version":3,"file":"EnhancedCameraView.web.js","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAElF,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,mDAAmD;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AASxD,MAAM,CAAC,MAAM,kBAAkB,GAAkC,CAAC,EAChE,YAAY,GAAG,2DAA2D,EAC1E,UAAU,EACV,UAAU,EAAE,iBAAiB,GAAG,OAAO,EACvC,KAAK,EACL,SAAS,EACT,OAAO,EACP,OAAO,EACP,WAAW,GAAG,KAAK,EACnB,SAAS,GAAG,KAAK,EACjB,OAAO,GAAG,MAAM,EAChB,iBAAiB,GAAG,IAAI,EACxB,gBAAgB,GAAG,IAAI,EACvB,gBAAgB,EAChB,IAAI,EACJ,OAAO,GAAG,IAAI,EACd,WAAW,GAAG,KAAK,EACnB,WAAW,GAAG,KAAK,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,GAAG,EAAE,EAClB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,GAAG,IAAI;AAClC,mCAAmC;AACnC,iBAAiB,GAAG,KAAK,EACzB,gBAAgB,EAChB,YAAY,GACb,EAAE,EAAE;IACH,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;IAExB,iBAAiB;IACjB,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAElD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAmB,iBAAiB,CAAC,CAAC;IAClF,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,oEAAoE;IACpE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IAC/D,mEAAmE;IACnE,kFAAkF;IAClF,oEAAoE;IAEpE,gCAAgC;IAChC,MAAM,eAAe,GAAG,MAAM,CAAC,mBAAmB,EAAE,WAAW,IAAI,KAAK,CAAC,CAAC;IAC1E,MAAM,iBAAiB,GAAG,MAAM,CAA8C,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;IAE7G,SAAS,CAAC,GAAG,EAAE;QACb,eAAe,CAAC,OAAO,GAAG,mBAAmB,EAAE,WAAW,IAAI,KAAK,CAAC;IACtE,CAAC,EAAE,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC5D,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,mBAAmB,GAAG,WAAW,CAAC,GAA0B,EAAE;QAClE,MAAM,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC;QAClC,MAAM,QAAQ,GAAG,OAAO,KAAK,QAAQ,CAAC;QACtC,OAAO;YACL,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa;YAC3D,KAAK,EAAE;gBACL,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;gBACzC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;aAC7C;YACD,MAAM,EAAE;gBACN,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;gBACxC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;aAC5C;SACF,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAE1B,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC;gBACpE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC3D,KAAK,EAAE,mBAAmB,EAAE;gBAC5B,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;YACH,UAAU,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACtD,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,WAAW,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;YACpD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,IAAI,CAAC;YACH,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,WAAW,GAA2B;gBAC1C,KAAK,EAAE,mBAAmB,EAAE;gBAC5B,KAAK,EAAE,WAAW;aACnB,CAAC;YACF,IAAI,SAAsB,CAAC;YAC3B,IAAI,CAAC;gBACH,SAAS,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YACrE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClD,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;oBACpC,MAAM,mBAAmB,GAA2B;wBAClD,KAAK,EAAE;4BACL,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa;4BAC3D,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE;4BAC/E,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE;yBAChF;wBACD,KAAK,EAAE,WAAW;qBACnB,CAAC;oBACF,SAAS,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;gBAC7E,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,CAAC;gBACZ,CAAC;YACH,CAAC;YACD,SAAS,CAAC,SAAS,CAAC,CAAC;YACrB,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;gBACvC,8FAA8F;gBAC9F,QAAQ,CAAC,OAAO,CAAC,gBAAgB,GAAG,GAAG,EAAE;oBACvC,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;oBAC3E,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YAC/C,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC;IAEF,iDAAiD;IACjD,UAAU;IACV,iDAAiD;IACjD,sBAAsB;IACtB,mDAAmD;IACnD,oBAAoB;IACpB,wBAAwB;IACxB,mFAAmF;IACnF,UAAU;IACV,MAAM;IACN,2CAA2C;IAE3C,MAAM,kBAAkB,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAChD,IAAI,CAAC;YACH,8DAA8D;YAC9D,yDAAyD;YACzD,8DAA8D;YAC9D,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC;gBAC9D,OAAO,CAAC,mDAAmD;YAC7D,CAAC;YACD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC;YAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;YACjC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YACD,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;YAChC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;YAClC,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;gBAC3B,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBACnC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACrB,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC/B,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACjC,CAAC;YACD,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAC1D,eAAe,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAEpE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,UAAU,IAAI,CAAC,aAAa,IAAI,mBAAmB,EAAE,OAAO,EAAE,CAAC;YAClE,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC;QACxB,IAAI,UAAU,GAA0C,IAAI,CAAC;QAC7D,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,kBAAkB,EAAE,CAAC;YACrB,UAAU,GAAG,WAAW,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,UAAU;gBAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC;IAE/G,4CAA4C;IAC5C,MAAM,uBAAuB,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,EAAE;QAC5D,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC;QAC3C,IAAI,CAAC,eAAe,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,IAAI,GAAG,GAAG,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC;YAC9F,iBAAiB,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;YACtD,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEvB,2BAA2B;IAC3B,wDAAwD;IACxD,sCAAsC;IACtC,oGAAoG;IAEpG,uDAAuD;IACvD,sCAAsC;IACtC,gCAAgC;IAEhC,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACjE,MAAM,WAAW,EAAE,CAAC;IACtB,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,0CAA0C;IAC1C,sCAAsC;IACtC,UAAU;IAEV,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACrC;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CACpC;;QACF,EAAE,IAAI,CACR;MAAA,EAAE,IAAI,CAAC,CACR,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAG,CAAC;IACpD,CAAC;IAED,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACrC;MAAA,CAAC,KAAK,CACJ,GAAG,CAAC,CAAC,QAAQ,CAAC,CACd,KAAK,CAAC,CAAC;YACL,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,OAAO;YAClB,SAAS,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;SAC7D,CAAC,CACF,QAAQ,CACR,WAAW,CACX,KAAK,EAEP;MAAA,CAAC,MAAM,CACL,GAAG,CAAC,CAAC,SAAS,CAAC,CACf,KAAK,CAAC,CAAC;YACL,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,SAAS;YACf,GAAG,EAAE,SAAS;SACf,CAAC,EAGJ;;MAAA,CAAC,iBAAiB,IAAI,aAAa,IAAI,CACrC,CAAC,iBAAiB,CAChB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,gBAAgB,CAAC,CAAC,uBAAuB,CAAC,CAC1C,OAAO,CAAC,CAAC,YAAY,CAAC;QACtB,6DAA6D;QAC7D,iDAAiD;QACjD,MAAM,CAAC,CAAC,iBAAiB,IAAI,aAAa,IAAI,CAAC,CAAC,mBAAmB,EAAE,WAAW,IAAI,KAAK,CAAC,CAAC,EAC3F,CACH,CAED;;MAAA,CAAC,gBAAgB,CAEjB;;MAAA,CAAC,IAAI,IAAI,CACP,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAC9B;UAAA,CAAC,IAAI,CACH,KAAK,CAAC,CAAC;gBACL,MAAM,CAAC,IAAI;gBACX;oBACE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG;oBACrB,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG;oBACpB,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG;oBAClC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG;oBACnC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;oBAC1C,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;oBAClC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,CAAC;iBACrC;aACF,CAAC,EAEN;QAAA,EAAE,IAAI,CAAC,CACR,CAED;;MAAA,CAAC,mBAAmB,EAAE,WAAW,IAAI,CACnC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CACrC;UAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,EAAE,IAAI,CAClE;QAAA,EAAE,IAAI,CAAC,CACR,CAED;;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CACpC;QAAA,CAAC,gBAAgB,IAAI,OAAO,IAAI,CAC9B,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CACnE;YAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,EAAE,IAAI,CACjD;UAAA,EAAE,gBAAgB,CAAC,CACpB,CACH;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,wDAAwD;IACxD,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,OAAO,EAAE;IAChD,mBAAmB,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,oBAAoB,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE;IAC5J,YAAY,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE;IACtF,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE;IACpM,eAAe,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;IACrE,iBAAiB,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE;IACxL,aAAa,EAAE,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE;IACjJ,iBAAiB,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;IACnC,aAAa,EAAE,EAAE,eAAe,EAAE,0BAA0B,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE;IAC7L,kBAAkB,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE;IACzF,qBAAqB,EAAE,EAAE,eAAe,EAAE,0BAA0B,EAAE;IACtE,eAAe,EAAE,EAAE,eAAe,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,EAAE;IACtF,oBAAoB,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE;IACpD,iBAAiB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;IACpF,YAAY,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;IAC7E,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE;IAClG,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE;IACpF,kBAAkB,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,oBAAoB,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IAClK,aAAa,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;CACpE,CAAC,CAAC","sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { View, StyleSheet, TouchableOpacity, Text, Platform } from 'react-native';\nimport { EnhancedCameraViewProps } from './OverLay/type';\nimport { useI18n } from '../hooks/useI18n';\nimport type { CodeType } from 'react-native-vision-camera';\n// 🚨 Import the WebBarcodeScanner we built earlier\nimport { WebBarcodeScanner } from './WebBarcodeScanner';\n\n// Add the specific properties needed for barcode scanning to the existing props\nexport interface ExtendedCameraProps extends EnhancedCameraViewProps {\n isScanningBarcode?: boolean;\n onBarcodeScanned?: (data: string) => void;\n barcodeTypes?: CodeType[];\n}\n\nexport const EnhancedCameraView: React.FC<ExtendedCameraProps> = ({\n instructions = 'Position yourself in the frame and tap the capture button',\n showCamera,\n cameraType: initialCameraType = 'front',\n style,\n onCapture,\n onError,\n onClose,\n enableFlash = false,\n enableHdr = false,\n quality = 'high',\n showCaptureButton = true,\n showSwitchCamera = true,\n overlayComponent,\n bbox,\n canFlip = true,\n enableVideo = false,\n isRecording = false,\n onVideoRecordingStart,\n onVideoRecordingStop,\n videoDuration = 10,\n onSilentCapture,\n silentCaptureResult,\n captureStabilizationDelayMs = 4000,\n // 🚨 New props for barcode support\n isScanningBarcode = false,\n onBarcodeScanned,\n barcodeTypes,\n}) => {\n const { t } = useI18n();\n\n // Platform check\n if (Platform.OS !== 'web') {\n console.warn('EnhancedCameraView.web.tsx should only be used on web platform');\n return null;\n }\n\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n const [cameraType, setCameraType] = useState<'front' | 'back'>(initialCameraType);\n const [hasPermission, setHasPermission] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n // const [flash, setFlash] = useState<'off' | 'on' | 'auto'>('off');\n const [stream, setStream] = useState<MediaStream | null>(null);\n // const [isRecordingVideo, setIsRecordingVideo] = useState(false);\n // const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);\n // const [recordedChunks, setRecordedChunks] = useState<Blob[]>([]);\n\n // 🚨 New Refs for Barcode Logic\n const isProcessingRef = useRef(silentCaptureResult?.isAnalyzing || false);\n const scannedBarcodeRef = useRef<{ value: string | null; emittedAt: number }>({ value: null, emittedAt: 0 });\n\n useEffect(() => {\n isProcessingRef.current = silentCaptureResult?.isAnalyzing || false;\n }, [silentCaptureResult?.isAnalyzing]);\n\n useEffect(() => {\n scannedBarcodeRef.current = { value: null, emittedAt: 0 };\n }, [isScanningBarcode]);\n\n useEffect(() => {\n if (showCamera) {\n checkPermissions();\n }\n }, [showCamera]);\n\n useEffect(() => {\n return () => {\n if (stream) {\n stream.getTracks().forEach(track => track.stop());\n }\n };\n }, [stream]);\n\n const getVideoConstraints = useCallback((): MediaTrackConstraints => {\n const isHigh = quality === 'high';\n const isMedium = quality === 'medium';\n return {\n facingMode: cameraType === 'front' ? 'user' : 'environment',\n width: {\n min: isHigh ? 1280 : isMedium ? 960 : 640,\n ideal: isHigh ? 2560 : isMedium ? 1280 : 640,\n },\n height: {\n min: isHigh ? 720 : isMedium ? 540 : 480,\n ideal: isHigh ? 1440 : isMedium ? 720 : 480,\n },\n };\n }, [cameraType, quality]);\n\n const checkPermissions = async () => {\n try {\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n onError?.({ message: 'Camera not supported in this browser' });\n return;\n }\n const tempStream = await navigator.mediaDevices.getUserMedia({\n video: getVideoConstraints(),\n audio: enableVideo,\n });\n tempStream.getTracks().forEach(track => track.stop());\n setHasPermission(true);\n await startCamera();\n } catch (error) {\n console.error('Error checking permissions:', error);\n onError?.({ message: 'Camera permissions not granted' });\n }\n };\n\n const startCamera = async () => {\n try {\n if (stream) {\n stream.getTracks().forEach(track => track.stop());\n }\n const constraints: MediaStreamConstraints = {\n video: getVideoConstraints(),\n audio: enableVideo,\n };\n let newStream: MediaStream;\n try {\n newStream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (err) {\n const name = err instanceof Error ? err.name : '';\n if (name === 'OverconstrainedError') {\n const fallbackConstraints: MediaStreamConstraints = {\n video: {\n facingMode: cameraType === 'front' ? 'user' : 'environment',\n width: { ideal: quality === 'high' ? 2560 : quality === 'medium' ? 1280 : 640 },\n height: { ideal: quality === 'high' ? 1440 : quality === 'medium' ? 720 : 480 },\n },\n audio: enableVideo,\n };\n newStream = await navigator.mediaDevices.getUserMedia(fallbackConstraints);\n } else {\n throw err;\n }\n }\n setStream(newStream);\n if (videoRef.current) {\n videoRef.current.srcObject = newStream;\n // 🚨 CRUCIAL FIX: Wait for the video to actually have metadata before saying it's initialized\n videoRef.current.onloadedmetadata = () => {\n console.log('✅ [WEB ENGINE] Camera stream loaded metadata. Initializing.');\n setIsInitialized(true);\n };\n }\n } catch (error) {\n console.error('Error starting camera:', error);\n onError?.({ message: 'Failed to start camera' });\n }\n };\n\n // const capturePhoto = useCallback(async () => {\n // try {\n // onCapture && onCapture({ success: true });\n // } catch (error) {\n // console.error('Error taking photo:', error);\n // onCapture?.({\n // success: false,\n // error: error instanceof Error ? error.message : 'Failed to capture photo',\n // });\n // }\n // }, [isInitialized, onCapture, onError]);\n\n const captureSilentPhoto = useCallback(async () => {\n try {\n // During barcode phase, we still need to take a photo to give\n // handleSilentCapture the image path for pendingCAImage.\n // IDCardCapture gates further processing via scanPhase state.\n if (!videoRef.current || !canvasRef.current || !isInitialized) {\n return; // Fail silently, no need to throw errors in a loop\n }\n const video = videoRef.current;\n const canvas = canvasRef.current;\n const context = canvas.getContext('2d');\n if (!context) {\n return;\n }\n canvas.width = video.videoWidth;\n canvas.height = video.videoHeight;\n if (cameraType === 'front') {\n context.save();\n context.translate(canvas.width, 0);\n context.scale(-1, 1);\n context.drawImage(video, 0, 0);\n context.restore();\n } else {\n context.drawImage(video, 0, 0);\n }\n const imageDataUrl = canvas.toDataURL('image/jpeg', 0.95);\n onSilentCapture?.({ success: true, path: imageDataUrl, barcode: null });\n } catch (error) {\n console.error('Error taking silent photo:', error);\n }\n }, [isInitialized, cameraType, onSilentCapture, isScanningBarcode]);\n\n useEffect(() => {\n if (!showCamera || !isInitialized || silentCaptureResult?.success) {\n return;\n }\n const delayMs = Math.max(0, captureStabilizationDelayMs);\n const intervalMs = 5000;\n let intervalId: ReturnType<typeof setInterval> | null = null;\n const timeoutId = setTimeout(() => {\n captureSilentPhoto();\n intervalId = setInterval(captureSilentPhoto, intervalMs);\n }, delayMs);\n return () => {\n clearTimeout(timeoutId);\n if (intervalId) clearInterval(intervalId);\n };\n }, [showCamera, isInitialized, captureStabilizationDelayMs, captureSilentPhoto, silentCaptureResult?.success]);\n\n // 🚨 Memoized Callback for Barcode Decoding\n const handleWebBarcodeScanned = useCallback((value: string) => {\n console.log(`🎉 [WEB SCANNER] SUCCESS! Decoded value:`, value);\n const now = Date.now();\n const previous = scannedBarcodeRef.current;\n if (!isProcessingRef.current && (value !== previous.value || now - previous.emittedAt > 1500)) {\n scannedBarcodeRef.current = { value, emittedAt: now };\n onBarcodeScanned?.(value);\n }\n }, [onBarcodeScanned]);\n\n // Video recording logic...\n // const startVideoRecording = useCallback(async () => {\n // /* ... Keep original logic ... */\n // }, [isInitialized, stream, videoDuration, onVideoRecordingStart, onVideoRecordingStop, onError]);\n\n // const stopVideoRecording = useCallback(async () => {\n // /* ... Keep original logic ... */\n // }, [mediaRecorder, onError]);\n\n const switchCamera = useCallback(async () => {\n setCameraType(current => current === 'front' ? 'back' : 'front');\n await startCamera();\n }, [cameraType]);\n\n // const toggleFlash = useCallback(() => {\n // /* ... Keep original logic ... */\n // }, []);\n\n if (!hasPermission) {\n return (\n <View style={[styles.container, style]}>\n <Text style={styles.permissionMessage}>\n Camera permission required. Please grant permission to continue.\n </Text>\n </View>\n );\n }\n\n if (!showCamera) {\n return <View style={[styles.container, style]} />;\n }\n\n return (\n <View style={[styles.container, style]}>\n <video\n ref={videoRef}\n style={{\n position: 'absolute',\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n transform: cameraType === 'front' ? 'scaleX(-1)' : undefined,\n }}\n autoPlay\n playsInline\n muted\n />\n <canvas\n ref={canvasRef}\n style={{\n position: 'absolute',\n left: '-9999px',\n top: '-9999px',\n }}\n />\n\n {isScanningBarcode && isInitialized && (\n <WebBarcodeScanner\n videoRef={videoRef}\n onBarcodeScanned={handleWebBarcodeScanned}\n formats={barcodeTypes}\n // Use silentCaptureResult.isAnalyzing (state) not the ref so\n // React re-renders with the correct active value\n active={isScanningBarcode && isInitialized && !(silentCaptureResult?.isAnalyzing ?? false)}\n />\n )}\n\n {overlayComponent}\n\n {bbox && (\n <View style={styles.bboxOverlay}>\n <View\n style={[\n styles.bbox,\n {\n left: `${bbox.xMin}%`,\n top: `${bbox.yMin}%`,\n width: `${bbox.xMax - bbox.xMin}%`,\n height: `${bbox.yMax - bbox.yMin}%`,\n borderColor: bbox.borderColor || '#2DBD60',\n borderWidth: bbox.borderWidth || 3,\n borderRadius: bbox.cornerRadius || 8,\n },\n ]}\n />\n </View>\n )}\n\n {silentCaptureResult?.isAnalyzing && (\n <View style={styles.analyzingContainer}>\n <Text style={styles.analyzingText}>{t('camera.analyzing')}</Text>\n </View>\n )}\n\n <View style={styles.controlsContainer}>\n {showSwitchCamera && canFlip && (\n <TouchableOpacity style={styles.controlButton} onPress={switchCamera}>\n <Text style={styles.controlButtonText}>🔄</Text>\n </TouchableOpacity>\n )}\n </View>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n // ... Keep all your original styles exactly as they are\n container: { flex: 1, backgroundColor: 'black' },\n instructionsOverlay: { position: 'absolute', top: 60, left: 20, right: 20, backgroundColor: 'rgba(0, 0, 0, 0.7)', padding: 15, borderRadius: 10, zIndex: 1 },\n instructions: { color: 'white', fontSize: 16, textAlign: 'center', fontWeight: '500' },\n closeButton: { position: 'absolute', top: 50, right: 20, backgroundColor: 'rgba(0, 0, 0, 0.7)', width: 40, height: 40, borderRadius: 20, justifyContent: 'center', alignItems: 'center', zIndex: 2 },\n closeButtonText: { color: 'white', fontSize: 20, fontWeight: 'bold' },\n controlsContainer: { position: 'absolute', bottom: 40, left: 0, right: 0, flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', paddingHorizontal: 40, zIndex: 1 },\n controlButton: { backgroundColor: 'rgba(0, 0, 0, 0.7)', width: 50, height: 50, borderRadius: 25, justifyContent: 'center', alignItems: 'center' },\n controlButtonText: { fontSize: 24 },\n captureButton: { backgroundColor: 'rgba(255, 255, 255, 0.3)', width: 80, height: 80, borderRadius: 40, justifyContent: 'center', alignItems: 'center', borderWidth: 3, borderColor: 'white' },\n captureButtonInner: { backgroundColor: 'white', width: 60, height: 60, borderRadius: 30 },\n captureButtonDisabled: { backgroundColor: 'rgba(255, 255, 255, 0.5)' },\n recordingButton: { backgroundColor: 'rgba(255, 59, 48, 0.3)', borderColor: '#FF3B30' },\n recordingButtonInner: { backgroundColor: '#FF3B30' },\n permissionMessage: { color: 'white', fontSize: 16, textAlign: 'center', margin: 20 },\n errorMessage: { color: 'red', fontSize: 16, textAlign: 'center', margin: 20 },\n bboxOverlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, pointerEvents: 'none' },\n bbox: { position: 'absolute', borderStyle: 'solid', backgroundColor: 'transparent' },\n analyzingContainer: { position: 'absolute', bottom: 100, alignSelf: 'center', backgroundColor: 'rgba(0, 0, 0, 0.7)', padding: 10, borderRadius: 10, zIndex: 1000 },\n analyzingText: { color: 'white', fontSize: 16, fontWeight: 'bold' },\n});\n"]}
@@ -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;AAwB5L,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;AAkCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAy8BtD,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;AAyB5L,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAmED,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;AA+CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAu1CtD,CAAC"}