@capgo/camera-preview 7.4.0-alpha.1 → 7.4.0-alpha.13

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
@@ -37,7 +37,7 @@ Take into account that this will make transparent all ion-content on application
37
37
  ```
38
38
 
39
39
  If the camera preview is not displaying after applying the above styles, apply transparent background color to the root div element of the parent component
40
- Ex: VueJS >> App.vue component
40
+ Ex: VueJS >> App.vue component
41
41
  ```html
42
42
  <template>
43
43
  <ion-app id="app">
@@ -76,6 +76,24 @@ Video and photo taken with the plugin are never removed, so do not forget to rem
76
76
  use https://capacitorjs.com/docs/apis/filesystem#deletefile for that
77
77
 
78
78
 
79
+ ## Fast base64 from file path (no bridge)
80
+
81
+ When using `storeToFile: true`, you can avoid sending large base64 strings over the Capacitor bridge:
82
+
83
+ ```ts
84
+ import { CameraPreview, getBase64FromFilePath } from '@capgo/camera-preview'
85
+
86
+ // Take a picture and get a file path
87
+ const { value: filePath } = await CameraPreview.capture({ quality: 85, storeToFile: true })
88
+
89
+ // Convert the file to base64 entirely on the JS side (fast, no bridge)
90
+ const base64 = await getBase64FromFilePath(filePath)
91
+
92
+ // Optionally cleanup the temp file natively
93
+ await CameraPreview.deleteFile({ path: filePath })
94
+ ```
95
+
96
+
79
97
  # Installation
80
98
 
81
99
  ```
@@ -234,6 +252,7 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
234
252
  * [`isRunning()`](#isrunning)
235
253
  * [`getAvailableDevices()`](#getavailabledevices)
236
254
  * [`getZoom()`](#getzoom)
255
+ * [`getZoomButtonValues()`](#getzoombuttonvalues)
237
256
  * [`setZoom(...)`](#setzoom)
238
257
  * [`getFlashMode()`](#getflashmode)
239
258
  * [`removeAllListeners()`](#removealllisteners)
@@ -242,6 +261,7 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
242
261
  * [`getPreviewSize()`](#getpreviewsize)
243
262
  * [`setPreviewSize(...)`](#setpreviewsize)
244
263
  * [`setFocus(...)`](#setfocus)
264
+ * [`addListener('screenResize', ...)`](#addlistenerscreenresize-)
245
265
  * [Interfaces](#interfaces)
246
266
  * [Type Aliases](#type-aliases)
247
267
  * [Enums](#enums)
@@ -559,6 +579,21 @@ Gets the current zoom state, including min/max and current lens info.
559
579
  --------------------
560
580
 
561
581
 
582
+ ### getZoomButtonValues()
583
+
584
+ ```typescript
585
+ getZoomButtonValues() => Promise<{ values: number[]; }>
586
+ ```
587
+
588
+ Returns zoom button values for quick switching.
589
+ - iOS/Android: includes 0.5 if ultra-wide available; 1 and 2 if wide available; 3 if telephoto available
590
+ - Web: unsupported
591
+
592
+ **Returns:** <code>Promise&lt;{ values: number[]; }&gt;</code>
593
+
594
+ --------------------
595
+
596
+
562
597
  ### setZoom(...)
563
598
 
564
599
  ```typescript
@@ -683,6 +718,22 @@ Sets the camera focus to a specific point in the preview.
683
718
  --------------------
684
719
 
685
720
 
721
+ ### addListener('screenResize', ...)
722
+
723
+ ```typescript
724
+ addListener(eventName: "screenResize", listenerFunc: (data: { width: number; height: number; x: number; y: number; }) => void) => Promise<PluginListenerHandle>
725
+ ```
726
+
727
+ | Param | Type |
728
+ | ------------------ | ---------------------------------------------------------------------------------------- |
729
+ | **`eventName`** | <code>'screenResize'</code> |
730
+ | **`listenerFunc`** | <code>(data: { width: number; height: number; x: number; y: number; }) =&gt; void</code> |
731
+
732
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
733
+
734
+ --------------------
735
+
736
+
686
737
  ### Interfaces
