Skip to content

Instantly share code, notes, and snippets.

@scvnathan
Last active September 1, 2021 16:08
Show Gist options
  • Save scvnathan/e9ff3a784fda80b408f514ab6f3acc68 to your computer and use it in GitHub Desktop.
Save scvnathan/e9ff3a784fda80b408f514ab6f3acc68 to your computer and use it in GitHub Desktop.
TS 4.4 compatible usePermission
import { useEffect, useState } from 'react';
import { noop, off, on } from './misc/util';
type PermissionDesc =
| PermissionDescriptor
| ExperimentalDevicePermissionDescriptor
| ExperimentalMidiPermissionDescriptor
| ExperimentalPushPermissionDescriptor;
interface ExtendedExperimentalPermissions extends Permissions {
query(permissionDesc: PermissionDesc): ReturnType<Permissions['query']>;
}
interface ExperimentalDevicePermissionDescriptor {
name: 'camera' | 'microphone' | 'speaker';
deviceId?: string;
}
interface ExperimentalMidiPermissionDescriptor {
name: 'midi';
sysex?: boolean;
}
interface ExperimentalPushPermissionDescriptor {
name: 'push';
userVisibleOnly?: boolean;
}
type State = PermissionState | '';
const usePermission = (permissionDesc: PermissionDesc): State => {
const [state, setState] = useState<State>('');
useEffect(() => {
let mounted = true;
let permissionStatus: PermissionStatus | null = null;
const onChange = () => {
if (!mounted) {
return;
}
setState(() => permissionStatus?.state ?? '');
};
(navigator.permissions as ExtendedExperimentalPermissions)
.query(permissionDesc)
.then((status) => {
permissionStatus = status;
on(permissionStatus, 'change', onChange);
onChange();
})
.catch(noop);
return () => {
permissionStatus && off(permissionStatus, 'change', onChange);
mounted = false;
permissionStatus = null;
};
}, [permissionDesc]);
return state;
};
export default usePermission;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment