@capgo/camera-preview 7.4.0-beta.6 → 7.4.0-beta.8

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.
@@ -60,11 +60,16 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
60
60
  CAPPluginMethod(name: "setDeviceId", returnType: CAPPluginReturnPromise),
61
61
  CAPPluginMethod(name: "getDeviceId", returnType: CAPPluginReturnPromise),
62
62
  CAPPluginMethod(name: "setAspectRatio", returnType: CAPPluginReturnPromise),
63
- CAPPluginMethod(name: "getAspectRatio", returnType: CAPPluginReturnPromise)
63
+ CAPPluginMethod(name: "getAspectRatio", returnType: CAPPluginReturnPromise),
64
+ CAPPluginMethod(name: "setGridMode", returnType: CAPPluginReturnPromise),
65
+ CAPPluginMethod(name: "getGridMode", returnType: CAPPluginReturnPromise),
66
+ CAPPluginMethod(name: "getPreviewSize", returnType: CAPPluginReturnPromise),
67
+ CAPPluginMethod(name: "setPreviewSize", returnType: CAPPluginReturnPromise)
64
68
  ]
65
69
  // Camera state tracking
66
70
  private var isInitializing: Bool = false
67
71
  private var isInitialized: Bool = false
72
+ private var backgroundSession: AVCaptureSession?
68
73
 
69
74
  var previewView: UIView!
70
75
  var cameraPosition = String()
@@ -83,7 +88,8 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
83
88
  var locationManager: CLLocationManager?
84
89
  var currentLocation: CLLocation?
85
90
  private var aspectRatio: String?
86
-
91
+ private var gridMode: String = "none"
92
+
87
93
  // MARK: - Transparency Methods
88
94
 
89
95
 
@@ -135,14 +141,26 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
135
141
  let paddingBottom = self.paddingBottom ?? 0
136
142
  let height = heightValue - paddingBottom
137
143
 
138
- if UIWindow.isLandscape {
139
- previewView.frame = CGRect(x: posY, y: posX, width: max(height, width), height: min(height, width))
140
- self.cameraController.previewLayer?.frame = previewView.frame
141
- }
144
+ // Handle auto-centering during rotation
145
+ if posX == -1 || posY == -1 {
146
+ // Trigger full recalculation for auto-centered views
147
+ self.updateCameraFrame()
148
+ } else {
149
+ // Manual positioning - use original rotation logic with no animation
150
+ CATransaction.begin()
151
+ CATransaction.setDisableActions(true)
152
+
153
+ if UIWindow.isLandscape {
154
+ previewView.frame = CGRect(x: posY, y: posX, width: max(height, width), height: min(height, width))
155
+ self.cameraController.previewLayer?.frame = previewView.bounds
156
+ }
142
157
 
143
- if UIWindow.isPortrait {
144
- previewView.frame = CGRect(x: posX, y: posY, width: min(height, width), height: max(height, width))
145
- self.cameraController.previewLayer?.frame = previewView.frame
158
+ if UIWindow.isPortrait {
159
+ previewView.frame = CGRect(x: posX, y: posY, width: min(height, width), height: max(height, width))
160
+ self.cameraController.previewLayer?.frame = previewView.bounds
161
+ }
162
+
163
+ CATransaction.commit()
146
164
  }
147
165
 
148
166
  if let connection = self.cameraController.fileVideoOutput?.connection(with: .video) {
@@ -162,11 +180,14 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
162
180
 
163
181
  cameraController.updateVideoOrientation()
164
182
 
165
- cameraController.updateVideoOrientation()
183
+ cameraController.updateVideoOrientation()
166
184
 
167
- // Update grid overlay frame if it exists
185
+ // Update grid overlay frame if it exists - no animation
168
186
  if let gridOverlay = self.cameraController.gridOverlayView {
187
+ CATransaction.begin()
188
+ CATransaction.setDisableActions(true)
169
189
  gridOverlay.frame = previewView.bounds
190
+ CATransaction.commit()
170
191
  }
171
192
 
172
193
  // Ensure webview remains transparent after rotation
@@ -174,15 +195,71 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
174
195
  self.makeWebViewTransparent()
175
196
  }
176
197
  }
