capacitor-camera-view 2.4.0 → 3.0.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.
Files changed (44) hide show
  1. package/CapacitorCameraView.podspec +1 -1
  2. package/Package.swift +1 -1
  3. package/README.md +341 -49
  4. package/android/build.gradle +0 -1
  5. package/android/src/main/AndroidManifest.xml +0 -1
  6. package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraError.kt +42 -0
  7. package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraView.kt +945 -207
  8. package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraViewPlugin.kt +87 -43
  9. package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/BarcodeDetectionResult.kt +28 -2
  10. package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/CameraDevice.kt +6 -1
  11. package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/CameraSessionConfiguration.kt +15 -1
  12. package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/TorchModeState.kt +15 -0
  13. package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/WebBoundingRect.kt +1 -1
  14. package/android/src/main/java/com/michaelwolz/capacitorcameraview/utils.kt +73 -19
  15. package/dist/docs.json +475 -30
  16. package/dist/esm/definitions.d.ts +478 -26
  17. package/dist/esm/definitions.js.map +1 -1
  18. package/dist/esm/utils.d.ts +59 -15
  19. package/dist/esm/utils.js +79 -38
  20. package/dist/esm/utils.js.map +1 -1
  21. package/dist/esm/web.d.ts +191 -13
  22. package/dist/esm/web.js +624 -141
  23. package/dist/esm/web.js.map +1 -1
  24. package/dist/plugin.cjs.js +711 -179
  25. package/dist/plugin.cjs.js.map +1 -1
  26. package/dist/plugin.js +711 -179
  27. package/dist/plugin.js.map +1 -1
  28. package/ios/Sources/CameraViewPlugin/CameraError.swift +147 -2
  29. package/ios/Sources/CameraViewPlugin/CameraEvents.swift +41 -19
  30. package/ios/Sources/CameraViewPlugin/CameraSessionConfiguration.swift +29 -1
  31. package/ios/Sources/CameraViewPlugin/CameraViewManager+BarcodeScan.swift +78 -23
  32. package/ios/Sources/CameraViewPlugin/CameraViewManager+DeferredStart.swift +37 -0
  33. package/ios/Sources/CameraViewPlugin/CameraViewManager+Focus.swift +131 -0
  34. package/ios/Sources/CameraViewPlugin/CameraViewManager+Lifecycle.swift +156 -0
  35. package/ios/Sources/CameraViewPlugin/CameraViewManager+PhotoCapture.swift +73 -41
  36. package/ios/Sources/CameraViewPlugin/CameraViewManager+ResolutionSelection.swift +57 -0
  37. package/ios/Sources/CameraViewPlugin/CameraViewManager+Rotation.swift +195 -0
  38. package/ios/Sources/CameraViewPlugin/CameraViewManager+VideoDataOutput.swift +24 -12
  39. package/ios/Sources/CameraViewPlugin/CameraViewManager+VideoRecording.swift +22 -73
  40. package/ios/Sources/CameraViewPlugin/CameraViewManager+Zoom.swift +113 -0
  41. package/ios/Sources/CameraViewPlugin/CameraViewManager.swift +450 -403
  42. package/ios/Sources/CameraViewPlugin/CameraViewPlugin.swift +98 -65
  43. package/ios/Sources/CameraViewPlugin/Utils.swift +61 -7
  44. package/package.json +25 -9
