瀏覽代碼

Add checkMultiple, improve parallelism

Mathieu Acthernoene 6 年之前
父節點
當前提交
de6edfaf1c
共有 1 個文件被更改,包括 79 次插入57 次删除
  1. 79
    57
      index.js

+ 79
- 57
index.js 查看文件

73
   rationale?: Rationale,
73
   rationale?: Rationale,
74
 |};
74
 |};
75
 
75
 
76
-const requestedKey = "@RNPermissions:requested";
77
-
78
 const platformPermissions = Object.values(
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
 function assertValidPermission(permission: string) {
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
 async function getRequestedPermissions() {
105
 async function getRequestedPermissions() {
96
   const requested = await AsyncStorage.getItem(requestedKey);
106
   const requested = await AsyncStorage.getItem(requestedKey);
107
+
97
   return requested ? JSON.parse(requested) : [];
108
   return requested ? JSON.parse(requested) : [];
98
 }
109
 }
99
 
110
 
100
-async function setRequestedPermission(permission: string) {
111
+async function setRequestedPermissions(permissions: string[]) {
101
   const requested = await getRequestedPermissions();
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
 async function internalCheck(
118
 async function internalCheck(
147
     return RESULTS.UNAVAILABLE;
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
 export function openSettings(): Promise<boolean> {
203
 export function openSettings(): Promise<boolean> {
162
   return internalCheck(permission);
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
 export function request(
219
 export function request(
166
   permission: string,
220
   permission: string,
167
   config: RequestConfig = {},
221
   config: RequestConfig = {},
173
 export function requestMultiple(
227
 export function requestMultiple(
174
   permissions: Permission[],
228
   permissions: Permission[],
175
 ): Promise<{ [permission: Permission]: PermissionStatus }> {
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
 }