@capgo/camera-preview 7.3.11 → 7.4.0-alpha.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.
Files changed (47) hide show
  1. package/CapgoCameraPreview.podspec +16 -13
  2. package/README.md +492 -73
  3. package/android/build.gradle +11 -0
  4. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  5. package/android/src/main/AndroidManifest.xml +5 -3
  6. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +968 -505
  7. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +3017 -0
  8. package/android/src/main/java/com/ahm/capacitor/camera/preview/GridOverlayView.java +119 -0
  9. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraDevice.java +63 -0
  10. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraLens.java +79 -0
  11. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraSessionConfiguration.java +167 -0
  12. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/LensInfo.java +40 -0
  13. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/ZoomFactors.java +35 -0
  14. package/dist/docs.json +1041 -161
  15. package/dist/esm/definitions.d.ts +484 -84
  16. package/dist/esm/definitions.js +10 -1
  17. package/dist/esm/definitions.js.map +1 -1
  18. package/dist/esm/web.d.ts +78 -3
  19. package/dist/esm/web.js +813 -68
  20. package/dist/esm/web.js.map +1 -1
  21. package/dist/plugin.cjs.js +819 -68
  22. package/dist/plugin.cjs.js.map +1 -1
  23. package/dist/plugin.js +819 -68
  24. package/dist/plugin.js.map +1 -1
  25. package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +1658 -0
  26. package/ios/Sources/CapgoCameraPreviewPlugin/GridOverlayView.swift +65 -0
  27. package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +1548 -0
  28. package/ios/Tests/CameraPreviewPluginTests/CameraPreviewPluginTests.swift +15 -0
  29. package/package.json +2 -2
  30. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraActivity.java +0 -1279
  31. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomSurfaceView.java +0 -29
  32. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomTextureView.java +0 -39
  33. package/android/src/main/java/com/ahm/capacitor/camera/preview/Preview.java +0 -461
  34. package/android/src/main/java/com/ahm/capacitor/camera/preview/TapGestureDetector.java +0 -24
  35. package/ios/Plugin/CameraController.swift +0 -809
  36. package/ios/Plugin/Info.plist +0 -24
  37. package/ios/Plugin/Plugin.h +0 -10
  38. package/ios/Plugin/Plugin.m +0 -18
  39. package/ios/Plugin/Plugin.swift +0 -511
  40. package/ios/Plugin.xcodeproj/project.pbxproj +0 -593
  41. package/ios/Plugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  42. package/ios/Plugin.xcworkspace/contents.xcworkspacedata +0 -10
  43. package/ios/Plugin.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  44. package/ios/PluginTests/Info.plist +0 -22
  45. package/ios/PluginTests/PluginTests.swift +0 -83
  46. package/ios/Podfile +0 -13
  47. package/ios/Podfile.lock +0 -23
