Skip to content

Commit

Permalink
feat(useauthorize): add useAuthorize hook
Browse files Browse the repository at this point in the history
  • Loading branch information
innocces committed Sep 9, 2021
1 parent e534fed commit c0ec57c
Show file tree
Hide file tree
Showing 11 changed files with 348 additions and 3 deletions.
1 change: 1 addition & 0 deletions packages/app/src/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default {
'pages/useAPICheck/index',
'pages/useUpdateManager/index',
'pages/useLaunchOptions/index',
'pages/useAuthorize/index',
// network
'pages/useRequest/index',
'pages/useRequest/defaultRequest/index',
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/constant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ export const ChildrenList: { [_: string]: APIChildrenItem[] } = {
id: 'useLaunchOptions',
name: 'useLaunchOptions 启动参数',
},
{
id: 'useAuthorize',
name: 'useAuthorize 用户授权',
},
],
[APIChildrenName.media]: [
{
Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/pages/useAuthorize/index.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
navigationBarTitleText: 'useAuthorize',
};
58 changes: 58 additions & 0 deletions packages/app/src/pages/useAuthorize/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useCallback } from 'react';
import { AtCheckbox, AtButton, AtNoticebar } from 'taro-ui';
import DocPage from '@components/DocPage';

import { useModal, useAuthorize, useEnv } from 'taro-hooks';
import { AuthSetting, ENV_TYPE } from '@tarojs/taro';

import 'taro-ui/dist/style/components/icon.scss';

const transferOptions = (setting: AuthSetting) =>
Object.entries(setting).map(([key, value]) => ({
label: key,
value: key,
disabled: typeof value === 'boolean' ? !value : value !== 'accept',
}));

export default () => {
const env = useEnv();
const [show] = useModal({ mask: true, title: '操作结果', showCancel: false });
const [{ authSetting, subscriptionsSetting }, { openSetting, authorize }] =
useAuthorize({ withSubscriptions: true });

const options = transferOptions({ ...authSetting, ...subscriptionsSetting });

const handleAuth = useCallback(() => {
authorize('scope.invoice').then(() => show({ content: '授权调用成功!' }));
}, [authorize, show]);

return (
<>
<AtNoticebar marquee>小程序专用hook</AtNoticebar>
<DocPage title="useAuthorize 用户授权" panelTitle="useAuthorize">
<AtButton
disabled={env !== ENV_TYPE.WEAPP}
onClick={() => openSetting()}
>
打开设置面板
</AtButton>
<AtButton
disabled={env !== ENV_TYPE.WEAPP}
className="gap"
onClick={handleAuth}
>
授权
</AtButton>
{env === ENV_TYPE.WEAPP && (
<AtCheckbox
options={options}
selectedList={options
.filter((v) => !v.disabled)
.map((v) => v.value)}
onChange={console.log}
/>
)}
</DocPage>
</>
);
};
2 changes: 1 addition & 1 deletion packages/app/src/pages/useRouter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import DocPage from '@components/DocPage';
import { View } from '@tarojs/components';

import { useRouter, useEnv } from 'taro-hooks';
import { getSystemInfoSync, ENV_TYPE } from '@tarojs/taro';
import { ENV_TYPE } from '@tarojs/taro';

