@capgo/camera-preview 8.8.1 → 8.9.0

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.
@@ -623,7 +623,10 @@ extension CameraController {
623
623
  self.photoOutput?.isHighResolutionCaptureEnabled = true
624
624
 
625
625
  // Create video output
626
- self.fileVideoOutput = AVCaptureMovieFileOutput()
626
+ let movieFileOutput = AVCaptureMovieFileOutput()
627
+ // MP4 does not support movie fragments; the default 10s interval drops the final partial segment on stop.
628
+ movieFileOutput.movieFragmentInterval = .invalid
629
+ self.fileVideoOutput = movieFileOutput
627
630
 
628
631
  // Create data output for preview
629
632
  self.dataOutput = AVCaptureVideoDataOutput()
@@ -1004,6 +1007,10 @@ extension CameraController {
1004
1007
  finalDevice.exposurePointOfInterest = CGPoint(x: 0.5, y: 0.5)
1005
1008
  }
1006
1009
  }
1010
+ // Default white balance to continuous auto (prevents a warm/yellow cast)
1011
+ if finalDevice.isWhiteBalanceModeSupported(.continuousAutoWhiteBalance) {
1012
+ finalDevice.whiteBalanceMode = .continuousAutoWhiteBalance
1013
+ }
1007
1014
  // Reset exposure compensation so sessions start neutral
1008
1015
  let minBias = finalDevice.minExposureTargetBias
1009
1016
  let maxBias = finalDevice.maxExposureTargetBias
@@ -2721,6 +2728,100 @@ extension CameraController {
2721
2728
  }
2722
2729
  }
2723
2730
 
