@capgo/camera-preview 7.4.0-beta.12 → 7.4.0-beta.15

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.
package/README.md CHANGED
@@ -241,6 +241,7 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
241
241
  * [`getDeviceId()`](#getdeviceid)
242
242
  * [`getPreviewSize()`](#getpreviewsize)
243
243
  * [`setPreviewSize(...)`](#setpreviewsize)
244
+ * [`setFocus(...)`](#setfocus)
244
245
  * [Interfaces](#interfaces)
245
246
  * [Type Aliases](#type-aliases)
246
247
  * [Enums](#enums)
@@ -561,14 +562,14 @@ Gets the current zoom state, including min/max and current lens info.
561
562
  ### setZoom(...)
562
563
 
563
564
  ```typescript
564
- setZoom(options: { level: number; ramp?: boolean; }) => Promise<void>
565
+ setZoom(options: { level: number; ramp?: boolean; autoFocus?: boolean; }) => Promise<void>
565
566
  ```
566
567
 
567
- Sets the camera's zoom level.
568
+ Sets the zoom level of the camera.
568
569
 
569
- | Param | Type | Description |
570
- | ------------- | ----------------------------------------------- | ----------------------------------------------------- |
571
- | **`options`** | <code>{ level: number; ramp?: boolean; }</code> | - The desired zoom level. `ramp` is currently unused. |
570
+ | Param | Type | Description |
571
+ | ------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
572
+ | **`options`** | <code>{ level: number; ramp?: boolean; autoFocus?: boolean; }</code> | - The desired zoom level. `ramp` is currently unused. `autoFocus` defaults to true. |
572
573
 
573
574
  **Since:** 7.4.0
574
575
 
@@ -651,20 +652,37 @@ Gets the current preview size and position.
651
652
  ### setPreviewSize(...)
652
653
 
653
654
  ```typescript
654
- setPreviewSize(options: { x: number; y: number; width: number; height: number; }) => Promise<{ width: number; height: number; x: number; y: number; }>
655
+ setPreviewSize(options: { x?: number; y?: number; width: number; height: number; }) => Promise<{ width: number; height: number; x: number; y: number; }>
655
656
  ```
656
657
 
657
658
  Sets the preview size and position.
658
659
 
659
- | Param | Type | Description |
660
- | ------------- | --------------------------------------------------------------------- | -------------------------------- |
661
- | **`options`** | <code>{ x: number; y: number; width: number; height: number; }</code> | The new position and dimensions. |
660
+ | Param | Type | Description |
661
+ | ------------- | ----------------------------------------------------------------------- | -------------------------------- |
662
+ | **`options`** | <code>{ x?: number; y?: number; width: number; height: number; }</code> | The new position and dimensions. |
662
663
 
663
664
  **Returns:** <code>Promise&lt;{ width: number; height: number; x: number; y: number; }&gt;</code>
664
665
 
665
666
  --------------------
666
667
 
667
668
 
669
+ ### setFocus(...)
670
+
671
+ ```typescript
672
+ setFocus(options: { x: number; y: number; }) => Promise<void>
673
+ ```
674
+
675
+ Sets the camera focus to a specific point in the preview.
676
+
677
+ | Param | Type | Description |
678
+ | ------------- | -------------------------------------- | -------------------- |
679
+ | **`options`** | <code>{ x: number; y: number; }</code> | - The focus options. |
680
+
681
+ **Since:** 8.1.0
682
+
683
+ --------------------
684
+
685
+
668
686
  ### Interfaces
669
687
 
670
688
 
@@ -689,13 +707,13 @@ Defines the configuration options for starting the camera preview.
689
707
  | **`position`** | <code>string</code> | The camera to use. | <code>"rear"</code> | |
690
708
  | **`storeToFile`** | <code>boolean</code> | If true, saves the captured image to a file and returns the file path. If false, returns a base64 encoded string. | <code>false</code> | |
691
709
  | **`disableExifHeaderStripping`** | <code>boolean</code> | If true, prevents the plugin from rotating the image based on EXIF data. | <code>false</code> | |
692
- | **`enableHighResolution`** | <code>boolean</code> | If true, enables high-resolution image capture. | <code>false</code> | |
693
710
  | **`disableAudio`** | <code>boolean</code> | If true, disables the audio stream, preventing audio permission requests. | <code>true</code> | |
694
711
  | **`lockAndroidOrientation`** | <code>boolean</code> | If true, locks the device orientation while the camera is active. | <code>false</code> | |
695
712
  | **`enableOpacity`** | <code>boolean</code> | If true, allows the camera preview's opacity to be changed. | <code>false</code> | |
696
713
  | **`enableZoom`** | <code>boolean</code> | If true, enables pinch-to-zoom functionality on the preview. | <code>false</code> | |
697
714
  | **`enableVideoMode`** | <code>boolean</code> | If true, uses the video-optimized preset for the camera session. | <code>false</code> | |
698
715
  | **`deviceId`** | <code>string</code> | The `deviceId` of the camera to use. If provided, `position` is ignored. | | |
716
+ | **`initialZoomLevel`** | <code>number</code> | The initial zoom level when starting the camera preview. If the requested zoom level is not available, the native plugin will reject. | <code>1.0</code> | 2.2.0 |
699
717
 
700
718
 
701
719
  #### ExifData
Binary file
@@ -10,6 +10,7 @@ import android.util.DisplayMetrics;
10
10
  import android.util.Log;
11
11
  import android.util.Size;
12
12
  import android.view.ViewGroup;
13
+ import android.webkit.WebView;
13
14
  import com.ahm.capacitor.camera.preview.model.CameraDevice;
14
15
  import com.ahm.capacitor.camera.preview.model.CameraSessionConfiguration;
15
16
  import com.ahm.capacitor.camera.preview.model.LensInfo;
@@ -277,14 +278,44 @@ public class CameraPreview
277
278
  call.reject("level parameter is required");
278
279
  return;
279
280
  }
281
+ Boolean autoFocus = call.getBoolean("autoFocus", true);
280
282
  try {
281
- cameraXView.setZoom(level);
283
+ cameraXView.setZoom(level, autoFocus);
282
284
  call.resolve();
283
285
  } catch (Exception e) {
284
286
  call.reject("Failed to set zoom: " + e.getMessage());
285
287
  }
286
288
  }
287
289
 
290
+ @PluginMethod
291
+ public void setFocus(PluginCall call) {
292
+ if (cameraXView == null || !cameraXView.isRunning()) {
293
+ call.reject("Camera is not running");
294
+ return;
295
+ }
296
+ Float x = call.getFloat("x");
297
+ Float y = call.getFloat("y");
298
+ if (x == null || y == null) {
299
+ call.reject("x and y parameters are required");
300
+ return;
301
+ }
302
+ // Reject if values are outside 0-1 range
303
+ if (x < 0f || x > 1f || y < 0f || y > 1f) {
304
+ call.reject("Focus coordinates must be between 0 and 1");
305
+ return;
306
+ }
307
+
308
+ getActivity()
309
+ .runOnUiThread(() -> {
310
+ try {
311
+ cameraXView.setFocus(x, y);
312
+ call.resolve();
313
+ } catch (Exception e) {
314
+ call.reject("Failed to set focus: " + e.getMessage());
315
+ }
316
+ });
317
+ }
318
+
288
319
  @PluginMethod
289
320
  public void setDeviceId(PluginCall call) {
290
321
  String deviceId = call.getString("deviceId");
@@ -412,8 +443,30 @@ public class CameraPreview
412
443
  "back".equals(positionParam))
413
444
  ? "back"
414
445
  : "front";
415
- final int x = call.getInt("x", 0);
416
- final int y = call.getInt("y", 0);
446
+ // Use -1 as default to indicate centering is needed when x/y not provided
447
+ final Integer xParam = call.getInt("x");
448
+ final Integer yParam = call.getInt("y");
449
+ final int x = xParam != null ? xParam : -1;
450
+ final int y = yParam != null ? yParam : -1;
451
+
452
+ Log.d("CameraPreview", "========================");
453
+ Log.d("CameraPreview", "CAMERA POSITION TRACKING START:");
454
+ Log.d(
455
+ "CameraPreview",
456
+ "1. RAW PARAMS - xParam: " + xParam + ", yParam: " + yParam
457
+ );
458
+ Log.d(
459
+ "CameraPreview",
460
+ "2. AFTER DEFAULT - x: " +
461
+ x +
462
+ " (center=" +
463
+ (x == -1) +
464
+ "), y: " +
465
+ y +
466
+ " (center=" +
467
+ (y == -1) +
468
+ ")"
469
+ );
417
470
  final int width = call.getInt("width", 0);
418
471
  final int height = call.getInt("height", 0);
419
472
  final int paddingBottom = call.getInt("paddingBottom", 0);
@@ -438,6 +491,7 @@ public class CameraPreview
438
491
  );
439
492
  final String aspectRatio = call.getString("aspectRatio", "4:3");
440
493
  final String gridMode = call.getString("gridMode", "none");
494
+ final float initialZoomLevel = call.getFloat("initialZoomLevel", 1.0f);
441
495
 
442
496
  // Check for conflict between aspectRatio and size
443
497
  if (
@@ -450,7 +504,7 @@ public class CameraPreview
450
504
  return;
451
505
  }
452
506
 
453
- float targetZoom = 1.0f;
507
+ float targetZoom = initialZoomLevel;
454
508
  // Check if the selected device is a physical ultra-wide
455
509
  if (originalDeviceId != null) {
456
510
  List<CameraDevice> devices = CameraXView.getAvailableDevicesStatic(
@@ -521,10 +575,84 @@ public class CameraPreview
521
575
  // Calculate pixel ratio
522
576
  float pixelRatio = metrics.density;
523
577
 
524
- // Try using just the pixel ratio without any webview offset for now
525
- int computedX = (int) (x * pixelRatio);
526
- int computedY = (int) (y * pixelRatio);
578
+ // Calculate position - center if x or y is -1
579
+ int computedX;
580
+ int computedY;
581
+
582
+ // Calculate dimensions first
583
+ int computedWidth = width != 0
584
+ ? (int) (width * pixelRatio)
585
+ : getBridge().getWebView().getWidth();
586
+ int computedHeight = height != 0
587
+ ? (int) (height * pixelRatio)
588
+ : getBridge().getWebView().getHeight();
589
+ computedHeight -= (int) (paddingBottom * pixelRatio);
527
590
 
591
+ Log.d("CameraPreview", "Positioning logic - x: " + x + ", y: " + y);
592
+
593
+ if (x == -1) {
594
+ // Center horizontally
595
+ int screenWidth = metrics.widthPixels;
596
+ computedX = (screenWidth - computedWidth) / 2;
597
+ Log.d(
598
+ "CameraPreview",
599
+ "Centering horizontally: screenWidth=" +
600
+ screenWidth +
601
+ ", computedWidth=" +
602
+ computedWidth +
603
+ ", computedX=" +
604
+ computedX
605
+ );
606
+ } else {
607
+ computedX = (int) (x * pixelRatio);
608
+ Log.d(
609
+ "CameraPreview",
610
+ "Using provided X position: " +
611
+ x +
612
+ " * " +
613
+ pixelRatio +
614
+ " = " +
615
+ computedX
616
+ );
617
+ }
618
+
619
+ if (y == -1) {
620
+ // Center vertically using full screen height
621
+ int screenHeight = metrics.heightPixels;
622
+ computedY = (screenHeight - computedHeight) / 2;
623
+ Log.d(
624
+ "CameraPreview",
625
+ "Centering vertically: screenHeight=" +
626
+ screenHeight +
627
+ ", computedHeight=" +
628
+ computedHeight +
629
+ ", computedY=" +
630
+ computedY
631
+ );
632
+ } else {
633
+ computedY = (int) (y * pixelRatio);
634
+ Log.d(
635
+ "CameraPreview",
636
+ "Using provided Y position: " +
637
+ y +
638
+ " * " +
639
+ pixelRatio +
640
+ " = " +
641
+ computedY
642
+ );
643
+ }
644
+
645
+ Log.d(
646
+ "CameraPreview",
647
+ "3. COMPUTED POSITION - x=" + computedX + ", y=" + computedY
648
+ );
649
+ Log.d(
650
+ "CameraPreview",
651
+ "4. COMPUTED SIZE - width=" +
652
+ computedWidth +
653
+ ", height=" +
654
+ computedHeight
655
+ );
528
656
  Log.d("CameraPreview", "=== COORDINATE DEBUG ===");
529
657
  Log.d(
530
658
  "CameraPreview",
@@ -579,14 +707,11 @@ public class CameraPreview
579
707
  computedY +
580
708
  ")"
581
709
  );
710
+ Log.d("CameraPreview", "5. IS_CENTERED - " + (x == -1 || y == -1));
582
711
  Log.d("CameraPreview", "========================");
583
- int computedWidth = width != 0
584
- ? (int) (width * pixelRatio)
585
- : getBridge().getWebView().getWidth();
586
- int computedHeight = height != 0
587
- ? (int) (height * pixelRatio)
588
- : getBridge().getWebView().getHeight();
589
- computedHeight -= (int) (paddingBottom * pixelRatio);
712
+
713
+ // Pass along whether we're centering so CameraXView knows not to add insets
714
+ boolean isCentered = (x == -1 || y == -1);
590
715
 
591
716
  CameraSessionConfiguration config = new CameraSessionConfiguration(
592
717
  finalDeviceId,
@@ -607,6 +732,7 @@ public class CameraPreview
607
732
  gridMode
608
733
  );
609
734
  config.setTargetZoom(finalTargetZoom);
735
+ config.setCentered(isCentered);
610
736
 
611
737
  bridge.saveCall(call);
612
738
  cameraStartCallbackId = call.getCallbackId();
@@ -650,11 +776,70 @@ public class CameraPreview
650
776
  .getDisplayMetrics();
651
777
  float pixelRatio = metrics.density;
652
778
 
779
+ // Check if edge-to-edge mode is active by looking at WebView insets
780
+ // If the WebView has a top margin, it means edge-to-edge is active
781
+ // and JavaScript positions are relative to WebView content area
782
+ int webViewTopInset = 0;
783
+ boolean isEdgeToEdgeActive = false;
784
+ WebView webView = getBridge().getWebView();
785
+ if (
786
+ webView != null &&
787
+ webView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams
788
+ ) {
789
+ webViewTopInset =
790
+ ((ViewGroup.MarginLayoutParams) webView.getLayoutParams()).topMargin;
791
+ isEdgeToEdgeActive = webViewTopInset > 0;
792
+ }
793
+
794
+ // Only convert to relative position if edge-to-edge is active
795
+ int relativeY = isEdgeToEdgeActive ? (y - webViewTopInset) : y;
796
+
797
+ Log.d("CameraPreview", "========================");
798
+ Log.d("CameraPreview", "CAMERA STARTED - POSITION RETURNED:");
799
+ Log.d(
800
+ "CameraPreview",
801
+ "7. RETURNED (pixels) - x=" +
802
+ x +
803
+ ", y=" +
804
+ y +
805
+ ", width=" +
806
+ width +
807
+ ", height=" +
808
+ height
809
+ );
810
+ Log.d(
811
+ "CameraPreview",
812
+ "8. EDGE-TO-EDGE - " + (isEdgeToEdgeActive ? "ACTIVE" : "INACTIVE")
813
+ );
814
+ Log.d("CameraPreview", "9. WEBVIEW INSET - " + webViewTopInset);
815
+ Log.d(
816
+ "CameraPreview",
817
+ "10. RELATIVE Y - " +
818
+ relativeY +
819
+ " (y=" +
820
+ y +
821
+ (isEdgeToEdgeActive ? " - inset=" + webViewTopInset : " unchanged") +
822
+ ")"
823
+ );
824
+ Log.d(
825
+ "CameraPreview",
826
+ "11. RETURNED (logical) - x=" +
827
+ (x / pixelRatio) +
828
+ ", y=" +
829
+ (relativeY / pixelRatio) +
830
+ ", width=" +
831
+ (width / pixelRatio) +
832
+ ", height=" +
833
+ (height / pixelRatio)
834
+ );
835
+ Log.d("CameraPreview", "12. PIXEL RATIO - " + pixelRatio);
836
+ Log.d("CameraPreview", "========================");
837
+
653
838
  JSObject result = new JSObject();
654
839
  result.put("width", width / pixelRatio);
655
840
  result.put("height", height / pixelRatio);
656
841
  result.put("x", x / pixelRatio);
657
- result.put("y", y / pixelRatio);
842
+ result.put("y", relativeY / pixelRatio);
658
843
  call.resolve(result);
659
844
  bridge.releaseCall(call);
660
845
  cameraStartCallbackId = null; // Prevent re-use