Skip to content

Commit 518c283

Browse files
committed
Workaround for expo/expo#39480.
1 parent 72f0ace commit 518c283

File tree

4 files changed

+79
-21
lines changed

4 files changed

+79
-21
lines changed

react-native/services/PermissionHelper/index.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,25 @@ export class PermissionHelper implements PermissionHelperInterface {
1717
* might only grant access to a small subset of resources.
1818
*/
1919
async acquire (
20-
permissions: ReadonlyArray<() => Promise<PermissionResponse>>,
20+
permissions: ReadonlyArray<{
21+
get: () => Promise<PermissionResponse>
22+
request: () => Promise<PermissionResponse>
23+
}>,
2124
onFailure: (showSettingsScreen: () => Promise<void>) => Promise<void>,
2225
onSuccess: () => Promise<void>
2326
): Promise<void> {
24-
for (const permission of permissions) {
25-
if (!(await permission()).granted) {
27+
for (const { get, request } of permissions) {
28+
const got = await get()
29+
30+
if (!got.granted) {
31+
if (got.canAskAgain) {
32+
const requested = await request()
33+
34+
if (requested.granted) {
35+
continue
36+
}
37+
}
38+
2639
await onFailure(showSettingsScreen)
2740
return
2841
}

react-native/services/PermissionHelper/unit.tsx

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,36 @@ test('executes the success callback when permissions are granted', async () => {
44
const onFailure = jest.fn().mockResolvedValue(undefined)
55
const onSuccess = jest.fn().mockResolvedValue(undefined)
66

7-
const firstPermission = jest.fn().mockResolvedValue({ granted: true })
8-
const secondPermission = jest.fn().mockResolvedValue({ granted: true })
9-
const thirdPermission = jest.fn().mockResolvedValue({ granted: true })
7+
const getFirstPermission = jest.fn().mockResolvedValue({ granted: false })
8+
const requestFirstPermission = jest.fn().mockResolvedValue({ granted: true })
9+
const getSecondPermission = jest.fn().mockResolvedValue({ granted: false })
10+
const requestSecondPermission = jest.fn().mockResolvedValue({ granted: true })
11+
const getThirdPermission = jest.fn().mockResolvedValue({ granted: false })
12+
const requestThirdPermission = jest.fn().mockResolvedValue({ granted: true })
1013

1114
const permissionHelper = new PermissionHelper()
1215

1316
await permissionHelper.acquire(
14-
[firstPermission, secondPermission, thirdPermission],
17+
[{
18+
get: getFirstPermission,
19+
request: requestFirstPermission
20+
}, {
21+
get: getSecondPermission,
22+
request: requestSecondPermission
23+
}, {
24+
get: getThirdPermission,
25+
request: requestThirdPermission
26+
}],
1527
onFailure,
1628
onSuccess
1729
)
1830

19-
expect(firstPermission).toHaveBeenCalledTimes(1)
20-
expect(secondPermission).toHaveBeenCalledTimes(1)
21-
expect(thirdPermission).toHaveBeenCalledTimes(1)
31+
expect(getFirstPermission).toHaveBeenCalledTimes(1)
32+
expect(requestFirstPermission).toHaveBeenCalledTimes(1)
33+
expect(getSecondPermission).toHaveBeenCalledTimes(1)
34+
expect(requestSecondPermission).toHaveBeenCalledTimes(1)
35+
expect(getThirdPermission).toHaveBeenCalledTimes(1)
36+
expect(requestThirdPermission).toHaveBeenCalledTimes(1)
2237
expect(onFailure).not.toHaveBeenCalled()
2338
expect(onSuccess).toBeCalledTimes(1)
2439
})
@@ -27,21 +42,36 @@ test('executes the failure callback when permissions are denied', async () => {
2742
const onFailure = jest.fn().mockResolvedValue(undefined)
2843
const onSuccess = jest.fn().mockResolvedValue(undefined)
2944

30-
const firstPermission = jest.fn().mockResolvedValue({ granted: true })
31-
const secondPermission = jest.fn().mockResolvedValue({ granted: false })
32-
const thirdPermission = jest.fn()
45+
const getFirstPermission = jest.fn().mockResolvedValue({ granted: false })
46+
const requestFirstPermission = jest.fn().mockResolvedValue({ granted: true })
47+
const getSecondPermission = jest.fn().mockResolvedValue({ granted: false })
48+
const requestSecondPermission = jest.fn().mockResolvedValue({ granted: false })
49+
const getThirdPermission = jest.fn().mockResolvedValue({ granted: false })
50+
const requestThirdPermission = jest.fn()
3351

3452
const permissionHelper = new PermissionHelper()
3553

3654
await permissionHelper.acquire(
37-
[firstPermission, secondPermission, thirdPermission],
55+
[{
56+
get: getFirstPermission,
57+
request: requestFirstPermission
58+
}, {
59+
get: getSecondPermission,
60+
request: requestSecondPermission
61+
}, {
62+
get: getThirdPermission,
63+
request: requestThirdPermission
64+
}],
3865
onFailure,
3966
onSuccess
4067
)
4168

42-
expect(firstPermission).toHaveBeenCalledTimes(1)
43-
expect(secondPermission).toHaveBeenCalledTimes(1)
44-
expect(thirdPermission).not.toHaveBeenCalled()
69+
expect(getFirstPermission).toHaveBeenCalledTimes(1)
70+
expect(requestFirstPermission).toHaveBeenCalledTimes(1)
71+
expect(getSecondPermission).toHaveBeenCalledTimes(1)
72+
expect(requestSecondPermission).toHaveBeenCalledTimes(1)
73+
expect(getThirdPermission).not.toHaveBeenCalled()
74+
expect(requestThirdPermission).not.toHaveBeenCalled()
4575
expect(onFailure).toBeCalledTimes(1)
4676
expect(onFailure).toBeCalledWith(showSettingsScreen)
4777
expect(onSuccess).not.toHaveBeenCalled()

react-native/services/PictureHelper/index.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ export class PictureHelper implements PictureHelperInterface {
2828
onSuccess: (uuid: string) => Promise<void>
2929
): Promise<void> {
3030
await this.permissionHelper.acquire(
31-
[ImagePicker.requestCameraPermissionsAsync, ImagePicker.requestMediaLibraryPermissionsAsync],
31+
[{
32+
get: ImagePicker.getCameraPermissionsAsync,
33+
request: ImagePicker.requestCameraPermissionsAsync
34+
}, {
35+
get: ImagePicker.getMediaLibraryPermissionsAsync,
36+
request: ImagePicker.requestMediaLibraryPermissionsAsync
37+
}],
3238
onPermissionDenied,
3339
async () => {
3440
const result = await ImagePicker.launchCameraAsync({
@@ -68,7 +74,10 @@ export class PictureHelper implements PictureHelperInterface {
6874
onSuccess: (uuid: string) => Promise<void>
6975
): Promise<void> {
7076
await this.permissionHelper.acquire(
71-
[ImagePicker.requestMediaLibraryPermissionsAsync],
77+
[{
78+
get: ImagePicker.getMediaLibraryPermissionsAsync,
79+
request: ImagePicker.requestMediaLibraryPermissionsAsync
80+
}],
7281
onPermissionDenied,
7382
async () => {
7483
const result = await ImagePicker.launchImageLibraryAsync({
@@ -101,7 +110,10 @@ export class PictureHelper implements PictureHelperInterface {
101110
onSuccess: (uuids: readonly string[]) => Promise<void>
102111
): Promise<void> {
103112
await this.permissionHelper.acquire(
104-
[ImagePicker.requestMediaLibraryPermissionsAsync],
113+
[{
114+
get: ImagePicker.getMediaLibraryPermissionsAsync,
115+
request: ImagePicker.requestMediaLibraryPermissionsAsync
116+
}],
105117
onPermissionDenied,
106118
async () => {
107119
const result = await ImagePicker.launchImageLibraryAsync({

react-native/types/PermissionHelperInterface/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ export interface PermissionHelperInterface {
1515
* might only grant access to a small subset of resources.
1616
*/
1717
acquire: (
18-
permissions: ReadonlyArray<() => Promise<PermissionResponse>>,
18+
permissions: ReadonlyArray<{
19+
get: () => Promise<PermissionResponse>
20+
request: () => Promise<PermissionResponse>
21+
}>,
1922
onFailure: (showSettingsScreen: () => Promise<void>) => Promise<void>,
2023
onSuccess: () => Promise<void>
2124
) => Promise<void>

0 commit comments

Comments
 (0)