package/dist/esm/web.d.ts CHANGED
@@ -1,6 +1,94 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
- import type { CameraSessionConfiguration, CameraViewPlugin, CameraPermissionType, GetAvailableDevicesResponse, GetFlashModeResponse, GetSupportedFlashModesResponse, GetTorchModeResponse, GetZoomResponse, IsTorchAvailableResponse, IsRunningResponse, PermissionStatus, CaptureResponse, FlashMode, CaptureOptions, VideoRecordingOptions, VideoRecordingResponse, BarcodeType } from './definitions';
3
- export declare const BARCODE_TYPE_TO_WEB_FORMAT: Readonly<Record<BarcodeType, BarcodeFormat | null>>;
2
+ import type { CameraSessionConfiguration, CameraViewPlugin, CameraErrorCode, CameraPermissionType, GetAvailableDevicesResponse, GetFlashModeResponse, GetSupportedFlashModesResponse, GetTorchModeResponse, GetZoomResponse, IsTorchAvailableResponse, IsRunningResponse, PermissionStatus, CaptureResponse, FlashMode, CaptureOptions, VideoRecordingOptions, VideoRecordingResponse, BarcodeType } from './definitions';
3
+ /**
4
+ * Suppression window in milliseconds during which a repeat of the same barcode
5
+ * (identical value + type) is not re-emitted. A genuinely new code still emits
6
+ * immediately. Kept consistent with the iOS and Android implementations.
7
+ */
8
+ export declare const BARCODE_SUPPRESSION_WINDOW_MS = 500;
9
+ /**
10
+ * Once the per-key dedupe map grows past this size, expired entries are pruned
11
+ * so a long session scanning many different codes stays bounded. Kept
12
+ * consistent with the iOS and Android implementations.
13
+ */
14
+ export declare const BARCODE_DEDUPE_MAP_PRUNE_THRESHOLD = 64;
15
+ /**
16
+ * Backstop for the "wait until the video is ready" step in
17
+ * {@link CameraViewWeb.startBarcodeDetection}. If the video element never
18
+ * fires `loadeddata` (e.g. a stalled stream), the wait settles anyway after
19
+ * this many milliseconds instead of leaving a dangling listener and a
20
+ * permanently pending promise.
21
+ */
22
+ export declare const BARCODE_VIDEO_READY_TIMEOUT_MS = 5000;
23
+ /**
24
+ * Baseline `ideal` capture resolution requested from `getUserMedia` in
25
+ * {@link CameraViewWeb.start}. Without any width/height hint, browsers default
26
+ * to a low-resolution stream (often 640x480), which caps capture quality.
27
+ *
28
+ * These are `ideal` (not `exact`/`min`) so devices that cannot deliver
29
+ * 1080p-class video still start at their best available resolution rather
30
+ * than failing acquisition.
31
+ */
32
+ export declare const DEFAULT_IDEAL_CAPTURE_WIDTH = 1920;
33
+ export declare const DEFAULT_IDEAL_CAPTURE_HEIGHT = 1080;
34
+ /**
35
+ * Bounds for the CSS `transform: scale()` zoom simulation used when the browser
36
+ * does not expose a native `zoom` track capability. `getZoom` reports this
37
+ * range and `setZoom` clamps the applied scale to it in fallback mode.
38
+ */
39
+ export declare const SIMULATED_ZOOM_MIN = 1;
40
+ export declare const SIMULATED_ZOOM_MAX = 3;
41
+ export declare const BARCODE_TYPE_TO_WEB_FORMAT: {
42
+ qr: "qr_code";
43
+ code128: "code_128";
44
+ code39: "code_39";
45
+ code39Mod43: null;
46
+ code93: "code_93";
47
+ codabar: "codabar";
48
+ ean8: "ean_8";
49
+ ean13: "ean_13";
50
+ interleaved2of5: "itf";
51
+ itf14: "itf";
52
+ pdf417: "pdf417";
53
+ aztec: "aztec";
54
+ dataMatrix: "data_matrix";
55
+ upcA: "upc_a";
56
+ upce: "upc_e";
57
+ };
58
+ /**
59
+ * Inverse of {@link BARCODE_TYPE_TO_WEB_FORMAT}: maps the web BarcodeDetector
60
+ * format back onto the cross-platform {@link BarcodeType} vocabulary so the
61
+ * `barcodeDetected` event emits the same `type` values as iOS and Android.
62
+ *
63
+ * Note: `interleaved2of5` and `itf14` both map to the web format `itf`, so the
64
+ * inversion has a collision that is resolved by insertion order — `itf14` comes
65
+ * last in {@link BARCODE_TYPE_TO_WEB_FORMAT} and wins, which is the intended
66
+ * result for `itf` detections.
67
+ */
68
+ export declare const WEB_FORMAT_TO_BARCODE_TYPE: Readonly<Partial<Record<BarcodeFormat, BarcodeType>>>;
69
+ /**
70
+ * Error thrown by the web implementation for a rejected plugin call.
71
+ *
72
+ * Carries a stable `code` from the {@link CameraErrorCode} vocabulary, the
73
+ * same public contract iOS and Android provide, so consumers can `switch` on
74
+ * `error.code` instead of matching on the human-readable `message`.
75
+ *
76
+ * Methods that reject via `WebPlugin.unimplemented()` are the one exception:
77
+ * those keep Capacitor's own `UNIMPLEMENTED` convention.
78
+ */
79
+ export declare class CameraViewError extends Error {
80
+ readonly code: CameraErrorCode;
81
+ constructor(message: string, code: CameraErrorCode);
82
+ }
83
+ /**
84
+ * Classifies a `getUserMedia` failure into the closest-fitting
85
+ * {@link CameraErrorCode}, shared by every acquisition site.
86
+ *
87
+ * `kind` selects which media type's dedicated codes apply for `NotFoundError`/
88
+ * `NotReadableError` so a missing/busy camera and a missing/busy microphone
89
+ * aren't conflated. Anything unmappable falls back to `UNKNOWN_ERROR`.
90
+ */
91
+ export declare function classifyGetUserMediaErrorCode(err: unknown, kind: 'camera' | 'microphone'): CameraErrorCode;
4
92
  /**
5
93
  * Web implementation of the CameraViewPlugin.
6
94
  * Optimized for performance and battery efficiency.
@@ -12,9 +100,15 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
12
100
  private stream;
13
101
  private currentCamera;
14
102
  private currentZoom;
103
+ private usingNativeZoom;
15
104
  private currentFlashMode;
105
+ private sessionAspectRatio;
106
+ private sessionPreviewScaleMode;
107
+ private sessionResolutionConstraints;
16
108
  private barcodeDetectionSupported;
17
109
  private barcodeDetector;
110
+ private barcodeDetectionAbortController;
111
+ private barcodeAnimationFrameId;
18
112
  private mediaRecorder;
19
113
  private recordedChunks;
20
114
  private recordingAudioTrack;
@@ -25,6 +119,26 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
25
119
  * Start the camera with the given configuration
26
120
  */
