@capgo/camera-preview 7.4.0-alpha.24 → 7.4.0-alpha.27

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.
@@ -1,5 +1,7 @@
1
1
  package com.ahm.capacitor.camera.preview;
2
2
 
3
+ import static androidx.core.content.ContextCompat.getSystemService;
4
+
3
5
  import android.content.Context;
4
6
  import android.content.res.Configuration;
5
7
  import android.graphics.Bitmap;
@@ -21,10 +23,13 @@ import android.util.Size;
21
23
  import android.view.MotionEvent;
22
24
  import android.view.View;
23
25
  import android.view.ViewGroup;
26
+ import android.view.WindowManager;
27
+ import android.view.WindowMetrics;
24
28
  import android.webkit.WebView;
25
29
  import android.widget.FrameLayout;
26
30
  import androidx.annotation.NonNull;
27
31
  import androidx.annotation.OptIn;
32
+ import androidx.annotation.RequiresApi;
28
33
  import androidx.camera.camera2.interop.Camera2CameraInfo;
29
34
  import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
30
35
  import androidx.camera.core.AspectRatio;
@@ -447,10 +452,29 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
447
452
  String aspectRatio = sessionConfig.getAspectRatio();
448
453
 
449
454
  // Get comprehensive display information
450
- DisplayMetrics metrics = context.getResources().getDisplayMetrics();
451
- int screenWidthPx = metrics.widthPixels;
452
- int screenHeightPx = metrics.heightPixels;
453
- float density = metrics.density;
455
+ int screenWidthPx, screenHeightPx;
456
+ float density;
457
+
458
+ // Get density using DisplayMetrics (available on all API levels)
459
+ WindowManager windowManager = (WindowManager) this.context.getSystemService(
460
+ Context.WINDOW_SERVICE
461
+ );
462
+ DisplayMetrics displayMetrics = new DisplayMetrics();
463
+ windowManager.getDefaultDisplay().getMetrics(displayMetrics);
464
+ density = displayMetrics.density;
465
+
466
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
467
+ // API 30+ (Android 11+) - use WindowMetrics for screen dimensions
468
+ WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
469
+ Rect bounds = metrics.getBounds();
470
+ screenWidthPx = bounds.width();
471
+ screenHeightPx = bounds.height();
472
+ } else {
473
+ // API < 30 - use legacy DisplayMetrics for screen dimensions
474
+ screenWidthPx = displayMetrics.widthPixels;
475
+ screenHeightPx = displayMetrics.heightPixels;
476
+ }
477
+
454
478
  int screenWidthDp = (int) (screenWidthPx / density);
455
479
  int screenHeightDp = (int) (screenHeightPx / density);
456
480
 
@@ -544,8 +568,8 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
544
568
  );
545
569
 
546
570
  // For centered mode with aspect ratio, calculate maximum size that fits
547
- int availableWidth = metrics.widthPixels;
548
- int availableHeight = metrics.heightPixels;
571
+ int availableWidth = screenWidthPx;
572
+ int availableHeight = screenHeightPx;
549
573
 
550
574
  Log.d(
551
575
  TAG,
@@ -3091,10 +3115,28 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
3091
3115
  );
3092
3116
 
3093
3117
  // Get comprehensive display information
3094
- DisplayMetrics metrics = context.getResources().getDisplayMetrics();
3095
- int screenWidthPx = metrics.widthPixels;
3096
- int screenHeightPx = metrics.heightPixels;
3097
- float density = metrics.density;
3118
+ WindowManager windowManager = (WindowManager) this.context.getSystemService(
3119
+ Context.WINDOW_SERVICE
3120
+ );
3121
+ int screenWidthPx, screenHeightPx;
3122
+ float density;
3123
+
3124
+ // Get density using DisplayMetrics (available on all API levels)
3125
+ DisplayMetrics displayMetrics = new DisplayMetrics();
3126
+ windowManager.getDefaultDisplay().getMetrics(displayMetrics);
3127
+ density = displayMetrics.density;
3128
+
3129
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
3130
+ // API 30+ (Android 11+) - use WindowMetrics for screen dimensions
3131
+ WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
3132
+ Rect bounds = metrics.getBounds();
3133
+ screenWidthPx = bounds.width();
3134
+ screenHeightPx = bounds.height();
3135
+ } else {
3136
+ // API < 30 - use legacy DisplayMetrics for screen dimensions
3137
+ screenWidthPx = displayMetrics.widthPixels;
3138
+ screenHeightPx = displayMetrics.heightPixels;
3139
+ }
3098
3140
 
3099
3141
  // Get WebView dimensions
3100
3142
  int webViewWidth = webView.getWidth();
@@ -504,23 +504,23 @@ extension CameraController {
504
504
  dataOutput?.connections.forEach { $0.videoOrientation = videoOrientation }
505
505
  photoOutput?.connections.forEach { $0.videoOrientation = videoOrientation }
506
506
  }