2731
+ // MARK: - White Balance Controls
2732
+
2733
+ func getWhiteBalanceModes() throws -> [String] {
2734
+ var currentCamera: AVCaptureDevice?
2735
+ switch currentCameraPosition {
2736
+ case .front:
2737
+ currentCamera = self.frontCamera
2738
+ case .rear:
2739
+ currentCamera = self.rearCamera
2740
+ default:
2741
+ break
2742
+ }
2743
+
2744
+ guard let device = currentCamera else {
2745
+ throw CameraControllerError.noCamerasAvailable
2746
+ }
2747
+
2748
+ var modes: [String] = []
2749
+ if device.isWhiteBalanceModeSupported(.locked) { modes.append("LOCK") }
2750
+ if device.isWhiteBalanceModeSupported(.autoWhiteBalance) { modes.append("AUTO") }
2751
+ if device.isWhiteBalanceModeSupported(.continuousAutoWhiteBalance) { modes.append("CONTINUOUS") }
2752
+ return modes
2753
+ }
2754
+
2755
+ func getWhiteBalanceMode() throws -> String {
2756
+ var currentCamera: AVCaptureDevice?
2757
+ switch currentCameraPosition {
2758
+ case .front:
2759
+ currentCamera = self.frontCamera
2760
+ case .rear:
2761
+ currentCamera = self.rearCamera
2762
+ default:
2763
+ break
2764
+ }
2765
+
2766
+ guard let device = currentCamera else {
2767
+ throw CameraControllerError.noCamerasAvailable
2768
+ }
2769
+
2770
+ switch device.whiteBalanceMode {
2771
+ case .locked:
2772
+ return "LOCK"
2773
+ case .autoWhiteBalance:
2774
+ return "AUTO"
2775
+ case .continuousAutoWhiteBalance:
2776
+ return "CONTINUOUS"
2777
+ @unknown default:
2778
+ return "CONTINUOUS"
2779
+ }
2780
+ }
2781
+
2782
+ func setWhiteBalanceMode(mode: String) throws {
2783
+ var currentCamera: AVCaptureDevice?
2784
+ switch currentCameraPosition {
2785
+ case .front:
2786
+ currentCamera = self.frontCamera
2787
+ case .rear:
2788
+ currentCamera = self.rearCamera
2789
+ default:
2790
+ break
2791
+ }
2792
+
2793
+ guard let device = currentCamera else {
2794
+ throw CameraControllerError.noCamerasAvailable
2795
+ }
2796
+
2797
+ let normalized = mode.uppercased()
2798
+ let desiredMode: AVCaptureDevice.WhiteBalanceMode?
2799
+ switch normalized {
2800
+ case "LOCK":
2801
+ desiredMode = .locked
2802
+ case "AUTO":
2803
+ desiredMode = .autoWhiteBalance
2804
+ case "CONTINUOUS":
2805
+ desiredMode = .continuousAutoWhiteBalance
2806
+ case "CUSTOM":
2807
+ throw CameraControllerError.invalidOperation
2808
+ default:
2809
+ throw CameraControllerError.invalidOperation
2810
+ }
2811
+
2812
+ guard let finalMode = desiredMode, device.isWhiteBalanceModeSupported(finalMode) else {
2813
+ throw CameraControllerError.invalidOperation
2814
+ }
2815
+
2816
+ do {
2817
+ try device.lockForConfiguration()
2818
+ device.whiteBalanceMode = finalMode
2819
+ device.unlockForConfiguration()
2820
+ } catch {
2821
+ throw CameraControllerError.invalidOperation
2822
+ }
2823
+ }
2824
+
2724
2825
  private func activeVideoDevice() -> AVCaptureDevice? {
2725
2826
  switch currentCameraPosition {
2726
2827
  case .front:
@@ -35,7 +35,7 @@ extension UIWindow {
35
35
  */
36
36
  @objc(CameraPreview)
37
37
  public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelegate {
38
- private let pluginVersion: String = "8.8.1"
38
+ private let pluginVersion: String = "8.9.0"
39
39
  public let identifier = "CameraPreviewPlugin"
40
40
  public let jsName = "CameraPreview"
41
41
  public let pluginMethods: [CAPPluginMethod] = [
@@ -90,6 +90,9 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
90
90
  CAPPluginMethod(name: "getExposureCompensationRange", returnType: CAPPluginReturnPromise),
91
91
  CAPPluginMethod(name: "getExposureCompensation", returnType: CAPPluginReturnPromise),
92
92
  CAPPluginMethod(name: "setExposureCompensation", returnType: CAPPluginReturnPromise),
93
+ CAPPluginMethod(name: "getWhiteBalanceModes", returnType: CAPPluginReturnPromise),
94
+ CAPPluginMethod(name: "getWhiteBalanceMode", returnType: CAPPluginReturnPromise),
95
+ CAPPluginMethod(name: "setWhiteBalanceMode", returnType: CAPPluginReturnPromise),
93
96
  CAPPluginMethod(name: "getSupportedVideoFrameRates", returnType: CAPPluginReturnPromise),
94
97
  CAPPluginMethod(name: "getVideoFrameRate", returnType: CAPPluginReturnPromise),
95
98
  CAPPluginMethod(name: "setVideoFrameRate", returnType: CAPPluginReturnPromise),
@@ -2392,6 +2395,58 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
2392
2395
  }
2393
2396
  }
2394
2397
 
2398
+ // MARK: - White Balance Bridge
2399
+
2400
+ @objc func getWhiteBalanceModes(_ call: CAPPluginCall) {
2401
+ guard isInitialized else {
2402
+ call.reject("Camera not initialized")
2403
+ return
2404
+ }
2405
+ do {
2406
+ let modes = try self.cameraController.getWhiteBalanceModes()
2407
+ call.resolve(["modes": modes])
2408
+ } catch {
2409
+ call.reject("Failed to get white balance modes: \(error.localizedDescription)")
2410
+ }
2411
+ }
2412
+
2413
+ @objc func getWhiteBalanceMode(_ call: CAPPluginCall) {
2414
+ guard isInitialized else {
2415
+ call.reject("Camera not initialized")
2416
+ return
2417
+ }
2418
+ do {
2419
+ let mode = try self.cameraController.getWhiteBalanceMode()
2420
+ call.resolve(["mode": mode])
2421
+ } catch {
2422
+ call.reject("Failed to get white balance mode: \(error.localizedDescription)")
2423
+ }
2424
+ }
2425
+
2426
+ @objc func setWhiteBalanceMode(_ call: CAPPluginCall) {
2427
+ guard isInitialized else {
2428
+ call.reject("Camera not initialized")
2429
+ return
2430
+ }
2431
+ guard let mode = call.getString("mode") else {
2432
+ call.reject("mode parameter is required")
2433
+ return
2434
+ }
2435
+ let normalized = mode.uppercased()
2436
+ let allowedModes: Set<String> = ["AUTO", "LOCK", "CONTINUOUS"]
2437
+ guard allowedModes.contains(normalized) else {
2438
+ let allowedList = Array(allowedModes).sorted().joined(separator: ", ")
2439
+ call.reject("Invalid white balance mode: \(mode). Allowed values: \(allowedList)")
2440
+ return
2441
+ }
2442
+ do {
2443
+ try self.cameraController.setWhiteBalanceMode(mode: normalized)
2444
+ call.resolve()
2445
+ } catch {
2446
+ call.reject("Failed to set white balance mode: \(error.localizedDescription)")
2447
+ }
2448
+ }
2449
+
2395
2450
  // MARK: - Exposure Bridge
2396
2451
 
2397
2452
  @objc func getExposureModes(_ call: CAPPluginCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/camera-preview",
3
- "version": "8.8.1",
3
+ "version": "8.9.0",
4
4
  "description": "Camera preview",
5
5
  "license": "MPL-2.0",
6
6
  "repository": {