export default () => {
const env = useEnv();
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/pages/useSystemInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React from 'react';
import { AtRadio } from 'taro-ui';
import DocPage from '@components/DocPage';

Expand Down
3 changes: 2 additions & 1 deletion packages/hooks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import useEnv from './useEnv';

// basic
import useLaunchOptions from './useLaunchOptions';
import useRouter from './useRouter';
import usePromise from './usePromise';
import useBase64ToArrayBuffer from './useBase64ToArrayBuffer';
Expand All @@ -24,6 +23,8 @@ import useNavigationBar from './useNavigationBar';
// wechat
import useAPICheck from './useAPICheck';
import useUpdateManager from './useUpdateManager';
import useLaunchOptions from './useLaunchOptions';
import useAuthorize from './useAuthorize';

// network
import useNetworkType from './useNetworkType';
Expand Down
92 changes: 92 additions & 0 deletions packages/hooks/src/useAuthorize/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
title: useAuthorize
nav:
title: Hooks
path: /hooks
order: 2
group:
title: 小程序
path: /wechat
---

# useAuthorize

直接调起用户授权信息、获取用户授权信息

## 何时使用

当需要在使用某些权限功能前进行授权或校验时

## API

```jsx | pure
const [
{ authSetting, subscriptionsSetting, miniprogramAuthSetting },
{ openSetting, authorize },
] = useAuthorize(option?);
```
## 参数说明
| 参数 | 说明 | 类型 | 默认值 |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| withSubscriptions | 是否同时获取用户订阅消息的订阅状态,默认不获取(注意: 该 hook 默认实时获取最新授权信息, 初始配置决定整个周期中获取配置行为) | `boolean` | `false` |
## 返回值说明
| 返回值 | 说明 | 类型 |
| ---------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| authSetting | 用户授权结果 | `AuthSetting` |
| subscriptionsSetting | 用户订阅消息设置 | `ISubscriptionsSetting` |
| miniprogramAuthSetting | 在插件中调用时,当前宿主小程序的用户授权结果 | `AuthSetting` |
| openSetting | 调起客户端小程序设置界面 | `(withSubscriptions?: boolean) => Promise<IROpenSettingSuccessCallbackResult>` |
| authorize | 提前向用户发起授权请求 | `(scope: keyof AuthSetting &#124; keyof IAuthSettingForMiniProgram, miniprogram?: boolean) => Promise<General.CallbackResult>` |
### ISubscriptionsSetting
| 参数 | 类型 | 说明 |
| ----------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| mainSwitch | `boolean` | 订阅消息总开关 |
| itemSetting | `{[_: string]: 'accept' &#124; 'reject' &#124; 'ban';}` | 每一项订阅消息的订阅状态,对象的键为一次性订阅消息的模板 id 或系统订阅消息的类型,值为'accept'、'reject'、'ban'中的其中一种。'accept'表示用户同意订阅这条消息,'reject'表示用户拒绝订阅这条消息,'ban'表示已被后台封禁 |
### IAuthSettingForMiniProgram
| 参数 | 类型 | 说明 |
| ---------------------- | --------- | ---------- |
| scope.record | `boolean` | 录音 |
| scope.writePhotosAlbum | `boolean` | 保存到相册 |
| scope.camera | `boolean` | 摄像头 |
### AuthSetting
| 参数 | 类型 | 说明 |
| ---------------------------- | --------- | -------------------------------------------- |
| scope.userInfo | `boolean` | 用户信息 |
| scope.userLocation | `boolean` | 地理位置 |
| scope.userLocationBackground | `boolean` | 后台定位 |
| scope.address | `boolean` | 通讯地址(已取消授权,可以直接调用对应接口) |
| scope.invoiceTitle | `boolean` | 发票抬头(已取消授权,可以直接调用对应接口) |
| scope.invoice | `boolean` | 获取发票(已取消授权,可以直接调用对应接口) |
| scope.werun | `boolean` | 微信运动步数 |
| scope.record | `boolean` | 录音功能 |
| scope.writePhotosAlbum | `boolean` | 保存到相册 |
| scope.camera | `boolean` | 摄像头 |
## 代码演示
<code src="@pages/useAuthorize" />
## Hook 支持度
| 微信小程序 | H5 | ReactNative |
| :--------: | :-: | :---------: |
| ✔️ | | |
## FAQ
### 1. 更多说明
- [authorize](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/authorize/wx.authorize.htmll)
- [openSetting](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/setting/wx.openSetting.html)
- [getSetting](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/setting/wx.openSetting.html)
- [scope](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html#scope-%E5%88%97%E8%A1%A8)
182 changes: 182 additions & 0 deletions packages/hooks/src/useAuthorize/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import { useCallback, useEffect, useState } from 'react';
import {
getSetting,
openSetting,
AuthSetting,
authorize,
General,
ENV_TYPE,
} from '@tarojs/taro';
import useEnv from '../useEnv';
import useVisible from '../useVisible';
import { typeOf } from '../utils/tool';

declare var wx: any;

// rewrite openSetting options
interface ISubscriptionsSetting {
mainSwitch?: boolean;
itemSetting?: {
[_: string]: 'accept' | 'reject' | 'ban';
};
}
interface IROpenSettingSuccessCallbackResult
extends openSetting.SuccessCallbackResult {
subscriptionsSetting?: ISubscriptionsSetting;
}

interface IOption {
withSubscriptions?: boolean;
}

interface IROpenSettingOption extends openSetting.Option {
success?: (result: IROpenSettingSuccessCallbackResult) => void;
}
type ROpenSetting = (
options: IROpenSettingOption & IOption,
) => Promise<IROpenSettingSuccessCallbackResult>;

interface IRGetSettingSuccessCallbackResult
extends openSetting.SuccessCallbackResult {
subscriptionsSetting?: ISubscriptionsSetting;
miniprogramAuthSetting?: AuthSetting;
}
interface IRGetSettingOption extends getSetting.Option {
success?: (result: IRGetSettingSuccessCallbackResult) => void;
}
type RGetSetting = (
options: IRGetSettingOption & IOption,
) => Promise<IRGetSettingSuccessCallbackResult>;

export type IOpenSettingAction = (
withSubscriptions?: boolean,
) => Promise<IROpenSettingSuccessCallbackResult>;

// plugin scope
export interface IAuthSettingForMiniProgram {
'scope.record'?: boolean;
'scope.writePhotosAlbum'?: boolean;
'scope.camera'?: boolean;
}
export type IAuthorizeAction = (
scope: keyof AuthSetting | keyof IAuthSettingForMiniProgram,
miniprogram?: boolean,
) => Promise<General.CallbackResult>;

export interface IAction {
openSetting: IOpenSettingAction;
authorize: IAuthorizeAction;
}

export interface IResult {
authSetting: AuthSetting;
subscriptionsSetting: ISubscriptionsSetting;
miniprogramAuthSetting: AuthSetting;
}

function useAuthorize(option?: IOption): [IResult, IAction] {
const env = useEnv();
const visible = useVisible();
const [authSetting, setAuthSetting] = useState<AuthSetting>({});
const [subscriptionsSetting, setSubscriptionsSetting] =
useState<ISubscriptionsSetting>({});
const [miniprogramAuthSetting, setMiniprogramAuthSetting] =
useState<AuthSetting>({});

useEffect(() => {
if (env === ENV_TYPE.WEAPP) {
getSettingAsync();
}
}, [env, visible]);

const getSettingAsync = useCallback(async () => {
try {
const { withSubscriptions = false } = option || {};
const {
authSetting: totalAuthSetting = {},
subscriptionsSetting: totalSubscriptionsSetting,
miniprogramAuthSetting: totalMiniprogramAuthSetting,
} = await (getSetting as RGetSetting)({
withSubscriptions,
});
setAuthSetting(totalAuthSetting);
if (withSubscriptions && totalSubscriptionsSetting) {
setSubscriptionsSetting(totalSubscriptionsSetting);
}
totalMiniprogramAuthSetting &&
setMiniprogramAuthSetting(totalMiniprogramAuthSetting);
} catch (e) {
console.log(e);
}
}, [option]);

const openSettingAsync = useCallback<IOpenSettingAction>(
(withSubscriptions = false) => {
return new Promise((resolve, reject) => {
if (env === ENV_TYPE.WEAPP) {
try {
(openSetting as ROpenSetting)({
withSubscriptions,
success: (res) => {
const {
authSetting: totalAuthSetting,
subscriptionsSetting: totalSubscriptionsSetting,
} = res;
if (withSubscriptions && totalSubscriptionsSetting) {
setSubscriptionsSetting(totalSubscriptionsSetting);
}
setAuthSetting(totalAuthSetting);
resolve(res);
},
fail: reject,
}).catch(reject);
} catch (e) {
reject({ errMsg: e });
}
} else {
reject({ errMsg: 'openSetting:fail' });
}
});
},
[env],
);

const authorizeAysnc = useCallback<IAuthorizeAction>(
(scope, miniprogram = false) => {
return new Promise((resolve, reject) => {
if (!scope || env === ENV_TYPE.WEAPP) {
try {
if (miniprogram && typeOf(wx, 'Object')) {
wx.authorizeForMiniProgram({
scope,
success: resolve,
fail: reject,
});
} else {
authorize({
scope,
success: resolve,
fail: reject,
}).catch(reject);
}
} catch (e) {
reject(e);
}
} else {
reject({ errMsg: 'authorize:fail' });
}
});
},
[authSetting, miniprogramAuthSetting],
);

return [
{ authSetting, subscriptionsSetting, miniprogramAuthSetting },
{
openSetting: openSettingAsync,
authorize: authorizeAysnc,
},
];
}

export default useAuthorize;
2 changes: 2 additions & 0 deletions packages/hooks/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ interface INavigator extends Navigator {
}

declare var navigator: INavigator;

declare var wx: any;
Loading

2 comments on commit c0ec57c

@vercel
Copy link

@vercel vercel bot commented on c0ec57c Sep 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

taro-hooks – ./

taro-hooks-innocces.vercel.app
taro-hooks-theta.vercel.app
taro-hooks-git-main-innocces.vercel.app

@vercel
Copy link

@vercel vercel bot commented on c0ec57c Sep 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

taro-hooks-h5 – ./

taro-hooks-h5-git-main-innocces.vercel.app
taro-hooks-h5-green.vercel.app
taro-hooks-h5-innocces.vercel.app

Please sign in to comment.