177
-
198
+
178
199
  @objc func setAspectRatio(_ call: CAPPluginCall) {
179
200
  guard self.isInitialized else {
180
201
  call.reject("camera not started")
181
202
  return
182
203
  }
183
- self.aspectRatio = call.getString("aspectRatio")
204
+
205
+ guard let newAspectRatio = call.getString("aspectRatio") else {
206
+ call.reject("aspectRatio parameter is required")
207
+ return
208
+ }
209
+
210
+ self.aspectRatio = newAspectRatio
211
+
212
+ // When aspect ratio changes, calculate maximum size possible from current position
213
+ if let posX = self.posX, let posY = self.posY {
214
+ let webViewWidth = self.webView?.frame.width ?? UIScreen.main.bounds.width
215
+ let webViewHeight = self.webView?.frame.height ?? UIScreen.main.bounds.height
216
+ let paddingBottom = self.paddingBottom ?? 0
217
+
218
+ // Calculate available space from current position
219
+ let availableWidth: CGFloat
220
+ let availableHeight: CGFloat
221
+
222
+ if posX == -1 || posY == -1 {
223
+ // Auto-centering mode - use full dimensions
224
+ availableWidth = webViewWidth
225
+ availableHeight = webViewHeight - paddingBottom
226
+ } else {
227
+ // Manual positioning - calculate remaining space
228
+ availableWidth = webViewWidth - posX
229
+ availableHeight = webViewHeight - posY - paddingBottom
230
+ }
231
+
232
+ // Parse aspect ratio - convert to portrait orientation for camera use
233
+ let ratioParts = newAspectRatio.split(separator: ":").map { Double($0) ?? 1.0 }
234
+ // For camera, we want portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
235
+ let ratio = ratioParts[1] / ratioParts[0]
236
+
237
+ // Calculate maximum size that fits the aspect ratio in available space
238
+ let maxWidthByHeight = availableHeight * CGFloat(ratio)
239
+ let maxHeightByWidth = availableWidth / CGFloat(ratio)
240
+
241
+ if maxWidthByHeight <= availableWidth {
242
+ // Height is the limiting factor
243
+ self.width = maxWidthByHeight
244
+ self.height = availableHeight
245
+ } else {
246
+ // Width is the limiting factor
247
+ self.width = availableWidth
248
+ self.height = maxHeightByWidth
249
+ }
250
+
251
+ print("[CameraPreview] Aspect ratio changed to \(newAspectRatio), new size: \(self.width!)x\(self.height!)")
252
+ }
253
+
184
254
  self.updateCameraFrame()
185
- call.resolve()
255
+
256
+ // Return the actual preview bounds
257
+ var result = JSObject()
258
+ result["x"] = Double(self.previewView.frame.origin.x)
259
+ result["y"] = Double(self.previewView.frame.origin.y)
260
+ result["width"] = Double(self.previewView.frame.width)
261
+ result["height"] = Double(self.previewView.frame.height)
262
+ call.resolve(result)
186
263
  }
187
264
 
188
265
  @objc func getAspectRatio(_ call: CAPPluginCall) {
@@ -190,9 +267,42 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
190
267
  call.reject("camera not started")
191
268
  return
192
269
  }
193
- call.resolve(["aspectRatio": self.aspectRatio ?? "fill"])
270
+ call.resolve(["aspectRatio": self.aspectRatio ?? "4:3"])
271
+ }
272
+
273
+ @objc func setGridMode(_ call: CAPPluginCall) {
274
+ guard self.isInitialized else {
275
+ call.reject("camera not started")
276
+ return
277
+ }
278
+
279
+ guard let gridMode = call.getString("gridMode") else {
280
+ call.reject("gridMode parameter is required")
281
+ return
282
+ }
283
+
284
+ self.gridMode = gridMode
285
+
286
+ // Update grid overlay
287
+ DispatchQueue.main.async {
288
+ if gridMode == "none" {
289
+ self.cameraController.removeGridOverlay()
290
+ } else {
291
+ self.cameraController.addGridOverlay(to: self.previewView, gridMode: gridMode)
292
+ }
293
+ }
294
+
295
+ call.resolve()
296
+ }
297
+
298
+ @objc func getGridMode(_ call: CAPPluginCall) {
299
+ guard self.isInitialized else {
300
+ call.reject("camera not started")
301
+ return
302
+ }
303
+ call.resolve(["gridMode": self.gridMode])
194
304
  }