@@ -1,24 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>CFBundleDevelopmentRegion</key>
6
- <string>$(DEVELOPMENT_LANGUAGE)</string>
7
- <key>CFBundleExecutable</key>
8
- <string>$(EXECUTABLE_NAME)</string>
9
- <key>CFBundleIdentifier</key>
10
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
- <key>CFBundleInfoDictionaryVersion</key>
12
- <string>6.0</string>
13
- <key>CFBundleName</key>
14
- <string>$(PRODUCT_NAME)</string>
15
- <key>CFBundlePackageType</key>
16
- <string>FMWK</string>
17
- <key>CFBundleShortVersionString</key>
18
- <string>1.0</string>
19
- <key>CFBundleVersion</key>
20
- <string>$(CURRENT_PROJECT_VERSION)</string>
21
- <key>NSPrincipalClass</key>
22
- <string></string>
23
- </dict>
24
- </plist>
@@ -1,10 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- //! Project version number for Plugin.
4
- FOUNDATION_EXPORT double PluginVersionNumber;
5
-
6
- //! Project version string for Plugin.
7
- FOUNDATION_EXPORT const unsigned char PluginVersionString[];
8
-
9
- // In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
10
-
@@ -1,18 +0,0 @@
1
- #import <Foundation/Foundation.h>
2
- #import <Capacitor/Capacitor.h>
3
-
4
- // Define the plugin using the CAP_PLUGIN Macro, and
5
- // each method the plugin supports using the CAP_PLUGIN_METHOD macro.
6
- CAP_PLUGIN(CameraPreview, "CameraPreview",
7
- CAP_PLUGIN_METHOD(start, CAPPluginReturnPromise);
8
- CAP_PLUGIN_METHOD(stop, CAPPluginReturnPromise);
9
- CAP_PLUGIN_METHOD(capture, CAPPluginReturnPromise);
10
- CAP_PLUGIN_METHOD(captureSample, CAPPluginReturnPromise);
11
- CAP_PLUGIN_METHOD(flip, CAPPluginReturnPromise);
12
- CAP_PLUGIN_METHOD(getSupportedFlashModes, CAPPluginReturnPromise);
13
- CAP_PLUGIN_METHOD(getHorizontalFov, CAPPluginReturnPromise);
14
- CAP_PLUGIN_METHOD(setFlashMode, CAPPluginReturnPromise);
15
- CAP_PLUGIN_METHOD(startRecordVideo, CAPPluginReturnPromise);
16
- CAP_PLUGIN_METHOD(stopRecordVideo, CAPPluginReturnPromise);
17
- CAP_PLUGIN_METHOD(getSupportedPictureSizes, CAPPluginReturnPromise);
18
- )
@@ -1,511 +0,0 @@
1
- import Foundation
2
- import Capacitor
3
- import AVFoundation
4
-
5
- extension UIWindow {
6
- static var isLandscape: Bool {
7
- if #available(iOS 13.0, *) {
8
- return UIApplication.shared.windows
9
- .first?
10
- .windowScene?
11
- .interfaceOrientation
12
- .isLandscape ?? false
13
- } else {
14
- return UIApplication.shared.statusBarOrientation.isLandscape
15
- }
16
- }
17
- static var isPortrait: Bool {
18
- if #available(iOS 13.0, *) {
19
- return UIApplication.shared.windows
20
- .first?
21
- .windowScene?
22
- .interfaceOrientation
23
- .isPortrait ?? false
24
- } else {
25
- return UIApplication.shared.statusBarOrientation.isPortrait
26
- }
27
- }
28
- }
29
-
30
- /**
31
- * Please read the Capacitor iOS Plugin Development Guide
32
- * here: https://capacitor.ionicframework.com/docs/plugins/ios
33
- */
34
- @objc(CameraPreview)
35
- public class CameraPreview: CAPPlugin, CAPBridgedPlugin {
36
- public let identifier = "CameraPreviewPlugin"
37
- public let jsName = "CameraPreview"
38
- public let pluginMethods: [CAPPluginMethod] = [
39
- CAPPluginMethod(name: "start", returnType: CAPPluginReturnPromise),
40
- CAPPluginMethod(name: "flip", returnType: CAPPluginReturnPromise),
41
- CAPPluginMethod(name: "stop", returnType: CAPPluginReturnPromise),
42
- CAPPluginMethod(name: "capture", returnType: CAPPluginReturnPromise),
43
- CAPPluginMethod(name: "captureSample", returnType: CAPPluginReturnPromise),
44
- CAPPluginMethod(name: "getSupportedFlashModes", returnType: CAPPluginReturnPromise),
45
- CAPPluginMethod(name: "getHorizontalFov", returnType: CAPPluginReturnPromise),
46
- CAPPluginMethod(name: "setFlashMode", returnType: CAPPluginReturnPromise),
47
- CAPPluginMethod(name: "startRecordVideo", returnType: CAPPluginReturnPromise),
48
- CAPPluginMethod(name: "stopRecordVideo", returnType: CAPPluginReturnPromise),
49
- CAPPluginMethod(name: "getTempFilePath", returnType: CAPPluginReturnPromise),
50
- CAPPluginMethod(name: "getSupportedPictureSizes", returnType: CAPPluginReturnPromise)
51
- ]
52
- // Camera state tracking
53
- private var isInitializing: Bool = false
54
- private var isInitialized: Bool = false
55
-
56
- var previewView: UIView!
57
- var cameraPosition = String()
58
- let cameraController = CameraController()
59
- var posX: CGFloat?
60
- var posY: CGFloat?
61
- var width: CGFloat?
62
- var height: CGFloat?
63
- var paddingBottom: CGFloat?
64
- var rotateWhenOrientationChanged: Bool?
65
- var toBack: Bool?
66
- var storeToFile: Bool?
67
- var enableZoom: Bool?
68
- var highResolutionOutput: Bool = false
69
- var disableAudio: Bool = false
70
-
71
- @objc func rotated() {
72
- guard let previewView = self.previewView,
73
- let posX = self.posX,
74
- let posY = self.posY,
75
- let width = self.width,
76
- let heightValue = self.height else {
77
- return
78
- }
79
- let paddingBottom = self.paddingBottom ?? 0
80
- let height = heightValue - paddingBottom
81
-
82
- if UIWindow.isLandscape {
83
- previewView.frame = CGRect(x: posY, y: posX, width: max(height, width), height: min(height, width))
84
- self.cameraController.previewLayer?.frame = previewView.frame
85
- }
86
-
87
- if UIWindow.isPortrait {
88
- previewView.frame = CGRect(x: posX, y: posY, width: min(height, width), height: max(height, width))
89
- self.cameraController.previewLayer?.frame = previewView.frame
90
- }
91
-
92
- if let connection = self.cameraController.fileVideoOutput?.connection(with: .video) {
93
- switch UIDevice.current.orientation {
94
- case .landscapeRight:
95
- connection.videoOrientation = .landscapeLeft
96
- case .landscapeLeft:
97
- connection.videoOrientation = .landscapeRight
98
- case .portrait:
99
- connection.videoOrientation = .portrait
100
- case .portraitUpsideDown:
101
- connection.videoOrientation = .portraitUpsideDown
102
- default:
103
- connection.videoOrientation = .portrait
104
- }
105
- }
106
-
107
- cameraController.updateVideoOrientation()
108
- }
109
-
110
- struct CameraInfo {
111
- let deviceID: String
112
- let position: String
113
- let pictureSizes: [CGSize]
114
- }
115
-
116
- func getSupportedPictureSizes() -> [CameraInfo] {
117
- var cameraInfos = [CameraInfo]()
118
-
119
- // Discover all available cameras
120
- let deviceTypes: [AVCaptureDevice.DeviceType] = [
121
- .builtInWideAngleCamera,
122
- .builtInTelephotoCamera,
123
- .builtInUltraWideCamera,
124
- .builtInTrueDepthCamera
125
- ]
126
-
127
- let session = AVCaptureDevice.DiscoverySession(
128
- deviceTypes: deviceTypes,
129
- mediaType: .video,
130
- position: .unspecified
131
- )
132
-
133
- let devices = session.devices
134
-
135
- for device in devices {
136
- // Determine the position of the camera
137
- var position = "Unknown"
138
- switch device.position {
139
- case .front:
140
- position = "Front"
141
- case .back:
142
- position = "Back"
143
- case .unspecified:
144
- position = "Unspecified"
145
- @unknown default:
146
- position = "Unknown"
147
- }
148
-
149
- var pictureSizes = [CGSize]()
150
-
151
- // Get supported formats
152
- for format in device.formats {
153
- let description = format.formatDescription
154
- let dimensions = CMVideoFormatDescriptionGetDimensions(description)
155
- let size = CGSize(width: CGFloat(dimensions.width), height: CGFloat(dimensions.height))
156
- if !pictureSizes.contains(size) {
157
- pictureSizes.append(size)
158
- }
159
- }
160
-
161
- // Sort sizes in descending order (largest to smallest)
162
- pictureSizes.sort { $0.width * $0.height > $1.width * $1.height }
163
-
164
- let cameraInfo = CameraInfo(deviceID: device.uniqueID, position: position, pictureSizes: pictureSizes)
165
- cameraInfos.append(cameraInfo)
166
- }
167
-
168
- return cameraInfos
169
- }
170
-
171
- @objc func getSupportedPictureSizes(_ call: CAPPluginCall) {
172
- let cameraInfos = getSupportedPictureSizes()
173
- call.resolve([
174
- "supportedPictureSizes": cameraInfos.map {
175
- return [
176
- "facing": $0.position,
177
- "supportedPictureSizes": $0.pictureSizes.map { size in
178
- return [
179
- "width": String(describing: size.width),
180
- "height": String(describing: size.height)
181
- ]
182
- }
183
- ]
184
- }
185
- ])
186
- }
187
-
188
- @objc func start(_ call: CAPPluginCall) {
189
- if self.isInitializing {
190
- call.reject("camera initialization in progress")
191
- return
192
- }
193
- if self.isInitialized {
194
- call.reject("camera already started")
195
- return
196
- }
197
- self.isInitializing = true
198
-
199
- self.cameraPosition = call.getString("position") ?? "rear"
200
- let cameraMode = call.getBool("cameraMode") ?? false
201
- self.highResolutionOutput = call.getBool("enableHighResolution") ?? false
202
- self.cameraController.highResolutionOutput = self.highResolutionOutput
203
-
204
- if call.getInt("width") != nil {
205
- self.width = CGFloat(call.getInt("width")!)
206
- } else {
207
- self.width = UIScreen.main.bounds.size.width
208
- }
209
- if call.getInt("height") != nil {
210
- self.height = CGFloat(call.getInt("height")!)
211
- } else {
212
- self.height = UIScreen.main.bounds.size.height
213
- }
214
- self.posX = call.getInt("x") != nil ? CGFloat(call.getInt("x")!)/UIScreen.main.scale: 0
215
- self.posY = call.getInt("y") != nil ? CGFloat(call.getInt("y")!) / (call.getBool("includeSafeAreaInsets") ?? false ? 1.0 : UIScreen.main.scale) + (call.getBool("includeSafeAreaInsets") ?? false ? UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0 : 0) : 0
216
- if call.getInt("paddingBottom") != nil {
217
- self.paddingBottom = CGFloat(call.getInt("paddingBottom")!)
218
- }
219
-
220
- self.rotateWhenOrientationChanged = call.getBool("rotateWhenOrientationChanged") ?? true
221
- self.toBack = call.getBool("toBack") ?? false
222
- self.storeToFile = call.getBool("storeToFile") ?? false
223
- self.enableZoom = call.getBool("enableZoom") ?? false
224
- self.disableAudio = call.getBool("disableAudio") ?? false
225
-
226
- AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
227
- guard granted else {
228
- call.reject("permission failed")
229
- return
230
- }
231
-
232
- DispatchQueue.main.async {
233
- if self.cameraController.captureSession?.isRunning ?? false {
234
- call.reject("camera already started")
235
- } else {
236
- self.cameraController.prepare(cameraPosition: self.cameraPosition, disableAudio: self.disableAudio, cameraMode: cameraMode) {error in
237
- if let error = error {
238
- print(error)
239
- call.reject(error.localizedDescription)
240
- return
241
- }
242
- let height = self.paddingBottom != nil ? self.height! - self.paddingBottom!: self.height!
243
- self.previewView = UIView(frame: CGRect(x: self.posX ?? 0, y: self.posY ?? 0, width: self.width!, height: height))
244
- self.webView?.isOpaque = false
245
- self.webView?.backgroundColor = UIColor.clear
246
- self.webView?.scrollView.backgroundColor = UIColor.clear
247
- self.webView?.superview?.addSubview(self.previewView)
248
- if self.toBack! {
249
- self.webView?.superview?.bringSubviewToFront(self.webView!)
250
- }
251
- try? self.cameraController.displayPreview(on: self.previewView)
252
-
253
- let frontView = self.toBack! ? self.webView : self.previewView
254
- self.cameraController.setupGestures(target: frontView ?? self.previewView, enableZoom: self.enableZoom!)
255
-
256
- if self.rotateWhenOrientationChanged == true {
257
- NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
258
- }
259
-
260
- self.isInitializing = false
261
- self.isInitialized = true
262
- call.resolve()
263
-
264
- }
265
- }
266
- }
267
- })
268
-
269
- }
270
-
271
- @objc func flip(_ call: CAPPluginCall) {
272
- guard isInitialized else {
273
- call.reject("Camera not initialized")
274
- return
275
- }
276
-
277
- DispatchQueue.main.async { [weak self] in
278
- guard let self = self else {
279
- call.reject("Camera controller deallocated")
280
- return
281
- }
282
-
283
- // Disable user interaction during flip
284
- self.previewView.isUserInteractionEnabled = false
285
-
286
- // Perform camera switch on background thread
287
- DispatchQueue.global(qos: .userInitiated).async {
288
- var retryCount = 0
289
- let maxRetries = 3
290
-
291
- func attemptFlip() {
292
- do {
293
- try self.cameraController.switchCameras()
294
-
295
- DispatchQueue.main.async {
296
- self.cameraController.previewLayer?.frame = self.previewView.bounds
297
- self.cameraController.previewLayer?.videoGravity = .resizeAspectFill
298
- self.previewView.isUserInteractionEnabled = true
299
- call.resolve()
300
- }
301
- } catch {
302
- retryCount += 1
303
-
304
- if retryCount < maxRetries {
305
- DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + 0.5) {
306
- attemptFlip()
307
- }
308
- } else {
309
- DispatchQueue.main.async {
310
- self.previewView.isUserInteractionEnabled = true
311
- print("Failed to flip camera after \(maxRetries) attempts: \(error.localizedDescription)")
312
- call.reject("Failed to flip camera: \(error.localizedDescription)")
313
- }
314
- }
315
- }
316
- }
317
-
318
- attemptFlip()
319
- }
320
- }
321
- }
322
-
323
- @objc func stop(_ call: CAPPluginCall) {
324
- DispatchQueue.main.async {
325
- if self.isInitializing {
326
- call.reject("cannot stop camera while initialization is in progress")
327
- return
328
- }
329
- if !self.isInitialized {
330
- call.reject("camera not initialized")
331
- return
332
- }
333
-
334
- // Always attempt to stop and clean up, regardless of captureSession state
335
- if let previewView = self.previewView {
336
- previewView.removeFromSuperview()
337
- self.previewView = nil
338
- }
339
-
340
- self.webView?.isOpaque = true
341
- self.isInitialized = false
342
- self.isInitializing = false
343
- self.cameraController.cleanup()
344
-
345
- call.resolve()
346
- }
347
- }
348
- // Get user's cache directory path
349
- @objc func getTempFilePath() -> URL {
350
- let path = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
351
- let identifier = UUID()
352
- let randomIdentifier = identifier.uuidString.replacingOccurrences(of: "-", with: "")
353
- let finalIdentifier = String(randomIdentifier.prefix(8))
354
- let fileName="cpcp_capture_"+finalIdentifier+".jpg"
355
- let fileUrl=path.appendingPathComponent(fileName)
356
- return fileUrl
357
- }
358
-
359
- @objc func capture(_ call: CAPPluginCall) {
360
- DispatchQueue.main.async {
361
-
362
- let quality: Int? = call.getInt("quality", 85)
363
-
364
- self.cameraController.captureImage { (image, error) in
365
-
366
- guard let image = image else {
367
- print(error ?? "Image capture error")
368
- guard let error = error else {
369
- call.reject("Image capture error")
370
- return
371
- }
372
- call.reject(error.localizedDescription)
373
- return
374
- }
375
- let imageData: Data?
376
- if self.cameraController.currentCameraPosition == .front {
377
- let flippedImage = image.withHorizontallyFlippedOrientation()
378
- imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality!/100))
379
- } else {
380
- imageData = image.jpegData(compressionQuality: CGFloat(quality!/100))
381
- }
382
-
383
- if self.storeToFile == false {
384
- let imageBase64 = imageData?.base64EncodedString()
385
- call.resolve(["value": imageBase64!])
386
- } else {
387
- do {
388
- let fileUrl=self.getTempFilePath()
389
- try imageData?.write(to: fileUrl)
390
- call.resolve(["value": fileUrl.absoluteString])
391
- } catch {
392
- call.reject("error writing image to file")
393
- }
394
- }
395
- }
396
- }
397
- }
398
-
399
- @objc func captureSample(_ call: CAPPluginCall) {
400
- DispatchQueue.main.async {
401
- let quality: Int? = call.getInt("quality", 85)
402
-
403
- self.cameraController.captureSample { image, error in
404
- guard let image = image else {
405
- print("Image capture error: \(String(describing: error))")
406
- call.reject("Image capture error: \(String(describing: error))")
407
- return
408
- }
409
-
410
- let imageData: Data?
411
- if self.cameraPosition == "front" {
412
- let flippedImage = image.withHorizontallyFlippedOrientation()
413
- imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality!/100))
414
- } else {
415
- imageData = image.jpegData(compressionQuality: CGFloat(quality!/100))
416
- }
417
-
418
- if self.storeToFile == false {
419
- let imageBase64 = imageData?.base64EncodedString()
420
- call.resolve(["value": imageBase64!])
421
- } else {
422
- do {
423
- let fileUrl = self.getTempFilePath()
424
- try imageData?.write(to: fileUrl)
425
- call.resolve(["value": fileUrl.absoluteString])
426
- } catch {
427
- call.reject("Error writing image to file")
428
- }
429
- }
430
- }
431
- }
432
- }
433
-
434
- @objc func getSupportedFlashModes(_ call: CAPPluginCall) {
435
- do {
436
- let supportedFlashModes = try self.cameraController.getSupportedFlashModes()
437
- call.resolve(["result": supportedFlashModes])
438
- } catch {
439
- call.reject("failed to get supported flash modes")
440
- }
441
- }
442
-
443
- @objc func getHorizontalFov(_ call: CAPPluginCall) {
444
- do {
445
- let horizontalFov = try self.cameraController.getHorizontalFov()
446
- call.resolve(["result": horizontalFov])
447
- } catch {
448
- call.reject("failed to get FOV")
449
- }
450
- }
451
-
452
- @objc func setFlashMode(_ call: CAPPluginCall) {
453
- guard let flashMode = call.getString("flashMode") else {
454
- call.reject("failed to set flash mode. required parameter flashMode is missing")
455
- return
456
- }
457
- do {
458
- var flashModeAsEnum: AVCaptureDevice.FlashMode?
459
- switch flashMode {
460
- case "off":
461
- flashModeAsEnum = AVCaptureDevice.FlashMode.off
462
- case "on":
463
- flashModeAsEnum = AVCaptureDevice.FlashMode.on
464
- case "auto":
465
- flashModeAsEnum = AVCaptureDevice.FlashMode.auto
466
- default: break
467
- }
468
- if flashModeAsEnum != nil {
469
- try self.cameraController.setFlashMode(flashMode: flashModeAsEnum!)
470
- } else if flashMode == "torch" {
471
- try self.cameraController.setTorchMode()
472
- } else {
473
- call.reject("Flash Mode not supported")
474
- return
475
- }
476
- call.resolve()
477
- } catch {
478
- call.reject("failed to set flash mode")
479
- }
480
- }
481
-
482
- @objc func startRecordVideo(_ call: CAPPluginCall) {
483
- DispatchQueue.main.async {
484
- do {
485
- try self.cameraController.captureVideo()
486
- call.resolve()
487
- } catch {
488
- call.reject(error.localizedDescription)
489
- }
490
- }
491
- }
492
-
493
- @objc func stopRecordVideo(_ call: CAPPluginCall) {
494
- DispatchQueue.main.async {
495
- self.cameraController.stopRecording { (fileURL, error) in
496
- guard let fileURL = fileURL else {
497
- print(error ?? "Video capture error")
498
- guard let error = error else {
499
- call.reject("Video capture error")
500
- return
501
- }
502
- call.reject(error.localizedDescription)
503
- return
504
- }
505
-
506
- call.resolve(["videoFilePath": fileURL.absoluteString])
507
- }
508
- }
509
- }
510
-
511
- }