From 4da40b9cbb49dff2397dccae2e3436facba037be Mon Sep 17 00:00:00 2001 From: allen Date: Thu, 27 Jun 2019 00:57:38 +0800 Subject: [PATCH 1/2] 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; From e0618815af5dce17714037232abb1fbe068fc98f Mon Sep 17 00:00:00 2001 From: allen Date: Tue, 2 Jul 2019 13:08:53 +0800 Subject: [PATCH 2/2] modify text --- README.md | 1 + docs/usePermission.md | 2 +- src/__stories__/usePermission.story.tsx | 2 +- src/usePermission.ts | 7 +++++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cf579266b6..156047304f 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ - [`useSessionStorage`](./docs/useSessionStorage.md) — manages a value in `sessionStorage`. - [`useThrottle` and `useThrottleFn`](./docs/useThrottle.md) — throttles a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usethrottle--demo) - [`useTitle`](./docs/useTitle.md) — sets title of the page. + - [`usePermission`](./docs/usePermission.md) — query permission from the user depends on the specific API.

- [**Lifecycles**](./docs/Lifecycles.md) diff --git a/docs/usePermission.md b/docs/usePermission.md index 4a6b688e5b..cc793240f2 100644 --- a/docs/usePermission.md +++ b/docs/usePermission.md @@ -1,6 +1,6 @@ # `usePermission` -React UI hook that query permission status from the user depends on the specific AP. +React side-effect hook that query permission status from the user depends on the specific API. ## Usage diff --git a/src/__stories__/usePermission.story.tsx b/src/__stories__/usePermission.story.tsx index 3ff7cf6c9a..77e21ca2f5 100644 --- a/src/__stories__/usePermission.story.tsx +++ b/src/__stories__/usePermission.story.tsx @@ -9,6 +9,6 @@ const Demo = () => { return
{JSON.stringify(state, null, 2)}
; }; -storiesOf('UI|usePermission', module) +storiesOf('Side effects|usePermission', module) .add('Docs', () => ) .add('Demo', () => ); diff --git a/src/usePermission.ts b/src/usePermission.ts index 37b0261031..2a08d7b1c9 100644 --- a/src/usePermission.ts +++ b/src/usePermission.ts @@ -7,13 +7,16 @@ type PermissionDesc = | MidiPermissionDescriptor | PushPermissionDescriptor; +type State = PermissionState | ''; + const noop = () => {}; -const usePermission = (permissionDesc: PermissionDesc): string => { - const [state, setState] = useState(''); +const usePermission = (permissionDesc: PermissionDesc): State => { let mounted = true; let permissionStatus: PermissionStatus | null = null; + const [state, setState] = useState(''); + const onChange = () => { if (mounted && permissionStatus) { setState(permissionStatus.state);