687
738
 
688
739
 
@@ -816,6 +867,13 @@ Represents the detailed information of the currently active lens.
816
867
  | **`digitalZoom`** | <code>number</code> | The current digital zoom factor applied on top of the base zoom. |
817
868
 
818
869
 
870
+ #### PluginListenerHandle
871
+
872
+ | Prop | Type |
873
+ | ------------ | ----------------------------------------- |
874
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
875
+
876
+
819
877
  ### Type Aliases
820
878
 
821
879
 
@@ -276,6 +276,53 @@ public class CameraPreview
276
276
  call.resolve(result);
277
277
  }
278
278
 
279
+ @PluginMethod
280
+ public void getZoomButtonValues(PluginCall call) {
281
+ // Build a sorted set to dedupe and order ascending
282
+ java.util.Set<Double> sorted = new java.util.TreeSet<>();
283
+ sorted.add(1.0);
284
+ sorted.add(2.0);
285
+
286
+ // Try to detect ultra-wide to include its min zoom (often 0.5)
287
+ try {
288
+ List<CameraDevice> devices = CameraXView.getAvailableDevicesStatic(
289
+ getContext()
290
+ );
291
+ ZoomFactors zoomFactors = cameraXView.getZoomFactors();
292
+ boolean hasUltraWide = false;
293
+ boolean hasTelephoto = false;
294
+ float minUltra = 0.5f;
295
+
296
+ for (CameraDevice device : devices) {
297
+ for (com.ahm.capacitor.camera.preview.model.LensInfo lens : device.getLenses()) {
298
+ if ("ultraWide".equals(lens.getDeviceType())) {
299
+ hasUltraWide = true;
300
+ // Use overall minZoom for that device as the button value to represent UW
301
+ minUltra = Math.max(minUltra, zoomFactors.getMin());
302
+ } else if ("telephoto".equals(lens.getDeviceType())) {
303
+ hasTelephoto = true;
304
+ }
305
+ }
306
+ }
307
+ if (hasUltraWide) {
308
+ sorted.add((double) minUltra);
309
+ }
310
+ if (hasTelephoto) {
311
+ sorted.add(3.0);
312
+ }
313
+ } catch (Exception ignored) {
314
+ // Ignore and keep defaults
315
+ }
316
+
317
+ JSObject result = new JSObject();
318
+ JSArray values = new JSArray();
319
+ for (Double v : sorted) {
320
+ values.put(v);
321
+ }
322
+ result.put("values", values);
323
+ call.resolve(result);
324
+ }
325
+
279
326
  @PluginMethod
280
327
  public void setZoom(PluginCall call) {
281
328
  if (cameraXView == null || !cameraXView.isRunning()) {
@@ -287,9 +334,8 @@ public class CameraPreview
287
334
  call.reject("level parameter is required");
288
335
  return;
289
336
  }
290
- Boolean autoFocus = call.getBoolean("autoFocus", true);
291
337
  try {
292
- cameraXView.setZoom(level, autoFocus);
338
+ cameraXView.setZoom(level);
293
339
  call.resolve();
294
340
  } catch (Exception e) {
295
341
  call.reject("Failed to set zoom: " + e.getMessage());
@@ -1191,4 +1237,22 @@ public class CameraPreview
1191
1237
  call.resolve(ret);
1192
1238
  });
1193
1239
  }
1240
+
1241
+ @PluginMethod
1242
+ public void deleteFile(PluginCall call) {
1243
+ String path = call.getString("path");
1244
+ if (path == null || path.isEmpty()) {
1245
+ call.reject("path parameter is required");
1246
+ return;
1247
+ }
1248
+ try {
1249
+ java.io.File f = new java.io.File(android.net.Uri.parse(path).getPath());
1250
+ boolean deleted = f.exists() && f.delete();
1251
+ JSObject ret = new JSObject();
1252
+ ret.put("success", deleted);
1253
+ call.resolve(ret);
1254
+ } catch (Exception e) {
1255
+ call.reject("Failed to delete file: " + e.getMessage());
1256
+ }
1257
+ }
1194
1258
  }
