@momo-kits/camerakit 0.161.1-beta.1 → 0.161.2-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.
|
@@ -84,10 +84,10 @@ static id CKConvertFollyDynamicToId(const folly::dynamic &dyn)
|
|
|
84
84
|
- (void)prepareView
|
|
85
85
|
{
|
|
86
86
|
_view = [[CKCameraView alloc] init];
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
// just need to pass something, it won't really be used on fabric, but it's used to create events (it won't impact sending them)
|
|
89
89
|
_view.reactTag = @-1;
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
__weak __typeof__(self) weakSelf = self;
|
|
92
92
|
|
|
93
93
|
[_view setOnReadCode:^(NSDictionary* event) {
|
|
@@ -137,7 +137,7 @@ static id CKConvertFollyDynamicToId(const folly::dynamic &dyn)
|
|
|
137
137
|
std::dynamic_pointer_cast<const facebook::react::CKCameraEventEmitter>(strongSelf->_eventEmitter)->onMRZ({.docMRZ = docMRZ});
|
|
138
138
|
}
|
|
139
139
|
}];
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
self.contentView = _view;
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -251,8 +251,8 @@ static id CKConvertFollyDynamicToId(const folly::dynamic &dyn)
|
|
|
251
251
|
_view.barcodeFrameSize = @{@"width": @(barcodeWidth), @"height": @(barcodeHeight)};
|
|
252
252
|
[changedProps addObject:@"barcodeFrameSize"];
|
|
253
253
|
}
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
|
|
255
|
+
|
|
256
256
|
[super updateProps:props oldProps:oldProps];
|
|
257
257
|
[_view didSetProps:changedProps];
|
|
258
258
|
}
|
|
@@ -260,12 +260,6 @@ static id CKConvertFollyDynamicToId(const folly::dynamic &dyn)
|
|
|
260
260
|
- (void)prepareForRecycle
|
|
261
261
|
{
|
|
262
262
|
[super prepareForRecycle];
|
|
263
|
-
|
|
264
|
-
if (_view != nil) {
|
|
265
|
-
[_view removeFromSuperview];
|
|
266
|
-
_view = nil;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
263
|
[self prepareView];
|
|
270
264
|
}
|
|
271
265
|
|
|
@@ -71,16 +71,22 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
71
71
|
// MARK: - Lifecycle
|
|
72
72
|
|
|
73
73
|
func cameraRemovedFromSuperview() {
|
|
74
|
-
sessionQueue.async {
|
|
75
|
-
|
|
74
|
+
sessionQueue.async {
|
|
75
|
+
if self.setupResult == .success {
|
|
76
|
+
// Only stop if session is running
|
|
77
|
+
guard self.session.isRunning else {
|
|
78
|
+
self.removeObservers()
|
|
79
|
+
return
|
|
80
|
+
}
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
// If we're currently configuring the session, mark pending stop
|
|
83
|
+
// and let the configuration completion handle it
|
|
84
|
+
if self.configurationDepth > 0 {
|
|
85
|
+
self.pendingStop = true
|
|
86
|
+
return
|
|
87
|
+
}
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
// observers once the transaction commits; otherwise remove them now.
|
|
83
|
-
if !self.pendingStop {
|
|
89
|
+
self.session.stopRunning()
|
|
84
90
|
self.removeObservers()
|
|
85
91
|
}
|
|
86
92
|
}
|
|
@@ -96,117 +102,96 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
96
102
|
|
|
97
103
|
deinit {
|
|
98
104
|
removeObservers()
|
|
99
|
-
|
|
100
|
-
// Ensure the capture hardware is released even if cameraRemovedFromSuperview()
|
|
101
|
-
// was never delivered (e.g. a forced React surface cleanup during rapid
|
|
102
|
-
// mount/unmount). Capture only the session object so the block does not
|
|
103
|
-
// resurrect `self`.
|
|
104
|
-
let session = self.session
|
|
105
|
-
sessionQueue.async {
|
|
106
|
-
if session.isRunning {
|
|
107
|
-
session.stopRunning()
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
105
|
}
|
|
111
106
|
|
|
112
107
|
// MARK: - Public
|
|
113
108
|
|
|
114
109
|
func setup(cameraType: CameraType, supportedBarcodeType: [CodeFormat]) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// This is the root-cause fix for:
|
|
130
|
-
// "[AVCaptureSession startRunning] startRunning may not be called between
|
|
131
|
-
// calls to beginConfiguration and commitConfiguration".
|
|
132
|
-
self.setupResult = self.configureSession(cameraType: cameraType,
|
|
133
|
-
supportedBarcodeType: supportedBarcodeType)
|
|
134
|
-
|
|
135
|
-
guard self.setupResult == .success else { return }
|
|
136
|
-
|
|
137
|
-
// Order matches the previous behaviour: start, then observe, then torch.
|
|
138
|
-
self.startSessionIfNeeded()
|
|
139
|
-
self.addObservers()
|
|
140
|
-
self.update(torchMode: self.torchMode)
|
|
110
|
+
|
|
111
|
+
// Setup the capture session with priority on basic video preview first
|
|
112
|
+
sessionQueue.async {
|
|
113
|
+
self.setupResult = self.setupBasicVideoInput(cameraType: cameraType)
|
|
114
|
+
|
|
115
|
+
if self.setupResult == .success {
|
|
116
|
+
self.session.startRunning()
|
|
117
|
+
|
|
118
|
+
self.setupAdditionalOutputs(supportedBarcodeType: supportedBarcodeType)
|
|
119
|
+
|
|
120
|
+
self.addObservers()
|
|
121
|
+
|
|
122
|
+
self.update(torchMode: self.torchMode)
|
|
123
|
+
}
|
|
141
124
|
|
|
142
|
-
|
|
143
|
-
// AVCaptureVideoPreviewLayer to a session from the main thread is
|
|
144
|
-
// sanctioned by AVFoundation (see Apple's AVCam) and does NOT open a
|
|
145
|
-
// session configuration transaction, so it cannot race startRunning().
|
|
146
|
-
DispatchQueue.main.async { [weak self] in
|
|
147
|
-
guard let self else { return }
|
|
125
|
+
DispatchQueue.main.async {
|
|
148
126
|
self.cameraPreview.session = self.session
|
|
149
127
|
self.cameraPreview.previewLayer.videoGravity = .resizeAspectFill
|
|
128
|
+
self.session.sessionPreset = .photo
|
|
150
129
|
self.setVideoOrientationToInterfaceOrientation()
|
|
151
130
|
}
|
|
152
131
|
}
|
|
153
|
-
|
|
154
|
-
DispatchQueue.global(qos: .utility).async {
|
|
155
|
-
self
|
|
132
|
+
|
|
133
|
+
DispatchQueue.global(qos: .utility).async {
|
|
134
|
+
self.initializeMotionManager()
|
|
156
135
|
}
|
|
136
|
+
|
|
157
137
|
}
|
|
158
138
|
|
|
159
139
|
// MARK: - Private optimization methods
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
/// transaction. Must be called on `sessionQueue`. Order is significant:
|
|
163
|
-
/// beginConfiguration -> addInput -> set preset -> addOutputs -> commitConfiguration.
|
|
164
|
-
private func configureSession(cameraType: CameraType, supportedBarcodeType: [CodeFormat]) -> SetupResult {
|
|
165
|
-
assertOnSessionQueue()
|
|
140
|
+
|
|
141
|
+
private func setupBasicVideoInput(cameraType: CameraType) -> SetupResult {
|
|
166
142
|
guard let videoDevice = self.getBestDevice(for: cameraType),
|
|
167
143
|
let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice) else {
|
|
168
144
|
return .sessionConfigurationFailed
|
|
169
145
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
146
|
+
|
|
147
|
+
configurationDepth += 1
|
|
148
|
+
session.beginConfiguration()
|
|
149
|
+
defer {
|
|
150
|
+
session.commitConfiguration()
|
|
151
|
+
configurationDepth -= 1
|
|
152
|
+
handlePendingStopIfNeeded()
|
|
177
153
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// supported by every camera device; if it somehow is not, we keep whatever
|
|
185
|
-
// preset the session defaults to rather than crashing.
|
|
186
|
-
if session.canSetSessionPreset(.photo) {
|
|
187
|
-
session.sessionPreset = .photo
|
|
154
|
+
|
|
155
|
+
if session.canAddInput(videoDeviceInput) {
|
|
156
|
+
session.addInput(videoDeviceInput)
|
|
157
|
+
self.videoDeviceInput = videoDeviceInput
|
|
158
|
+
self.resetZoom(forDevice: videoDevice)
|
|
159
|
+
return .success
|
|
188
160
|
}
|
|
189
|
-
|
|
190
|
-
|
|
161
|
+
return .sessionConfigurationFailed
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private func setupAdditionalOutputs(supportedBarcodeType: [CodeFormat]) {
|
|
165
|
+
configurationDepth += 1
|
|
166
|
+
session.beginConfiguration()
|
|
167
|
+
defer {
|
|
168
|
+
session.commitConfiguration()
|
|
169
|
+
configurationDepth -= 1
|
|
170
|
+
handlePendingStopIfNeeded()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Add photo output
|
|
191
174
|
if #available(iOS 13.0, *) {
|
|
192
175
|
if let maxPhotoQualityPrioritization = maxPhotoQualityPrioritization {
|
|
193
176
|
photoOutput.maxPhotoQualityPrioritization = maxPhotoQualityPrioritization.avQualityPrioritization
|
|
194
177
|
}
|
|
195
178
|
}
|
|
179
|
+
|
|
196
180
|
if session.canAddOutput(photoOutput) {
|
|
197
181
|
session.addOutput(photoOutput)
|
|
198
|
-
|
|
199
|
-
if let photoOutputConnection = self.photoOutput.connection(with: .video)
|
|
200
|
-
|
|
201
|
-
|
|
182
|
+
|
|
183
|
+
if let photoOutputConnection = self.photoOutput.connection(with: .video) {
|
|
184
|
+
if photoOutputConnection.isVideoStabilizationSupported {
|
|
185
|
+
photoOutputConnection.preferredVideoStabilizationMode = .auto
|
|
186
|
+
}
|
|
202
187
|
}
|
|
203
188
|
}
|
|
204
|
-
|
|
205
|
-
//
|
|
189
|
+
|
|
190
|
+
// Add metadata output for barcode scanning
|
|
206
191
|
if self.session.canAddOutput(metadataOutput) {
|
|
207
192
|
self.session.addOutput(metadataOutput)
|
|
208
193
|
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
|
|
209
|
-
|
|
194
|
+
|
|
210
195
|
let availableTypes = self.metadataOutput.availableMetadataObjectTypes
|
|
211
196
|
let filteredTypes = supportedBarcodeType
|
|
212
197
|
.map { $0.toAVMetadataObjectType() }
|
|
@@ -214,49 +199,29 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
214
199
|
|
|
215
200
|
metadataOutput.metadataObjectTypes = filteredTypes
|
|
216
201
|
}
|
|
217
|
-
|
|
218
|
-
//
|
|
219
|
-
if textRequest != nil && self.session.canAddOutput(self.videoDataOutput) {
|
|
202
|
+
|
|
203
|
+
// add for text detections
|
|
204
|
+
if (textRequest != nil && self.session.canAddOutput(self.videoDataOutput)) {
|
|
220
205
|
self.session.addOutput(self.videoDataOutput)
|
|
221
206
|
}
|
|
222
|
-
|
|
223
|
-
return .success
|
|
224
207
|
}
|
|
225
208
|
|
|
226
209
|
// MARK: - Pause / Resume non-essential outputs
|
|
227
|
-
|
|
228
|
-
/// Disables OCR + barcode work while a photo is captured.
|
|
229
|
-
/// MUST be called on `sessionQueue` (these are capture-output mutations).
|
|
230
210
|
private func pauseNonEssentialOutputs() {
|
|
231
|
-
assertOnSessionQueue()
|
|
232
211
|
videoDataOutput.setSampleBufferDelegate(nil, queue: nil)
|
|
233
212
|
metadataOutput.rectOfInterest = CGRect(x: 0, y: 0, width: 0, height: 0)
|
|
234
213
|
}
|
|
235
|
-
|
|
236
|
-
/// Re-enables OCR + barcode work after a capture. May be called from any
|
|
237
|
-
/// thread (photo-capture completion handlers run on an arbitrary queue), so it
|
|
238
|
-
/// hops to the main queue only to read preview-layer geometry and applies all
|
|
239
|
-
/// output mutations back on `sessionQueue`.
|
|
214
|
+
|
|
240
215
|
private func resumeNonEssentialOutputs() {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// metadataOutputRectConverted must be read on the main thread.
|
|
253
|
-
DispatchQueue.main.async { [weak self] in
|
|
254
|
-
guard let self else { return }
|
|
255
|
-
let rect = self.cameraPreview.previewLayer.metadataOutputRectConverted(fromLayerRect: scanner)
|
|
256
|
-
self.sessionQueue.async { [weak self] in
|
|
257
|
-
self?.metadataOutput.rectOfInterest = rect
|
|
258
|
-
}
|
|
259
|
-
}
|
|
216
|
+
if textDetectionEnabled {
|
|
217
|
+
videoDataOutput.setSampleBufferDelegate(self, queue: globalOCRQueue)
|
|
218
|
+
}
|
|
219
|
+
// Restore real rect of interest
|
|
220
|
+
if let scanner = scannerFrameSize, scanner != .zero {
|
|
221
|
+
metadataOutput.rectOfInterest =
|
|
222
|
+
cameraPreview.previewLayer.metadataOutputRectConverted(fromLayerRect: scanner)
|
|
223
|
+
} else {
|
|
224
|
+
metadataOutput.rectOfInterest = CGRect(x: 0, y: 0, width: 1, height: 1)
|
|
260
225
|
}
|
|
261
226
|
}
|
|
262
227
|
|
|
@@ -396,18 +361,21 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
396
361
|
func update(maxPhotoQualityPrioritization: MaxPhotoQualityPrioritization?) {
|
|
397
362
|
guard #available(iOS 13.0, *) else { return }
|
|
398
363
|
guard maxPhotoQualityPrioritization != self.maxPhotoQualityPrioritization else { return }
|
|
399
|
-
sessionQueue.async {
|
|
400
|
-
|
|
401
|
-
self.beginConfiguration()
|
|
402
|
-
defer {
|
|
364
|
+
sessionQueue.async {
|
|
365
|
+
self.configurationDepth += 1
|
|
366
|
+
self.session.beginConfiguration()
|
|
367
|
+
defer {
|
|
368
|
+
self.session.commitConfiguration()
|
|
369
|
+
self.configurationDepth -= 1
|
|
370
|
+
self.handlePendingStopIfNeeded()
|
|
371
|
+
}
|
|
403
372
|
self.maxPhotoQualityPrioritization = maxPhotoQualityPrioritization
|
|
404
373
|
self.photoOutput.maxPhotoQualityPrioritization = maxPhotoQualityPrioritization?.avQualityPrioritization ?? .balanced
|
|
405
374
|
}
|
|
406
375
|
}
|
|
407
376
|
|
|
408
377
|
func update(cameraType: CameraType) {
|
|
409
|
-
sessionQueue.async {
|
|
410
|
-
guard let self else { return }
|
|
378
|
+
sessionQueue.async {
|
|
411
379
|
if self.videoDeviceInput?.device.position == cameraType.avPosition {
|
|
412
380
|
return
|
|
413
381
|
}
|
|
@@ -419,10 +387,15 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
419
387
|
let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice) else {
|
|
420
388
|
return
|
|
421
389
|
}
|
|
422
|
-
|
|
390
|
+
|
|
423
391
|
self.removeObservers()
|
|
424
|
-
self.
|
|
425
|
-
|
|
392
|
+
self.configurationDepth += 1
|
|
393
|
+
self.session.beginConfiguration()
|
|
394
|
+
defer {
|
|
395
|
+
self.session.commitConfiguration()
|
|
396
|
+
self.configurationDepth -= 1
|
|
397
|
+
self.handlePendingStopIfNeeded()
|
|
398
|
+
}
|
|
426
399
|
|
|
427
400
|
// Remove the existing device input first, since using the front and back camera simultaneously is not supported.
|
|
428
401
|
self.session.removeInput(currentViewDeviceInput)
|
|
@@ -463,6 +436,9 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
463
436
|
the main thread and session configuration is done on the session queue.
|
|
464
437
|
*/
|
|
465
438
|
|
|
439
|
+
// Pause OCR + barcode before capturing
|
|
440
|
+
self.pauseNonEssentialOutputs()
|
|
441
|
+
|
|
466
442
|
DispatchQueue.main.async { [weak self] in
|
|
467
443
|
guard let self = self else {
|
|
468
444
|
onError("Camera was deallocated")
|
|
@@ -504,9 +480,6 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
504
480
|
photoOutputConnection.videoOrientation = videoPreviewLayerOrientation
|
|
505
481
|
}
|
|
506
482
|
|
|
507
|
-
// Pause OCR + barcode work on the session queue, right before capture.
|
|
508
|
-
self.pauseNonEssentialOutputs()
|
|
509
|
-
|
|
510
483
|
let settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
|
|
511
484
|
if #available(iOS 13.0, *) {
|
|
512
485
|
settings.photoQualityPrioritization = self.photoOutput.maxPhotoQualityPrioritization
|
|
@@ -856,99 +829,39 @@ class RealCamera: NSObject, CameraProtocol, AVCaptureMetadataOutputObjectsDelega
|
|
|
856
829
|
|
|
857
830
|
print("Capture session runtime error: \(error)")
|
|
858
831
|
|
|
859
|
-
// Automatically try to restart the session if media services were reset
|
|
860
|
-
// (After a reset the session is NOT running, so the restart is routed
|
|
861
|
-
// through the guarded helper, which only starts when it is safe to.)
|
|
832
|
+
// Automatically try to restart the session running if media services were reset
|
|
862
833
|
if error.code == .mediaServicesWereReset {
|
|
863
|
-
sessionQueue.async {
|
|
864
|
-
self
|
|
834
|
+
sessionQueue.async {
|
|
835
|
+
if self.session.isRunning {
|
|
836
|
+
self.session.startRunning()
|
|
837
|
+
}
|
|
865
838
|
}
|
|
866
839
|
}
|
|
867
840
|
}
|
|
868
841
|
|
|
869
842
|
func startCamera() {
|
|
870
|
-
sessionQueue.async {
|
|
871
|
-
self
|
|
843
|
+
self.sessionQueue.async {
|
|
844
|
+
if !self.session.isRunning {
|
|
845
|
+
self.session.startRunning()
|
|
846
|
+
}
|
|
872
847
|
}
|
|
873
848
|
}
|
|
874
849
|
|
|
875
850
|
func stopCamera() {
|
|
876
|
-
sessionQueue.async {
|
|
877
|
-
self
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
// MARK: - Session configuration transaction helpers
|
|
882
|
-
|
|
883
|
-
/// Debug-only tripwire enforcing the core invariant of this class: EVERY
|
|
884
|
-
/// AVCaptureSession mutation and start/stop happens on `sessionQueue`. The whole
|
|
885
|
-
/// "startRunning may not be called between beginConfiguration and
|
|
886
|
-
/// commitConfiguration" crash class is prevented precisely because nothing
|
|
887
|
-
/// touches the session off this serial queue. If a future change — or an
|
|
888
|
-
/// external caller such as a mini-app native bridge — ever reaches one of these
|
|
889
|
-
/// methods on the wrong queue, this fails loudly in DEBUG/QA instead of
|
|
890
|
-
/// crashing randomly in production. Compiled out of release builds, so it can
|
|
891
|
-
/// never add a production crash.
|
|
892
|
-
private func assertOnSessionQueue() {
|
|
893
|
-
#if DEBUG
|
|
894
|
-
dispatchPrecondition(condition: .onQueue(sessionQueue))
|
|
895
|
-
#endif
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
/// Opens a session configuration transaction and tracks nesting depth.
|
|
899
|
-
/// MUST be balanced by `commitConfiguration()` (use `defer`) and MUST run on
|
|
900
|
-
/// `sessionQueue`.
|
|
901
|
-
private func beginConfiguration() {
|
|
902
|
-
assertOnSessionQueue()
|
|
903
|
-
configurationDepth += 1
|
|
904
|
-
session.beginConfiguration()
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
/// Closes a session configuration transaction and flushes a stop that was
|
|
908
|
-
/// requested while the transaction was open. MUST run on `sessionQueue`.
|
|
909
|
-
private func commitConfiguration() {
|
|
910
|
-
assertOnSessionQueue()
|
|
911
|
-
session.commitConfiguration()
|
|
912
|
-
configurationDepth -= 1
|
|
913
|
-
handlePendingStopIfNeeded()
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
/// Starts the session only when it is safe to do so. MUST run on `sessionQueue`.
|
|
917
|
-
/// Because every begin/commit pair is synchronous on the serial session queue,
|
|
918
|
-
/// `configurationDepth` is always 0 at the start of a fresh queue block — the
|
|
919
|
-
/// depth check is therefore defence-in-depth against ever calling this from
|
|
920
|
-
/// inside an open transaction.
|
|
921
|
-
private func startSessionIfNeeded() {
|
|
922
|
-
assertOnSessionQueue()
|
|
923
|
-
guard setupResult == .success,
|
|
924
|
-
configurationDepth == 0,
|
|
925
|
-
!pendingStop,
|
|
926
|
-
!session.isRunning else {
|
|
927
|
-
return
|
|
928
|
-
}
|
|
929
|
-
session.startRunning()
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
/// Stops the session, deferring until the current transaction commits if one
|
|
933
|
-
/// is open. MUST run on `sessionQueue`.
|
|
934
|
-
private func stopSessionIfNeeded() {
|
|
935
|
-
assertOnSessionQueue()
|
|
936
|
-
guard session.isRunning else { return }
|
|
937
|
-
if configurationDepth > 0 {
|
|
938
|
-
pendingStop = true
|
|
939
|
-
return
|
|
851
|
+
self.sessionQueue.async {
|
|
852
|
+
if self.session.isRunning {
|
|
853
|
+
self.session.stopRunning()
|
|
854
|
+
}
|
|
940
855
|
}
|
|
941
|
-
session.stopRunning()
|
|
942
856
|
}
|
|
943
857
|
|
|
944
858
|
// MARK: - Private helper for safe session stop
|
|
945
|
-
|
|
859
|
+
|
|
946
860
|
private func handlePendingStopIfNeeded() {
|
|
947
861
|
// Must be called on sessionQueue after configuration completes
|
|
948
|
-
assertOnSessionQueue()
|
|
949
862
|
// Only execute if all configurations are done (depth == 0)
|
|
950
863
|
guard configurationDepth == 0 && pendingStop else { return }
|
|
951
|
-
|
|
864
|
+
|
|
952
865
|
pendingStop = false
|
|
953
866
|
if session.isRunning {
|
|
954
867
|
session.stopRunning()
|
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.1",
|
|
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
|
+
}
|