first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
# use-stream-permissions
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`useStreamPermissions` exposes the microphone permission state with the typed
`MediaPermissionState` enum (`"granted" | "denied" | "prompt" | "unknown"`) and a
`request()` callback that triggers `navigator.mediaDevices.getUserMedia` via the
session. The hook decouples React components from the browser's permission API surface
so consumers can render a permissions banner, a "click to enable mic" button, or a
hard-blocked error UI without touching `navigator` themselves.
The hook is provider-bound — it does not poll `navigator.permissions.query` itself.
Chunk A's session is responsible for keeping the permission state fresh (either by
listening to the `PermissionStatus` `change` event or by re-querying on
`getUserMedia` errors) and emitting `'permission-changed'` so the provider's
render-bump version increments.
## Features
- Stable `request` callback (`useCallback`-wrapped) for safe use in event handlers.
- Re-renders on every `'permission-changed'` event channel.
- Returns the typed enum rather than the browser's `string` so consumers can do
exhaustive switches.
- Throws `REACT_AUDIO_STREAM.NO_PROVIDER` outside a `<StreamProvider>`.
## Usage: Basic
```tsx
const { state, request } = useStreamPermissions();
if (state === "denied") return <PermissionsBlockedBanner />;
return <button onClick={request}>Enable microphone</button>;
```
## Usage: Advanced
```tsx
const { state, request } = useStreamPermissions();
useEffect(() => {
if (state === "prompt") {
// Auto-request as soon as the user navigates into the room view.
void request();
}
}, [state, request]);
```
## API Reference
- `UseStreamPermissionsResult` — `{ state, request }`
- `useStreamPermissions(): UseStreamPermissionsResult`
## Implementation Notes
`request` resolves with the next permission state rather than `void` so a consumer that
wants to chain into `connect()` immediately after granting can do so without a separate
re-render hop. The session implementation is responsible for emitting
`'permission-changed'` synchronously after the resolve, which keeps the React render
state aligned with the promise result.