@trustchex/react-native-sdk 1.163.7 → 1.163.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TrustchexSDK.podspec +0 -1
- package/ios/VisionCameraPlugins/BarcodeScanner/BarcodeScannerFrameProcessorPlugin-Bridging-Header.h +9 -0
- package/ios/VisionCameraPlugins/BarcodeScanner/BarcodeScannerFrameProcessorPlugin.swift +173 -157
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +15 -3
- package/lib/module/Shared/EIDReader/constants/eidConstants.js +65 -0
- package/lib/module/Shared/EIDReader/data/country.js +21 -44
- package/lib/module/Shared/EIDReader/data/countryInterface.js +1 -0
- package/lib/module/Shared/EIDReader/data/countryRegistry.js +65 -0
- package/lib/module/Shared/EIDReader/data/isoCountry.js +5 -1
- package/lib/module/Shared/EIDReader/data/unicodeCountry.js +5 -1
- package/lib/module/Shared/EIDReader/defaultFileSystem.js +4 -4
- package/lib/module/Shared/EIDReader/eidService.js +52 -51
- package/lib/module/Shared/EIDReader/lds/cvcaFile.js +2 -2
- package/lib/module/Shared/EIDReader/tlv/tlvCore.js +161 -0
- package/lib/module/Shared/EIDReader/tlv/tlvInputStream.js +4 -4
- package/lib/module/Shared/EIDReader/tlv/tlvOutputState.js +4 -4
- package/lib/module/Shared/EIDReader/tlv/tlvOutputStream.js +13 -11
- package/lib/module/Shared/VisionCameraPlugins/BarcodeScanner/index.js +0 -2
- package/lib/module/Shared/VisionCameraPlugins/BarcodeScanner/scanCodes.js +2 -0
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/constants/eidConstants.d.ts +58 -0
- package/lib/typescript/src/Shared/EIDReader/constants/eidConstants.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/data/country.d.ts +4 -5
- package/lib/typescript/src/Shared/EIDReader/data/country.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/data/countryInterface.d.ts +21 -0
- package/lib/typescript/src/Shared/EIDReader/data/countryInterface.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/data/countryRegistry.d.ts +14 -0
- package/lib/typescript/src/Shared/EIDReader/data/countryRegistry.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/data/isoCountry.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/data/unicodeCountry.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/tlv/tlvCore.d.ts +22 -0
- package/lib/typescript/src/Shared/EIDReader/tlv/tlvCore.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/tlv/tlvOutputStream.d.ts +2 -2
- package/lib/typescript/src/Shared/EIDReader/tlv/tlvOutputStream.d.ts.map +1 -1
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/index.d.ts +0 -2
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/index.d.ts.map +1 -1
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/scanCodes.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Shared/Components/QrCodeScannerCamera.tsx +15 -2
- package/src/Shared/EIDReader/constants/eidConstants.ts +67 -0
- package/src/Shared/EIDReader/data/country.ts +16 -47
- package/src/Shared/EIDReader/data/countryInterface.ts +21 -0
- package/src/Shared/EIDReader/data/countryRegistry.ts +73 -0
- package/src/Shared/EIDReader/data/isoCountry.ts +4 -0
- package/src/Shared/EIDReader/data/unicodeCountry.ts +4 -0
- package/src/Shared/EIDReader/defaultFileSystem.ts +4 -4
- package/src/Shared/EIDReader/eidService.ts +58 -53
- package/src/Shared/EIDReader/lds/cvcaFile.ts +2 -2
- package/src/Shared/EIDReader/tlv/tlvCore.ts +170 -0
- package/src/Shared/EIDReader/tlv/tlvInputStream.ts +4 -4
- package/src/Shared/EIDReader/tlv/tlvOutputState.ts +4 -4
- package/src/Shared/EIDReader/tlv/tlvOutputStream.ts +13 -12
- package/src/Shared/VisionCameraPlugins/BarcodeScanner/index.ts +0 -4
- package/src/Shared/VisionCameraPlugins/BarcodeScanner/scanCodes.ts +2 -0
- package/lib/module/Shared/VisionCameraPlugins/BarcodeScanner/components/BarcodeCamera.js +0 -66
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/components/BarcodeCamera.d.ts +0 -13
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/components/BarcodeCamera.d.ts.map +0 -1
- package/src/Shared/VisionCameraPlugins/BarcodeScanner/components/BarcodeCamera.tsx +0 -85
package/TrustchexSDK.podspec
CHANGED
package/ios/VisionCameraPlugins/BarcodeScanner/BarcodeScannerFrameProcessorPlugin-Bridging-Header.h
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#ifndef BarcodeScannerFrameProcessorPlugin_Bridging_Header_h
|
|
2
|
+
#define BarcodeScannerFrameProcessorPlugin_Bridging_Header_h
|
|
3
|
+
|
|
4
|
+
#if VISION_CAMERA_ENABLE_FRAME_PROCESSORS
|
|
5
|
+
#import <VisionCamera/FrameProcessorPlugin.h>
|
|
6
|
+
#import <VisionCamera/Frame.h>
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
#endif /* BarcodeScannerFrameProcessorPlugin_Bridging_Header_h */
|
|
@@ -1,172 +1,188 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
-
import VisionCamera
|
|
3
2
|
import Vision
|
|
3
|
+
import VisionCamera
|
|
4
4
|
|
|
5
5
|
@objc(BarcodeScannerFrameProcessorPlugin)
|
|
6
6
|
public class BarcodeScannerFrameProcessorPlugin: FrameProcessorPlugin {
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
public override init(proxy: VisionCameraProxyHolder, options: [AnyHashable: Any]! = [:]) {
|
|
9
|
+
super.init(proxy: proxy, options: options)
|
|
10
|
+
print(
|
|
11
|
+
"BarcodeScannerFrameProcessorPlugin: Initialized with options: \(String(describing: options))"
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public override func callback(_ frame: Frame, withArguments arguments: [AnyHashable: Any]?)
|
|
16
|
+
-> Any?
|
|
17
|
+
{
|
|
18
|
+
print("BarcodeScannerFrameProcessorPlugin: callback called")
|
|
19
|
+
|
|
20
|
+
// Get the pixel buffer from the frame
|
|
21
|
+
guard let imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer) else {
|
|
22
|
+
print("BarcodeScannerFrameProcessorPlugin: Could not get pixel buffer from frame")
|
|
23
|
+
return []
|
|
24
|
+
}
|
|
12
25
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return .code93
|
|
36
|
-
case "data-matrix":
|
|
37
|
-
return .dataMatrix
|
|
38
|
-
case "ean-13":
|
|
39
|
-
return .ean13
|
|
40
|
-
case "ean-8":
|
|
41
|
-
return .ean8
|
|
42
|
-
case "itf":
|
|
43
|
-
return .i2of5
|
|
44
|
-
case "pdf-417":
|
|
45
|
-
return .pdf417
|
|
46
|
-
case "qr":
|
|
47
|
-
return .qr
|
|
48
|
-
case "upc-e":
|
|
49
|
-
return .upce
|
|
50
|
-
default:
|
|
51
|
-
return nil
|
|
52
|
-
}
|
|
53
|
-
}
|
|
26
|
+
// Parse barcode types from arguments (default to QR codes)
|
|
27
|
+
var symbologies: [VNBarcodeSymbology] = [.qr]
|
|
28
|
+
|
|
29
|
+
if let arguments = arguments,
|
|
30
|
+
let barcodeTypes = arguments["barcodeTypes"] as? [String]
|
|
31
|
+
{
|
|
32
|
+
symbologies = barcodeTypes.compactMap { type in
|
|
33
|
+
switch type {
|
|
34
|
+
case "aztec": return .aztec
|
|
35
|
+
case "codabar": return .codabar
|
|
36
|
+
case "code-128": return .code128
|
|
37
|
+
case "code-39": return .code39
|
|
38
|
+
case "code-93": return .code93
|
|
39
|
+
case "data-matrix": return .dataMatrix
|
|
40
|
+
case "ean-13": return .ean13
|
|
41
|
+
case "ean-8": return .ean8
|
|
42
|
+
case "itf": return .i2of5
|
|
43
|
+
case "pdf-417": return .pdf417
|
|
44
|
+
case "qr": return .qr
|
|
45
|
+
case "upc-a": return .ean13 // UPC-A is subset of EAN-13
|
|
46
|
+
case "upc-e": return .upce
|
|
47
|
+
default: return nil
|
|
54
48
|
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
// Use semaphore to make async Vision calls synchronous for frame processor
|
|
53
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
54
|
+
var detectedBarcodes: [VNBarcodeObservation] = []
|
|
55
|
+
var visionError: Error? = nil
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
// Create Vision request handler
|
|
58
|
+
let handler = VNImageRequestHandler(cvPixelBuffer: imageBuffer, options: [:])
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} catch {
|
|
67
|
-
return []
|
|
68
|
-
}
|
|
60
|
+
// Create barcode detection request
|
|
61
|
+
let request = VNDetectBarcodesRequest { (request, error) in
|
|
62
|
+
defer { semaphore.signal() }
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Add barcode type
|
|
77
|
-
let type: String
|
|
78
|
-
switch barcode.symbology {
|
|
79
|
-
case .aztec:
|
|
80
|
-
type = "aztec"
|
|
81
|
-
case .codabar:
|
|
82
|
-
type = "codabar"
|
|
83
|
-
case .code128:
|
|
84
|
-
type = "code-128"
|
|
85
|
-
case .code39:
|
|
86
|
-
type = "code-39"
|
|
87
|
-
case .code93:
|
|
88
|
-
type = "code-93"
|
|
89
|
-
case .dataMatrix:
|
|
90
|
-
type = "data-matrix"
|
|
91
|
-
case .ean13:
|
|
92
|
-
type = "ean-13"
|
|
93
|
-
case .ean8:
|
|
94
|
-
type = "ean-8"
|
|
95
|
-
case .i2of5, .i2of5Checksum, .itf14:
|
|
96
|
-
type = "itf"
|
|
97
|
-
case .pdf417:
|
|
98
|
-
type = "pdf-417"
|
|
99
|
-
case .qr:
|
|
100
|
-
type = "qr"
|
|
101
|
-
case .upce:
|
|
102
|
-
type = "upc-e"
|
|
103
|
-
default:
|
|
104
|
-
type = "unknown"
|
|
105
|
-
}
|
|
106
|
-
barcodeDict["type"] = type
|
|
107
|
-
|
|
108
|
-
// Convert bounding box to our format
|
|
109
|
-
let boundingBox = barcode.boundingBox
|
|
110
|
-
let imageSize = CGSize(width: CVPixelBufferGetWidth(imageBuffer), height: CVPixelBufferGetHeight(imageBuffer))
|
|
111
|
-
|
|
112
|
-
// Vision framework uses normalized coordinates (0-1), convert to pixel coordinates
|
|
113
|
-
let origin = CGPoint(
|
|
114
|
-
x: boundingBox.origin.x * imageSize.width,
|
|
115
|
-
y: (1 - boundingBox.origin.y - boundingBox.size.height) * imageSize.height // Flip Y coordinate
|
|
116
|
-
)
|
|
117
|
-
let size = CGSize(
|
|
118
|
-
width: boundingBox.size.width * imageSize.width,
|
|
119
|
-
height: boundingBox.size.height * imageSize.height
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
barcodeDict["boundingBox"] = [
|
|
123
|
-
"origin": [
|
|
124
|
-
"x": origin.x,
|
|
125
|
-
"y": origin.y
|
|
126
|
-
],
|
|
127
|
-
"size": [
|
|
128
|
-
"width": size.width,
|
|
129
|
-
"height": size.height
|
|
130
|
-
]
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
// Convert corner points to our format
|
|
134
|
-
let topLeft = CGPoint(
|
|
135
|
-
x: barcode.topLeft.x * imageSize.width,
|
|
136
|
-
y: (1 - barcode.topLeft.y) * imageSize.height
|
|
137
|
-
)
|
|
138
|
-
let topRight = CGPoint(
|
|
139
|
-
x: barcode.topRight.x * imageSize.width,
|
|
140
|
-
y: (1 - barcode.topRight.y) * imageSize.height
|
|
141
|
-
)
|
|
142
|
-
let bottomLeft = CGPoint(
|
|
143
|
-
x: barcode.bottomLeft.x * imageSize.width,
|
|
144
|
-
y: (1 - barcode.bottomLeft.y) * imageSize.height
|
|
145
|
-
)
|
|
146
|
-
let bottomRight = CGPoint(
|
|
147
|
-
x: barcode.bottomRight.x * imageSize.width,
|
|
148
|
-
y: (1 - barcode.bottomRight.y) * imageSize.height
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
barcodeDict["cornerPoints"] = [
|
|
152
|
-
["x": topLeft.x, "y": topLeft.y],
|
|
153
|
-
["x": topRight.x, "y": topRight.y],
|
|
154
|
-
["x": bottomRight.x, "y": bottomRight.y],
|
|
155
|
-
["x": bottomLeft.x, "y": bottomLeft.y]
|
|
156
|
-
]
|
|
157
|
-
|
|
158
|
-
// Add native data
|
|
159
|
-
var nativeDict: [String: Any] = [:]
|
|
160
|
-
|
|
161
|
-
if let descriptor = barcode.barcodeDescriptor {
|
|
162
|
-
nativeDict["descriptor"] = descriptor
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
barcodeDict["native"] = nativeDict
|
|
166
|
-
|
|
167
|
-
return barcodeDict
|
|
168
|
-
}
|
|
64
|
+
if let error = error {
|
|
65
|
+
print("BarcodeScannerFrameProcessorPlugin: Vision error: \(error.localizedDescription)")
|
|
66
|
+
visionError = error
|
|
67
|
+
return
|
|
68
|
+
}
|
|
169
69
|
|
|
170
|
-
|
|
70
|
+
detectedBarcodes = request.results as? [VNBarcodeObservation] ?? []
|
|
71
|
+
print("BarcodeScannerFrameProcessorPlugin: Detected \(detectedBarcodes.count) barcodes")
|
|
171
72
|
}
|
|
73
|
+
|
|
74
|
+
// Set symbologies
|
|
75
|
+
request.symbologies = symbologies
|
|
76
|
+
|
|
77
|
+
// Perform the request
|
|
78
|
+
do {
|
|
79
|
+
try handler.perform([request])
|
|
80
|
+
} catch {
|
|
81
|
+
print(
|
|
82
|
+
"BarcodeScannerFrameProcessorPlugin: Error performing Vision request: \(error.localizedDescription)"
|
|
83
|
+
)
|
|
84
|
+
return []
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Wait for completion with timeout
|
|
88
|
+
let waitResult = semaphore.wait(timeout: .now() + 0.1) // 100ms timeout
|
|
89
|
+
if waitResult == .timedOut {
|
|
90
|
+
print("BarcodeScannerFrameProcessorPlugin: Vision request timed out")
|
|
91
|
+
return []
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Check for errors
|
|
95
|
+
if let error = visionError {
|
|
96
|
+
print(
|
|
97
|
+
"BarcodeScannerFrameProcessorPlugin: Vision processing failed: \(error.localizedDescription)"
|
|
98
|
+
)
|
|
99
|
+
return []
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Convert results to pixel coordinates at iOS level
|
|
103
|
+
let result = detectedBarcodes.compactMap { barcode -> [String: Any]? in
|
|
104
|
+
guard let barcodeValue = barcode.payloadStringValue, !barcodeValue.isEmpty else {
|
|
105
|
+
return nil
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
print("BarcodeScannerFrameProcessorPlugin: Processing barcode: \(barcodeValue)")
|
|
109
|
+
|
|
110
|
+
var map: [String: Any] = [:]
|
|
111
|
+
|
|
112
|
+
// Main value that TypeScript interface expects
|
|
113
|
+
map["value"] = barcodeValue
|
|
114
|
+
|
|
115
|
+
// Convert from normalized (0-1) coordinates to pixel coordinates
|
|
116
|
+
let frameWidth = frame.width
|
|
117
|
+
let frameHeight = frame.height
|
|
118
|
+
let boundingBox = barcode.boundingBox
|
|
119
|
+
|
|
120
|
+
// Convert from normalized (0-1) with bottom-left origin to pixel coordinates with top-left origin
|
|
121
|
+
let left = boundingBox.origin.x * CGFloat(frameWidth)
|
|
122
|
+
let bottom = boundingBox.origin.y * CGFloat(frameHeight)
|
|
123
|
+
let width = boundingBox.size.width * CGFloat(frameWidth)
|
|
124
|
+
let height = boundingBox.size.height * CGFloat(frameHeight)
|
|
125
|
+
let top = CGFloat(frameHeight) - bottom - height // Flip Y coordinate from bottom-left to top-left
|
|
126
|
+
|
|
127
|
+
// Create bounding box in pixel coordinates with top-left origin
|
|
128
|
+
map["boundingBox"] = [
|
|
129
|
+
"origin": [
|
|
130
|
+
"x": Int(left),
|
|
131
|
+
"y": Int(top),
|
|
132
|
+
],
|
|
133
|
+
"size": [
|
|
134
|
+
"width": Int(width),
|
|
135
|
+
"height": Int(height),
|
|
136
|
+
],
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
// Convert corner points to pixel coordinates with top-left origin
|
|
140
|
+
let cornerPoints = [
|
|
141
|
+
[
|
|
142
|
+
"x": Int(barcode.topLeft.x * CGFloat(frameWidth)),
|
|
143
|
+
"y": Int((1.0 - barcode.topLeft.y) * CGFloat(frameHeight)),
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
"x": Int(barcode.topRight.x * CGFloat(frameWidth)),
|
|
147
|
+
"y": Int((1.0 - barcode.topRight.y) * CGFloat(frameHeight)),
|
|
148
|
+
],
|
|
149
|
+
[
|
|
150
|
+
"x": Int(barcode.bottomRight.x * CGFloat(frameWidth)),
|
|
151
|
+
"y": Int((1.0 - barcode.bottomRight.y) * CGFloat(frameHeight)),
|
|
152
|
+
],
|
|
153
|
+
[
|
|
154
|
+
"x": Int(barcode.bottomLeft.x * CGFloat(frameWidth)),
|
|
155
|
+
"y": Int((1.0 - barcode.bottomLeft.y) * CGFloat(frameHeight)),
|
|
156
|
+
],
|
|
157
|
+
]
|
|
158
|
+
map["cornerPoints"] = cornerPoints
|
|
159
|
+
|
|
160
|
+
// Map barcode symbology to TypeScript BarcodeType strings
|
|
161
|
+
let typeString: String
|
|
162
|
+
switch barcode.symbology {
|
|
163
|
+
case .aztec: typeString = "aztec"
|
|
164
|
+
case .codabar: typeString = "codabar"
|
|
165
|
+
case .code128: typeString = "code-128"
|
|
166
|
+
case .code39: typeString = "code-39"
|
|
167
|
+
case .code93: typeString = "code-93"
|
|
168
|
+
case .dataMatrix: typeString = "data-matrix"
|
|
169
|
+
case .ean13: typeString = "ean-13"
|
|
170
|
+
case .ean8: typeString = "ean-8"
|
|
171
|
+
case .i2of5, .i2of5Checksum, .itf14: typeString = "itf"
|
|
172
|
+
case .pdf417: typeString = "pdf-417"
|
|
173
|
+
case .qr: typeString = "qr"
|
|
174
|
+
case .upce: typeString = "upc-e"
|
|
175
|
+
default: typeString = "unknown"
|
|
176
|
+
}
|
|
177
|
+
map["type"] = typeString
|
|
178
|
+
|
|
179
|
+
print(
|
|
180
|
+
"BarcodeScannerFrameProcessorPlugin: Converted barcode - value: \(barcodeValue), type: \(typeString), boundingBox: \(map["boundingBox"] ?? "nil")"
|
|
181
|
+
)
|
|
182
|
+
return map
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
print("BarcodeScannerFrameProcessorPlugin: Returning \(result.count) processed barcodes")
|
|
186
|
+
return result
|
|
187
|
+
}
|
|
172
188
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import React, { useEffect } from 'react';
|
|
4
|
-
import { View, StyleSheet, ActivityIndicator, Text as TextView, Text, Linking } from 'react-native';
|
|
4
|
+
import { View, StyleSheet, ActivityIndicator, Text as TextView, Text, Linking, Platform } from 'react-native';
|
|
5
5
|
import { Camera, useCameraDevice, useCameraFormat, useCameraPermission, useFrameProcessor } from 'react-native-vision-camera';
|
|
6
6
|
import { useRunOnJS, useSharedValue } from 'react-native-worklets-core';
|
|
7
7
|
import { useKeepAwake } from "../Libs/native-keep-awake.utils.js";
|
|
@@ -71,8 +71,20 @@ const QrCodeScannerCamera = ({
|
|
|
71
71
|
return false;
|
|
72
72
|
};
|
|
73
73
|
const handleQrCode = useRunOnJS((code, width, height, orientation) => {
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
// TODO: Fix iOS coordinates - iOS coordinate system conversion may be incorrect
|
|
75
|
+
// causing frame checking to fail. Need to verify coordinate normalization
|
|
76
|
+
// between iOS Vision framework and React Native coordinate systems.
|
|
77
|
+
|
|
78
|
+
// On iOS, skip frame checking and scan any QR code found
|
|
79
|
+
if (Platform.OS === 'ios') {
|
|
80
|
+
if (code.value) {
|
|
81
|
+
onQrCodeScanned(code.value);
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
// On Android, continue with frame checking
|
|
85
|
+
if (isInScanningFrame(code, width, height, orientation) && code.value) {
|
|
86
|
+
onQrCodeScanned(code.value);
|
|
87
|
+
}
|
|
76
88
|
}
|
|
77
89
|
}, [onQrCodeScanned]);
|
|
78
90
|
const frameProcessor = useFrameProcessor(frame => {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Constants used throughout the EID Reader module.
|
|
5
|
+
* This file helps avoid circular dependencies by centralizing shared constants.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const EID_CONSTANTS = {
|
|
9
|
+
// Transceive lengths
|
|
10
|
+
EXTENDED_MAX_TRANSCEIVE_LENGTH: 65536,
|
|
11
|
+
NORMAL_MAX_TRANSCEIVE_LENGTH: 256,
|
|
12
|
+
DEFAULT_MAX_BLOCKSIZE: 223,
|
|
13
|
+
// File identifiers
|
|
14
|
+
EF_CARD_ACCESS: 0x011c,
|
|
15
|
+
EF_CARD_SECURITY: 0x011d,
|
|
16
|
+
EF_DG1: 0x0101,
|
|
17
|
+
EF_DG2: 0x0102,
|
|
18
|
+
EF_DG3: 0x0103,
|
|
19
|
+
EF_DG4: 0x0104,
|
|
20
|
+
EF_DG5: 0x0105,
|
|
21
|
+
EF_DG6: 0x0106,
|
|
22
|
+
EF_DG7: 0x0107,
|
|
23
|
+
EF_DG8: 0x0108,
|
|
24
|
+
EF_DG9: 0x0109,
|
|
25
|
+
EF_DG10: 0x010a,
|
|
26
|
+
EF_DG11: 0x010b,
|
|
27
|
+
EF_DG12: 0x010c,
|
|
28
|
+
EF_DG13: 0x010d,
|
|
29
|
+
EF_DG14: 0x010e,
|
|
30
|
+
EF_DG15: 0x010f,
|
|
31
|
+
EF_DG16: 0x0110,
|
|
32
|
+
EF_SOD: 0x011d,
|
|
33
|
+
EF_COM: 0x011e,
|
|
34
|
+
EF_CVCA: 0x011c,
|
|
35
|
+
// Short file identifiers
|
|
36
|
+
SFI_CARD_ACCESS: 0x1c,
|
|
37
|
+
SFI_CARD_SECURITY: 0x1d,
|
|
38
|
+
SFI_DG1: 0x01,
|
|
39
|
+
SFI_DG2: 0x02,
|
|
40
|
+
SFI_DG3: 0x03,
|
|
41
|
+
SFI_DG4: 0x04,
|
|
42
|
+
SFI_DG5: 0x05,
|
|
43
|
+
SFI_DG6: 0x06,
|
|
44
|
+
SFI_DG7: 0x07,
|
|
45
|
+
SFI_DG8: 0x08,
|
|
46
|
+
SFI_DG9: 0x09,
|
|
47
|
+
SFI_DG10: 0x0a,
|
|
48
|
+
SFI_DG11: 0x0b,
|
|
49
|
+
SFI_DG12: 0x0c,
|
|
50
|
+
SFI_DG13: 0x0d,
|
|
51
|
+
SFI_DG14: 0x0e,
|
|
52
|
+
SFI_DG15: 0x0f,
|
|
53
|
+
SFI_DG16: 0x10,
|
|
54
|
+
SFI_COM: 0x1e,
|
|
55
|
+
SFI_SOD: 0x1d,
|
|
56
|
+
SFI_CVCA: 0x1c,
|
|
57
|
+
// PACE key references
|
|
58
|
+
NO_PACE_KEY_REFERENCE: 0x00,
|
|
59
|
+
MRZ_PACE_KEY_REFERENCE: 0x01,
|
|
60
|
+
CAN_PACE_KEY_REFERENCE: 0x02,
|
|
61
|
+
PIN_PACE_KEY_REFERENCE: 0x03,
|
|
62
|
+
PUK_PACE_KEY_REFERENCE: 0x04,
|
|
63
|
+
// Applet AID
|
|
64
|
+
APPLET_AID: new Uint8Array([0xa0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01])
|
|
65
|
+
};
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { ISOCountry } from "./isoCountry.js";
|
|
4
|
-
import { UnicodeCountry } from "./unicodeCountry.js";
|
|
5
3
|
export class Country {
|
|
6
|
-
static SUB_CLASSES = [ISOCountry, UnicodeCountry];
|
|
7
4
|
static getInstance(code) {
|
|
5
|
+
// Note: This will be dynamically resolved at runtime
|
|
6
|
+
const {
|
|
7
|
+
CountryRegistry
|
|
8
|
+
} = require('./countryRegistry');
|
|
8
9
|
if (typeof code === 'number') {
|
|
9
|
-
|
|
10
|
-
for (const country of values) {
|
|
11
|
-
if (country.valueOf() === code) {
|
|
12
|
-
return country;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
throw new Error('Illegal country code ' + code.toString(16));
|
|
10
|
+
return CountryRegistry.fromNumericCode(code);
|
|
16
11
|
} else if (typeof code === 'string') {
|
|
17
12
|
code = code.trim();
|
|
18
13
|
switch (code.length) {
|
|
19
14
|
case 2:
|
|
20
|
-
return
|
|
15
|
+
return CountryRegistry.fromAlpha2(code);
|
|
21
16
|
case 3:
|
|
22
|
-
return
|
|
17
|
+
return CountryRegistry.fromAlpha3(code);
|
|
23
18
|
default:
|
|
24
19
|
throw new Error('Illegal country code ' + code);
|
|
25
20
|
}
|
|
@@ -28,39 +23,21 @@ export class Country {
|
|
|
28
23
|
}
|
|
29
24
|
}
|
|
30
25
|
static values() {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const method = subClass.values;
|
|
36
|
-
const subClassValues = method.call(null);
|
|
37
|
-
result.push(...subClassValues);
|
|
38
|
-
} catch (e) {
|
|
39
|
-
console.debug(`Exception: ${e}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
static fromAlpha2(code) {
|
|
46
|
-
const values = Country.values();
|
|
47
|
-
for (const country of values) {
|
|
48
|
-
if (country.toAlpha2Code() === code) {
|
|
49
|
-
return country;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
throw new Error('Unknown country code ' + code);
|
|
26
|
+
const {
|
|
27
|
+
CountryRegistry
|
|
28
|
+
} = require('./countryRegistry');
|
|
29
|
+
return CountryRegistry.values();
|
|
53
30
|
}
|
|
54
|
-
static
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
throw new Error('Unknown country code ' + code);
|
|
31
|
+
static fromAlpha2(alpha2Code) {
|
|
32
|
+
const {
|
|
33
|
+
CountryRegistry
|
|
34
|
+
} = require('./countryRegistry');
|
|
35
|
+
return CountryRegistry.fromAlpha2(alpha2Code);
|
|
62
36
|
}
|
|
63
|
-
static
|
|
64
|
-
|
|
37
|
+
static fromAlpha3(alpha3Code) {
|
|
38
|
+
const {
|
|
39
|
+
CountryRegistry
|
|
40
|
+
} = require('./countryRegistry');
|
|
41
|
+
return CountryRegistry.fromAlpha3(alpha3Code);
|
|
65
42
|
}
|
|
66
43
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Registry for country implementations to avoid circular dependencies.
|
|
5
|
+
*/
|
|
6
|
+
export class CountryRegistry {
|
|
7
|
+
static countryTypes = [];
|
|
8
|
+
static register(countryType) {
|
|
9
|
+
if (!CountryRegistry.countryTypes.includes(countryType)) {
|
|
10
|
+
CountryRegistry.countryTypes.push(countryType);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
static getRegisteredTypes() {
|
|
14
|
+
return [...CountryRegistry.countryTypes];
|
|
15
|
+
}
|
|
16
|
+
static values() {
|
|
17
|
+
const result = [];
|
|
18
|
+
for (const countryType of CountryRegistry.countryTypes) {
|
|
19
|
+
try {
|
|
20
|
+
const values = countryType.values?.();
|
|
21
|
+
if (Array.isArray(values)) {
|
|
22
|
+
result.push(...values);
|
|
23
|
+
}
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.debug(`Exception getting values from ${countryType.name}: ${e}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
static fromAlpha2(alpha2Code) {
|
|
31
|
+
for (const countryType of CountryRegistry.countryTypes) {
|
|
32
|
+
try {
|
|
33
|
+
const country = countryType.fromAlpha2?.(alpha2Code);
|
|
34
|
+
if (country) {
|
|
35
|
+
return country;
|
|
36
|
+
}
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// Continue to next type
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`Unknown country code: ${alpha2Code}`);
|
|
42
|
+
}
|
|
43
|
+
static fromAlpha3(alpha3Code) {
|
|
44
|
+
for (const countryType of CountryRegistry.countryTypes) {
|
|
45
|
+
try {
|
|
46
|
+
const country = countryType.fromAlpha3?.(alpha3Code);
|
|
47
|
+
if (country) {
|
|
48
|
+
return country;
|
|
49
|
+
}
|
|
50
|
+
} catch (e) {
|
|
51
|
+
// Continue to next type
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Unknown country code: ${alpha3Code}`);
|
|
55
|
+
}
|
|
56
|
+
static fromNumericCode(numericCode) {
|
|
57
|
+
const values = CountryRegistry.values();
|
|
58
|
+
for (const country of values) {
|
|
59
|
+
if (country.valueOf() === numericCode) {
|
|
60
|
+
return country;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
throw new Error(`Unknown country code: ${numericCode.toString(16)}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { Country } from "./country.js";
|
|
4
|
+
import { CountryRegistry } from "./countryRegistry.js";
|
|
4
5
|
export class ISOCountry extends Country {
|
|
5
6
|
static AD = new ISOCountry(32, 'AD', 'AND', 'Andorra', 'Andorran');
|
|
6
7
|
static AE = new ISOCountry(1924, 'AE', 'ARE', 'United Arab Emirates', 'Emirati, Emirian');
|
|
@@ -280,4 +281,7 @@ export class ISOCountry extends Country {
|
|
|
280
281
|
toAlpha3Code() {
|
|
281
282
|
return this.alpha3Code;
|
|
282
283
|
}
|
|
283
|
-
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Register this country type with the registry
|
|
287
|
+
CountryRegistry.register(ISOCountry);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { Country } from "./country.js";
|
|
4
|
+
import { CountryRegistry } from "./countryRegistry.js";
|
|
4
5
|
export class UnicodeCountry extends Country {
|
|
5
6
|
static AD = new UnicodeCountry(32, 'AD', 'AND', 'Andorra', 'Andorran');
|
|
6
7
|
static AE = new UnicodeCountry(1924, 'AE', 'ARE', 'United Arab Emirates', 'Emirati, Emirian');
|
|
@@ -275,4 +276,7 @@ export class UnicodeCountry extends Country {
|
|
|
275
276
|
toAlpha3Code() {
|
|
276
277
|
return this.alpha3Code;
|
|
277
278
|
}
|
|
278
|
-
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Register this country type with the registry
|
|
282
|
+
CountryRegistry.register(UnicodeCountry);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { EID_CONSTANTS } from "./constants/eidConstants.js";
|
|
4
4
|
import { ByteArrayInputStream } from "./java/byteArrayInputStream.js";
|
|
5
5
|
import { DefaultFileInfo } from "./defaultFileInfo.js";
|
|
6
6
|
import { ISO7816_SW } from "./smartcards/iso7816.js";
|
|
@@ -19,7 +19,7 @@ export class DefaultFileSystem {
|
|
|
19
19
|
this.isSelected = false;
|
|
20
20
|
this.isSFIEnabled = isSFIEnabled;
|
|
21
21
|
this.fidToSFI = fidToSFI;
|
|
22
|
-
this.maxReadBinaryLength =
|
|
22
|
+
this.maxReadBinaryLength = EID_CONSTANTS.EXTENDED_MAX_TRANSCEIVE_LENGTH;
|
|
23
23
|
}
|
|
24
24
|
setWrapper(wrapper) {
|
|
25
25
|
this.oldWrapper = this.wrapper;
|
|
@@ -90,9 +90,9 @@ export class DefaultFileSystem {
|
|
|
90
90
|
return result;
|
|
91
91
|
} catch (error) {
|
|
92
92
|
const sw = error.getSW();
|
|
93
|
-
if ((sw & ISO7816_SW.WRONG_LENGTH) === ISO7816_SW.WRONG_LENGTH && this.maxReadBinaryLength >
|
|
93
|
+
if ((sw & ISO7816_SW.WRONG_LENGTH) === ISO7816_SW.WRONG_LENGTH && this.maxReadBinaryLength > EID_CONSTANTS.DEFAULT_MAX_BLOCKSIZE) {
|
|
94
94
|
this.wrapper = this.oldWrapper;
|
|
95
|
-
this.maxReadBinaryLength =
|
|
95
|
+
this.maxReadBinaryLength = EID_CONSTANTS.DEFAULT_MAX_BLOCKSIZE;
|
|
96
96
|
return new Uint8Array(0);
|
|
97
97
|
}
|
|
98
98
|
throw new Error(`Read binary failed on file ${fileInfo == null ? this.selectedFID.toString(16) : fileInfo}`);
|