@chipmobilesdk/rn-camera 0.2.0 → 0.3.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/CHANGELOG.md +207 -93
- package/README.md +390 -364
- package/package.json +52 -47
- package/skills/sdk-rn-camera/SKILL.md +76 -75
- package/src/config/types.ts +143 -149
- package/src/core/capabilities.ts +41 -44
- package/src/core/captureController.ts +120 -120
- package/src/core/controller.ts +522 -518
- package/src/core/sessionMachine.ts +104 -111
- package/src/diagnostics/errors.ts +94 -92
- package/src/diagnostics/logger.ts +47 -31
- package/src/geometry/coordinateMapping.ts +129 -129
- package/src/index.ts +78 -78
- package/src/native/cameraEngine.ts +7 -2
- package/src/native/visionCameraPeer.ts +30 -0
- package/src/permissions/permissionPort.ts +24 -20
- package/src/react/CameraPreview.tsx +137 -125
- package/src/react/VisionCameraFeed.tsx +181 -178
- package/src/react/hooks.ts +56 -58
- package/src/storage/artifactStore.ts +141 -141
- package/src/testing/conformance.ts +140 -0
- package/src/testing/index.ts +27 -0
- package/src/testing/testCameraAdapter.ts +246 -256
package/CHANGELOG.md
CHANGED
|
@@ -1,93 +1,207 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
`
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
and
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
and
|
|
42
|
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- `
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
1
|
+
# @chipmobilesdk/rn-camera
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- One diagnostic stream: install a sink with `installSdkSink` from
|
|
8
|
+
`@chipmobilesdk/rn-core` and it receives what every package observes (events,
|
|
9
|
+
failures, warnings) as `SdkDiagnostic`s, redacted. Listeners are notified through
|
|
10
|
+
rn-core, so a listener that throws no longer stops the others nor fails the call that
|
|
11
|
+
notified, and its error is reported rather than swallowed. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
|
|
12
|
+
|
|
13
|
+
- rn-ads: a banner's auto-refresh is a new cycle, so its `loaded` and `impression`
|
|
14
|
+
events are no longer deduplicated away; the dedupe memory is bounded. A throwing
|
|
15
|
+
status, consent or placement listener is reported as an `internal_error` event.
|
|
16
|
+
- rn-i18n: new `onDiagnostic` config receives every diagnostic (`I18nDiagnostic`,
|
|
17
|
+
with a stable `code`); without it, warnings go to `console.warn` in development
|
|
18
|
+
builds only. The warn-once memory is bounded.
|
|
19
|
+
- rn-chart: now depends on rn-core for its diagnostics.
|
|
20
|
+
- rn-payment: status, entitlement and pending listeners report a throw to the logger
|
|
21
|
+
instead of swallowing it.
|
|
22
|
+
|
|
23
|
+
- The package's errors extend `SdkError` from the new `@chipmobilesdk/rn-core`
|
|
24
|
+
dependency: `isSdkError` recognises them alongside every other package's, and each
|
|
25
|
+
carries `pkg`, `code` and `retryable`. Names and codes are unchanged. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
|
|
26
|
+
|
|
27
|
+
- rn-ai and rn-camera: `retryable` is the new name of `recoverable`, which stays as a
|
|
28
|
+
deprecated alias.
|
|
29
|
+
- rn-auth: `retryable` is true for `network-unavailable`. `redact` also removes URLs,
|
|
30
|
+
e-mail addresses and UUIDs.
|
|
31
|
+
- rn-ads: `redact` also removes JWTs and e-mail addresses, and reduces an `AdsError`
|
|
32
|
+
to its code.
|
|
33
|
+
- rn-ai: an error message quoted from the gateway is pattern-redacted.
|
|
34
|
+
- rn-camera: `redact` also removes JWTs, e-mail addresses and UUIDs.
|
|
35
|
+
- rn-theme: `ThemeConfigError` has `code: 'invalid_config'` and `ThemeContrastError`
|
|
36
|
+
`code: 'contrast'` (new `ThemeErrorCode` type).
|
|
37
|
+
- rn-i18n: `I18nConfigError` has `code: 'invalid_config'` and `UnitConversionError`
|
|
38
|
+
`code: 'unit_conversion'` (new `I18nErrorCode` type).
|
|
39
|
+
|
|
40
|
+
- Native peers load through `lazyPeer` from `@chipmobilesdk/rn-core`, on first use,
|
|
41
|
+
and a missing one is each package's own typed error. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
|
|
42
|
+
|
|
43
|
+
- rn-auth: creating `auth` no longer loads react-native-app-auth or
|
|
44
|
+
react-native-keychain; each loads on first use. New entrypoints
|
|
45
|
+
`@chipmobilesdk/rn-auth/app-auth` and `/keychain`. The default platform comes from
|
|
46
|
+
rn-core.
|
|
47
|
+
- rn-camera: a preview whose VisionCamera feed cannot load fails the session with
|
|
48
|
+
`cameraUnavailable` (new `controller.reportSurfaceUnavailable()`), instead of
|
|
49
|
+
showing black with no error. A missing VisionCamera module is `cameraUnavailable`.
|
|
50
|
+
- rn-notification: `createMmkvStore` reports a fallback to memory as
|
|
51
|
+
`STATE_STORE_DEGRADED` (to the SDK sinks and a new `onDegraded` option) and
|
|
52
|
+
exposes `durable`.
|
|
53
|
+
- rn-payment: an iOS app validates its catalog against the iOS product ids; the
|
|
54
|
+
default platform used to be Android everywhere. A missing react-native-iap is
|
|
55
|
+
`PAYMENT_UNAVAILABLE`.
|
|
56
|
+
- rn-theme: `buildThemes` runs without React Native (new `hairlineWidth` option) and
|
|
57
|
+
importing the package no longer loads Unistyles; `applyThemeMode` loads it on
|
|
58
|
+
first use.
|
|
59
|
+
- rn-ads, rn-local-db: the same loading, with the same error codes as before.
|
|
60
|
+
|
|
61
|
+
- Port conformance suites: one list of checks that a package's fake and its real adapter
|
|
62
|
+
both pass, so a test written against the fake proves something about the device. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
|
|
63
|
+
|
|
64
|
+
- rn-core: `@chipmobilesdk/rn-core/testing` adds `runChecks`, `expectConformance`,
|
|
65
|
+
`ensure` and `createFaultRegistry` (deterministic fault injection by named point).
|
|
66
|
+
- rn-camera: a `./testing` entrypoint with `runPermissionPortConformance`,
|
|
67
|
+
`runCameraEngineConformance` and the test adapter, which stays on the main
|
|
68
|
+
entrypoint too until the next major. `createTestCamera(...).prompts()` counts system
|
|
69
|
+
prompts.
|
|
70
|
+
- rn-payment: `runProviderPortConformance` in `./testing`, passed by the fake store and
|
|
71
|
+
the Play adapter.
|
|
72
|
+
- rn-ads: `runAdsEngineConformance` in `./testing`, passed by the fake engine and the
|
|
73
|
+
AdMob adapter.
|
|
74
|
+
- rn-auth: a `./testing` entrypoint with `createMemorySecureStore`,
|
|
75
|
+
`runSecureTokenStoreConformance` and `runOidcAuthClientConformance`, passed by the
|
|
76
|
+
in-memory doubles and the keychain and app-auth adapters.
|
|
77
|
+
|
|
78
|
+
- One app-lifecycle source, and a startup that needs no extra frame. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
|
|
79
|
+
|
|
80
|
+
- rn-core: `appLifecycle()`, a shared, reference-counted `AppState` subscription that
|
|
81
|
+
reports changes only (`active`, `inactive`, `background`), with `onForeground` for a
|
|
82
|
+
return from the background and `createManualLifecycle` in `./testing`.
|
|
83
|
+
- rn-camera, rn-ads and rn-notification hear the lifecycle through it instead of
|
|
84
|
+
subscribing to `AppState` each, so an app holds one native listener. The camera
|
|
85
|
+
controller's core layer no longer imports `react-native`.
|
|
86
|
+
- rn-payment: `syncOnForeground(engine)` and `<PaymentProvider syncOnForeground>` call
|
|
87
|
+
`handleForeground()` on each return from the background. Off by default; calling
|
|
88
|
+
`handleForeground()` yourself works as before.
|
|
89
|
+
- rn-i18n: `i18n.initSync()` resolves the locale before the first render when the
|
|
90
|
+
storage adapter has the new optional `getItemSync`, and returns false otherwise.
|
|
91
|
+
`localeStorageFromKeyValue(port)` builds such an adapter from rn-core's
|
|
92
|
+
`KeyValuePort` (MMKV).
|
|
93
|
+
|
|
94
|
+
### Patch Changes
|
|
95
|
+
|
|
96
|
+
- `createCameraController` accepts an explicit `undefined` for `store` and `logger`, so
|
|
97
|
+
apps compiling with `exactOptionalPropertyTypes` type-check against the package.
|
|
98
|
+
`VisionCameraFeed` leaves `torchMode` unset until the app first touches the torch,
|
|
99
|
+
instead of passing `undefined`. No other change. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
|
|
100
|
+
- Updated dependencies ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17), [#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17), [#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17)):
|
|
101
|
+
- @chipmobilesdk/rn-core@0.1.0
|
|
102
|
+
|
|
103
|
+
## 0.2.1
|
|
104
|
+
|
|
105
|
+
### Patch Changes
|
|
106
|
+
|
|
107
|
+
- Packaging only; no code change. The package no longer declares `engines.node`: a
|
|
108
|
+
React Native package does not run on Node, so the field only produced install
|
|
109
|
+
warnings in apps on another Node version. rn-i18n's command-line tooling does run
|
|
110
|
+
on Node; its README's compatibility table states the version it needs. ([#14](https://github.com/operationd8979/chip-mobile-sdk/pull/14))
|
|
111
|
+
|
|
112
|
+
## [0.2.0] — 2026-11-01
|
|
113
|
+
|
|
114
|
+
Lifecycle and capture-path fixes. **No code change is required**; two behaviours
|
|
115
|
+
change (see Changed), and a store that should manage VisionCamera captures needs a
|
|
116
|
+
`FileSystemBridge` with `move()`.
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
|
|
120
|
+
- **`useCameraController` survives a StrictMode remount.** The cleanup disposed the
|
|
121
|
+
only controller and the remount kept it, so the screen showed `idle` forever and
|
|
122
|
+
backgrounding no longer released the camera. A disposed controller is now replaced,
|
|
123
|
+
and constructing one has no side effects (it subscribes on first use), so a
|
|
124
|
+
controller React builds and discards no longer leaks listeners.
|
|
125
|
+
- **`CameraPreview` subscribes to the controller.** It read `controller.state` once
|
|
126
|
+
per render, so the feed could stay unmounted after the session became active unless
|
|
127
|
+
the parent re-rendered. `useCameraState` now uses `useSyncExternalStore`.
|
|
128
|
+
- **A failed capture no longer leaves `capturing: true` published**, and `capturing:
|
|
129
|
+
true` is now published at all — the single-flight slot was taken after the first
|
|
130
|
+
emit. A raw native or engine error is turned into `CameraError('captureFailed')`
|
|
131
|
+
(or `storageFailure` when saving fails), with no file path in the message.
|
|
132
|
+
- **Foregrounding restarts only a session that backgrounding interrupted.** It used
|
|
133
|
+
to start any idle or stopped session while a preview was mounted — including one
|
|
134
|
+
the user had stopped, one never started, and one whose permission had been revoked.
|
|
135
|
+
A foreground that arrives while the release is still running now waits for it
|
|
136
|
+
instead of being dropped.
|
|
137
|
+
- **Use after dispose is defined.** `start`, `resume`, `capture`, and the permission
|
|
138
|
+
and capability reads reject with `CameraError('notReady')`; `stop`, `pause` and
|
|
139
|
+
`cleanup` are safe no-ops.
|
|
140
|
+
- **VisionCamera captures can be cleaned up.** They were saved in VisionCamera's own
|
|
141
|
+
temporary directory, outside the store, so `cleanup()` refused them and the 24-hour
|
|
142
|
+
sweep never saw them. The controller now moves each package-temporary capture into
|
|
143
|
+
the store (`ArtifactStore.adopt`), and the sweep spares captures adopted by the
|
|
144
|
+
running process. With no store, or a bridge without `move()`, the logger reports
|
|
145
|
+
`unmanaged:no-store` / `unmanaged:store-cannot-adopt` once.
|
|
146
|
+
- **No more "Camera is not active" error on every session start.** The feed sent
|
|
147
|
+
`torchMode="off"` on mount; VisionCamera applies it before the camera is active
|
|
148
|
+
and leaves the native rejection unhandled. The prop is now left unset until the
|
|
149
|
+
torch is first turned on.
|
|
150
|
+
- **One throwing state listener no longer breaks a transition** or starves the other
|
|
151
|
+
listeners; it is logged as `listener-threw`.
|
|
152
|
+
|
|
153
|
+
### Changed
|
|
154
|
+
|
|
155
|
+
- **`effectiveQuality` and `effectiveMaxDimension` report what was applied.** The
|
|
156
|
+
VisionCamera adapter echoed the request hints. Quality is fixed on the photo output
|
|
157
|
+
(0.9) and nothing resizes, so it now reports `0.9` and an unavailable max dimension.
|
|
158
|
+
- **Unmounting a preview over an idle controller leaves it `idle`**, rather than
|
|
159
|
+
driving it through `stopping` to `stopped` and calling the engine's `stop()`.
|
|
160
|
+
|
|
161
|
+
### Added
|
|
162
|
+
|
|
163
|
+
- `ArtifactStore.adopt?(uri)` and `FileSystemBridge.move?(from, to)`, both optional.
|
|
164
|
+
`createMemoryFileSystem()` implements `move`.
|
|
165
|
+
|
|
166
|
+
### Docs
|
|
167
|
+
|
|
168
|
+
- The README no longer claims quality and max-dimension hints are applied, or a
|
|
169
|
+
single active session per process.
|
|
170
|
+
|
|
171
|
+
## 0.1.1 — 2026-08-01
|
|
172
|
+
|
|
173
|
+
### Changed
|
|
174
|
+
|
|
175
|
+
- The package now ships its agent skill (`skills/`), which consuming apps
|
|
176
|
+
copy in with `scripts/sync-sdk-skills.mjs`. No code change.
|
|
177
|
+
|
|
178
|
+
## 0.1.0 — 2026-07-26
|
|
179
|
+
|
|
180
|
+
Initial release. New package, no existing consumers, **no migration required**.
|
|
181
|
+
|
|
182
|
+
### Added
|
|
183
|
+
|
|
184
|
+
- **Permission handling** as a seven-state contract (`undetermined`, `requesting`, `granted`, `denied`, `deniedPermanently`, `unavailable`, `unsupported`). Reading status never prompts; requesting never re-prompts after a permanent denial; revocations made in system settings are pushed to subscribers without an app restart.
|
|
185
|
+
- **`CameraPreview`** surface with `cover`/`contain` resize modes, an overlay slot via `children`, and pass-through of consumer accessibility properties. Ships no styled UI and takes no theme dependency.
|
|
186
|
+
- **Still capture** returning a file reference plus metadata. Undeterminable fields (`fileSize`, `orientation`) are explicitly marked unavailable rather than guessed or omitted. Quality and max-dimension hints are normalized and reported back as effective values.
|
|
187
|
+
- **Session lifecycle** — start, pause, resume, stop — that releases the camera on background, unmount, and stop, restarts on foreground when a surface is still mounted, and reports a single active session per controller.
|
|
188
|
+
- **Artifact ownership and cleanup**: an optional `destination` on the capture request switches the result to app-owned and writes there directly; everything else lands in the package cache directory. `cleanup()` is idempotent and refuses anything the package does not own. Orphans are swept at initialization under a 24-hour time-to-live.
|
|
189
|
+
- **Capability reporting** for camera positions, flash, torch, orientation, and camera-less devices, with capture-time flash modes and a continuous torch that is forced off on pause, stop, and background.
|
|
190
|
+
- **Coordinate mapping** — pure, bidirectional, accounting for scale, letterbox or crop, orientation, and front-camera mirroring, accurate within 2 device-independent pixels on a round trip.
|
|
191
|
+
- **Typed error taxonomy** of 11 codes, each carrying a `recoverable` flag, plus a `redact()` helper.
|
|
192
|
+
- **Test adapter** (`createTestCamera`) implementing the same published ports as the production adapters, so consuming apps can drive every permission, capability, and capture path with no hardware and no permission prompts.
|
|
193
|
+
- **Opt-in diagnostics logger**, defaulting to no logging.
|
|
194
|
+
|
|
195
|
+
### Guarantees
|
|
196
|
+
|
|
197
|
+
- No network egress of any kind.
|
|
198
|
+
- No location read, no location permission requested.
|
|
199
|
+
- Nothing written to the device photo library or gallery.
|
|
200
|
+
- No capture history or index retained.
|
|
201
|
+
- No on-device inference, no frame processor, no AI-derived labels.
|
|
202
|
+
|
|
203
|
+
### Notes
|
|
204
|
+
|
|
205
|
+
- `react-native-vision-camera` (>= 5.1.1) is a **peer dependency**; the consuming app installs and links it. This package authors no native source.
|
|
206
|
+
- Android `minSdkVersion` remains **24** — VisionCamera 5.1.1 declares 23 and resolves the root project value first.
|
|
207
|
+
- The local frame-processing extension point is documented in the README but deliberately not exported. It is designed to arrive as an additive minor release.
|