@@ -102,6 +102,7 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
102
102
  private GridOverlayView gridOverlayView;
103
103
  private FrameLayout previewContainer;
104
104
  private View focusIndicatorView;
105
+ private long focusIndicatorAnimationId = 0; // Incrementing token to invalidate previous animations
105
106
  private CameraSelector currentCameraSelector;
106
107
  private String currentDeviceId;
107
108
  private int currentFlashMode = ImageCapture.FLASH_MODE_OFF;
@@ -726,7 +727,7 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
726
727
  }
727
728
  }
728
729
 
729
- setZoomInternal(initialZoom);
730
+ setZoom(initialZoom);
730
731
  }
731
732
 
732
733
  isRunning = true;
@@ -1040,12 +1041,40 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1040
1041
  saveImageToGallery(bytes);
1041
1042
  }
1042
1043
 
1043
- String base64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
1044
+ String resultValue;
1045
+ boolean returnFileUri =
1046
+ sessionConfig != null && sessionConfig.isStoreToFile();
1047
+ if (returnFileUri) {
1048
+ // Persist processed image to a file and return its URI to avoid heavy base64 bridging
1049
+ try {
1050
+ String fileName =
1051
+ "cpcp_" +
1052
+ new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(
1053
+ new java.util.Date()
1054
+ ) +
1055
+ ".jpg";
1056
+ File outDir = context.getCacheDir();
1057
+ File outFile = new File(outDir, fileName);
1058
+ FileOutputStream outFos = new FileOutputStream(outFile);
1059
+ outFos.write(bytes);
1060
+ outFos.close();
1061
+
1062
+ // Return a file path; apps can convert via Capacitor.convertFileSrc on JS side
1063
+ resultValue = outFile.getAbsolutePath();
1064
+ } catch (IOException ioEx) {
1065
+ Log.e(TAG, "capturePhoto: Failed to write image file", ioEx);
1066
+ // Fallback to base64 if file write fails
1067
+ resultValue = Base64.encodeToString(bytes, Base64.NO_WRAP);
1068
+ }
1069
+ } else {
1070
+ // Backward-compatible behavior
1071
+ resultValue = Base64.encodeToString(bytes, Base64.NO_WRAP);
1072
+ }
1044
1073
 
1045
1074
  tempFile.delete();
1046
1075
 
1047
1076
  if (listener != null) {
1048
- listener.onPictureTaken(base64, exifData);
1077
+ listener.onPictureTaken(resultValue, exifData);
1049
1078
  }
1050
1079
  } catch (Exception e) {
1051
1080
  Log.e(TAG, "capturePhoto: Error processing image", e);
@@ -1605,7 +1634,7 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1605
1634
  }
1606
1635
  }
1607
1636
 