195
-
305
+
196
306
  @objc func appDidBecomeActive() {
197
307
  if self.isInitialized {
198
308
  DispatchQueue.main.async {
@@ -308,18 +418,33 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
308
418
  self.highResolutionOutput = call.getBool("enableHighResolution") ?? false
309
419
  self.cameraController.highResolutionOutput = self.highResolutionOutput
310
420
 
311
- if call.getInt("width") != nil {
312
- self.width = CGFloat(call.getInt("width")!)
421
+ // Set width - use screen width if not provided or if 0
422
+ if let width = call.getInt("width"), width > 0 {
423
+ self.width = CGFloat(width)
313
424
  } else {
314
425
  self.width = UIScreen.main.bounds.size.width
315
426
  }
316
- if call.getInt("height") != nil {
317
- self.height = CGFloat(call.getInt("height")!)
427
+
428
+ // Set height - use screen height if not provided or if 0
429
+ if let height = call.getInt("height"), height > 0 {
430
+ self.height = CGFloat(height)
318
431
  } else {
319
432
  self.height = UIScreen.main.bounds.size.height
320
433
  }
321
- self.posX = call.getInt("x") != nil ? CGFloat(call.getInt("x")!)/UIScreen.main.scale: 0
322
- 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
434
+
435
+ // Set x position - use exact CSS pixel value from web view, or mark for centering
436
+ if let x = call.getInt("x") {
437
+ self.posX = CGFloat(x)
438
+ } else {
439
+ self.posX = -1 // Use -1 to indicate auto-centering
440
+ }
441
+
442
+ // Set y position - use exact CSS pixel value from web view, or mark for centering
443
+ if let y = call.getInt("y") {
444
+ self.posY = CGFloat(y)
445
+ } else {
446
+ self.posY = -1 // Use -1 to indicate auto-centering
447
+ }
323
448
  if call.getInt("paddingBottom") != nil {
324
449
  self.paddingBottom = CGFloat(call.getInt("paddingBottom")!)
325
450
  }
@@ -330,7 +455,15 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
330
455
  self.enableZoom = call.getBool("enableZoom") ?? false
331
456
  self.disableAudio = call.getBool("disableAudio") ?? true
332
457
  self.aspectRatio = call.getString("aspectRatio")
333
- let gridMode = call.getString("gridMode") ?? "none"
458
+ self.gridMode = call.getString("gridMode") ?? "none"
459
+ if self.aspectRatio != nil && (call.getInt("width") != nil || call.getInt("height") != nil) {
460
+ call.reject("Cannot set both aspectRatio and size (width/height). Use setPreviewSize after start.")
461
+ return
462
+ }
463
+
464
+ print("[CameraPreview] Camera start parameters - aspectRatio: \(String(describing: self.aspectRatio)), gridMode: \(self.gridMode)")
465
+ print("[CameraPreview] Screen dimensions: \(UIScreen.main.bounds.size)")
466
+ print("[CameraPreview] Final frame dimensions - width: \(self.width), height: \(self.height), x: \(self.posX), y: \(self.posY)")
334
467
 
335
468
  AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
336
469
  guard granted else {
@@ -348,55 +481,73 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
348
481
  call.reject(error.localizedDescription)
349
482
  return
350
483
  }
351
- self.updateCameraFrame()
352
-
353
- // Make webview transparent - comprehensive approach
354
- self.makeWebViewTransparent()
484
+ self.completeStartCamera(call: call)
485
+ }
486
+ }
487
+ }
488
+ })
489
+ }
355
490
 
