@cleanuidev/react-native-scanner 1.0.0-beta.1
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/LICENSE +20 -0
- package/README.md +609 -0
- package/Scanner.podspec +20 -0
- package/android/build.gradle +90 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/java/com/scanner/CameraInfoModule.kt +253 -0
- package/android/src/main/java/com/scanner/ScannerPackage.kt +21 -0
- package/android/src/main/java/com/scanner/ScannerView.kt +783 -0
- package/android/src/main/java/com/scanner/ScannerViewManager.kt +181 -0
- package/android/src/main/java/com/scanner/utils/BarcodeFrameManager.kt +170 -0
- package/android/src/main/java/com/scanner/views/BarcodeFrameOverlayView.kt +43 -0
- package/android/src/main/java/com/scanner/views/FocusAreaView.kt +124 -0
- package/ios/BarcodeDetectionManager.swift +229 -0
- package/ios/BarcodeFrameManager.swift +175 -0
- package/ios/BarcodeFrameOverlayView.swift +102 -0
- package/ios/CameraManager.swift +396 -0
- package/ios/CoordinateTransformer.swift +140 -0
- package/ios/FocusAreaOverlayView.swift +161 -0
- package/ios/Models.swift +341 -0
- package/ios/Protocols.swift +194 -0
- package/ios/ScannerView.h +14 -0
- package/ios/ScannerView.mm +358 -0
- package/ios/ScannerViewImpl.swift +580 -0
- package/ios/react-native-scanner-Bridging-Header.h +26 -0
- package/lib/module/CameraInfoModule.js +8 -0
- package/lib/module/CameraInfoModule.js.map +1 -0
- package/lib/module/ScannerViewNativeComponent.ts +121 -0
- package/lib/module/hooks/useCameraInfo.js +106 -0
- package/lib/module/hooks/useCameraInfo.js.map +1 -0
- package/lib/module/index.js +13 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +47 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/CameraInfoModule.d.ts +8 -0
- package/lib/typescript/src/CameraInfoModule.d.ts.map +1 -0
- package/lib/typescript/src/ScannerViewNativeComponent.d.ts +91 -0
- package/lib/typescript/src/ScannerViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useCameraInfo.d.ts +25 -0
- package/lib/typescript/src/hooks/useCameraInfo.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +8 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +145 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +178 -0
- package/src/CameraInfoModule.ts +11 -0
- package/src/ScannerViewNativeComponent.ts +121 -0
- package/src/hooks/useCameraInfo.ts +190 -0
- package/src/index.tsx +30 -0
- package/src/types.ts +177 -0
package/ios/Models.swift
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Models.swift
|
|
3
|
+
// react-native-scanner
|
|
4
|
+
//
|
|
5
|
+
// Created for iOS barcode scanner implementation
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import UIKit
|
|
10
|
+
import Vision
|
|
11
|
+
|
|
12
|
+
// MARK: - Barcode Format Enum
|
|
13
|
+
|
|
14
|
+
/// Supported barcode formats, mapped from React Native props
|
|
15
|
+
enum BarcodeFormat: String {
|
|
16
|
+
case qrCode = "QR_CODE"
|
|
17
|
+
case code128 = "CODE_128"
|
|
18
|
+
case code39 = "CODE_39"
|
|
19
|
+
case ean13 = "EAN_13"
|
|
20
|
+
case ean8 = "EAN_8"
|
|
21
|
+
case upcA = "UPC_A"
|
|
22
|
+
case upcE = "UPC_E"
|
|
23
|
+
case dataMatrix = "DATA_MATRIX"
|
|
24
|
+
case pdf417 = "PDF_417"
|
|
25
|
+
case aztec = "AZTEC"
|
|
26
|
+
case itf = "ITF"
|
|
27
|
+
|
|
28
|
+
/// Convert to Vision framework symbology
|
|
29
|
+
var visionSymbology: VNBarcodeSymbology {
|
|
30
|
+
switch self {
|
|
31
|
+
case .qrCode: return .qr
|
|
32
|
+
case .code128: return .code128
|
|
33
|
+
case .code39: return .code39
|
|
34
|
+
case .ean13: return .ean13
|
|
35
|
+
case .ean8: return .ean8
|
|
36
|
+
case .upcA: return .upce // Note: UPCA is handled as UPCE in Vision
|
|
37
|
+
case .upcE: return .upce
|
|
38
|
+
case .dataMatrix: return .dataMatrix
|
|
39
|
+
case .pdf417: return .pdf417
|
|
40
|
+
case .aztec: return .aztec
|
|
41
|
+
case .itf: return .itf14
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Get all supported formats
|
|
46
|
+
static var allFormats: [BarcodeFormat] {
|
|
47
|
+
return [.qrCode, .code128, .code39, .ean13, .ean8, .upcA, .upcE, .dataMatrix, .pdf417, .aztec, .itf]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// MARK: - Barcode Scan Strategy
|
|
52
|
+
|
|
53
|
+
/// Strategy for processing multiple detected barcodes
|
|
54
|
+
enum BarcodeScanStrategy: String {
|
|
55
|
+
case one = "ONE" // Process only the first barcode
|
|
56
|
+
case all = "ALL" // Process all detected barcodes
|
|
57
|
+
case biggest = "BIGGEST" // Process only the largest barcode by area
|
|
58
|
+
case sortByBiggest = "SORT_BY_BIGGEST" // Process all barcodes sorted by size
|
|
59
|
+
|
|
60
|
+
static var defaultStrategy: BarcodeScanStrategy { .all }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// MARK: - Frame Size
|
|
64
|
+
|
|
65
|
+
/// Size configuration for focus area frame
|
|
66
|
+
enum FrameSize {
|
|
67
|
+
case square(size: CGFloat)
|
|
68
|
+
case rectangle(width: CGFloat, height: CGFloat)
|
|
69
|
+
|
|
70
|
+
/// Get the CGSize representation
|
|
71
|
+
var size: CGSize {
|
|
72
|
+
switch self {
|
|
73
|
+
case .square(let size):
|
|
74
|
+
return CGSize(width: size, height: size)
|
|
75
|
+
case .rectangle(let width, let height):
|
|
76
|
+
return CGSize(width: width, height: height)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Create from React Native prop (number or object)
|
|
81
|
+
static func from(value: Any) -> FrameSize {
|
|
82
|
+
if let number = value as? NSNumber {
|
|
83
|
+
return .square(size: CGFloat(number.doubleValue))
|
|
84
|
+
} else if let dict = value as? [String: Any],
|
|
85
|
+
let width = dict["width"] as? NSNumber,
|
|
86
|
+
let height = dict["height"] as? NSNumber {
|
|
87
|
+
return .rectangle(width: CGFloat(width.doubleValue), height: CGFloat(height.doubleValue))
|
|
88
|
+
}
|
|
89
|
+
return .square(size: 300) // Default
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// MARK: - Focus Area Configuration
|
|
94
|
+
|
|
95
|
+
/// Configuration for the focus area overlay
|
|
96
|
+
struct FocusAreaConfig {
|
|
97
|
+
var enabled: Bool // Whether to restrict scanning to focus area only
|
|
98
|
+
var showOverlay: Bool // Whether to draw the focus area overlay
|
|
99
|
+
var size: FrameSize // Size of the focus area
|
|
100
|
+
var borderColor: UIColor // Color of the focus area border
|
|
101
|
+
var tintColor: UIColor // Color of the semi-transparent overlay
|
|
102
|
+
var position: CGPoint // Position as percentage (0-100)
|
|
103
|
+
|
|
104
|
+
/// Default configuration
|
|
105
|
+
static var defaultConfig: FocusAreaConfig {
|
|
106
|
+
return FocusAreaConfig(
|
|
107
|
+
enabled: false,
|
|
108
|
+
showOverlay: false,
|
|
109
|
+
size: .square(size: 300),
|
|
110
|
+
borderColor: .clear,
|
|
111
|
+
tintColor: UIColor.black.withAlphaComponent(0.5),
|
|
112
|
+
position: CGPoint(x: 50, y: 50)
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Create from React Native prop dictionary
|
|
117
|
+
static func from(dict: [String: Any]) -> FocusAreaConfig {
|
|
118
|
+
var config = defaultConfig
|
|
119
|
+
|
|
120
|
+
if let enabled = dict["enabled"] as? Bool {
|
|
121
|
+
config.enabled = enabled
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if let showOverlay = dict["showOverlay"] as? Bool {
|
|
125
|
+
config.showOverlay = showOverlay
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if let sizeValue = dict["size"] {
|
|
129
|
+
config.size = FrameSize.from(value: sizeValue)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if let borderColorStr = dict["borderColor"] as? String {
|
|
133
|
+
config.borderColor = UIColor(hexString: borderColorStr)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if let tintColorStr = dict["tintColor"] as? String {
|
|
137
|
+
// Match Android behavior: tintColor is treated as a base color with 50% opacity
|
|
138
|
+
// unless the user explicitly supplies an 8-digit ARGB value.
|
|
139
|
+
let trimmed = tintColorStr.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
|
140
|
+
let parsed = UIColor(hexString: tintColorStr)
|
|
141
|
+
if trimmed.count == 8 {
|
|
142
|
+
// ARGB includes alpha; respect it.
|
|
143
|
+
config.tintColor = parsed
|
|
144
|
+
} else {
|
|
145
|
+
// Force semi-transparent overlay like Android (alpha ~ 0.5)
|
|
146
|
+
config.tintColor = parsed.withAlphaComponent(0.5)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if let positionDict = dict["position"] as? [String: Any],
|
|
151
|
+
let x = positionDict["x"] as? NSNumber,
|
|
152
|
+
let y = positionDict["y"] as? NSNumber {
|
|
153
|
+
config.position = CGPoint(x: CGFloat(x.doubleValue), y: CGFloat(y.doubleValue))
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return config
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// MARK: - Barcode Frames Configuration
|
|
161
|
+
|
|
162
|
+
/// Configuration for barcode frame visualization
|
|
163
|
+
struct BarcodeFramesConfig {
|
|
164
|
+
var enabled: Bool // Whether to draw frames around detected barcodes
|
|
165
|
+
var color: UIColor // Color of barcode frames
|
|
166
|
+
var onlyInFocusArea: Bool // Only show frames for barcodes in focus area
|
|
167
|
+
|
|
168
|
+
/// Default configuration
|
|
169
|
+
static var defaultConfig: BarcodeFramesConfig {
|
|
170
|
+
return BarcodeFramesConfig(
|
|
171
|
+
enabled: false,
|
|
172
|
+
color: .yellow,
|
|
173
|
+
onlyInFocusArea: false
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/// Create from React Native prop dictionary
|
|
178
|
+
static func from(dict: [String: Any]) -> BarcodeFramesConfig {
|
|
179
|
+
var config = defaultConfig
|
|
180
|
+
|
|
181
|
+
if let enabled = dict["enabled"] as? Bool {
|
|
182
|
+
config.enabled = enabled
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if let colorStr = dict["color"] as? String {
|
|
186
|
+
config.color = UIColor(hexString: colorStr)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if let onlyInFocusArea = dict["onlyInFocusArea"] as? Bool {
|
|
190
|
+
config.onlyInFocusArea = onlyInFocusArea
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return config
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// MARK: - Barcode Detection Result
|
|
198
|
+
|
|
199
|
+
/// Detected barcode information
|
|
200
|
+
struct BarcodeDetectionResult {
|
|
201
|
+
let data: String // The scanned barcode data
|
|
202
|
+
let format: String // The format of the barcode
|
|
203
|
+
let timestamp: TimeInterval // Timestamp when scanned (milliseconds)
|
|
204
|
+
let boundingBox: CGRect? // Bounding box in view coordinates
|
|
205
|
+
let area: CGFloat? // Area of the barcode
|
|
206
|
+
|
|
207
|
+
/// Convert to dictionary for React Native event
|
|
208
|
+
func toDictionary() -> [String: Any] {
|
|
209
|
+
var dict: [String: Any] = [
|
|
210
|
+
"data": data,
|
|
211
|
+
"format": format,
|
|
212
|
+
"timestamp": timestamp
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
if let box = boundingBox {
|
|
216
|
+
dict["boundingBox"] = [
|
|
217
|
+
"left": box.minX,
|
|
218
|
+
"top": box.minY,
|
|
219
|
+
"right": box.maxX,
|
|
220
|
+
"bottom": box.maxY
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if let area = area {
|
|
225
|
+
dict["area"] = area
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return dict
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// Create from Vision barcode observation
|
|
232
|
+
static func from(observation: VNBarcodeObservation,
|
|
233
|
+
boundingBox: CGRect? = nil,
|
|
234
|
+
format: String? = nil) -> BarcodeDetectionResult? {
|
|
235
|
+
guard let payloadString = observation.payloadStringValue else { return nil }
|
|
236
|
+
|
|
237
|
+
let detectedFormat = format ?? observation.symbology.rawValue
|
|
238
|
+
let timestamp = Date().timeIntervalSince1970 * 1000 // Convert to milliseconds
|
|
239
|
+
|
|
240
|
+
let area = boundingBox.map { $0.width * $0.height }
|
|
241
|
+
|
|
242
|
+
return BarcodeDetectionResult(
|
|
243
|
+
data: payloadString,
|
|
244
|
+
format: detectedFormat,
|
|
245
|
+
timestamp: timestamp,
|
|
246
|
+
boundingBox: boundingBox,
|
|
247
|
+
area: area
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// MARK: - Barcode Frame Data
|
|
253
|
+
|
|
254
|
+
/// Data for a single barcode frame
|
|
255
|
+
struct BarcodeFrame {
|
|
256
|
+
let rect: CGRect
|
|
257
|
+
var lastSeenTime: Date
|
|
258
|
+
|
|
259
|
+
init(rect: CGRect, lastSeenTime: Date = Date()) {
|
|
260
|
+
self.rect = rect
|
|
261
|
+
self.lastSeenTime = lastSeenTime
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// MARK: - Scanner Error
|
|
266
|
+
|
|
267
|
+
/// Error information for scanner errors
|
|
268
|
+
struct ScannerError {
|
|
269
|
+
let error: String
|
|
270
|
+
let code: String
|
|
271
|
+
|
|
272
|
+
/// Convert to dictionary for React Native event
|
|
273
|
+
func toDictionary() -> [String: Any] {
|
|
274
|
+
return [
|
|
275
|
+
"error": error,
|
|
276
|
+
"code": code
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/// Common error codes
|
|
281
|
+
enum ErrorCode: String {
|
|
282
|
+
case cameraPermissionDenied = "CAMERA_PERMISSION_DENIED"
|
|
283
|
+
case cameraInitializationFailed = "CAMERA_INITIALIZATION_FAILED"
|
|
284
|
+
case cameraNotAvailable = "CAMERA_NOT_AVAILABLE"
|
|
285
|
+
case barcodeDetectionFailed = "BARCODE_DETECTION_FAILED"
|
|
286
|
+
case unknown = "UNKNOWN_ERROR"
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/// Create from error code
|
|
290
|
+
static func from(code: ErrorCode, message: String) -> ScannerError {
|
|
291
|
+
return ScannerError(error: message, code: code.rawValue)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// MARK: - Load Event
|
|
296
|
+
|
|
297
|
+
/// Load event payload
|
|
298
|
+
struct LoadEventPayload {
|
|
299
|
+
let success: Bool
|
|
300
|
+
let error: String?
|
|
301
|
+
|
|
302
|
+
/// Convert to dictionary for React Native event
|
|
303
|
+
func toDictionary() -> [String: Any] {
|
|
304
|
+
var dict: [String: Any] = ["success": success]
|
|
305
|
+
if let error = error {
|
|
306
|
+
dict["error"] = error
|
|
307
|
+
}
|
|
308
|
+
return dict
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// MARK: - UIColor Extension
|
|
313
|
+
|
|
314
|
+
extension UIColor {
|
|
315
|
+
/// Create UIColor from hex string
|
|
316
|
+
convenience init(hexString: String) {
|
|
317
|
+
let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
|
318
|
+
var int: UInt64 = 0
|
|
319
|
+
Scanner(string: hex).scanHexInt64(&int)
|
|
320
|
+
|
|
321
|
+
let a, r, g, b: UInt64
|
|
322
|
+
switch hex.count {
|
|
323
|
+
case 3: // RGB (12-bit)
|
|
324
|
+
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
|
|
325
|
+
case 6: // RGB (24-bit)
|
|
326
|
+
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
|
|
327
|
+
case 8: // ARGB (32-bit)
|
|
328
|
+
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
|
|
329
|
+
default:
|
|
330
|
+
(a, r, g, b) = (255, 0, 0, 0)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
self.init(
|
|
334
|
+
red: CGFloat(r) / 255,
|
|
335
|
+
green: CGFloat(g) / 255,
|
|
336
|
+
blue: CGFloat(b) / 255,
|
|
337
|
+
alpha: CGFloat(a) / 255
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Protocols.swift
|
|
3
|
+
// react-native-scanner
|
|
4
|
+
//
|
|
5
|
+
// Protocol definitions for scanner components
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import AVFoundation
|
|
10
|
+
import Vision
|
|
11
|
+
|
|
12
|
+
// MARK: - Scanner View Delegate
|
|
13
|
+
|
|
14
|
+
/// Delegate protocol for scanner events to be sent to React Native
|
|
15
|
+
@objc protocol ScannerViewDelegate: AnyObject {
|
|
16
|
+
/// Called when barcodes are detected
|
|
17
|
+
/// - Parameter barcodes: Array of detected barcode dictionaries
|
|
18
|
+
func scannerDidDetectBarcodes(_ barcodes: [[String: Any]])
|
|
19
|
+
|
|
20
|
+
/// Called when an error occurs
|
|
21
|
+
/// - Parameter error: Error information dictionary
|
|
22
|
+
func scannerDidEncounterError(_ error: [String: Any])
|
|
23
|
+
|
|
24
|
+
/// Called when the scanner is loaded and ready
|
|
25
|
+
/// - Parameter info: Load information dictionary
|
|
26
|
+
func scannerDidLoad(_ info: [String: Any])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// MARK: - Camera Manager Delegate
|
|
30
|
+
|
|
31
|
+
/// Delegate protocol for camera events
|
|
32
|
+
protocol CameraManagerDelegate: AnyObject {
|
|
33
|
+
/// Called when a new video frame is captured
|
|
34
|
+
/// - Parameters:
|
|
35
|
+
/// - manager: The camera manager
|
|
36
|
+
/// - sampleBuffer: The captured sample buffer
|
|
37
|
+
func cameraManager(_ manager: CameraManager, didOutput sampleBuffer: CMSampleBuffer)
|
|
38
|
+
|
|
39
|
+
/// Called when camera initialization fails
|
|
40
|
+
/// - Parameters:
|
|
41
|
+
/// - manager: The camera manager
|
|
42
|
+
/// - error: The error that occurred
|
|
43
|
+
func cameraManagerDidFail(_ manager: CameraManager, error: Error)
|
|
44
|
+
|
|
45
|
+
/// Called when camera successfully starts
|
|
46
|
+
/// - Parameter manager: The camera manager
|
|
47
|
+
func cameraManagerDidStart(_ manager: CameraManager)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// MARK: - Barcode Detection Delegate
|
|
51
|
+
|
|
52
|
+
/// Delegate protocol for barcode detection events
|
|
53
|
+
protocol BarcodeDetectionDelegate: AnyObject {
|
|
54
|
+
/// Called when barcodes are detected in a frame
|
|
55
|
+
/// - Parameters:
|
|
56
|
+
/// - manager: The detection manager
|
|
57
|
+
/// - observations: Array of barcode observations
|
|
58
|
+
func barcodeDetectionManager(_ manager: BarcodeDetectionManager,
|
|
59
|
+
didDetect observations: [VNBarcodeObservation])
|
|
60
|
+
|
|
61
|
+
/// Called when barcode detection fails
|
|
62
|
+
/// - Parameters:
|
|
63
|
+
/// - manager: The detection manager
|
|
64
|
+
/// - error: The error that occurred
|
|
65
|
+
func barcodeDetectionManager(_ manager: BarcodeDetectionManager,
|
|
66
|
+
didFailWith error: Error)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// MARK: - Barcode Frame Manager Delegate
|
|
70
|
+
|
|
71
|
+
/// Delegate protocol for barcode frame changes
|
|
72
|
+
protocol BarcodeFrameManagerDelegate: AnyObject {
|
|
73
|
+
/// Called when the active barcode frames change
|
|
74
|
+
/// - Parameters:
|
|
75
|
+
/// - manager: The frame manager
|
|
76
|
+
/// - frames: Array of active frame rectangles
|
|
77
|
+
func barcodeFrameManager(_ manager: BarcodeFrameManager,
|
|
78
|
+
didUpdateFrames frames: [CGRect])
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// MARK: - Camera Control Protocol
|
|
82
|
+
|
|
83
|
+
/// Protocol for camera control operations
|
|
84
|
+
protocol CameraControlProtocol {
|
|
85
|
+
/// Start the camera session
|
|
86
|
+
func startCamera()
|
|
87
|
+
|
|
88
|
+
/// Stop the camera session
|
|
89
|
+
func stopCamera()
|
|
90
|
+
|
|
91
|
+
/// Set torch/flashlight state
|
|
92
|
+
/// - Parameter enabled: Whether torch should be enabled
|
|
93
|
+
func setTorch(enabled: Bool)
|
|
94
|
+
|
|
95
|
+
/// Set zoom level
|
|
96
|
+
/// - Parameter level: The zoom level (clamped to device limits)
|
|
97
|
+
func setZoom(level: CGFloat)
|
|
98
|
+
|
|
99
|
+
/// Check if torch is available
|
|
100
|
+
/// - Returns: True if torch is available
|
|
101
|
+
func isTorchAvailable() -> Bool
|
|
102
|
+
|
|
103
|
+
/// Get the preview layer for displaying camera feed
|
|
104
|
+
/// - Returns: The AVCaptureVideoPreviewLayer
|
|
105
|
+
func getPreviewLayer() -> AVCaptureVideoPreviewLayer?
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// MARK: - Barcode Scanner Protocol
|
|
109
|
+
|
|
110
|
+
/// Protocol for barcode scanning operations
|
|
111
|
+
protocol BarcodeScannerProtocol {
|
|
112
|
+
/// Pause barcode scanning
|
|
113
|
+
func pauseScanning()
|
|
114
|
+
|
|
115
|
+
/// Resume barcode scanning
|
|
116
|
+
func resumeScanning()
|
|
117
|
+
|
|
118
|
+
/// Check if scanning is paused
|
|
119
|
+
/// - Returns: True if scanning is paused
|
|
120
|
+
func isScanningPaused() -> Bool
|
|
121
|
+
|
|
122
|
+
/// Set the barcode formats to detect
|
|
123
|
+
/// - Parameter formats: Array of barcode formats
|
|
124
|
+
func setBarcodeFormats(_ formats: [BarcodeFormat])
|
|
125
|
+
|
|
126
|
+
/// Set the scan strategy
|
|
127
|
+
/// - Parameter strategy: The scan strategy to use
|
|
128
|
+
func setScanStrategy(_ strategy: BarcodeScanStrategy)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// MARK: - Focus Area Protocol
|
|
132
|
+
|
|
133
|
+
/// Protocol for focus area operations
|
|
134
|
+
protocol FocusAreaProtocol {
|
|
135
|
+
/// Update focus area configuration
|
|
136
|
+
/// - Parameter config: The new configuration
|
|
137
|
+
func updateFocusArea(config: FocusAreaConfig)
|
|
138
|
+
|
|
139
|
+
/// Get the current focus area frame in view coordinates
|
|
140
|
+
/// - Returns: The focus area rectangle
|
|
141
|
+
func getFocusAreaFrame() -> CGRect?
|
|
142
|
+
|
|
143
|
+
/// Check if a point is within the focus area
|
|
144
|
+
/// - Parameter point: The point to check
|
|
145
|
+
/// - Returns: True if the point is within the focus area
|
|
146
|
+
func isPointInFocusArea(_ point: CGPoint) -> Bool
|
|
147
|
+
|
|
148
|
+
/// Check if a rectangle intersects or is contained in the focus area
|
|
149
|
+
/// - Parameter rect: The rectangle to check
|
|
150
|
+
/// - Returns: True if the rectangle intersects or is contained
|
|
151
|
+
func isRectInFocusArea(_ rect: CGRect) -> Bool
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// MARK: - Barcode Frame Display Protocol
|
|
155
|
+
|
|
156
|
+
/// Protocol for displaying barcode frames
|
|
157
|
+
protocol BarcodeFrameDisplayProtocol {
|
|
158
|
+
/// Update the barcode frames configuration
|
|
159
|
+
/// - Parameter config: The new configuration
|
|
160
|
+
func updateBarcodeFrames(config: BarcodeFramesConfig)
|
|
161
|
+
|
|
162
|
+
/// Set the barcode boxes to display
|
|
163
|
+
/// - Parameter boxes: Array of rectangles to display
|
|
164
|
+
func setBarcodeBoxes(_ boxes: [CGRect])
|
|
165
|
+
|
|
166
|
+
/// Clear all barcode boxes
|
|
167
|
+
func clearBarcodeBoxes()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// MARK: - Coordinate Transformation Protocol
|
|
171
|
+
|
|
172
|
+
/// Protocol for coordinate transformation operations
|
|
173
|
+
protocol CoordinateTransformationProtocol {
|
|
174
|
+
/// Transform Vision framework coordinates to view coordinates
|
|
175
|
+
/// - Parameters:
|
|
176
|
+
/// - visionRect: Rectangle in Vision coordinate space (normalized, bottom-left origin)
|
|
177
|
+
/// - viewSize: The size of the view
|
|
178
|
+
/// - previewLayer: The preview layer for additional transformation
|
|
179
|
+
/// - Returns: Rectangle in view coordinate space
|
|
180
|
+
static func transformVisionRectToViewRect(_ visionRect: CGRect,
|
|
181
|
+
viewSize: CGSize,
|
|
182
|
+
previewLayer: AVCaptureVideoPreviewLayer?) -> CGRect
|
|
183
|
+
|
|
184
|
+
/// Transform view coordinates to Vision framework coordinates
|
|
185
|
+
/// - Parameters:
|
|
186
|
+
/// - viewRect: Rectangle in view coordinate space
|
|
187
|
+
/// - viewSize: The size of the view
|
|
188
|
+
/// - previewLayer: The preview layer for additional transformation
|
|
189
|
+
/// - Returns: Rectangle in Vision coordinate space
|
|
190
|
+
static func transformViewRectToVisionRect(_ viewRect: CGRect,
|
|
191
|
+
viewSize: CGSize,
|
|
192
|
+
previewLayer: AVCaptureVideoPreviewLayer?) -> CGRect
|
|
193
|
+
}
|
|
194
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <React/RCTViewComponentView.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
#ifndef ScannerViewNativeComponent_h
|
|
5
|
+
#define ScannerViewNativeComponent_h
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
@interface ScannerView : RCTViewComponentView
|
|
10
|
+
@end
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_END
|
|
13
|
+
|
|
14
|
+
#endif /* ScannerViewNativeComponent_h */
|