27
121
  start(options?: CameraSessionConfiguration): Promise<void>;
122
+ /**
123
+ * Builds the resolution/aspect-ratio part of the `getUserMedia` video
124
+ * constraints for a session.
125
+ *
126
+ * `captureMaxDimension` replaces the ideal width (the longer edge in the
127
+ * stream's landscape-oriented coordinate space) and the ideal height is
128
+ * derived from the configured ratio. Everything stays `ideal` so acquisition
129
+ * degrades gracefully on devices that cannot deliver the request.
130
+ */
131
+ private buildResolutionConstraints;
132
+ /**
133
+ * Map a `getUserMedia` failure from the real-constraints acquisition in
134
+ * `start()` onto the plugin's error contract.
135
+ *
136
+ * `NotAllowedError` maps to `PERMISSION_DENIED`, `NotFoundError` (no
137
+ * matching device) to `CAMERA_UNAVAILABLE`, and `NotReadableError` (device
138
+ * claimed by another process) to `DEVICE_LOCKED`, matching the codes
139
+ * iOS/Android use. Anything else falls back to `UNKNOWN_ERROR`.
140
+ */
141
+ private mapStartAcquisitionError;
28
142
  /**
29
143
  * Stop the camera and release resources
30
144
  */
@@ -37,15 +151,28 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
37
151
  * Capture a photo using the camera and return it as a base64-encoded JPEG image.
38
152
  * Preserves what the user actually sees in the UI, including cropping from object-fit: cover.
39
153
  */
40
- capture<T extends CaptureOptions>(options: T): Promise<CaptureResponse<T>>;
154
+ capture<T extends CaptureOptions = CaptureOptions & {
155
+ saveToFile?: undefined;
156
+ }>(options?: T): Promise<CaptureResponse<T>>;
41
157
  /**
42
158
  * Web implementation already uses images from the video stream, so this is the same as `capture()`
43
159
  */
44
- captureSample<T extends CaptureOptions>(options: T): Promise<CaptureResponse<T>>;
160
+ captureSample<T extends CaptureOptions = CaptureOptions & {
161
+ saveToFile?: undefined;
162
+ }>(options?: T): Promise<CaptureResponse<T>>;
45
163
  /**
46
164
  * Start recording video using MediaRecorder API
47
165
  */
48
166
  startRecording(options?: VideoRecordingOptions): Promise<void>;
167
+ /**
168
+ * Maps a failure caught by `startRecording()`'s try/catch onto the closest-
169
+ * fitting `CameraErrorCode`, without altering the existing wrapped message.
170
+ *
171
+ * A `DOMException` here can only come from the microphone `getUserMedia`
172
+ * call, so it is classified with `kind: 'microphone'`. The two other
173
+ * distinguishable failures are plain `Error`s matched by message text.
174
+ */
175
+ private mapRecordingStartErrorCode;
49
176
  /**
50
177
  * Stop the current video recording
51
178
  */
@@ -55,20 +182,60 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
55
182
  */
56
183
  flipCamera(): Promise<void>;
57
184
  /**
58
- * Get available camera devices
185
+ * Get available camera devices.
186
+ *
187
+ * Position detection prefers the `facingMode` capability of the active video
188
+ * track, since it is a standardized signal rather than a locale-dependent
189
+ * string. Every other device falls back to matching the English word "front"
190
+ * in `device.label` — which is empty for all devices until camera permission
191
+ * has been granted once, so the fallback resolves to `'back'` in that case.
59
192
  */
