@momo-kits/camerakit 0.161.1-beta.1 → 0.161.2-beta.16
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.
|
@@ -232,7 +232,7 @@ static id CKConvertFollyDynamicToId(const folly::dynamic &dyn)
|
|
|
232
232
|
}
|
|
233
233
|
id zoomMode = CKConvertFollyDynamicToId(newProps.zoomMode);
|
|
234
234
|
if (zoomMode != nil) {
|
|
235
|
-
_view.zoomMode = [
|
|
235
|
+
_view.zoomMode = [zoomMode isEqualToString:@"on"] ? CKZoomModeOn : CKZoomModeOff;
|
|
236
236
|
[changedProps addObject:@"zoomMode"];
|
|
237
237
|
}
|
|
238
238
|
id zoom = CKConvertFollyDynamicToId(newProps.zoom);
|
|
@@ -18,12 +18,8 @@ import Foundation
|
|
|
18
18
|
return CameraView()
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
@objc public static func capture(camera: CameraView,
|
|
22
|
-
|
|
23
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
24
|
-
reject: @escaping RCTPromiseRejectBlock) {
|
|
25
|
-
camera.capture(options as! [String: Any], onSuccess: { resolve($0) },
|
|
26
|
-
onError: { reject("capture_error", $0, nil) })
|
|
21
|
+
@objc public static func capture(camera: CameraView, options: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
22
|
+
camera.capture((options as? [String: Any]) ?? [:], onSuccess: { resolve($0) }, onError: { reject("capture_error", $0, nil) })
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
@objc public static func checkDeviceCameraAuthorizationStatus(_ resolve: @escaping RCTPromiseResolveBlock,
|
|
@@ -361,8 +361,8 @@ public class CameraView: UIView {
|
|
|
361
361
|
let features = detector?.features(in: ciImage)
|
|
362
362
|
|
|
363
363
|
if let firstFeature = features?.first as? CIQRCodeFeature {
|
|
364
|
-
if
|
|
365
|
-
self.onBarcodeRead(barcode:
|
|
364
|
+
if let messageString = firstFeature.messageString {
|
|
365
|
+
self.onBarcodeRead(barcode: messageString, codeFormat: CodeFormat.qr)
|
|
366
366
|
}
|
|
367
367
|
return
|
|
368
368
|
}
|
|
@@ -22,19 +22,19 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
22
22
|
|
|
23
23
|
private let cameraPreview = RealPreviewView(frame: .zero)
|
|
24
24
|
private let session = AVCaptureSession()
|
|
25
|
-
|
|
26
|
-
private let sessionQueue =
|
|
27
|
-
|
|
25
|
+
private static let sharedSessionQueue = DispatchQueue(label: "com.tesla.react-native-camera-kit.session")
|
|
26
|
+
private let sessionQueue = RealCamera.sharedSessionQueue
|
|
27
|
+
|
|
28
28
|
// utilities
|
|
29
29
|
private var setupResult: SetupResult = .notStarted
|
|
30
30
|
private var configurationDepth: Int = 0 // Tracks nested beginConfiguration/commitConfiguration calls
|
|
31
31
|
private var pendingStop: Bool = false // Queues stop request during configuration
|
|
32
32
|
private var backgroundRecordingId: UIBackgroundTaskIdentifier = .invalid
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
private var videoDeviceInput: AVCaptureDeviceInput?
|
|
35
35
|
private let photoOutput = AVCapturePhotoOutput()
|
|
36
36
|
private let metadataOutput = AVCaptureMetadataOutput()
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
private var resizeMode: ResizeMode = .cover
|
|
39
39
|
private var flashMode: FlashMode = .auto
|
|
40
40
|
private var torchMode: TorchMode = .off
|
|
@@ -49,25 +49,27 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
49
49
|
private var lastOnZoom: Double?
|
|
50
50
|
private var zoom: Double?
|
|
51
51
|
private var maxZoom: Double?
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
private var deviceOrientation = UIDeviceOrientation.unknown
|
|
54
54
|
private var motionManager: CMMotionManager?
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
// KVO observation
|
|
57
57
|
private var adjustingFocusObservation: NSKeyValueObservation?
|
|
58
58
|
|
|
59
|
+
private var notificationObservers: [NSObjectProtocol] = []
|
|
60
|
+
|
|
59
61
|
// Keep delegate objects in memory to avoid collecting them before photo capturing finishes
|
|
60
62
|
private var inProgressPhotoCaptureDelegates = [Int64: PhotoCaptureDelegate]()
|
|
61
|
-
|
|
63
|
+
|
|
62
64
|
private var onTextRead: ((_ text: String) -> Void)?
|
|
63
65
|
private let videoDataOutput = AVCaptureVideoDataOutput()
|
|
64
66
|
private var textRequest: VNRecognizeTextRequest?
|
|
65
67
|
private var textDetectionEnabled = false
|
|
66
68
|
private var lastTextProcess = Date.distantPast
|
|
67
69
|
private let textThrottle: TimeInterval = 0.35 // seconds
|
|
68
|
-
|
|
70
|
+
|
|
69
71
|
private var zoomStartedAt: Double = 1.0
|
|
70
|
-
|
|
72
|
+
|
|
71
73
|
// MARK: - Lifecycle
|
|
72
74
|
|
|
73
75
|
func cameraRemovedFromSuperview() {
|
|
@@ -93,7 +95,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
93
95
|
UIDevice.current.endGeneratingDeviceOrientationNotifications()
|
|
94
96
|
#endif
|
|
95
97
|
}
|
|
96
|
-
|
|
98
|
+
|
|
97
99
|
deinit {
|
|
98
100
|
removeObservers()
|
|
99
101
|
|
|
@@ -108,7 +110,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
|
-
|
|
113
|
+
|
|
112
114
|
// MARK: - Public
|
|
113
115
|
|
|
114
116
|
func setup(cameraType: CameraType, supportedBarcodeType: [CodeFormat]) {
|
|
@@ -222,7 +224,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
222
224
|
|
|
223
225
|
return .success
|
|
224
226
|
}
|
|
225
|
-
|
|
227
|
+
|
|
226
228
|
// MARK: - Pause / Resume non-essential outputs
|
|
227
229
|
|
|
228
230
|
/// Disables OCR + barcode work while a photo is captured.
|
|
@@ -259,14 +261,14 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
259
261
|
}
|
|
260
262
|
}
|
|
261
263
|
}
|
|
262
|
-
|
|
264
|
+
|
|
263
265
|
func zoomPinchStart() {
|
|
264
266
|
sessionQueue.async {
|
|
265
267
|
guard let videoDevice = self.videoDeviceInput?.device else { return }
|
|
266
268
|
self.zoomStartedAt = videoDevice.videoZoomFactor
|
|
267
269
|
}
|
|
268
270
|
}
|
|
269
|
-
|
|
271
|
+
|
|
270
272
|
func zoomPinchChange(pinchScale: CGFloat) {
|
|
271
273
|
guard !pinchScale.isNaN else { return }
|
|
272
274
|
|
|
@@ -275,7 +277,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
275
277
|
|
|
276
278
|
let desiredZoomFactor = (self.zoomStartedAt / self.defaultZoomFactor(for: videoDevice)) * pinchScale
|
|
277
279
|
let zoomForDevice = self.getValidZoom(forDevice: videoDevice, zoom: desiredZoomFactor)
|
|
278
|
-
|
|
280
|
+
|
|
279
281
|
if zoomForDevice != self.normalizedZoom(for: videoDevice) {
|
|
280
282
|
// Only trigger zoom changes if it's an uncontrolled component (zoom isn't manually set)
|
|
281
283
|
// otherwise it's likely to cause issues inf. loops
|
|
@@ -286,14 +288,14 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
290
|
}
|
|
289
|
-
|
|
291
|
+
|
|
290
292
|
func update(maxZoom: Double?) {
|
|
291
293
|
self.maxZoom = maxZoom
|
|
292
294
|
|
|
293
295
|
// Re-update zoom value in case the max was increased
|
|
294
296
|
self.update(zoom: self.zoom)
|
|
295
297
|
}
|
|
296
|
-
|
|
298
|
+
|
|
297
299
|
func update(zoom: Double?) {
|
|
298
300
|
sessionQueue.async {
|
|
299
301
|
self.zoom = zoom
|
|
@@ -304,7 +306,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
304
306
|
self.setZoomFor(videoDevice, to: zoomForDevice)
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
|
-
|
|
309
|
+
|
|
308
310
|
/**
|
|
309
311
|
`desiredZoom` can be nil when we want to notify what the zoom factor really is
|
|
310
312
|
*/
|
|
@@ -325,11 +327,11 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
325
327
|
lastOnZoom = desiredOrCameraZoom
|
|
326
328
|
self.onZoomCallback?(["zoom": desiredOrCameraZoom])
|
|
327
329
|
}
|
|
328
|
-
|
|
330
|
+
|
|
329
331
|
func update(onZoom: RCTDirectEventBlock?) {
|
|
330
332
|
self.onZoomCallback = onZoom
|
|
331
333
|
}
|
|
332
|
-
|
|
334
|
+
|
|
333
335
|
func focus(at touchPoint: CGPoint, focusBehavior: FocusBehavior) {
|
|
334
336
|
DispatchQueue.main.async {
|
|
335
337
|
let devicePoint = self.cameraPreview.previewLayer.captureDevicePointConverted(fromLayerPoint: touchPoint)
|
|
@@ -344,7 +346,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
344
346
|
self.resetFocus = nil
|
|
345
347
|
self.focusFinished = nil
|
|
346
348
|
}
|
|
347
|
-
|
|
349
|
+
|
|
348
350
|
do {
|
|
349
351
|
try videoDevice.lockForConfiguration()
|
|
350
352
|
|
|
@@ -367,11 +369,11 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
367
369
|
}
|
|
368
370
|
}
|
|
369
371
|
}
|
|
370
|
-
|
|
372
|
+
|
|
371
373
|
func update(onOrientationChange: RCTDirectEventBlock?) {
|
|
372
374
|
self.onOrientationChange = onOrientationChange
|
|
373
375
|
}
|
|
374
|
-
|
|
376
|
+
|
|
375
377
|
func update(torchMode: TorchMode) {
|
|
376
378
|
sessionQueue.async {
|
|
377
379
|
self.torchMode = torchMode
|
|
@@ -388,23 +390,23 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
388
390
|
}
|
|
389
391
|
}
|
|
390
392
|
}
|
|
391
|
-
|
|
393
|
+
|
|
392
394
|
func update(flashMode: FlashMode) {
|
|
393
395
|
self.flashMode = flashMode
|
|
394
396
|
}
|
|
395
|
-
|
|
397
|
+
|
|
396
398
|
func update(maxPhotoQualityPrioritization: MaxPhotoQualityPrioritization?) {
|
|
397
399
|
guard #available(iOS 13.0, *) else { return }
|
|
398
|
-
guard maxPhotoQualityPrioritization != self.maxPhotoQualityPrioritization else { return }
|
|
399
400
|
sessionQueue.async { [weak self] in
|
|
400
401
|
guard let self else { return }
|
|
402
|
+
guard maxPhotoQualityPrioritization != self.maxPhotoQualityPrioritization else { return }
|
|
401
403
|
self.beginConfiguration()
|
|
402
404
|
defer { self.commitConfiguration() }
|
|
403
405
|
self.maxPhotoQualityPrioritization = maxPhotoQualityPrioritization
|
|
404
406
|
self.photoOutput.maxPhotoQualityPrioritization = maxPhotoQualityPrioritization?.avQualityPrioritization ?? .balanced
|
|
405
407
|
}
|
|
406
408
|
}
|
|
407
|
-
|
|
409
|
+
|
|
408
410
|
func update(cameraType: CameraType) {
|
|
409
411
|
sessionQueue.async { [weak self] in
|
|
410
412
|
guard let self else { return }
|
|
@@ -426,7 +428,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
426
428
|
|
|
427
429
|
// Remove the existing device input first, since using the front and back camera simultaneously is not supported.
|
|
428
430
|
self.session.removeInput(currentViewDeviceInput)
|
|
429
|
-
|
|
431
|
+
|
|
430
432
|
if self.session.canAddInput(videoDeviceInput) {
|
|
431
433
|
self.session.addInput(videoDeviceInput)
|
|
432
434
|
self.resetZoom(forDevice: videoDevice)
|
|
@@ -435,14 +437,14 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
435
437
|
// If it fails, put back current camera
|
|
436
438
|
self.session.addInput(currentViewDeviceInput)
|
|
437
439
|
}
|
|
438
|
-
|
|
440
|
+
|
|
439
441
|
self.addObservers()
|
|
440
442
|
|
|
441
443
|
// We need to reapply the configuration after reloading the camera
|
|
442
444
|
self.update(torchMode: self.torchMode)
|
|
443
445
|
}
|
|
444
446
|
}
|
|
445
|
-
|
|
447
|
+
|
|
446
448
|
func update(resizeMode: ResizeMode) {
|
|
447
449
|
DispatchQueue.main.async {
|
|
448
450
|
switch resizeMode {
|
|
@@ -453,7 +455,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
453
455
|
}
|
|
454
456
|
}
|
|
455
457
|
}
|
|
456
|
-
|
|
458
|
+
|
|
457
459
|
func capturePicture(onWillCapture: @escaping () -> Void,
|
|
458
460
|
onSuccess: @escaping (_ imageData: Data, _ thumbnailData: Data?, _ dimensions: CMVideoDimensions) -> Void,
|
|
459
461
|
onError: @escaping (_ message: String) -> Void) {
|
|
@@ -462,36 +464,41 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
462
464
|
entering the session queue. Do this to ensure that UI elements are accessed on
|
|
463
465
|
the main thread and session configuration is done on the session queue.
|
|
464
466
|
*/
|
|
465
|
-
|
|
467
|
+
|
|
466
468
|
DispatchQueue.main.async { [weak self] in
|
|
467
469
|
guard let self = self else {
|
|
468
470
|
onError("Camera was deallocated")
|
|
469
471
|
return
|
|
470
472
|
}
|
|
471
|
-
|
|
473
|
+
|
|
472
474
|
let videoPreviewLayerOrientation =
|
|
473
475
|
self.videoOrientation(from: self.deviceOrientation) ?? self.cameraPreview.previewLayer.connection?.videoOrientation
|
|
474
|
-
|
|
476
|
+
|
|
475
477
|
self.sessionQueue.async { [weak self] in
|
|
476
478
|
guard let self = self else {
|
|
477
479
|
onError("Camera was deallocated")
|
|
478
480
|
return
|
|
479
481
|
}
|
|
480
482
|
|
|
483
|
+
guard self.inProgressPhotoCaptureDelegates.isEmpty else {
|
|
484
|
+
onError("Capture already in progress")
|
|
485
|
+
return
|
|
486
|
+
}
|
|
487
|
+
|
|
481
488
|
// Validate that the session is ready for photo capture
|
|
482
489
|
guard self.session.isRunning else {
|
|
483
490
|
print("Cannot capture photo: session is not running")
|
|
484
491
|
onError("Camera session is not running")
|
|
485
492
|
return
|
|
486
493
|
}
|
|
487
|
-
|
|
494
|
+
|
|
488
495
|
// Ensure photo output has an active video connection
|
|
489
496
|
guard let photoOutputConnection = self.photoOutput.connection(with: .video) else {
|
|
490
497
|
print("Cannot capture photo: no video connection available")
|
|
491
498
|
onError("Camera connection is not available")
|
|
492
499
|
return
|
|
493
500
|
}
|
|
494
|
-
|
|
501
|
+
|
|
495
502
|
// Verify the connection is active and enabled
|
|
496
503
|
guard photoOutputConnection.isActive && photoOutputConnection.isEnabled else {
|
|
497
504
|
print("Cannot capture photo: video connection is not active or enabled")
|
|
@@ -520,32 +527,30 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
520
527
|
with: settings,
|
|
521
528
|
onWillCapture: onWillCapture,
|
|
522
529
|
onCaptureSuccess: { [weak self] uniqueID, imageData, thumbnailData, dimensions in
|
|
523
|
-
|
|
524
|
-
self?.inProgressPhotoCaptureDelegates[uniqueID] = nil
|
|
530
|
+
self?.sessionQueue.async { self?.inProgressPhotoCaptureDelegates[uniqueID] = nil }
|
|
525
531
|
onSuccess(imageData, thumbnailData, dimensions)
|
|
526
532
|
self?.resumeNonEssentialOutputs()
|
|
527
533
|
},
|
|
528
534
|
onCaptureError: { [weak self] uniqueID, errorMessage in
|
|
529
|
-
|
|
530
|
-
self?.inProgressPhotoCaptureDelegates[uniqueID] = nil
|
|
535
|
+
self?.sessionQueue.async { self?.inProgressPhotoCaptureDelegates[uniqueID] = nil }
|
|
531
536
|
onError(errorMessage)
|
|
532
537
|
self?.resumeNonEssentialOutputs()
|
|
533
538
|
}
|
|
534
539
|
)
|
|
535
|
-
|
|
540
|
+
|
|
536
541
|
self.inProgressPhotoCaptureDelegates[photoCaptureDelegate.requestedPhotoSettings.uniqueID] = photoCaptureDelegate
|
|
537
542
|
self.photoOutput.capturePhoto(with: settings, delegate: photoCaptureDelegate)
|
|
538
543
|
}
|
|
539
544
|
}
|
|
540
545
|
}
|
|
541
|
-
|
|
546
|
+
|
|
542
547
|
// MARK: - Barcode scanning
|
|
543
548
|
func isBarcodeScannerEnabled(_ isEnabled: Bool,
|
|
544
549
|
supportedBarcodeTypes supportedBarcodeType: [CodeFormat],
|
|
545
550
|
onBarcodeRead: ((_ barcode: String,_ codeFormat:CodeFormat) -> Void)?) {
|
|
546
551
|
sessionQueue.async {
|
|
547
552
|
self.onBarcodeRead = onBarcodeRead
|
|
548
|
-
|
|
553
|
+
|
|
549
554
|
let availableTypes = self.metadataOutput.availableMetadataObjectTypes
|
|
550
555
|
let newTypes: [AVMetadataObject.ObjectType]
|
|
551
556
|
if isEnabled && onBarcodeRead != nil {
|
|
@@ -562,11 +567,11 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
562
567
|
}
|
|
563
568
|
}
|
|
564
569
|
}
|
|
565
|
-
|
|
570
|
+
|
|
566
571
|
func update(barcodeFrameSize: CGSize?) {
|
|
567
572
|
self.barcodeFrameSize = barcodeFrameSize
|
|
568
573
|
}
|
|
569
|
-
|
|
574
|
+
|
|
570
575
|
func update(scannerFrameSize: CGRect?) {
|
|
571
576
|
guard self.scannerFrameSize != scannerFrameSize else { return }
|
|
572
577
|
self.sessionQueue.async {
|
|
@@ -574,11 +579,11 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
574
579
|
if !self.session.isRunning {
|
|
575
580
|
return
|
|
576
581
|
}
|
|
577
|
-
|
|
582
|
+
|
|
578
583
|
DispatchQueue.main.async {
|
|
579
584
|
var visibleRect: CGRect?
|
|
580
|
-
if scannerFrameSize
|
|
581
|
-
visibleRect = self.cameraPreview.previewLayer.metadataOutputRectConverted(fromLayerRect: scannerFrameSize
|
|
585
|
+
if let scannerFrameSize, scannerFrameSize != .zero {
|
|
586
|
+
visibleRect = self.cameraPreview.previewLayer.metadataOutputRectConverted(fromLayerRect: scannerFrameSize)
|
|
582
587
|
}
|
|
583
588
|
|
|
584
589
|
self.sessionQueue.async {
|
|
@@ -593,7 +598,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
593
598
|
}
|
|
594
599
|
}
|
|
595
600
|
}
|
|
596
|
-
|
|
601
|
+
|
|
597
602
|
|
|
598
603
|
func isTextDetectionEnabled(_ isEnabled: Bool, onTextRead: ((String) -> Void)?) {
|
|
599
604
|
sessionQueue.async {
|
|
@@ -608,26 +613,26 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
608
613
|
self.textRequest?.recognitionLanguages = ["en", "fr", "de", "es", "vi"]
|
|
609
614
|
self.textRequest?.recognitionLevel = .accurate
|
|
610
615
|
self.textRequest?.usesLanguageCorrection = false
|
|
611
|
-
|
|
616
|
+
|
|
612
617
|
self.videoDataOutput.alwaysDiscardsLateVideoFrames = true
|
|
613
618
|
self.videoDataOutput.setSampleBufferDelegate(self, queue: globalOCRQueue)
|
|
614
619
|
self.videoDataOutput.videoSettings = [
|
|
615
620
|
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
|
|
616
621
|
]
|
|
617
|
-
|
|
622
|
+
|
|
618
623
|
} else {
|
|
619
624
|
self.textRequest = nil
|
|
620
625
|
}
|
|
621
626
|
}
|
|
622
627
|
}
|
|
623
|
-
|
|
628
|
+
|
|
624
629
|
// AVCaptureVideoDataOutputSampleBufferDelegate
|
|
625
630
|
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
|
626
631
|
guard textDetectionEnabled, let request = textRequest else { return }
|
|
627
632
|
let now = Date()
|
|
628
633
|
if now.timeIntervalSince(lastTextProcess) < textThrottle { return }
|
|
629
634
|
lastTextProcess = now
|
|
630
|
-
|
|
635
|
+
|
|
631
636
|
globalOCRQueue.async {
|
|
632
637
|
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
|
|
633
638
|
var requestOptions: [VNImageOption: Any] = [:]
|
|
@@ -640,7 +645,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
640
645
|
}
|
|
641
646
|
}
|
|
642
647
|
}
|
|
643
|
-
|
|
648
|
+
|
|
644
649
|
// MARK: - AVCaptureMetadataOutputObjectsDelegate
|
|
645
650
|
|
|
646
651
|
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
|
|
@@ -654,7 +659,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
654
659
|
|
|
655
660
|
onBarcodeRead?(codeStringValue,barcodeType)
|
|
656
661
|
}
|
|
657
|
-
|
|
662
|
+
|
|
658
663
|
// MARK: - Private
|
|
659
664
|
|
|
660
665
|
private func videoOrientation(from deviceOrientation: UIDeviceOrientation) -> AVCaptureVideoOrientation? {
|
|
@@ -673,7 +678,7 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
673
678
|
@unknown default: return nil
|
|
674
679
|
}
|
|
675
680
|
}
|
|
676
|
-
|
|
681
|
+
|
|
677
682
|
private func videoOrientation(from interfaceOrientation: UIInterfaceOrientation) -> AVCaptureVideoOrientation {
|
|
678
683
|
switch interfaceOrientation {
|
|
679
684
|
case .portrait:
|
|
@@ -688,14 +693,14 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
688
693
|
@unknown default: return .portrait
|
|
689
694
|
}
|
|
690
695
|
}
|
|
691
|
-
|
|
696
|
+
|
|
692
697
|
private func getBestDevice(for cameraType: CameraType) -> AVCaptureDevice? {
|
|
693
698
|
if let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: cameraType.avPosition) {
|
|
694
699
|
return device // single-lens/physical device
|
|
695
700
|
}
|
|
696
701
|
return nil
|
|
697
702
|
}
|
|
698
|
-
|
|
703
|
+
|
|
699
704
|
private func defaultZoomFactor(for videoDevice: AVCaptureDevice) -> CGFloat {
|
|
700
705
|
let fallback = 1.0
|
|
701
706
|
guard #available(iOS 13.0, *) else { return fallback }
|
|
@@ -756,7 +761,9 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
756
761
|
motionManager = CMMotionManager()
|
|
757
762
|
motionManager?.accelerometerUpdateInterval = 0.2
|
|
758
763
|
motionManager?.gyroUpdateInterval = 0.2
|
|
759
|
-
|
|
764
|
+
|
|
765
|
+
motionManager?.startAccelerometerUpdates(to: OperationQueue(), withHandler: { [weak self] (accelerometerData, error) -> Void in
|
|
766
|
+
guard let self else { return }
|
|
760
767
|
guard error == nil else {
|
|
761
768
|
print("\(error!)")
|
|
762
769
|
return
|
|
@@ -767,12 +774,13 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
767
774
|
}
|
|
768
775
|
|
|
769
776
|
guard let newOrientation = self.deviceOrientation(from: accelerometerData.acceleration),
|
|
770
|
-
newOrientation != self.deviceOrientation
|
|
777
|
+
newOrientation != self.deviceOrientation,
|
|
778
|
+
let orientation = Orientation(from: newOrientation) else {
|
|
771
779
|
return
|
|
772
780
|
}
|
|
773
781
|
|
|
774
782
|
self.deviceOrientation = newOrientation
|
|
775
|
-
self.onOrientationChange?(["orientation":
|
|
783
|
+
self.onOrientationChange?(["orientation": orientation.rawValue])
|
|
776
784
|
})
|
|
777
785
|
#endif
|
|
778
786
|
}
|
|
@@ -797,30 +805,34 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
797
805
|
// MARK: Private observers
|
|
798
806
|
|
|
799
807
|
private func addObservers() {
|
|
800
|
-
|
|
808
|
+
if adjustingFocusObservation == nil {
|
|
809
|
+
adjustingFocusObservation = videoDeviceInput?.device.observe(\.isAdjustingFocus,
|
|
810
|
+
options: .new,
|
|
811
|
+
changeHandler: { [weak self] _, change in
|
|
812
|
+
guard let self, let isFocusing = change.newValue else { return }
|
|
801
813
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
guard let self, let isFocusing = change.newValue else { return }
|
|
806
|
-
|
|
807
|
-
self.isAdjustingFocus(isFocusing: isFocusing)
|
|
808
|
-
})
|
|
814
|
+
self.isAdjustingFocus(isFocusing: isFocusing)
|
|
815
|
+
})
|
|
816
|
+
}
|
|
809
817
|
|
|
810
|
-
|
|
811
|
-
object: videoDeviceInput?.device,
|
|
812
|
-
queue: nil,
|
|
813
|
-
using: { [weak self] notification in self?.subjectAreaDidChange(notification: notification) })
|
|
814
|
-
NotificationCenter.default.addObserver(forName: .AVCaptureSessionRuntimeError,
|
|
815
|
-
object: session,
|
|
816
|
-
queue: nil,
|
|
817
|
-
using: { [weak self] notification in self?.sessionRuntimeError(notification: notification) })
|
|
818
|
+
guard notificationObservers.isEmpty else { return }
|
|
818
819
|
|
|
820
|
+
let subjectAreaToken = NotificationCenter.default.addObserver(
|
|
821
|
+
forName: .AVCaptureDeviceSubjectAreaDidChange,
|
|
822
|
+
object: videoDeviceInput?.device,
|
|
823
|
+
queue: nil,
|
|
824
|
+
using: { [weak self] notification in self?.subjectAreaDidChange(notification: notification) })
|
|
825
|
+
let runtimeErrorToken = NotificationCenter.default.addObserver(
|
|
826
|
+
forName: .AVCaptureSessionRuntimeError,
|
|
827
|
+
object: session,
|
|
828
|
+
queue: nil,
|
|
829
|
+
using: { [weak self] notification in self?.sessionRuntimeError(notification: notification) })
|
|
830
|
+
notificationObservers = [subjectAreaToken, runtimeErrorToken]
|
|
819
831
|
}
|
|
820
832
|
|
|
821
833
|
private func removeObservers() {
|
|
822
|
-
|
|
823
|
-
|
|
834
|
+
notificationObservers.forEach { NotificationCenter.default.removeObserver($0) }
|
|
835
|
+
notificationObservers.removeAll()
|
|
824
836
|
|
|
825
837
|
adjustingFocusObservation?.invalidate()
|
|
826
838
|
adjustingFocusObservation = nil
|
package/package.json
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
2
|
+
"name": "@momo-kits/camerakit",
|
|
3
|
+
"version": "0.161.2-beta.16",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/teslamotors/react-native-camera-kit.git"
|
|
7
|
+
},
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"registry": "https://registry.npmjs.org/"
|
|
10
|
+
},
|
|
11
|
+
"description": "A high performance, fully featured, rock solid camera library for React Native applications",
|
|
12
|
+
"nativePackage": true,
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "echo",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"lint": "yarn eslint -c .eslintrc.js"
|
|
17
|
+
},
|
|
18
|
+
"main": "./src/index.ts",
|
|
19
|
+
"dependencies": {},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"react": "19.0.0",
|
|
23
|
+
"react-native": "0.80.1"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": "*",
|
|
27
|
+
"react-native": "*"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"codegenConfig": {
|
|
33
|
+
"name": "rncamerakit_specs",
|
|
34
|
+
"type": "all",
|
|
35
|
+
"jsSrcsDir": "src/specs",
|
|
36
|
+
"android": {
|
|
37
|
+
"javaPackageName": "com.rncamerakit"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"packageManager": "yarn@1.22.22"
|
|
41
|
+
}
|