1608
- public void setZoom(float zoomRatio, boolean autoFocus) throws Exception {
1637
+ public void setZoom(float zoomRatio) throws Exception {
1609
1638
  if (camera == null) {
1610
1639
  throw new Exception("Camera not initialized");
1611
1640
  }
@@ -1614,26 +1643,16 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1614
1643
 
1615
1644
  // Just let CameraX handle everything - it should automatically switch lenses
1616
1645
  try {
1617
- ListenableFuture<Void> zoomFuture = camera
1618
- .getCameraControl()
1619
- .setZoomRatio(zoomRatio);
1646
+ ZoomFactors zoomFactors = getZoomFactors();
1620
1647
 
1621
- // Add callback to see what actually happened
1622
- zoomFuture.addListener(
1623
- () -> {
1624
- try {
1625
- zoomFuture.get();
1626
- Log.d(TAG, "Zoom successfully set to " + zoomRatio);
1627
- // Trigger autofocus after zoom if requested
1628
- if (autoFocus) {
1629
- triggerAutoFocus();
1630
- }
1631
- } catch (Exception e) {
1632
- Log.e(TAG, "Error setting zoom: " + e.getMessage());
1633
- }
1634
- },
1635
- ContextCompat.getMainExecutor(context)
1636
- );
1648
+ if (zoomRatio < zoomFactors.getMin()) {
1649
+ zoomRatio = zoomFactors.getMin();
1650
+ } else if (zoomRatio > zoomFactors.getMax()) {
1651
+ zoomRatio = zoomFactors.getMax();
1652
+ }
1653
+
1654
+ camera.getCameraControl().setZoomRatio(zoomRatio);
1655
+ // Note: autofocus is intentionally not triggered on zoom because it's done by CameraX
1637
1656
  } catch (Exception e) {
1638
1657
  Log.e(TAG, "Failed to set zoom: " + e.getMessage());
1639
1658
  throw e;
@@ -1748,8 +1767,11 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1748
1767
  return;
1749
1768
  }
1750
1769
 
1751
- // Remove any existing focus indicator
1770
+ // Remove any existing focus indicator and cancel its animation
1752
1771
  if (focusIndicatorView != null) {
1772
+ try {
1773
+ focusIndicatorView.clearAnimation();
1774
+ } catch (Exception ignore) {}
1753
1775
  previewContainer.removeView(focusIndicatorView);
1754
1776
  focusIndicatorView = null;
1755
1777
  }
@@ -1783,11 +1805,14 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1783
1805
  container.setBackground(drawable);
1784
1806
 
1785
1807
  focusIndicatorView = container;
1808
+ // Bump animation token; everything after this must validate against this token
1809
+ final long thisAnimationId = ++focusIndicatorAnimationId;
1810
+ final View thisIndicatorView = focusIndicatorView;
1786
1811
 
1787
1812
  // Set initial state for smooth animation
1788
1813
  focusIndicatorView.setAlpha(1f); // Start visible
1789
- focusIndicatorView.setScaleX(1.8f); // Start larger for scale-in effect
1790
- focusIndicatorView.setScaleY(1.8f);
1814
+ focusIndicatorView.setScaleX(1.4f); // Start slightly larger for a quick scale-in
1815
+ focusIndicatorView.setScaleY(1.4f);
1791
1816
  focusIndicatorView.setVisibility(View.VISIBLE);
1792
1817
 
1793
1818
  // Ensure container doesn't intercept touch events
@@ -1813,16 +1838,16 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1813
1838
 
1814
1839
  // Smooth scale down animation with easing (no fade needed since we start visible)
1815
1840
  ScaleAnimation scaleAnimation = new ScaleAnimation(
1816
- 1.8f,
1841
+ 1.4f,
1817
1842
  1.0f,
1818
- 1.8f,
1843
+ 1.4f,
1819
1844
  1.0f,
1820
1845
  Animation.RELATIVE_TO_SELF,
1821
1846
  0.5f,
1822
1847
  Animation.RELATIVE_TO_SELF,
1823
1848
  0.5f
1824
1849
  );
1825
- scaleAnimation.setDuration(300);
1850
+ scaleAnimation.setDuration(120);
1826
1851
  scaleAnimation.setInterpolator(
1827
1852
  new android.view.animation.OvershootInterpolator(1.2f)
1828
1853
  );
@@ -1830,108 +1855,50 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1830
1855
  // Start the animation
1831
1856
  focusIndicatorView.startAnimation(scaleAnimation);
1832
1857
 
1833
- // Schedule fade out and removal with smoother timing
1858
+ // Schedule fast fade out and removal
1834
1859
  focusIndicatorView.postDelayed(
1835
1860
  new Runnable() {
1836
1861
  @Override
1837
1862
  public void run() {
1838
- if (focusIndicatorView != null) {
1839
- // Smooth fade to semi-transparent
1840
- AlphaAnimation fadeToTransparent = new AlphaAnimation(1f, 0.4f);
1841
- fadeToTransparent.setDuration(400);
1842
- fadeToTransparent.setInterpolator(
1843
- new android.view.animation.AccelerateInterpolator()
1844
- );
1845
-
1846
- fadeToTransparent.setAnimationListener(
1847
- new Animation.AnimationListener() {
1848
- @Override
1849
- public void onAnimationStart(Animation animation) {
1850
- Log.d(TAG, "showFocusIndicator: Fade to transparent started");
1851
- }
1852
-
1853
- @Override
1854
- public void onAnimationEnd(Animation animation) {
1855
- Log.d(
1856
- TAG,
1857
- "showFocusIndicator: Fade to transparent ended, starting final fade out"
1858
- );
1859
- // Final smooth fade out and scale down
1860
- if (focusIndicatorView != null) {
1861
- AnimationSet finalAnimation = new AnimationSet(false);
1862
-
1863
- AlphaAnimation finalFadeOut = new AlphaAnimation(0.4f, 0f);
1864
- finalFadeOut.setDuration(500);
1865
- finalFadeOut.setStartOffset(300);
1866
- finalFadeOut.setInterpolator(
1867
- new android.view.animation.AccelerateInterpolator()
1868
- );
1869
-
1870
- ScaleAnimation finalScaleDown = new ScaleAnimation(
1871
- 1.0f,
1872
- 0.9f,
1873
- 1.0f,
1874
- 0.9f,
1875
- Animation.RELATIVE_TO_SELF,
1876
- 0.5f,
1877
- Animation.RELATIVE_TO_SELF,
1878
- 0.5f
1879
- );
1880
- finalScaleDown.setDuration(500);
1881
- finalScaleDown.setStartOffset(300);
1882
- finalScaleDown.setInterpolator(
1883
- new android.view.animation.AccelerateInterpolator()
1884
- );
1885
-
1886
- finalAnimation.addAnimation(finalFadeOut);
1887
- finalAnimation.addAnimation(finalScaleDown);
1888
-
1889
- finalAnimation.setAnimationListener(
1890
- new Animation.AnimationListener() {
1891
- @Override
1892
- public void onAnimationStart(Animation animation) {
1893
- Log.d(
1894
- TAG,
1895
- "showFocusIndicator: Final animation started"
1896
- );
1897
- }
1898
-
1899
- @Override
1900
- public void onAnimationEnd(Animation animation) {
1901
- Log.d(
1902
- TAG,
1903
- "showFocusIndicator: Final animation ended, removing indicator"
1904
- );
1905
- // Remove the focus indicator
1906
- if (
1907
- focusIndicatorView != null &&
1908
- previewContainer != null
1909
- ) {
1910
- previewContainer.removeView(focusIndicatorView);
1911
- focusIndicatorView = null;
1912
- }
1913
- }
1914
-
1915
- @Override
1916
- public void onAnimationRepeat(Animation animation) {}
1917
- }
1918
- );
1919
-
1920
- focusIndicatorView.startAnimation(finalAnimation);
1863
+ // Ensure this runnable belongs to the latest indicator
1864
+ if (
1865
+ focusIndicatorView != null &&
1866
+ thisIndicatorView == focusIndicatorView &&
1867
+ thisAnimationId == focusIndicatorAnimationId
1868
+ ) {
1869
+ focusIndicatorView
1870
+ .animate()
1871
+ .alpha(0f)
1872
+ .scaleX(0.9f)
1873
+ .scaleY(0.9f)
1874
+ .setDuration(180)
1875
+ .setInterpolator(
1876
+ new android.view.animation.AccelerateInterpolator()
1877
+ )
1878
+ .withEndAction(
1879
+ new Runnable() {
1880
+ @Override
1881
+ public void run() {
1882
+ if (
1883
+ focusIndicatorView != null &&
1884
+ previewContainer != null &&
1885
+ thisIndicatorView == focusIndicatorView &&
1886
+ thisAnimationId == focusIndicatorAnimationId
1887
+ ) {
1888
+ try {
1889
+ focusIndicatorView.clearAnimation();
1890
+ } catch (Exception ignore) {}
1891
+ previewContainer.removeView(focusIndicatorView);
1892
+ focusIndicatorView = null;
1893
+ }
1921
1894
  }
1922
1895
  }
1923
-
1924
- @Override
1925
- public void onAnimationRepeat(Animation animation) {}
1926
- }
1927
- );
1928
-
1929
- focusIndicatorView.startAnimation(fadeToTransparent);
1896
+ );
1930
1897
  }
1931
1898
  }
1932
1899
  },
1933
- 800
1934
- ); // Optimal timing for smooth focus feedback
1900
+ 250
1901
+ ); // Faster feedback
1935
1902
  }
1936
1903
 
1937
1904
  public static List<Size> getSupportedPictureSizes(String facing) {
@@ -1957,89 +1924,6 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
1957
1924
  return sizes;
1958
1925
  }
1959
1926
 
1960
- private void setZoomInternal(float zoomRatio) {
1961
- if (camera != null) {
1962
- try {
1963
- float minZoom = Objects.requireNonNull(
1964
- camera.getCameraInfo().getZoomState().getValue()
1965
- ).getMinZoomRatio();
1966
- float maxZoom = camera
1967
- .getCameraInfo()
1968
- .getZoomState()
1969
- .getValue()
1970
- .getMaxZoomRatio();
1971
- float currentZoom = camera
1972
- .getCameraInfo()
1973
- .getZoomState()
1974
- .getValue()
1975
- .getZoomRatio();
1976
-
1977
- Log.d(
1978
- TAG,
1979
- "setZoomInternal: Current camera range: " +
1980
- minZoom +
1981
- "-" +
1982
- maxZoom +
1983
- ", current: " +
1984
- currentZoom
1985
- );
1986
- Log.d(TAG, "setZoomInternal: Requesting zoom: " + zoomRatio);
1987
-
1988
- // Try to set zoom directly - let CameraX handle lens switching
1989
- ListenableFuture<Void> zoomFuture = camera
1990
- .getCameraControl()
1991
- .setZoomRatio(zoomRatio);
1992
-
1993
- zoomFuture.addListener(
1994
- () -> {
1995
- try {
1996
- zoomFuture.get(); // Check if zoom was successful
1997
- float newZoom = Objects.requireNonNull(
1998
- camera.getCameraInfo().getZoomState().getValue()
1999
- ).getZoomRatio();
2000
- Log.d(
2001
- TAG,
2002
- "setZoomInternal: Zoom set successfully to " +
2003
- newZoom +
2004
- " (requested: " +
2005
- zoomRatio +
2006
- ")"
2007
- );
2008
-
2009
- // Check if CameraX switched cameras
2010
- String newCameraId = getCameraId(camera.getCameraInfo());
2011
- if (!newCameraId.equals(currentDeviceId)) {
2012
- currentDeviceId = newCameraId;
2013
- Log.d(
2014
- TAG,
2015
- "setZoomInternal: CameraX switched to camera: " + newCameraId
2016
- );
2017
- }
2018
- } catch (Exception e) {
2019
- Log.w(
2020
- TAG,
2021
- "setZoomInternal: Zoom operation failed: " + e.getMessage()
2022
- );
2023
- // Fallback: clamp to current camera's range
2024
- float clampedZoom = Math.max(
2025
- minZoom,
2026
- Math.min(zoomRatio, maxZoom)
2027
- );
2028
- camera.getCameraControl().setZoomRatio(clampedZoom);
2029
- Log.d(
2030
- TAG,
2031
- "setZoomInternal: Fallback - clamped zoom to " + clampedZoom
2032
- );
2033
- }
2034
- },
2035
- mainExecutor
2036
- );
2037
- } catch (Exception e) {
2038
- Log.e(TAG, "setZoomInternal: Error setting zoom", e);
2039
- }
2040
- }
2041
- }
2042
-
2043
1927
  public static List<String> getSupportedFlashModesStatic() {
2044
1928
  try {
2045
1929
  // For static method, we can return common flash modes
package/dist/docs.json CHANGED
@@ -471,6 +471,16 @@
471
471
  ],
472
472
  "slug": "getzoom"
473
473
  },
474
+ {
475
+ "name": "getZoomButtonValues",
476
+ "signature": "() => Promise<{ values: number[]; }>",
477
+ "parameters": [],
478
+ "returns": "Promise<{ values: number[]; }>",
479
+ "tags": [],
480
+ "docs": "Returns zoom button values for quick switching.\n- iOS/Android: includes 0.5 if ultra-wide available; 1 and 2 if wide available; 3 if telephoto available\n- Web: unsupported",
481
+ "complexTypes": [],
482
+ "slug": "getzoombuttonvalues"
483
+ },
474
484
  {
475
485
  "name": "setZoom",
476
486
  "signature": "(options: { level: number; ramp?: boolean; autoFocus?: boolean; }) => Promise<void>",
@@ -651,6 +661,29 @@
651
661
  "docs": "Sets the camera focus to a specific point in the preview.",
652
662
  "complexTypes": [],
653
663
  "slug": "setfocus"
664
+ },
665
+ {
666
+ "name": "addListener",
667
+ "signature": "(eventName: \"screenResize\", listenerFunc: (data: { width: number; height: number; x: number; y: number; }) => void) => Promise<PluginListenerHandle>",
668
+ "parameters": [
669
+ {
670
+ "name": "eventName",
671
+ "docs": "",
672
+ "type": "'screenResize'"
673
+ },
674
+ {
675
+ "name": "listenerFunc",
676
+ "docs": "",
677
+ "type": "(data: { width: number; height: number; x: number; y: number; }) => void"
678
+ }
679
+ ],
680
+ "returns": "Promise<PluginListenerHandle>",
681
+ "tags": [],
682
+ "docs": "",
683
+ "complexTypes": [
684
+ "PluginListenerHandle"
685
+ ],
686
+ "slug": "addlistenerscreenresize-"
654
687
  }
655
688
  ],
656
689
  "properties": []
@@ -1357,6 +1390,22 @@
1357
1390
  "type": "number"
1358
1391
  }
1359
1392
  ]