507
-
507
+
508
508
  private func setDefaultZoomAfterFlip() {
509
509
  let device = (currentCameraPosition == .rear) ? rearCamera : frontCamera
510
510
  guard let device = device else {
511
511
  print("[CameraPreview] No device available for default zoom after flip")
512
512
  return
513
513
  }
514
-
514
+
515
515
  // Set zoom to 1.0x in UI terms, accounting for display multiplier
516
516
  let multiplier = self.getDisplayZoomMultiplier()
517
517
  let targetUIZoom: Float = 1.0 // We want 1.0x in the UI
518
518
  let nativeZoom = multiplier != 1.0 ? (targetUIZoom / multiplier) : targetUIZoom
519
-
519
+
520
520
  let minZoom = device.minAvailableVideoZoomFactor
521
521
  let maxZoom = min(device.maxAvailableVideoZoomFactor, saneMaxZoomFactor)
522
522
  let clampedZoom = max(minZoom, min(CGFloat(nativeZoom), maxZoom))
523
-
523
+
524
524
  do {
525
525
  try device.lockForConfiguration()
526
526
  device.videoZoomFactor = clampedZoom
@@ -621,7 +621,7 @@ extension CameraController {
621
621
 
622
622
  // Update video orientation
623
623
  self.updateVideoOrientation()
624
-
624
+
625
625
  // Set default 1.0 zoom level after camera switch to prevent iOS 18+ zoom jumps
626
626
  DispatchQueue.main.async { [weak self] in
627
627
  self?.setDefaultZoomAfterFlip()
@@ -170,18 +170,62 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
170
170
  }
171
171
 
172
172
  var values: [Float] = []
173
- if hasUltraWide { values.append(0.5) }
173
+ if hasUltraWide {
174
+ values.append(0.5)
175
+ }
174
176
  if hasWide {
175
177
  values.append(1.0)
176
- values.append(2.0)
178
+ if self.isProModelSupportingOptical2x() {
179
+ values.append(2.0)
180
+ }
181
+ }
182
+ if hasTele {
183
+ // Use the virtual device's switch-over zoom factors when available
184
+ let displayMultiplier = self.cameraController.getDisplayZoomMultiplier()
185
+ var teleStep: Float
186
+
187
+ if #available(iOS 13.0, *) {
188
+ let switchFactors = device.virtualDeviceSwitchOverVideoZoomFactors
189
+ if !switchFactors.isEmpty {
190
+ // Choose the highest switch-over factor (typically the wide->tele threshold)
191
+ let maxSwitch = switchFactors.map { $0.floatValue }.max() ?? Float(device.maxAvailableVideoZoomFactor)
192
+ teleStep = maxSwitch * displayMultiplier
193
+ } else {
194
+ teleStep = Float(device.maxAvailableVideoZoomFactor) * displayMultiplier
195
+ }
196
+ } else {
197
+ teleStep = Float(device.maxAvailableVideoZoomFactor) * displayMultiplier
198
+ }
199
+ values.append(teleStep)
177
200
  }
178
- if hasTele { values.append(3.0) }
179
201
 
180
202
  // Deduplicate and sort
181
203
  let uniqueSorted = Array(Set(values)).sorted()
182
204
  call.resolve(["values": uniqueSorted])
183
205
  }
184
206
 
207
+ private func isProModelSupportingOptical2x() -> Bool {
208
+ // Detects iPhone 14 Pro/Pro Max, 15 Pro/Pro Max, and 16 Pro/Pro Max
209
+ var systemInfo = utsname()
210
+ uname(&systemInfo)
211
+ let mirror = Mirror(reflecting: systemInfo.machine)
212
+ let identifier = mirror.children.reduce("") { partialResult, element in
213
+ guard let value = element.value as? Int8, value != 0 else { return partialResult }
214
+ return partialResult + String(UnicodeScalar(UInt8(value)))
215
+ }
216
+
217
+ // Known identifiers: 14 Pro (iPhone15,2), 14 Pro Max (iPhone15,3),
218
+ // 15 Pro (iPhone16,1), 15 Pro Max (iPhone16,2),
219
+ // 16 Pro (iPhone17,1), 16 Pro Max (iPhone17,2),
220
+ // 17 Pro (iPhone18,1), 17 Pro Max (iPhone18,2)
221
+ let supportedIdentifiers: Set<String> = [
222
+ "iPhone15,2", "iPhone15,3", // 14 Pro / 14 Pro Max
223
+ "iPhone16,1", "iPhone16,2", // 15 Pro / 15 Pro Max
224
+ "iPhone17,1", "iPhone17,2" // 16 Pro / 16 Pro Max
225
+ ]
226
+ return supportedIdentifiers.contains(identifier)
227
+ }
228
+
185
229
  @objc func rotated() {
186
230
  guard let previewView = self.previewView,
187
231
  let posX = self.posX,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/camera-preview",
3
- "version": "7.4.0-alpha.24",
3
+ "version": "7.4.0-alpha.27",
4
4
  "description": "Camera preview",
5
5
  "license": "MIT",
6
6
  "repository": {