60
193
  getAvailableDevices(): Promise<GetAvailableDevicesResponse>;
61
194
  /**
62
- * Get current zoom information (web has limited zoom support)
195
+ * Get current zoom information.
196
+ *
197
+ * When the active video track exposes a native `zoom` capability (Chromium
198
+ * on capable cameras), the real min/max/current are reported. Otherwise the
199
+ * simulated CSS-scale range is returned.
63
200
  */
64
201
  getZoom(): Promise<GetZoomResponse>;
65
202
  /**
66
- * Set zoom level (limited support in web)
203
+ * Set the zoom level.
204
+ *
205
+ * Prefers real zoom via `track.applyConstraints({ advanced: [{ zoom }] })`
206
+ * when the browser exposes the native `zoom` capability, clamping to the
207
+ * reported range. Falls back to a CSS `transform: scale()` simulation
208
+ * otherwise.
67
209
  */
68
210
  setZoom(options: {
69
211
  level: number;
70
212
  ramp?: boolean;
71
213
  }): Promise<void>;
214
+ /**
215
+ * The video track backing the active stream, or `null`.
216
+ */
217
+ private getVideoTrack;
218
+ /**
219
+ * Reads the native `zoom` capability off a track, if the browser both
220
+ * supports `getCapabilities()` and exposes a usable `zoom` range on this
221
+ * device. Returns `null` when native zoom is unavailable (CSS fallback).
222
+ */
223
+ private getNativeZoomCapability;
224
+ /**
225
+ * The effective CSS `transform: scale()` factor currently applied to the
226
+ * preview: `1` when native zoom is in use (no transform), otherwise
227
+ * `currentZoom` clamped to the simulated range. Used both to set the
228
+ * transform and to compensate captures for it.
229
+ */
230
+ private getCssZoomScale;
231
+ /**
232
+ * Set the focus/metering point (not supported in web).
233
+ *
234
+ * The `pointsOfInterest` media-track constraint has effectively no browser
235
+ * support, so this rejects with `unimplemented` rather than silently doing
236
+ * nothing. Left as a hook for a future implementation.
237
+ */
238
+ setFocusPoint(): Promise<void>;
72
239
  /**
73
240
  * Get current flash mode
74
241
  */
@@ -78,7 +245,10 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
78
245
  */
79
246
  getSupportedFlashModes(): Promise<GetSupportedFlashModesResponse>;
80
247
  /**
81
- * Set flash mode (limited support in web)
248
+ * Set flash mode (limited support in web).
249
+ *
250
+ * Only `'off'` is supported on web; any other mode rejects rather than
251
+ * silently accepting a mode it cannot apply.
82
252
  */
83
253
  setFlashMode(options: {
84
254
  mode: FlashMode;
@@ -88,7 +258,11 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
88
258
  */
89
259
  isTorchAvailable(): Promise<IsTorchAvailableResponse>;
90
260
  /**
91
- * Get torch mode (not supported in web)
261
+ * Get torch mode (not supported in web).
262
+ *
263
+ * Follows the documented contract for `getTorchMode()`: callers must check
264
+ * `isTorchAvailable()` first, which always reports `false` on web, so this throws
265
+ * rather than returning a fabricated "off" state.
92
266
  */
93
267
  getTorchMode(): Promise<GetTorchModeResponse>;
94
268
  /**
@@ -99,6 +273,14 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
99
273
  * Check camera and microphone permission without requesting
100
274
  */
101
275
  checkPermissions(): Promise<PermissionStatus>;
276
+ /**
277
+ * Resolves the current state of a single permission.
278
+ *
279
+ * Queried independently per permission name so one unsupported query (e.g.
280
+ * Firefox does not support querying `'microphone'`) rejects on its own
281
+ * instead of collapsing *both* permissions to `'prompt'`.
282
+ */
283
+ private checkSinglePermission;
102
284
  /**
103
285
  * Request camera and/or microphone permissions from the user.
104
286
  * By default, only camera permission is requested.
@@ -110,10 +292,6 @@ export declare class CameraViewWeb extends WebPlugin implements CameraViewPlugin
110
292
  * Start barcode detection if supported
111
293
  */
112
294
  private startBarcodeDetection;
113
- /**
114
- * Clean up resources when the plugin is disposed
115
- */
116
- handleOnDestroy(): Promise<void>;
117
295
  /**
118
296
  * Check if barcode detection is supported in this browser
119
297
  */