491
+ override public func load() {
492
+ super.load()
493
+ // Initialize camera session in background for faster startup
494
+ prepareBackgroundCamera()
495
+ }
356
496
 
357
- self.webView?.superview?.addSubview(self.previewView)
358
- if self.toBack! {
359
- self.webView?.superview?.bringSubviewToFront(self.webView!)
360
- }
361
- try? self.cameraController.displayPreview(on: self.previewView)
497
+ private func prepareBackgroundCamera() {
498
+ DispatchQueue.global(qos: .background).async {
499
+ AVCaptureDevice.requestAccess(for: .video) { granted in
500
+ guard granted else { return }
501
+
502
+ // Pre-initialize camera controller for faster startup
503
+ DispatchQueue.main.async {
504
+ self.cameraController.prepareBasicSession()
505
+ }
506
+ }
507
+ }
508
+ }
362
509
 
363
- let frontView = self.toBack! ? self.webView : self.previewView
364
- self.cameraController.setupGestures(target: frontView ?? self.previewView, enableZoom: self.enableZoom!)
510
+ private func completeStartCamera(call: CAPPluginCall) {
511
+ // Create and configure the preview view first
512
+ self.updateCameraFrame()
365
513
 
366
- // Add grid overlay if enabled
367
- if gridMode != "none" {
368
- self.cameraController.addGridOverlay(to: self.previewView, gridMode: gridMode)
369
- }
514
+ // Make webview transparent - comprehensive approach
515
+ self.makeWebViewTransparent()
370
516
 
371
- // Add grid overlay if enabled
372
- if gridMode != "none" {
373
- self.cameraController.addGridOverlay(to: self.previewView, gridMode: gridMode)
374
- }
517
+ // Add the preview view to the webview itself to use same coordinate system
518
+ self.webView?.addSubview(self.previewView)
519
+ if self.toBack! {
520
+ self.webView?.sendSubviewToBack(self.previewView)
521
+ }
375
522
 
376
- if self.rotateWhenOrientationChanged == true {
377
- NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
378
- }
523
+ // Display the camera preview on the configured view
524
+ try? self.cameraController.displayPreview(on: self.previewView)
525
+
526
+ let frontView = self.toBack! ? self.webView : self.previewView
527
+ self.cameraController.setupGestures(target: frontView ?? self.previewView, enableZoom: self.enableZoom!)
379
528
 
529
+ // Add grid overlay if enabled
530
+ if self.gridMode != "none" {
531
+ self.cameraController.addGridOverlay(to: self.previewView, gridMode: self.gridMode)
532
+ }
380
533
 
381
- // Add observers for app state changes to maintain transparency
382
- NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
383
- NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
534
+ if self.rotateWhenOrientationChanged == true {
535
+ NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
536
+ }
384
537
 
385
- self.isInitializing = false
386
- self.isInitialized = true
387
-
388
- var returnedObject = JSObject()
389
- returnedObject["width"] = self.previewView.frame.width as any JSValue
390
- returnedObject["height"] = self.previewView.frame.height as any JSValue
391
- returnedObject["x"] = self.previewView.frame.origin.x as any JSValue
392
- returnedObject["y"] = self.previewView.frame.origin.y as any JSValue
393
- call.resolve(returnedObject)
538
+ // Add observers for app state changes to maintain transparency
539
+ NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
540
+ NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
394
541
 
395
- }
396
- }
397
- }
398
- })
542
+ self.isInitializing = false
543
+ self.isInitialized = true
399
544
 
545
+ var returnedObject = JSObject()
546
+ returnedObject["width"] = self.previewView.frame.width as any JSValue
547
+ returnedObject["height"] = self.previewView.frame.height as any JSValue
548
+ returnedObject["x"] = self.previewView.frame.origin.x as any JSValue
549
+ returnedObject["y"] = self.previewView.frame.origin.y as any JSValue
550
+ call.resolve(returnedObject)
400
551
  }
401
552
 
