diff --git a/docs/usePermission.md b/docs/usePermission.md new file mode 100644 index 0000000000..4a6b688e5b --- /dev/null +++ b/docs/usePermission.md @@ -0,0 +1,20 @@ +# `usePermission` + +React UI hook that query permission status from the user depends on the specific AP. + + +## Usage + +```jsx +import {usePermission} from 'react-use'; + +const Demo = () => { + const state = usePermission({ name: 'microphone' }); + + return ( +
+      {JSON.stringify(state, null, 2)}
+    
+ ); +}; +``` diff --git a/src/__stories__/usePermission.story.tsx b/src/__stories__/usePermission.story.tsx new file mode 100644 index 0000000000..3ff7cf6c9a --- /dev/null +++ b/src/__stories__/usePermission.story.tsx @@ -0,0 +1,14 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { usePermission } from '..'; +import ShowDocs from './util/ShowDocs'; + +const Demo = () => { + const state = usePermission({ name: 'microphone' }); + + return
{JSON.stringify(state, null, 2)}
; +}; + +storiesOf('UI|usePermission', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/index.ts b/src/index.ts index be432e22d6..69002fa119 100644 --- a/src/index.ts +++ b/src/index.ts @@ -47,6 +47,7 @@ import useNumber from './useNumber'; import useObservable from './useObservable'; import useOrientation from './useOrientation'; import usePageLeave from './usePageLeave'; +import usePermission from './usePermission'; import usePrevious from './usePrevious'; import usePromise from './usePromise'; import useRaf from './useRaf'; @@ -123,6 +124,7 @@ export { useObservable, useOrientation, usePageLeave, + usePermission, usePrevious, usePromise, useRaf, diff --git a/src/usePermission.ts b/src/usePermission.ts new file mode 100644 index 0000000000..37b0261031 --- /dev/null +++ b/src/usePermission.ts @@ -0,0 +1,46 @@ +import { useEffect, useState } from 'react'; +import { off, on } from './util'; + +type PermissionDesc = + | PermissionDescriptor + | DevicePermissionDescriptor + | MidiPermissionDescriptor + | PushPermissionDescriptor; + +const noop = () => {}; + +const usePermission = (permissionDesc: PermissionDesc): string => { + const [state, setState] = useState(''); + let mounted = true; + let permissionStatus: PermissionStatus | null = null; + + const onChange = () => { + if (mounted && permissionStatus) { + setState(permissionStatus.state); + } + }; + + const changeState = () => { + onChange(); + on(permissionStatus, 'change', onChange); + }; + + useEffect(() => { + navigator.permissions + .query(permissionDesc) + .then(status => { + permissionStatus = status; + changeState(); + }) + .catch(noop); + + return () => { + mounted = false; + permissionStatus && off(permissionStatus, 'change', onChange); + }; + }, []); + + return state; +}; + +export default usePermission;