1393
+ },
1394
+ {
1395
+ "name": "PluginListenerHandle",
1396
+ "slug": "pluginlistenerhandle",
1397
+ "docs": "",
1398
+ "tags": [],
1399
+ "methods": [],
1400
+ "properties": [
1401
+ {
1402
+ "name": "remove",
1403
+ "tags": [],
1404
+ "docs": "",
1405
+ "complexTypes": [],
1406
+ "type": "() => Promise<void>"
1407
+ }
1408
+ ]
1360
1409
  }
1361
1410
  ],
1362
1411
  "enums": [
@@ -1,3 +1,4 @@
1
+ import type { PluginListenerHandle } from "@capacitor/core";
1
2
  export type CameraPosition = "rear" | "front";
2
3
  export type FlashMode = CameraPreviewFlashMode;
3
4
  export type GridMode = "none" | "3x3" | "4x4";
@@ -487,6 +488,14 @@ export interface CameraPreviewPlugin {
487
488
  current: number;
488
489
  lens: LensInfo;
489
490
  }>;
491
+ /**
492
+ * Returns zoom button values for quick switching.
493
+ * - iOS/Android: includes 0.5 if ultra-wide available; 1 and 2 if wide available; 3 if telephoto available
494
+ * - Web: unsupported
495
+ */
496
+ getZoomButtonValues(): Promise<{
497
+ values: number[];
498
+ }>;
490
499
  /**
491
500
  * Sets the zoom level of the camera.
492
501
  *
@@ -572,4 +581,10 @@ export interface CameraPreviewPlugin {
572
581
  x: number;
573
582
  y: number;
574
583
  }): Promise<void>;
584
+ addListener(eventName: "screenResize", listenerFunc: (data: {
585
+ width: number;
586
+ height: number;
587
+ x: number;
588
+ y: number;
589
+ }) => void): Promise<PluginListenerHandle>;
575
590
  }