UNPKG

5.47 kBPlain TextView Raw
1import { Platform } from 'react-native';
2
3import {
4 coalesceExpirations,
5 coalesceStatuses,
6 coalesceCanAskAgain,
7 coalesceGranted,
8} from './CoalescedPermissions';
9import Permissions from './ExpoPermissions';
10import {
11 PermissionResponse,
12 PermissionType,
13 PermissionMap,
14 PermissionStatus,
15 PermissionExpiration,
16 PermissionInfo,
17} from './Permissions.types';
18
19export {
20 PermissionStatus,
21 PermissionResponse,
22 PermissionExpiration,
23 PermissionMap,
24 PermissionInfo,
25 PermissionType,
26};
27
28export const CAMERA = 'camera';
29export const MEDIA_LIBRARY = 'mediaLibrary';
30export const MEDIA_LIBRARY_WRITE_ONLY = 'mediaLibraryWriteOnly';
31/**
32 * @deprecated Use `MEDIA_LIBRARY` or `MEDIA_LIBRARY_WRITE_ONLY`
33 */
34export const CAMERA_ROLL = MEDIA_LIBRARY;
35export const AUDIO_RECORDING = 'audioRecording';
36/** @deprecated Use `LOCATION_FOREGROUND` or `LOCATION_BACKGROUND` instead */
37export const LOCATION = 'location';
38export const LOCATION_FOREGROUND = 'locationForeground';
39export const LOCATION_BACKGROUND = 'locationBackground';
40export const USER_FACING_NOTIFICATIONS = 'userFacingNotifications';
41export const NOTIFICATIONS = 'notifications';
42export const CONTACTS = 'contacts';
43export const CALENDAR = 'calendar';
44export const REMINDERS = 'reminders';
45export const SYSTEM_BRIGHTNESS = 'systemBrightness';
46export const MOTION = 'motion';
47
48// Map corresponding permission to correct package
49const PERMISSION_MODULE_MAPPING = {
50 [CAMERA]: 'expo-camera',
51 [CAMERA_ROLL]: 'expo-media-library',
52 [MEDIA_LIBRARY]: 'expo-media-library',
53 [MEDIA_LIBRARY_WRITE_ONLY]: 'expo-media-library',
54 [AUDIO_RECORDING]: 'expo-av',
55 [LOCATION]: 'expo-location',
56 [USER_FACING_NOTIFICATIONS]: 'expo-notifications',
57 [NOTIFICATIONS]: 'expo-notifications',
58 [CONTACTS]: 'expo-contacts',
59 [CALENDAR]: 'expo-calendar',
60 [REMINDERS]: 'expo-calendar',
61 [SYSTEM_BRIGHTNESS]: 'expo-brightness',
62 [MOTION]: 'expo-sensors',
63};
64
65export async function getAsync(...types: PermissionType[]): Promise<PermissionResponse> {
66 console.warn(
67 `expo-permissions is now deprecated — the functionality has been moved to other expo packages that directly use these permissions (e.g. expo-location, expo-camera). The package will be removed in the upcoming releases.`
68 );
69
70 if (Platform.OS === 'ios') {
71 return await _handleMultiPermissionsRequestIOSAsync(types, Permissions.getAsync);
72 }
73 return await _handlePermissionsRequestAsync(types, Permissions.getAsync);
74}
75
76export async function askAsync(...types: PermissionType[]): Promise<PermissionResponse> {
77 console.warn(
78 `expo-permissions is now deprecated — the functionality has been moved to other expo packages that directly use these permissions (e.g. expo-location, expo-camera). The package will be removed in the upcoming releases.`
79 );
80
81 if (Platform.OS === 'ios') {
82 return await _handleMultiPermissionsRequestIOSAsync(types, Permissions.askAsync);
83 }
84 return await _handlePermissionsRequestAsync(types, Permissions.askAsync);
85}
86
87async function _handleSinglePermissionRequestIOSAsync(
88 type: PermissionType,
89 handlePermission: (type: PermissionType) => Promise<PermissionInfo>
90): Promise<PermissionInfo> {
91 if (Platform.OS !== 'web' && type === 'motion') {
92 return {
93 status: PermissionStatus.GRANTED,
94 expires: 'never',
95 granted: true,
96 canAskAgain: true,
97 };
98 }
99 try {
100 return await handlePermission(type);
101 } catch (error) {
102 // We recognize the permission's library, so we inform the user to link that library to request the permission.
103 if (error.code === 'E_PERMISSIONS_UNKNOWN' && PERMISSION_MODULE_MAPPING[type]) {
104 const library = PERMISSION_MODULE_MAPPING[type];
105 error.message = `${error.message}, please install and link the package ${PERMISSION_MODULE_MAPPING[type]}, see more at https://github.com/expo/expo/tree/master/packages/${library}`;
106 }
107 throw error;
108 }
109}
110
111async function _handleMultiPermissionsRequestIOSAsync(
112 types: PermissionType[],
113 handlePermission: (type: PermissionType) => Promise<PermissionInfo>
114): Promise<PermissionResponse> {
115 if (!types.length) {
116 throw new Error('At least one permission type must be specified');
117 }
118
119 const permissions = {};
120 for (const type of types) {
121 permissions[type] = await _handleSinglePermissionRequestIOSAsync(type, handlePermission);
122 }
123
124 return {
125 status: coalesceStatuses(permissions),
126 expires: coalesceExpirations(permissions),
127 canAskAgain: coalesceCanAskAgain(permissions),
128 granted: coalesceGranted(permissions),
129 permissions,
130 };
131}
132
133async function _handlePermissionsRequestAsync(
134 types: PermissionType[],
135 handlePermissions: (types: PermissionType[]) => Promise<PermissionMap>
136): Promise<PermissionResponse> {
137 if (!types.length) {
138 throw new Error('At least one permission type must be specified');
139 }
140
141 if (Platform.OS !== 'web' && types.length === 1 && types[0] === 'motion') {
142 const approvedPermission = {
143 status: PermissionStatus.GRANTED,
144 expires: 'never',
145 granted: true,
146 canAskAgain: true,
147 };
148 return {
149 ...approvedPermission,
150 // @ts-ignore
151 permissions: { motion: approvedPermission },
152 };
153 }
154
155 const permissions = await handlePermissions(types);
156 return {
157 status: coalesceStatuses(permissions),
158 expires: coalesceExpirations(permissions),
159 canAskAgain: coalesceCanAskAgain(permissions),
160 granted: coalesceGranted(permissions),
161 permissions,
162 };
163}