From 4da40b9cbb49dff2397dccae2e3436facba037be Mon Sep 17 00:00:00 2001 From: allen Date: Thu, 27 Jun 2019 00:57:38 +0800 Subject: [PATCH] feat: add usePermission --- docs/usePermission.md | 20 +++++++++++ src/__stories__/usePermission.story.tsx | 14 ++++++++ src/index.ts | 2 ++ src/usePermission.ts | 46 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 docs/usePermission.md create mode 100644 src/__stories__/usePermission.story.tsx create mode 100644 src/usePermission.ts 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;