@symbiote-native/camera 0.0.0 → 0.1.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.
- package/README.md +228 -30
- package/build/core/camera-view-handle.js +10 -4
- package/build/react/index.d.ts +1 -1
- package/build/react/index.js +1 -1
- package/build/solid/index.d.ts +1 -1
- package/build/solid/index.js +1 -1
- package/build/vue/index.d.ts +1 -1
- package/build/vue/index.js +1 -1
- package/build-ngc/core/camera-view-events.js.map +1 -1
- package/build-ngc/core/camera-view-handle.js +10 -4
- package/build-ngc/core/camera-view-handle.js.map +1 -1
- package/build-ngc/core/native-module.js.map +1 -1
- package/package.json +15 -15
- package/src/core/android-barcode.ts +4 -1
- package/src/core/camera-view-events.ts +8 -3
- package/src/core/camera-view-handle.ts +18 -6
- package/src/core/native-module.ts +5 -4
- package/src/core/types.ts +4 -15
- package/src/react/index.ts +4 -1
- package/src/solid/index.ts +4 -1
- package/src/svelte/use-camera-permissions.svelte.ts +1 -3
- package/src/vue/camera-view.ts +4 -1
- package/src/vue/index.ts +4 -1
package/README.md
CHANGED
|
@@ -4,54 +4,252 @@
|
|
|
4
4
|
[SymbioteNative](../../README.md) adapter: React, Vue, Svelte, Solid and Angular. The camera
|
|
5
5
|
preview, pictures, video recording and barcode scanning.
|
|
6
6
|
|
|
7
|
+
Built the same way as [`@symbiote-native/clipboard`](../clipboard)'s `ClipboardPasteButton`, an
|
|
8
|
+
`expo-modules-core` native view reached through `requireNativeViewManager` (see the
|
|
9
|
+
`symbiote-expo-native-module` project skill: why `expo-modules-core` is depended on directly and never
|
|
10
|
+
the `expo` meta-package, why the upstream JS is hand-ported into `core/`, and how autolinking finds the
|
|
11
|
+
native module). One render function in `core/` returns a descriptor and every adapter only turns it into
|
|
12
|
+
its own element.
|
|
13
|
+
|
|
7
14
|
## Install
|
|
8
15
|
|
|
16
|
+
**New app:**
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx @symbiote-native/cli new my-app --camera
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Existing SymbioteNative app:**
|
|
23
|
+
|
|
9
24
|
```bash
|
|
10
|
-
npx @symbiote-native/cli
|
|
11
|
-
npx @symbiote-native/cli add --camera # existing app
|
|
25
|
+
npx @symbiote-native/cli add --camera
|
|
12
26
|
```
|
|
13
27
|
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
Either way: installs `@symbiote-native/camera` and wires the native autolinking automatically,
|
|
29
|
+
see [`@symbiote-native/cli`](../cli).
|
|
30
|
+
|
|
31
|
+
<details>
|
|
32
|
+
<summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @symbiote-native/camera
|
|
36
|
+
```
|
|
16
37
|
|
|
17
|
-
|
|
38
|
+
Depends on `expo-camera` and `expo-modules-core` directly (regular dependencies, pinned to exact
|
|
39
|
+
versions, since this package's `core/` is hand-ported against one specific native API shape).
|
|
40
|
+
Never install `expo-camera` yourself, and never add the `expo` package to this project: it bundles
|
|
41
|
+
its own Metro/Babel pipeline that conflicts with this project's own.
|
|
42
|
+
|
|
43
|
+
### Required one-time step: native autolinking wiring
|
|
44
|
+
|
|
45
|
+
`expo-camera`'s native code is discovered by `expo-modules-autolinking`, not by RN's own
|
|
46
|
+
`react-native.config.cjs` mechanism. Wire it into the native host app **once**, it covers this package
|
|
47
|
+
and every other `expo-modules-core` package with zero further changes. The steps and the
|
|
48
|
+
mechanics behind them are in the `symbiote-expo-native-module` skill and in
|
|
49
|
+
[`@symbiote-native/network`](../network)'s README; the reference app is `examples/expo-react`.
|
|
50
|
+
|
|
51
|
+
### Permissions
|
|
52
|
+
|
|
53
|
+
The package declares what `expo-camera`'s config plugin adds, and the `expo-modules-link` postinstall
|
|
54
|
+
writes it into the app:
|
|
55
|
+
|
|
56
|
+
| File | Entry |
|
|
57
|
+
| --------------------- | ---------------------------------------------------------- |
|
|
58
|
+
| `Info.plist` | `NSCameraUsageDescription`, `NSMicrophoneUsageDescription` |
|
|
59
|
+
| `AndroidManifest.xml` | `CAMERA`, `RECORD_AUDIO` |
|
|
60
|
+
|
|
61
|
+
iOS wants the microphone text even if you only take pictures, because the same view can record. Reword
|
|
62
|
+
both texts to fit your app.
|
|
63
|
+
|
|
64
|
+
</details>
|
|
65
|
+
|
|
66
|
+
## Shape
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
src/core/ camera-view.ts - createCameraView(getNode): render, the handle (camera-view-handle.ts)
|
|
70
|
+
and the barcode throttle. camera-api.ts - the statics of upstream's class and the
|
|
71
|
+
permission calls. props.ts, picture-options.ts, picture-ref.ts, types.ts.
|
|
72
|
+
src/react/ @symbiote-native/camera/react - CameraView, useCameraPermissions, useMicrophonePermissions
|
|
73
|
+
src/vue/ @symbiote-native/camera/vue - the same names
|
|
74
|
+
src/svelte/ @symbiote-native/camera/svelte - the same names ({ status, requestPermission, getPermission })
|
|
75
|
+
src/solid/ @symbiote-native/camera/solid - the same names
|
|
76
|
+
src/angular/ @symbiote-native/camera/angular - CameraView, CameraPermissionsService, MicrophonePermissionsService
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Use it
|
|
80
|
+
|
|
81
|
+
### React
|
|
18
82
|
|
|
19
83
|
```tsx
|
|
84
|
+
import { useRef } from 'react';
|
|
20
85
|
import { CameraView, useCameraPermissions, type ICameraViewHandle } from '@symbiote-native/camera/react';
|
|
21
86
|
|
|
22
87
|
const [permission, requestPermission] = useCameraPermissions();
|
|
23
|
-
const
|
|
88
|
+
const camera = useRef<ICameraViewHandle>(null);
|
|
89
|
+
|
|
90
|
+
return permission?.granted === true ? (
|
|
91
|
+
<>
|
|
92
|
+
<CameraView ref={camera} style={{ flex: 1 }} facing="back" />
|
|
93
|
+
<button title="Take picture" onPress={() => camera.current?.takePictureAsync({ quality: 0.8 })} />
|
|
94
|
+
</>
|
|
95
|
+
) : (
|
|
96
|
+
<button title="Allow the camera" onPress={() => requestPermission()} />
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Vue
|
|
101
|
+
|
|
102
|
+
```vue
|
|
103
|
+
<script setup lang="ts">
|
|
104
|
+
import { ref } from 'vue';
|
|
105
|
+
import { CameraView, useCameraPermissions, type ICameraViewHandle } from '@symbiote-native/camera/vue';
|
|
106
|
+
|
|
107
|
+
const [permission, requestPermission] = useCameraPermissions();
|
|
108
|
+
const camera = ref<ICameraViewHandle | null>(null);
|
|
109
|
+
</script>
|
|
110
|
+
|
|
111
|
+
<template>
|
|
112
|
+
<template v-if="permission?.granted === true">
|
|
113
|
+
<CameraView ref="camera" :style="{ flex: 1 }" facing="back" />
|
|
114
|
+
<button title="Take picture" @press="camera?.takePictureAsync({ quality: 0.8 })" />
|
|
115
|
+
</template>
|
|
116
|
+
<button v-else title="Allow the camera" @press="requestPermission()" />
|
|
117
|
+
</template>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Angular
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { Component, inject } from '@angular/core';
|
|
124
|
+
import { SYMBIOTE_ELEMENTS } from '@symbiote-native/angular';
|
|
125
|
+
import { CameraPermissionsService, CameraView } from '@symbiote-native/camera/angular';
|
|
126
|
+
|
|
127
|
+
@Component({
|
|
128
|
+
standalone: true,
|
|
129
|
+
imports: [CameraView, SYMBIOTE_ELEMENTS],
|
|
130
|
+
template: `
|
|
131
|
+
@if (permission()?.granted === true) {
|
|
132
|
+
<CameraView #camera [style]="{ flex: 1 }" facing="back" />
|
|
133
|
+
<button title="Take picture" (press)="camera.takePictureAsync({ quality: 0.8 })" />
|
|
134
|
+
} @else {
|
|
135
|
+
<button title="Allow the camera" (press)="request()" />
|
|
136
|
+
}
|
|
137
|
+
`,
|
|
138
|
+
})
|
|
139
|
+
export class CameraCard {
|
|
140
|
+
private readonly service = inject(CameraPermissionsService);
|
|
141
|
+
readonly permission = this.service.connect();
|
|
142
|
+
|
|
143
|
+
request(): void {
|
|
144
|
+
void this.service.request();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Svelte
|
|
150
|
+
|
|
151
|
+
```svelte
|
|
152
|
+
<script lang="ts">
|
|
153
|
+
import { CameraView, useCameraPermissions, type ICameraViewHandle } from '@symbiote-native/camera/svelte';
|
|
24
154
|
|
|
25
|
-
|
|
155
|
+
const permission = useCameraPermissions();
|
|
156
|
+
let camera = $state<ICameraViewHandle | undefined>();
|
|
157
|
+
</script>
|
|
26
158
|
|
|
27
|
-
|
|
159
|
+
{#if permission.status?.granted === true}
|
|
160
|
+
<CameraView bind:this={camera} style={{ flex: 1 }} facing="back" />
|
|
161
|
+
<button title="Take picture" onPress={() => camera?.takePictureAsync({ quality: 0.8 })} />
|
|
162
|
+
{:else}
|
|
163
|
+
<button title="Allow the camera" onPress={() => permission.requestPermission()} />
|
|
164
|
+
{/if}
|
|
28
165
|
```
|
|
29
166
|
|
|
30
|
-
|
|
31
|
-
`takePictureAsync`, `recordAsync`, `toggleRecordingAsync`, `stopRecording`, `pausePreview`,
|
|
32
|
-
`resumePreview`, `getAvailablePictureSizesAsync`, `getAvailableLensesAsync` and
|
|
33
|
-
`getSupportedFeatures`. A `ref` carries it in React and Solid (`ref={fn}`), the exposed members of
|
|
34
|
-
a template ref in Vue, `bind:this` in Svelte and `@ViewChild` in Angular.
|
|
167
|
+
### Solid
|
|
35
168
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
`scanFromURLAsync` and `PictureRef` keep their names. The permission hooks are
|
|
40
|
-
`useCameraPermissions` and `useMicrophonePermissions`, in Angular `CameraPermissionsService` and
|
|
41
|
-
`MicrophonePermissionsService`.
|
|
169
|
+
```tsx
|
|
170
|
+
import { Show, createSignal } from 'solid-js';
|
|
171
|
+
import { CameraView, useCameraPermissions, type ICameraViewHandle } from '@symbiote-native/camera/solid';
|
|
42
172
|
|
|
43
|
-
|
|
173
|
+
const [permission, requestPermission] = useCameraPermissions();
|
|
174
|
+
const [camera, setCamera] = createSignal<ICameraViewHandle>();
|
|
175
|
+
|
|
176
|
+
<Show
|
|
177
|
+
when={permission()?.granted === true}
|
|
178
|
+
fallback={<button title="Allow the camera" onPress={() => requestPermission()} />}
|
|
179
|
+
>
|
|
180
|
+
<CameraView ref={setCamera} style={{ flex: 1 }} facing="back" />
|
|
181
|
+
<button title="Take picture" onPress={() => camera()?.takePictureAsync({ quality: 0.8 })} />
|
|
182
|
+
</Show>;
|
|
183
|
+
```
|
|
44
184
|
|
|
45
|
-
|
|
46
|
-
postinstall writes it into the app:
|
|
185
|
+
## API
|
|
47
186
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
187
|
+
```ts
|
|
188
|
+
<CameraView facing? flash? mode? zoom? mute? enableTorch? active? // active is iOS only
|
|
189
|
+
barcodeScannerSettings? onBarcodeScanned? onCameraReady? onMountError? ... />
|
|
190
|
+
// handle: takePictureAsync, recordAsync, toggleRecordingAsync, stopRecording, pausePreview,
|
|
191
|
+
// resumePreview, getAvailablePictureSizesAsync, getAvailableLensesAsync, getSupportedFeatures
|
|
52
192
|
|
|
53
|
-
|
|
193
|
+
isCameraAvailableAsync(): Promise<boolean> // was CameraView.isAvailableAsync
|
|
194
|
+
getAvailableVideoCodecsAsync(): Promise<ICameraVideoCodec[]> // iOS
|
|
195
|
+
launchScanner(options?): Promise<void> dismissScanner(): Promise<void>
|
|
196
|
+
onModernBarcodeScanned(listener): EventSubscription isModernBarcodeScannerAvailable(): boolean
|
|
197
|
+
scanFromURLAsync(url, barcodeTypes = ['qr']): Promise<ICameraBarcodeScanningResult[]>
|
|
198
|
+
Camera.getCameraPermissionsAsync() and the three twins // request and microphone variants
|
|
199
|
+
```
|
|
54
200
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
201
|
+
`PictureRef` keeps its name. Ported from upstream's `CameraView.tsx`, `Camera.ts` and `Camera.types.ts`.
|
|
202
|
+
|
|
203
|
+
## Notes
|
|
204
|
+
|
|
205
|
+
- **The postinstall asks for both permissions.** It writes `NSCameraUsageDescription` and
|
|
206
|
+
`NSMicrophoneUsageDescription` into `Info.plist` and `CAMERA` and `RECORD_AUDIO` into the Android
|
|
207
|
+
manifest. iOS needs the microphone text even if you only take pictures, because the same view can
|
|
208
|
+
record. Reword both texts to fit your app.
|
|
209
|
+
- **Ask first, then render.** Show `CameraView` only once `useCameraPermissions` reports `granted`.
|
|
210
|
+
- **`onBarcodeScanned` turns scanning on.** The scanner is enabled exactly when you pass the prop,
|
|
211
|
+
and `barcodeScannerSettings={{ barcodeTypes: [...] }}` narrows what it looks for.
|
|
212
|
+
- **`CameraView` takes no children.** The native view does not host them, so draw controls and
|
|
213
|
+
frames as siblings, absolutely positioned over it.
|
|
214
|
+
- **The handle works after `onCameraReady`.** `takePictureAsync` and `recordAsync` before that can
|
|
215
|
+
fail or return nothing.
|
|
216
|
+
- **`active={false}` stops the camera session without unmounting the view.** iOS only, it is on by
|
|
217
|
+
default.
|
|
218
|
+
- **Not ported.** The web build (`.web` files, the browser barcode detector) and the plugin's `barcodeScannerEnabled: false` switch, which only trims the native binary size. The only upstream test covers the web manager, the suites here are written against the native behavior.
|
|
219
|
+
|
|
220
|
+
## Common questions
|
|
221
|
+
|
|
222
|
+
- **iOS crash when the camera opens.** A missing usage description. The postinstall writes
|
|
223
|
+
`NSCameraUsageDescription` and `NSMicrophoneUsageDescription`, iOS wants both for the camera view.
|
|
224
|
+
- **Black preview.** Render the view only when permission is `granted`, test on a device (the iOS
|
|
225
|
+
Simulator has no camera) and wait for `onCameraReady` before calling the handle.
|
|
226
|
+
- **The barcode callback.** Passing `onBarcodeScanned` turns the scanner on. To scan once, pass
|
|
227
|
+
`undefined` after the first result.
|
|
228
|
+
- **Children.** `CameraView` takes none, upstream says to overlay a sibling with absolute
|
|
229
|
+
positioning.
|
|
230
|
+
- **Mounting and unmounting freezes or crashes iOS.** Keep the view mounted and set `active={false}`
|
|
231
|
+
(iOS) to stop the session.
|
|
232
|
+
- **Torch turns off at once.** Set `enableTorch` after `onCameraReady`.
|
|
233
|
+
- **System scanner.** `launchScanner()`, iOS 16+ and Google's code scanner on Android.
|
|
234
|
+
|
|
235
|
+
Sources: [Expo docs: Camera](https://docs.expo.dev/versions/latest/sdk/camera/),
|
|
236
|
+
[expo/expo#11736](https://github.com/expo/expo/issues/11736),
|
|
237
|
+
[expo/expo#16126](https://github.com/expo/expo/issues/16126),
|
|
238
|
+
[expo/expo#37150](https://github.com/expo/expo/issues/37150),
|
|
239
|
+
[expo/expo#34957](https://github.com/expo/expo/issues/34957),
|
|
240
|
+
[expo/expo#48780](https://github.com/expo/expo/issues/48780),
|
|
241
|
+
[expo/expo#36352](https://github.com/expo/expo/issues/36352).
|
|
242
|
+
|
|
243
|
+
## Test it
|
|
244
|
+
|
|
245
|
+
No device is needed for the logic. The core tests (`src/core/*.test.ts`) replace `expo-modules-core`
|
|
246
|
+
(`requireNativeViewManager`, `Platform`) and assert the descriptor a render function returns. The
|
|
247
|
+
adapter tests (`src/{react,vue,solid,angular}/**/*.test.*`, `vitest`) render the real component over the
|
|
248
|
+
recording Fabric with an injected view config and assert the committed payload, and Svelte's
|
|
249
|
+
`*.smoke.test.ts` compile the `.svelte` files and mount them. Painting itself is verified on a device in
|
|
250
|
+
the six `examples/expo-*` canary apps (`examples/expo-react`, `examples/expo-vue-sfc`,
|
|
251
|
+
`examples/expo-vue-tsx`, `examples/expo-svelte`, `examples/expo-solid`, `examples/expo-angular`), see the
|
|
252
|
+
parent [README](../../README.md).
|
|
253
|
+
|
|
254
|
+
The permission hooks are tested with a fake native module (`use-camera-permissions.test.*`, the Angular
|
|
255
|
+
service test), the same pattern as every permission package.
|
|
@@ -2,7 +2,7 @@ import { Platform, requireNativeModule } from 'expo-modules-core';
|
|
|
2
2
|
import { defineExpoViewMethods, getNativeTag } from '@symbiote-native/engine';
|
|
3
3
|
import { CAMERA_MODULE_NAME } from './constants.js';
|
|
4
4
|
import { expoCamera } from './native-module.js';
|
|
5
|
-
import { ensurePictureOptions, ensureRecordingOptions } from './picture-options.js';
|
|
5
|
+
import { ensurePictureOptions, ensureRecordingOptions, } from './picture-options.js';
|
|
6
6
|
const callViewFunction = defineExpoViewMethods(requireNativeModule, CAMERA_MODULE_NAME);
|
|
7
7
|
export function createCameraViewHandle(getNode) {
|
|
8
8
|
// Like upstream's `ref.current?.`, a view that has not committed yet answers nothing
|
|
@@ -16,13 +16,19 @@ export function createCameraViewHandle(getNode) {
|
|
|
16
16
|
const pictureOptions = ensurePictureOptions(options);
|
|
17
17
|
// The picture ref is an iOS feature, Android answers a plain picture
|
|
18
18
|
if (Platform.select({ ios: Boolean(options?.pictureRef), default: false })) {
|
|
19
|
-
return call('takePictureRef', [
|
|
19
|
+
return call('takePictureRef', [
|
|
20
|
+
pictureOptions,
|
|
21
|
+
]);
|
|
20
22
|
}
|
|
21
|
-
return call('takePicture', [
|
|
23
|
+
return call('takePicture', [
|
|
24
|
+
pictureOptions,
|
|
25
|
+
]);
|
|
22
26
|
}
|
|
23
27
|
return {
|
|
24
28
|
takePictureAsync,
|
|
25
|
-
recordAsync: async (options) => call('record', [
|
|
29
|
+
recordAsync: async (options) => call('record', [
|
|
30
|
+
ensureRecordingOptions(options),
|
|
31
|
+
]),
|
|
26
32
|
toggleRecordingAsync: async () => call('toggleRecording'),
|
|
27
33
|
stopRecording: () => {
|
|
28
34
|
call('stopRecording');
|
package/build/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CameraView } from './camera-view';
|
|
2
2
|
export type { ICameraViewReactProps } from './camera-view';
|
|
3
|
-
export { useCameraPermissions, useMicrophonePermissions } from './use-camera-permissions';
|
|
3
|
+
export { useCameraPermissions, useMicrophonePermissions, } from './use-camera-permissions';
|
|
4
4
|
export type { IUseCameraPermissionsHook } from './use-camera-permissions';
|
|
5
5
|
export * from '../core';
|
package/build/react/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/camera/react: камера, съёмка, запись видео и сканирование кодов на общем ядре
|
|
2
2
|
export { CameraView } from './camera-view.js';
|
|
3
|
-
export { useCameraPermissions, useMicrophonePermissions } from './use-camera-permissions.js';
|
|
3
|
+
export { useCameraPermissions, useMicrophonePermissions, } from './use-camera-permissions.js';
|
|
4
4
|
export * from '../core/index.js';
|
package/build/solid/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CameraView } from './camera-view';
|
|
2
|
-
export { useCameraPermissions, useMicrophonePermissions } from './use-camera-permissions';
|
|
2
|
+
export { useCameraPermissions, useMicrophonePermissions, } from './use-camera-permissions';
|
|
3
3
|
export type { IUseCameraPermissionsHook } from './use-camera-permissions';
|
|
4
4
|
export * from '../core';
|
package/build/solid/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/camera/solid: камера, съёмка, запись видео и сканирование кодов на общем ядре
|
|
2
2
|
export { CameraView } from './camera-view.js';
|
|
3
|
-
export { useCameraPermissions, useMicrophonePermissions } from './use-camera-permissions.js';
|
|
3
|
+
export { useCameraPermissions, useMicrophonePermissions, } from './use-camera-permissions.js';
|
|
4
4
|
export * from '../core/index.js';
|
package/build/vue/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CameraView } from './camera-view';
|
|
2
|
-
export { useCameraPermissions, useMicrophonePermissions } from './use-camera-permissions';
|
|
2
|
+
export { useCameraPermissions, useMicrophonePermissions, } from './use-camera-permissions';
|
|
3
3
|
export type { IUseCameraPermissionsHook } from './use-camera-permissions';
|
|
4
4
|
export * from '../core';
|
package/build/vue/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/camera/vue: камера, съёмка, запись видео и сканирование кодов на общем ядре
|
|
2
2
|
export { CameraView } from './camera-view.js';
|
|
3
|
-
export { useCameraPermissions, useMicrophonePermissions } from './use-camera-permissions.js';
|
|
3
|
+
export { useCameraPermissions, useMicrophonePermissions, } from './use-camera-permissions.js';
|
|
4
4
|
export * from '../core/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"camera-view-events.js","sourceRoot":"","sources":["../../src/core/camera-view-events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAWvD,SAAS,QAAQ,CAAC,KAAc,EAAE,GAAW,EAAE,IAAY;IACzD,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;AACzD,CAAC;AAED,MAAM,YAAY,GAA8B,
|
|
1
|
+
{"version":3,"file":"camera-view-events.js","sourceRoot":"","sources":["../../src/core/camera-view-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { Platform, requireNativeModule } from 'expo-modules-core';
|
|
|
2
2
|
import { defineExpoViewMethods, getNativeTag } from '@symbiote-native/engine';
|
|
3
3
|
import { CAMERA_MODULE_NAME } from './constants';
|
|
4
4
|
import { expoCamera } from './native-module';
|
|
5
|
-
import { ensurePictureOptions, ensureRecordingOptions } from './picture-options';
|
|
5
|
+
import { ensurePictureOptions, ensureRecordingOptions, } from './picture-options';
|
|
6
6
|
const callViewFunction = defineExpoViewMethods(requireNativeModule, CAMERA_MODULE_NAME);
|
|
7
7
|
export function createCameraViewHandle(getNode) {
|
|
8
8
|
// Like upstream's `ref.current?.`, a view that has not committed yet answers nothing
|
|
@@ -16,13 +16,19 @@ export function createCameraViewHandle(getNode) {
|
|
|
16
16
|
const pictureOptions = ensurePictureOptions(options);
|
|
17
17
|
// The picture ref is an iOS feature, Android answers a plain picture
|
|
18
18
|
if (Platform.select({ ios: Boolean(options?.pictureRef), default: false })) {
|
|
19
|
-
return call('takePictureRef', [
|
|
19
|
+
return call('takePictureRef', [
|
|
20
|
+
pictureOptions,
|
|
21
|
+
]);
|
|
20
22
|
}
|
|
21
|
-
return call('takePicture', [
|
|
23
|
+
return call('takePicture', [
|
|
24
|
+
pictureOptions,
|
|
25
|
+
]);
|
|
22
26
|
}
|
|
23
27
|
return {
|
|
24
28
|
takePictureAsync,
|
|
25
|
-
recordAsync: async (options) => call('record', [
|
|
29
|
+
recordAsync: async (options) => call('record', [
|
|
30
|
+
ensureRecordingOptions(options),
|
|
31
|
+
]),
|
|
26
32
|
toggleRecordingAsync: async () => call('toggleRecording'),
|
|
27
33
|
stopRecording: () => {
|
|
28
34
|
call('stopRecording');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"camera-view-handle.js","sourceRoot":"","sources":["../../src/core/camera-view-handle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,
|
|
1
|
+
{"version":3,"file":"camera-view-handle.js","sourceRoot":"","sources":["../../src/core/camera-view-handle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAiC3B,MAAM,gBAAgB,GAAG,qBAAqB,CAC5C,mBAAmB,EACnB,kBAAkB,CACnB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CACpC,OAA+C;IAE/C,qFAAqF;IACrF,SAAS,IAAI,CACX,MAAc,EACd,OAA2B,EAAE;QAE7B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAChE,OAAO,gBAAgB,CAAU,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAQD,KAAK,UAAU,gBAAgB,CAAC,OAA+B;QAC7D,MAAM,cAAc,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACrD,qEAAqE;QACrE,IACE,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EACtE,CAAC;YACD,OAAO,IAAI,CAA6B,gBAAgB,EAAE;gBACxD,cAAc;aACf,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAkC,aAAa,EAAE;YAC1D,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,gBAAgB;QAChB,WAAW,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE,CAC3B,IAAI,CAA2B,QAAQ,EAAE;YACvC,sBAAsB,CAAC,OAAO,CAAC;SAChC,CAAC;QACJ,oBAAoB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAgB,iBAAiB,CAAC;QACxE,aAAa,EAAE,GAAG,EAAE;YAClB,IAAI,CAAC,eAAe,CAAC,CAAC;QACxB,CAAC;QACD,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAgB,cAAc,CAAC;QAC7D,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAgB,eAAe,CAAC;QAC/D,6BAA6B,EAAE,KAAK,IAAI,EAAE,CACxC,CAAC,MAAM,IAAI,CAAoB,0BAA0B,CAAC,CAAC,IAAI,EAAE;QACnE,uBAAuB,EAAE,KAAK,IAAI,EAAE,CAClC,CAAC,MAAM,IAAI,CAAoB,oBAAoB,CAAC,CAAC,IAAI,EAAE;QAC7D,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;YAC3B,+BAA+B,EAC7B,UAAU,CAAC,+BAA+B;YAC5C,6BAA6B,EAAE,UAAU,CAAC,6BAA6B;SACxE,CAAC;QACF,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,IAAI;KACrC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAMxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAMxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAkDjD,MAAM,CAAC,MAAM,UAAU,GACrB,mBAAmB,CAAsB,kBAAkB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/camera",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "expo-camera wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. The camera preview, pictures, video recording and barcode scanning.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"expo-camera": "57.0.6",
|
|
69
69
|
"expo-modules-core": "57.0.20",
|
|
70
|
-
"@symbiote-native/components": "3.
|
|
70
|
+
"@symbiote-native/components": "3.2.0"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
73
|
"@angular/core": ">=20",
|
|
@@ -77,12 +77,12 @@
|
|
|
77
77
|
"solid-js": ">=1.9.0",
|
|
78
78
|
"svelte": ">=5.56.0",
|
|
79
79
|
"vue": ">=3.5.0",
|
|
80
|
-
"@symbiote-native/angular": "^3.
|
|
81
|
-
"@symbiote-native/engine": "^1.
|
|
82
|
-
"@symbiote-native/react": "^3.
|
|
83
|
-
"@symbiote-native/
|
|
84
|
-
"@symbiote-native/
|
|
85
|
-
"@symbiote-native/vue": "^3.
|
|
80
|
+
"@symbiote-native/angular": "^3.3.0",
|
|
81
|
+
"@symbiote-native/engine": "^1.6.0",
|
|
82
|
+
"@symbiote-native/react": "^3.3.0",
|
|
83
|
+
"@symbiote-native/solid": "^3.2.0",
|
|
84
|
+
"@symbiote-native/svelte": "^3.2.0",
|
|
85
|
+
"@symbiote-native/vue": "^3.3.0"
|
|
86
86
|
},
|
|
87
87
|
"peerDependenciesMeta": {
|
|
88
88
|
"@symbiote-native/angular": {
|
|
@@ -130,13 +130,13 @@
|
|
|
130
130
|
"solid-js": "^1.9.14",
|
|
131
131
|
"svelte": "^5.56.0",
|
|
132
132
|
"typescript": "~6.0.0",
|
|
133
|
-
"@symbiote-native/angular": "3.
|
|
134
|
-
"@symbiote-native/engine": "1.
|
|
135
|
-
"@symbiote-native/
|
|
136
|
-
"@symbiote-native/
|
|
137
|
-
"@symbiote-native/
|
|
138
|
-
"@symbiote-native/test-utils": "0.4.
|
|
139
|
-
"@symbiote-native/
|
|
133
|
+
"@symbiote-native/angular": "3.3.0",
|
|
134
|
+
"@symbiote-native/engine": "1.6.0",
|
|
135
|
+
"@symbiote-native/react": "3.3.0",
|
|
136
|
+
"@symbiote-native/solid": "3.2.0",
|
|
137
|
+
"@symbiote-native/svelte": "3.2.0",
|
|
138
|
+
"@symbiote-native/test-utils": "0.4.7",
|
|
139
|
+
"@symbiote-native/vue": "3.3.0"
|
|
140
140
|
},
|
|
141
141
|
"scripts": {
|
|
142
142
|
"typecheck": "tsc --build",
|
|
@@ -40,7 +40,10 @@ export type IAndroidBarcode =
|
|
|
40
40
|
subject?: string;
|
|
41
41
|
body?: string;
|
|
42
42
|
})
|
|
43
|
-
| (IAndroidBarcodeKind<'phone'> & {
|
|
43
|
+
| (IAndroidBarcodeKind<'phone'> & {
|
|
44
|
+
number?: string;
|
|
45
|
+
phoneNumberType?: string;
|
|
46
|
+
})
|
|
44
47
|
| (IAndroidBarcodeKind<'wifi'> & {
|
|
45
48
|
ssid?: string;
|
|
46
49
|
password?: string;
|
|
@@ -15,8 +15,9 @@ function hasField(value: unknown, key: string, kind: string): boolean {
|
|
|
15
15
|
return typeof Reflect.get(Object(value), key) === kind;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const isMountError: IGuard<ICameraMountError> = (
|
|
19
|
-
|
|
18
|
+
const isMountError: IGuard<ICameraMountError> = (
|
|
19
|
+
value,
|
|
20
|
+
): value is ICameraMountError => hasField(value, 'message', 'string');
|
|
20
21
|
|
|
21
22
|
const isOrientation: IGuard<ICameraResponsiveOrientation> = (
|
|
22
23
|
value,
|
|
@@ -87,7 +88,11 @@ export function createCameraViewEvents(): ICameraViewEvents {
|
|
|
87
88
|
typeof onBarcodeScanned === 'function'
|
|
88
89
|
? throttledScan(result => onBarcodeScanned(result))
|
|
89
90
|
: undefined,
|
|
90
|
-
onAvailableLensesChanged: forward(
|
|
91
|
+
onAvailableLensesChanged: forward(
|
|
92
|
+
props,
|
|
93
|
+
'onAvailableLensesChanged',
|
|
94
|
+
isLenses,
|
|
95
|
+
),
|
|
91
96
|
onResponsiveOrientationChanged: forward(
|
|
92
97
|
props,
|
|
93
98
|
'onResponsiveOrientationChanged',
|
|
@@ -4,7 +4,10 @@ import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
|
4
4
|
import { CAMERA_MODULE_NAME } from './constants';
|
|
5
5
|
import { expoCamera } from './native-module';
|
|
6
6
|
import type { ICameraPictureRef } from './native-module';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
ensurePictureOptions,
|
|
9
|
+
ensureRecordingOptions,
|
|
10
|
+
} from './picture-options';
|
|
8
11
|
import type {
|
|
9
12
|
ICameraCapturedPicture,
|
|
10
13
|
ICameraPictureOptions,
|
|
@@ -64,16 +67,24 @@ export function createCameraViewHandle(
|
|
|
64
67
|
async function takePictureAsync(options?: ICameraPictureOptions) {
|
|
65
68
|
const pictureOptions = ensurePictureOptions(options);
|
|
66
69
|
// The picture ref is an iOS feature, Android answers a plain picture
|
|
67
|
-
if (
|
|
68
|
-
|
|
70
|
+
if (
|
|
71
|
+
Platform.select({ ios: Boolean(options?.pictureRef), default: false })
|
|
72
|
+
) {
|
|
73
|
+
return call<Promise<ICameraPictureRef>>('takePictureRef', [
|
|
74
|
+
pictureOptions,
|
|
75
|
+
]);
|
|
69
76
|
}
|
|
70
|
-
return call<Promise<ICameraCapturedPicture>>('takePicture', [
|
|
77
|
+
return call<Promise<ICameraCapturedPicture>>('takePicture', [
|
|
78
|
+
pictureOptions,
|
|
79
|
+
]);
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
return {
|
|
74
83
|
takePictureAsync,
|
|
75
84
|
recordAsync: async options =>
|
|
76
|
-
call<Promise<{ uri: string }>>('record', [
|
|
85
|
+
call<Promise<{ uri: string }>>('record', [
|
|
86
|
+
ensureRecordingOptions(options),
|
|
87
|
+
]),
|
|
77
88
|
toggleRecordingAsync: async () => call<Promise<void>>('toggleRecording'),
|
|
78
89
|
stopRecording: () => {
|
|
79
90
|
call('stopRecording');
|
|
@@ -85,7 +96,8 @@ export function createCameraViewHandle(
|
|
|
85
96
|
getAvailableLensesAsync: async () =>
|
|
86
97
|
(await call<Promise<string[]>>('getAvailableLenses')) ?? [],
|
|
87
98
|
getSupportedFeatures: () => ({
|
|
88
|
-
isModernBarcodeScannerAvailable:
|
|
99
|
+
isModernBarcodeScannerAvailable:
|
|
100
|
+
expoCamera.isModernBarcodeScannerAvailable,
|
|
89
101
|
toggleRecordingAsyncAvailable: expoCamera.toggleRecordingAsyncAvailable,
|
|
90
102
|
}),
|
|
91
103
|
getHostNode: () => getNode() ?? null,
|
|
@@ -20,7 +20,9 @@ export type ICameraPictureRef = SharedRef<'image'> & {
|
|
|
20
20
|
width: number;
|
|
21
21
|
height: number;
|
|
22
22
|
/** Saves the image into the cache directory */
|
|
23
|
-
savePictureAsync(
|
|
23
|
+
savePictureAsync(
|
|
24
|
+
options?: ICameraSavePictureOptions,
|
|
25
|
+
): Promise<ICameraPhotoResult>;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
export type ICameraPictureRefClass = abstract new (
|
|
@@ -52,6 +54,5 @@ export type ICameraNativeModule = {
|
|
|
52
54
|
): EventSubscription;
|
|
53
55
|
};
|
|
54
56
|
|
|
55
|
-
export const expoCamera =
|
|
56
|
-
CAMERA_MODULE_NAME
|
|
57
|
-
);
|
|
57
|
+
export const expoCamera =
|
|
58
|
+
requireNativeModule<ICameraNativeModule>(CAMERA_MODULE_NAME);
|
package/src/core/types.ts
CHANGED
|
@@ -30,23 +30,12 @@ export type ICameraVideoCodec = 'avc1' | 'hvc1' | 'jpeg' | 'apcn' | 'ap4h';
|
|
|
30
30
|
|
|
31
31
|
/** On Android all but `off` turn the stabilization on, the device picks the method */
|
|
32
32
|
export type ICameraVideoStabilization =
|
|
33
|
-
| '
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
| 'auto';
|
|
37
|
-
|
|
38
|
-
export type ICameraVideoQuality =
|
|
39
|
-
| '2160p'
|
|
40
|
-
| '1080p'
|
|
41
|
-
| '720p'
|
|
42
|
-
| '480p'
|
|
43
|
-
| '4:3';
|
|
33
|
+
'off' | 'standard' | 'cinematic' | 'auto';
|
|
34
|
+
|
|
35
|
+
export type ICameraVideoQuality = '2160p' | '1080p' | '720p' | '480p' | '4:3';
|
|
44
36
|
|
|
45
37
|
export type ICameraOrientation =
|
|
46
|
-
| '
|
|
47
|
-
| 'portraitUpsideDown'
|
|
48
|
-
| 'landscapeLeft'
|
|
49
|
-
| 'landscapeRight';
|
|
38
|
+
'portrait' | 'portraitUpsideDown' | 'landscapeLeft' | 'landscapeRight';
|
|
50
39
|
|
|
51
40
|
export type ICameraBarcodeType =
|
|
52
41
|
| 'aztec'
|
package/src/react/index.ts
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
export { CameraView } from './camera-view';
|
|
4
4
|
export type { ICameraViewReactProps } from './camera-view';
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
useCameraPermissions,
|
|
7
|
+
useMicrophonePermissions,
|
|
8
|
+
} from './use-camera-permissions';
|
|
6
9
|
export type { IUseCameraPermissionsHook } from './use-camera-permissions';
|
|
7
10
|
export * from '../core';
|
package/src/solid/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// @symbiote-native/camera/solid: камера, съёмка, запись видео и сканирование кодов на общем ядре
|
|
2
2
|
|
|
3
3
|
export { CameraView } from './camera-view';
|
|
4
|
-
export {
|
|
4
|
+
export {
|
|
5
|
+
useCameraPermissions,
|
|
6
|
+
useMicrophonePermissions,
|
|
7
|
+
} from './use-camera-permissions';
|
|
5
8
|
export type { IUseCameraPermissionsHook } from './use-camera-permissions';
|
|
6
9
|
export * from '../core';
|
|
@@ -6,9 +6,7 @@ import {
|
|
|
6
6
|
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
7
7
|
import type { PermissionResponse } from 'expo-modules-core';
|
|
8
8
|
|
|
9
|
-
export type IUseCameraPermissionsHook = (
|
|
10
|
-
options?: IPermissionHookBehavior,
|
|
11
|
-
) => {
|
|
9
|
+
export type IUseCameraPermissionsHook = (options?: IPermissionHookBehavior) => {
|
|
12
10
|
readonly status: PermissionResponse | null;
|
|
13
11
|
requestPermission: () => Promise<PermissionResponse>;
|
|
14
12
|
getPermission: () => Promise<PermissionResponse>;
|
package/src/vue/camera-view.ts
CHANGED
|
@@ -2,4 +2,7 @@ import { defineNativeViewComponent } from '@symbiote-native/vue';
|
|
|
2
2
|
import { createCameraView } from '../core';
|
|
3
3
|
|
|
4
4
|
/** Vue twin of `expo-camera`'s `CameraView` */
|
|
5
|
-
export const CameraView = defineNativeViewComponent(
|
|
5
|
+
export const CameraView = defineNativeViewComponent(
|
|
6
|
+
'CameraView',
|
|
7
|
+
createCameraView,
|
|
8
|
+
);
|
package/src/vue/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// @symbiote-native/camera/vue: камера, съёмка, запись видео и сканирование кодов на общем ядре
|
|
2
2
|
|
|
3
3
|
export { CameraView } from './camera-view';
|
|
4
|
-
export {
|
|
4
|
+
export {
|
|
5
|
+
useCameraPermissions,
|
|
6
|
+
useMicrophonePermissions,
|
|
7
|
+
} from './use-camera-permissions';
|
|
5
8
|
export type { IUseCameraPermissionsHook } from './use-camera-permissions';
|
|
6
9
|
export * from '../core';
|