Просмотр исходного кода

Add checkMultiple, improve parallelism

Mathieu Acthernoene 6 лет назад
Родитель
Сommit
de6edfaf1c
1 измененных файлов: 79 добавлений и 57 удалений
  1. 79
    57
      index.js

+ 79
- 57
index.js Просмотреть файл

@@ -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
 }