402
553
  @objc func flip(_ call: CAPPluginCall) {
@@ -424,8 +575,13 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
424
575
  try self.cameraController.switchCameras()
425
576
 
426
577
  DispatchQueue.main.async {
578
+ // Update preview layer frame without animation
579
+ CATransaction.begin()
580
+ CATransaction.setDisableActions(true)
427
581
  self.cameraController.previewLayer?.frame = self.previewView.bounds
428
582
  self.cameraController.previewLayer?.videoGravity = .resizeAspectFill
583
+ CATransaction.commit()
584
+
429
585
  self.previewView.isUserInteractionEnabled = true
430
586
 
431
587
 
@@ -876,8 +1032,13 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
876
1032
  try self.cameraController.swapToDevice(deviceId: deviceId)
877
1033
 
878
1034
  DispatchQueue.main.async {
1035
+ // Update preview layer frame without animation
1036
+ CATransaction.begin()
1037
+ CATransaction.setDisableActions(true)
879
1038
  self.cameraController.previewLayer?.frame = self.previewView.bounds
880
1039
  self.cameraController.previewLayer?.videoGravity = .resizeAspectFill
1040
+ CATransaction.commit()
1041
+
881
1042
  self.previewView.isUserInteractionEnabled = true
882
1043
 
883
1044
 
@@ -921,36 +1082,130 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
921
1082
  }
922
1083
 
923
1084
  private func updateCameraFrame() {
924
- guard let width = self.width, var height = self.height, let posX = self.posX, let posY = self.posY else { return }
1085
+ guard let width = self.width, var height = self.height, let posX = self.posX, let posY = self.posY else {
1086
+ return
1087
+ }
1088
+
925
1089
  let paddingBottom = self.paddingBottom ?? 0
926
1090
  height -= paddingBottom
927
1091
 
928
- var frame = CGRect(x: posX, y: posY, width: width, height: height)
929
-
930
- if let aspectRatio = self.aspectRatio, aspectRatio != "fill" {
931
- let ratioParts = aspectRatio.split(separator: ":").map { Double($0) ?? 1.0 }
932
- let ratio = ratioParts[0] / ratioParts[1]
933
- let viewWidth = Double(width)
934
- let viewHeight = Double(height)
1092
+ // Cache webView dimensions for performance
1093
+ let webViewWidth = self.webView?.frame.width ?? UIScreen.main.bounds.width
1094
+ let webViewHeight = self.webView?.frame.height ?? UIScreen.main.bounds.height
1095
+
1096
+ var finalX = posX
1097
+ var finalY = posY
1098
+ var finalWidth = width
1099
+ var finalHeight = height
1100
+
1101
+ // Handle auto-centering when position is -1
1102
+ if posX == -1 || posY == -1 {
1103
+ finalWidth = webViewWidth
1104
+
1105
+ // Calculate height based on aspect ratio or use provided height
1106
+ if let aspectRatio = self.aspectRatio {
1107
+ let ratioParts = aspectRatio.split(separator: ":").compactMap { Double($0) }
1108
+ if ratioParts.count == 2 {
1109
+ // For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
1110
+ let ratio = ratioParts[1] / ratioParts[0]
1111
+ finalHeight = finalWidth / CGFloat(ratio)
1112
+ }
1113
+ }
1114
+
1115
+ finalX = posX == -1 ? 0 : posX
1116
+
1117
+ if posY == -1 {
1118
+ let availableHeight = webViewHeight - paddingBottom
1119
+ finalY = finalHeight < availableHeight ? (availableHeight - finalHeight) / 2 : 0
1120
+ }
1121
+ }
935
1122
 
936
- if viewWidth / ratio > viewHeight {
937
- let newWidth = viewHeight * ratio
938
- frame.origin.x += (viewWidth - newWidth) / 2
939
- frame.size.width = newWidth
940
- } else {
941
- let newHeight = viewWidth / ratio
942
- frame.origin.y += (viewHeight - newHeight) / 2
943
- frame.size.height = newHeight
1123
+ var frame = CGRect(x: finalX, y: finalY, width: finalWidth, height: finalHeight)
1124
+
1125
+ // Apply aspect ratio adjustments only if not auto-centering
1126
+ if posX != -1 && posY != -1, let aspectRatio = self.aspectRatio {
1127
+ let ratioParts = aspectRatio.split(separator: ":").compactMap { Double($0) }
1128
+ if ratioParts.count == 2 {
1129
+ // For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
1130
+ let ratio = ratioParts[1] / ratioParts[0]
1131
+ let currentRatio = Double(finalWidth) / Double(finalHeight)
1132
+
1133
+ if currentRatio > ratio {
1134
+ let newWidth = Double(finalHeight) * ratio
1135
+ frame.origin.x = finalX + (Double(finalWidth) - newWidth) / 2
1136
+ frame.size.width = CGFloat(newWidth)
1137
+ } else {
1138
+ let newHeight = Double(finalWidth) / ratio
1139
+ frame.origin.y = finalY + (Double(finalHeight) - newHeight) / 2
1140
+ frame.size.height = CGFloat(newHeight)
1141
+ }
944
1142
  }
945
1143
  }
1144
+
1145
+ // Disable ALL animations for frame updates - we want instant positioning
1146
+ CATransaction.begin()
1147
+ CATransaction.setDisableActions(true)
946
1148
 
1149
+ // Batch UI updates for better performance
947
1150
  if self.previewView == nil {
948
1151
  self.previewView = UIView(frame: frame)
1152
+ self.previewView.backgroundColor = UIColor.clear
949
1153
  } else {
950
1154
  self.previewView.frame = frame
951
1155
  }
1156
+
1157
+ // Update preview layer frame efficiently
1158
+ if let previewLayer = self.cameraController.previewLayer {
1159
+ previewLayer.frame = self.previewView.bounds
1160
+ }
1161
+
1162
+ // Update grid overlay frame if it exists
1163
+ if let gridOverlay = self.cameraController.gridOverlayView {
1164
+ gridOverlay.frame = self.previewView.bounds
1165
+ }
1166
+
1167
+ CATransaction.commit()
1168
+ }
1169
+
1170
+ @objc func getPreviewSize(_ call: CAPPluginCall) {
1171
+ guard self.isInitialized else {
1172
+ call.reject("camera not started")
1173
+ return
1174
+ }
1175
+ var result = JSObject()
1176
+ result["x"] = Double(self.previewView.frame.origin.x)
1177
+ result["y"] = Double(self.previewView.frame.origin.y)
1178
+ result["width"] = Double(self.previewView.frame.width)
1179
+ result["height"] = Double(self.previewView.frame.height)
1180
+ call.resolve(result)
1181
+ }
1182
+
1183
+ @objc func setPreviewSize(_ call: CAPPluginCall) {
1184
+ guard self.isInitialized else {
1185
+ call.reject("camera not started")
1186
+ return
1187
+ }
1188
+
1189
+ // Only update position if explicitly provided, otherwise keep auto-centering
1190
+ if let x = call.getInt("x") {
1191
+ self.posX = CGFloat(x)
1192
+ }
1193
+ if let y = call.getInt("y") {
1194
+ self.posY = CGFloat(y)
1195
+ }
1196
+ if let width = call.getInt("width") { self.width = CGFloat(width) }
1197
+ if let height = call.getInt("height") { self.height = CGFloat(height) }
1198
+
1199
+ // Direct update without animation for better performance
1200
+ self.updateCameraFrame()
1201
+ self.makeWebViewTransparent()
952
1202
 
953
- // Update the preview layer frame to match the preview view
954
- self.cameraController.previewLayer?.frame = frame
1203
+ // Return the actual preview bounds
1204
+ var result = JSObject()
1205
+ result["x"] = Double(self.previewView.frame.origin.x)
1206
+ result["y"] = Double(self.previewView.frame.origin.y)
1207
+ result["width"] = Double(self.previewView.frame.width)
1208
+ result["height"] = Double(self.previewView.frame.height)
1209
+ call.resolve(result)
955
1210
  }
956
1211
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/camera-preview",
3
- "version": "7.4.0-beta.6",
3
+ "version": "7.4.0-beta.8",
4
4
  "description": "Camera preview",
5
5
  "license": "MIT",
6
6
  "repository": {