|
@@ -73,41 +73,46 @@ export type RequestConfig = {|
|
73
|
73
|
rationale?: Rationale,
|
74
|
74
|
|};
|
75
|
75
|
|
76
|
|
-const requestedKey = "@RNPermissions:requested";
|
77
|
|
-
|
78
|
76
|
const platformPermissions = Object.values(
|
79
|
|
- Platform.OS === "android" ? ANDROID_PERMISSIONS : IOS_PERMISSIONS,
|
|
77
|
+ Platform.OS === "ios" ? IOS_PERMISSIONS : ANDROID_PERMISSIONS,
|
80
|
78
|
);
|
81
|
79
|
|
82
|
80
|
function assertValidPermission(permission: string) {
|
83
|
|
- if (platformPermissions.includes(permission)) {
|
84
|
|
- return;
|
85
|
|
- }
|
|
81
|
+ if (!platformPermissions.includes(permission)) {
|
|
82
|
+ const bulletsList = `• ${platformPermissions.join("\n• ")}`;
|
|
83
|
+ const alertSentence = `Invalid ${
|
|
84
|
+ Platform.OS
|
|
85
|
+ } permission "${permission}". Must be one of:\n\n`;
|
86
|
86
|
|
87
|
|
- const bulletsList = `• ${platformPermissions.join("\n• ")}`;
|
88
|
|
- const alertSentence = `Invalid ${
|
89
|
|
- Platform.OS
|
90
|
|
- } permission "${permission}". Must be one of:\n\n`;
|
|
87
|
+ throw new Error(`${alertSentence}${bulletsList}`);
|
|
88
|
+ }
|
|
89
|
+}
|
91
|
90
|
|
92
|
|
- throw new Error(`${alertSentence}${bulletsList}`);
|
|
91
|
+function getUnavailablePermissions(permissions: string[]) {
|
|
92
|
+ return Promise.all(
|
|
93
|
+ permissions.map(p => RNPermissions.isPermissionAvailable(p)),
|
|
94
|
+ ).then(result =>
|
|
95
|
+ result.reduce(
|
|
96
|
+ (acc, isAvailable, i) =>
|
|
97
|
+ isAvailable ? acc : { ...acc, [permissions[i]]: RESULTS.UNAVAILABLE },
|
|
98
|
+ {},
|
|
99
|
+ ),
|
|
100
|
+ );
|
93
|
101
|
}
|
94
|
102
|
|
|
103
|
+const requestedKey = "@RNPermissions:requested";
|
|
104
|
+
|
95
|
105
|
async function getRequestedPermissions() {
|
96
|
106
|
const requested = await AsyncStorage.getItem(requestedKey);
|
|
107
|
+
|
97
|
108
|
return requested ? JSON.parse(requested) : [];
|
98
|
109
|
}
|
99
|
110
|
|
100
|
|
-async function setRequestedPermission(permission: string) {
|
|
111
|
+async function setRequestedPermissions(permissions: string[]) {
|
101
|
112
|
const requested = await getRequestedPermissions();
|
|
113
|
+ const dedup = [...new Set([...requested, ...permissions])];
|
102
|
114
|
|
103
|
|
- if (requested.includes(permission)) {
|
104
|
|
- return;
|
105
|
|
- }
|
106
|
|
-
|
107
|
|
- return await AsyncStorage.setItem(
|
108
|
|
- requestedKey,
|
109
|
|
- JSON.stringify([...requested, permission]),
|
110
|
|
- );
|
|
115
|
+ return AsyncStorage.setItem(requestedKey, dedup);
|
111
|
116
|
}
|
112
|
117
|
|
113
|
118
|
async function internalCheck(
|
|
@@ -147,10 +152,52 @@ async function internalRequest(
|
147
|
152
|
return RESULTS.UNAVAILABLE;
|
148
|
153
|
}
|
149
|
154
|
|
150
|
|
- const result = await PermissionsAndroid.request(permission, rationale);
|
151
|
|
- await setRequestedPermission(permission);
|
|
155
|
+ const status = await PermissionsAndroid.request(permission, rationale);
|
|
156
|
+
|
|
157
|
+ // set permission as requested
|
|
158
|
+ await setRequestedPermissions([permission]);
|
|
159
|
+ return status;
|
|
160
|
+}
|
152
|
161
|
|
153
|
|
- return result;
|
|
162
|
+async function internalCheckMultiple(
|
|
163
|
+ permissions: Permission[],
|
|
164
|
+): Promise<{ [permission: Permission]: PermissionStatus }> {
|
|
165
|
+ const result = await getUnavailablePermissions(permissions);
|
|
166
|
+ const unavailable = Object.keys(result);
|
|
167
|
+ const available = permissions.filter(p => !unavailable.includes(p));
|
|
168
|
+
|
|
169
|
+ return Promise.all(available.map(p => internalCheck(p)))
|
|
170
|
+ .then(statuses =>
|
|
171
|
+ statuses.reduce((acc, s, i) => ({ ...acc, [available[i]]: s }), {}),
|
|
172
|
+ )
|
|
173
|
+ .then(statuses => ({ ...result, ...statuses }));
|
|
174
|
+}
|
|
175
|
+
|
|
176
|
+async function internalRequestMultiple(
|
|
177
|
+ permissions: Permission[],
|
|
178
|
+): Promise<{ [permission: Permission]: PermissionStatus }> {
|
|
179
|
+ if (Platform.OS !== "android") {
|
|
180
|
+ const result = {};
|
|
181
|
+
|
|
182
|
+ for (let i = 0; i < permissions.length; i++) {
|
|
183
|
+ const permission = permissions[i];
|
|
184
|
+ // avoid checking them all at once
|
|
185
|
+ result[permission] = await internalRequest(permission);
|
|
186
|
+ }
|
|
187
|
+
|
|
188
|
+ return result;
|
|
189
|
+ }
|
|
190
|
+
|
|
191
|
+ const result = await getUnavailablePermissions(permissions);
|
|
192
|
+ const unavailable = Object.keys(result);
|
|
193
|
+
|
|
194
|
+ const statuses = await PermissionsAndroid.requestMultiple(
|
|
195
|
+ permissions.filter(p => !unavailable.includes(p)),
|
|
196
|
+ ).then(statuses => ({ ...result, ...statuses }));
|
|
197
|
+
|
|
198
|
+ // set permissions as requested
|
|
199
|
+ await setRequestedPermissions(permissions);
|
|
200
|
+ return status;
|
154
|
201
|
}
|
155
|
202
|
|
156
|
203
|
export function openSettings(): Promise<boolean> {
|
|
@@ -162,6 +209,13 @@ export function check(permission: Permission): Promise<PermissionStatus> {
|
162
|
209
|
return internalCheck(permission);
|
163
|
210
|
}
|
164
|
211
|
|
|
212
|
+export function checkMultiple(
|
|
213
|
+ permissions: Permission[],
|
|
214
|
+): Promise<{ [permission: Permission]: PermissionStatus }> {
|
|
215
|
+ permissions.forEach(assertValidPermission);
|
|
216
|
+ return internalCheckMultiple(permissions);
|
|
217
|
+}
|
|
218
|
+
|
165
|
219
|
export function request(
|
166
|
220
|
permission: string,
|
167
|
221
|
config: RequestConfig = {},
|
|
@@ -173,38 +227,6 @@ export function request(
|
173
|
227
|
export function requestMultiple(
|
174
|
228
|
permissions: Permission[],
|
175
|
229
|
): Promise<{ [permission: Permission]: PermissionStatus }> {
|
176
|
|
- permissions.forEach(permission => {
|
177
|
|
- assertValidPermission(permission);
|
178
|
|
- });
|
179
|
|
-
|
180
|
|
- return (async () => {
|
181
|
|
- const result = {};
|
182
|
|
-
|
183
|
|
- if (Platform.OS !== "android") {
|
184
|
|
- for (let index = 0; index < permissions.length; index++) {
|
185
|
|
- const permission = permissions[index];
|
186
|
|
- result[permission] = await request(permission);
|
187
|
|
- }
|
188
|
|
-
|
189
|
|
- return result;
|
190
|
|
- }
|
191
|
|
-
|
192
|
|
- const available = [];
|
193
|
|
-
|
194
|
|
- for (let index = 0; index < permissions.length; index++) {
|
195
|
|
- const permission = permissions[index];
|
196
|
|
-
|
197
|
|
- // @TODO Do checks in parallel to improve performances
|
198
|
|
- if (await RNPermissions.isPermissionAvailable(permission)) {
|
199
|
|
- available.push(permission);
|
200
|
|
- } else {
|
201
|
|
- result[permission] = RESULTS.UNAVAILABLE;
|
202
|
|
- }
|
203
|
|
- }
|
204
|
|
-
|
205
|
|
- return PermissionsAndroid.requestMultiple(available).then(statuses => ({
|
206
|
|
- ...result,
|
207
|
|
- ...statuses,
|
208
|
|
- }));
|
209
|
|
- })();
|
|
230
|
+ permissions.forEach(assertValidPermission);
|
|
231
|
+ return internalRequestMultiple(permissions);
|
210
|
232
|
}
|