react-native-permission-handler 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -15
- package/dist/chunk-FJ23EV7L.mjs +127 -0
- package/dist/chunk-FJ23EV7L.mjs.map +1 -0
- package/dist/engines/expo.d.mts +23 -10
- package/dist/engines/expo.d.ts +23 -10
- package/dist/engines/expo.js +17 -8
- package/dist/engines/expo.js.map +1 -1
- package/dist/engines/expo.mjs +17 -8
- package/dist/engines/expo.mjs.map +1 -1
- package/dist/engines/rnp.d.mts +45 -2
- package/dist/engines/rnp.d.ts +45 -2
- package/dist/engines/rnp.js +47 -1
- package/dist/engines/rnp.js.map +1 -1
- package/dist/engines/rnp.mjs +1 -1
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/engines/expo.test.ts +76 -0
- package/src/engines/expo.ts +44 -15
- package/src/engines/rnp.test.ts +41 -11
- package/src/engines/rnp.ts +50 -2
- package/dist/chunk-EU3KPRTI.mjs +0 -81
- package/dist/chunk-EU3KPRTI.mjs.map +0 -1
package/dist/engines/rnp.js
CHANGED
|
@@ -30,6 +30,7 @@ function p(ios, android) {
|
|
|
30
30
|
return import_react_native.Platform.select({ ios, android, default: ios }) ?? ios;
|
|
31
31
|
}
|
|
32
32
|
var Permissions = {
|
|
33
|
+
// Cross-platform
|
|
33
34
|
CAMERA: p("ios.permission.CAMERA", "android.permission.CAMERA"),
|
|
34
35
|
MICROPHONE: p("ios.permission.MICROPHONE", "android.permission.RECORD_AUDIO"),
|
|
35
36
|
CONTACTS: p("ios.permission.CONTACTS", "android.permission.READ_CONTACTS"),
|
|
@@ -51,8 +52,53 @@ var Permissions = {
|
|
|
51
52
|
"ios.permission.PHOTO_LIBRARY_ADD_ONLY",
|
|
52
53
|
"android.permission.WRITE_EXTERNAL_STORAGE"
|
|
53
54
|
),
|
|
55
|
+
MEDIA_LIBRARY: p("ios.permission.MEDIA_LIBRARY", "android.permission.READ_MEDIA_AUDIO"),
|
|
54
56
|
BLUETOOTH: p("ios.permission.BLUETOOTH", "android.permission.BLUETOOTH_CONNECT"),
|
|
55
|
-
|
|
57
|
+
SPEECH_RECOGNITION: p("ios.permission.SPEECH_RECOGNITION", "android.permission.RECORD_AUDIO"),
|
|
58
|
+
MOTION: p("ios.permission.MOTION", "android.permission.ACTIVITY_RECOGNITION"),
|
|
59
|
+
NOTIFICATIONS: "notifications",
|
|
60
|
+
// iOS-only
|
|
61
|
+
IOS: {
|
|
62
|
+
APP_TRACKING_TRANSPARENCY: "ios.permission.APP_TRACKING_TRANSPARENCY",
|
|
63
|
+
FACE_ID: "ios.permission.FACE_ID",
|
|
64
|
+
REMINDERS: "ios.permission.REMINDERS",
|
|
65
|
+
SIRI: "ios.permission.SIRI",
|
|
66
|
+
STOREKIT: "ios.permission.STOREKIT"
|
|
67
|
+
},
|
|
68
|
+
// Android-only
|
|
69
|
+
ANDROID: {
|
|
70
|
+
ACCEPT_HANDOVER: "android.permission.ACCEPT_HANDOVER",
|
|
71
|
+
ACCESS_COARSE_LOCATION: "android.permission.ACCESS_COARSE_LOCATION",
|
|
72
|
+
ACCESS_MEDIA_LOCATION: "android.permission.ACCESS_MEDIA_LOCATION",
|
|
73
|
+
ADD_VOICEMAIL: "com.android.voicemail.permission.ADD_VOICEMAIL",
|
|
74
|
+
ANSWER_PHONE_CALLS: "android.permission.ANSWER_PHONE_CALLS",
|
|
75
|
+
BLUETOOTH_ADVERTISE: "android.permission.BLUETOOTH_ADVERTISE",
|
|
76
|
+
BLUETOOTH_SCAN: "android.permission.BLUETOOTH_SCAN",
|
|
77
|
+
BODY_SENSORS: "android.permission.BODY_SENSORS",
|
|
78
|
+
BODY_SENSORS_BACKGROUND: "android.permission.BODY_SENSORS_BACKGROUND",
|
|
79
|
+
CALL_PHONE: "android.permission.CALL_PHONE",
|
|
80
|
+
GET_ACCOUNTS: "android.permission.GET_ACCOUNTS",
|
|
81
|
+
NEARBY_WIFI_DEVICES: "android.permission.NEARBY_WIFI_DEVICES",
|
|
82
|
+
PROCESS_OUTGOING_CALLS: "android.permission.PROCESS_OUTGOING_CALLS",
|
|
83
|
+
READ_CALL_LOG: "android.permission.READ_CALL_LOG",
|
|
84
|
+
READ_EXTERNAL_STORAGE: "android.permission.READ_EXTERNAL_STORAGE",
|
|
85
|
+
READ_MEDIA_AUDIO: "android.permission.READ_MEDIA_AUDIO",
|
|
86
|
+
READ_MEDIA_IMAGES: "android.permission.READ_MEDIA_IMAGES",
|
|
87
|
+
READ_MEDIA_VIDEO: "android.permission.READ_MEDIA_VIDEO",
|
|
88
|
+
READ_MEDIA_VISUAL_USER_SELECTED: "android.permission.READ_MEDIA_VISUAL_USER_SELECTED",
|
|
89
|
+
READ_PHONE_NUMBERS: "android.permission.READ_PHONE_NUMBERS",
|
|
90
|
+
READ_PHONE_STATE: "android.permission.READ_PHONE_STATE",
|
|
91
|
+
READ_SMS: "android.permission.READ_SMS",
|
|
92
|
+
RECEIVE_MMS: "android.permission.RECEIVE_MMS",
|
|
93
|
+
RECEIVE_SMS: "android.permission.RECEIVE_SMS",
|
|
94
|
+
RECEIVE_WAP_PUSH: "android.permission.RECEIVE_WAP_PUSH",
|
|
95
|
+
SEND_SMS: "android.permission.SEND_SMS",
|
|
96
|
+
USE_SIP: "android.permission.USE_SIP",
|
|
97
|
+
UWB_RANGING: "android.permission.UWB_RANGING",
|
|
98
|
+
WRITE_CALL_LOG: "android.permission.WRITE_CALL_LOG",
|
|
99
|
+
WRITE_CONTACTS: "android.permission.WRITE_CONTACTS",
|
|
100
|
+
WRITE_EXTERNAL_STORAGE: "android.permission.WRITE_EXTERNAL_STORAGE"
|
|
101
|
+
}
|
|
56
102
|
};
|
|
57
103
|
function createRNPEngine() {
|
|
58
104
|
return {
|
package/dist/engines/rnp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/engines/rnp.ts"],"sourcesContent":["import { Platform } from \"react-native\";\nimport {\n type Permission,\n check,\n checkNotifications,\n openSettings,\n request,\n requestNotifications,\n} from \"react-native-permissions\";\nimport type { PermissionEngine, PermissionStatus } from \"../types\";\n\nfunction p(ios: string, android: string): string {\n return Platform.select({ ios, android, default: ios }) ?? ios;\n}\n\n/**\n * Cross-platform permission constants
|
|
1
|
+
{"version":3,"sources":["../../src/engines/rnp.ts"],"sourcesContent":["import { Platform } from \"react-native\";\nimport {\n type Permission,\n check,\n checkNotifications,\n openSettings,\n request,\n requestNotifications,\n} from \"react-native-permissions\";\nimport type { PermissionEngine, PermissionStatus } from \"../types\";\n\nfunction p(ios: string, android: string): string {\n return Platform.select({ ios, android, default: ios }) ?? ios;\n}\n\n/**\n * Cross-platform permission constants that resolve to the correct\n * platform-specific string at runtime via Platform.select.\n */\nexport const Permissions = {\n // Cross-platform\n CAMERA: p(\"ios.permission.CAMERA\", \"android.permission.CAMERA\"),\n MICROPHONE: p(\"ios.permission.MICROPHONE\", \"android.permission.RECORD_AUDIO\"),\n CONTACTS: p(\"ios.permission.CONTACTS\", \"android.permission.READ_CONTACTS\"),\n CALENDARS: p(\"ios.permission.CALENDARS\", \"android.permission.READ_CALENDAR\"),\n CALENDARS_WRITE_ONLY: p(\n \"ios.permission.CALENDARS_WRITE_ONLY\",\n \"android.permission.WRITE_CALENDAR\",\n ),\n LOCATION_WHEN_IN_USE: p(\n \"ios.permission.LOCATION_WHEN_IN_USE\",\n \"android.permission.ACCESS_FINE_LOCATION\",\n ),\n LOCATION_ALWAYS: p(\n \"ios.permission.LOCATION_ALWAYS\",\n \"android.permission.ACCESS_BACKGROUND_LOCATION\",\n ),\n PHOTO_LIBRARY: p(\"ios.permission.PHOTO_LIBRARY\", \"android.permission.READ_MEDIA_IMAGES\"),\n PHOTO_LIBRARY_ADD_ONLY: p(\n \"ios.permission.PHOTO_LIBRARY_ADD_ONLY\",\n \"android.permission.WRITE_EXTERNAL_STORAGE\",\n ),\n MEDIA_LIBRARY: p(\"ios.permission.MEDIA_LIBRARY\", \"android.permission.READ_MEDIA_AUDIO\"),\n BLUETOOTH: p(\"ios.permission.BLUETOOTH\", \"android.permission.BLUETOOTH_CONNECT\"),\n SPEECH_RECOGNITION: p(\"ios.permission.SPEECH_RECOGNITION\", \"android.permission.RECORD_AUDIO\"),\n MOTION: p(\"ios.permission.MOTION\", \"android.permission.ACTIVITY_RECOGNITION\"),\n NOTIFICATIONS: \"notifications\",\n\n // iOS-only\n IOS: {\n APP_TRACKING_TRANSPARENCY: \"ios.permission.APP_TRACKING_TRANSPARENCY\",\n FACE_ID: \"ios.permission.FACE_ID\",\n REMINDERS: \"ios.permission.REMINDERS\",\n SIRI: \"ios.permission.SIRI\",\n STOREKIT: \"ios.permission.STOREKIT\",\n },\n\n // Android-only\n ANDROID: {\n ACCEPT_HANDOVER: \"android.permission.ACCEPT_HANDOVER\",\n ACCESS_COARSE_LOCATION: \"android.permission.ACCESS_COARSE_LOCATION\",\n ACCESS_MEDIA_LOCATION: \"android.permission.ACCESS_MEDIA_LOCATION\",\n ADD_VOICEMAIL: \"com.android.voicemail.permission.ADD_VOICEMAIL\",\n ANSWER_PHONE_CALLS: \"android.permission.ANSWER_PHONE_CALLS\",\n BLUETOOTH_ADVERTISE: \"android.permission.BLUETOOTH_ADVERTISE\",\n BLUETOOTH_SCAN: \"android.permission.BLUETOOTH_SCAN\",\n BODY_SENSORS: \"android.permission.BODY_SENSORS\",\n BODY_SENSORS_BACKGROUND: \"android.permission.BODY_SENSORS_BACKGROUND\",\n CALL_PHONE: \"android.permission.CALL_PHONE\",\n GET_ACCOUNTS: \"android.permission.GET_ACCOUNTS\",\n NEARBY_WIFI_DEVICES: \"android.permission.NEARBY_WIFI_DEVICES\",\n PROCESS_OUTGOING_CALLS: \"android.permission.PROCESS_OUTGOING_CALLS\",\n READ_CALL_LOG: \"android.permission.READ_CALL_LOG\",\n READ_EXTERNAL_STORAGE: \"android.permission.READ_EXTERNAL_STORAGE\",\n READ_MEDIA_AUDIO: \"android.permission.READ_MEDIA_AUDIO\",\n READ_MEDIA_IMAGES: \"android.permission.READ_MEDIA_IMAGES\",\n READ_MEDIA_VIDEO: \"android.permission.READ_MEDIA_VIDEO\",\n READ_MEDIA_VISUAL_USER_SELECTED: \"android.permission.READ_MEDIA_VISUAL_USER_SELECTED\",\n READ_PHONE_NUMBERS: \"android.permission.READ_PHONE_NUMBERS\",\n READ_PHONE_STATE: \"android.permission.READ_PHONE_STATE\",\n READ_SMS: \"android.permission.READ_SMS\",\n RECEIVE_MMS: \"android.permission.RECEIVE_MMS\",\n RECEIVE_SMS: \"android.permission.RECEIVE_SMS\",\n RECEIVE_WAP_PUSH: \"android.permission.RECEIVE_WAP_PUSH\",\n SEND_SMS: \"android.permission.SEND_SMS\",\n USE_SIP: \"android.permission.USE_SIP\",\n UWB_RANGING: \"android.permission.UWB_RANGING\",\n WRITE_CALL_LOG: \"android.permission.WRITE_CALL_LOG\",\n WRITE_CONTACTS: \"android.permission.WRITE_CONTACTS\",\n WRITE_EXTERNAL_STORAGE: \"android.permission.WRITE_EXTERNAL_STORAGE\",\n },\n} as const;\n\nexport function createRNPEngine(): PermissionEngine {\n return {\n async check(permission: string): Promise<PermissionStatus> {\n if (permission === \"notifications\") {\n const result = await checkNotifications();\n return result.status as PermissionStatus;\n }\n return (await check(permission as Permission)) as PermissionStatus;\n },\n\n async request(permission: string): Promise<PermissionStatus> {\n if (permission === \"notifications\") {\n const result = await requestNotifications([\"alert\", \"badge\", \"sound\"]);\n return result.status as PermissionStatus;\n }\n return (await request(permission as Permission)) as PermissionStatus;\n },\n\n async openSettings(): Promise<void> {\n await openSettings();\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAyB;AACzB,sCAOO;AAGP,SAAS,EAAE,KAAa,SAAyB;AAC/C,SAAO,6BAAS,OAAO,EAAE,KAAK,SAAS,SAAS,IAAI,CAAC,KAAK;AAC5D;AAMO,IAAM,cAAc;AAAA;AAAA,EAEzB,QAAQ,EAAE,yBAAyB,2BAA2B;AAAA,EAC9D,YAAY,EAAE,6BAA6B,iCAAiC;AAAA,EAC5E,UAAU,EAAE,2BAA2B,kCAAkC;AAAA,EACzE,WAAW,EAAE,4BAA4B,kCAAkC;AAAA,EAC3E,sBAAsB;AAAA,IACpB;AAAA,IACA;AAAA,EACF;AAAA,EACA,sBAAsB;AAAA,IACpB;AAAA,IACA;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf;AAAA,IACA;AAAA,EACF;AAAA,EACA,eAAe,EAAE,gCAAgC,sCAAsC;AAAA,EACvF,wBAAwB;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAAA,EACA,eAAe,EAAE,gCAAgC,qCAAqC;AAAA,EACtF,WAAW,EAAE,4BAA4B,sCAAsC;AAAA,EAC/E,oBAAoB,EAAE,qCAAqC,iCAAiC;AAAA,EAC5F,QAAQ,EAAE,yBAAyB,yCAAyC;AAAA,EAC5E,eAAe;AAAA;AAAA,EAGf,KAAK;AAAA,IACH,2BAA2B;AAAA,IAC3B,SAAS;AAAA,IACT,WAAW;AAAA,IACX,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA,SAAS;AAAA,IACP,iBAAiB;AAAA,IACjB,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,yBAAyB;AAAA,IACzB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,wBAAwB;AAAA,IACxB,eAAe;AAAA,IACf,uBAAuB;AAAA,IACvB,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,iCAAiC;AAAA,IACjC,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,wBAAwB;AAAA,EAC1B;AACF;AAEO,SAAS,kBAAoC;AAClD,SAAO;AAAA,IACL,MAAM,MAAM,YAA+C;AACzD,UAAI,eAAe,iBAAiB;AAClC,cAAM,SAAS,UAAM,oDAAmB;AACxC,eAAO,OAAO;AAAA,MAChB;AACA,aAAQ,UAAM,uCAAM,UAAwB;AAAA,IAC9C;AAAA,IAEA,MAAM,QAAQ,YAA+C;AAC3D,UAAI,eAAe,iBAAiB;AAClC,cAAM,SAAS,UAAM,sDAAqB,CAAC,SAAS,SAAS,OAAO,CAAC;AACrE,eAAO,OAAO;AAAA,MAChB;AACA,aAAQ,UAAM,yCAAQ,UAAwB;AAAA,IAChD;AAAA,IAEA,MAAM,eAA8B;AAClC,gBAAM,8CAAa;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
|
package/dist/engines/rnp.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -57,6 +57,7 @@ var init_rnp = __esm({
|
|
|
57
57
|
import_react_native = require("react-native");
|
|
58
58
|
import_react_native_permissions = require("react-native-permissions");
|
|
59
59
|
Permissions = {
|
|
60
|
+
// Cross-platform
|
|
60
61
|
CAMERA: p("ios.permission.CAMERA", "android.permission.CAMERA"),
|
|
61
62
|
MICROPHONE: p("ios.permission.MICROPHONE", "android.permission.RECORD_AUDIO"),
|
|
62
63
|
CONTACTS: p("ios.permission.CONTACTS", "android.permission.READ_CONTACTS"),
|
|
@@ -78,8 +79,53 @@ var init_rnp = __esm({
|
|
|
78
79
|
"ios.permission.PHOTO_LIBRARY_ADD_ONLY",
|
|
79
80
|
"android.permission.WRITE_EXTERNAL_STORAGE"
|
|
80
81
|
),
|
|
82
|
+
MEDIA_LIBRARY: p("ios.permission.MEDIA_LIBRARY", "android.permission.READ_MEDIA_AUDIO"),
|
|
81
83
|
BLUETOOTH: p("ios.permission.BLUETOOTH", "android.permission.BLUETOOTH_CONNECT"),
|
|
82
|
-
|
|
84
|
+
SPEECH_RECOGNITION: p("ios.permission.SPEECH_RECOGNITION", "android.permission.RECORD_AUDIO"),
|
|
85
|
+
MOTION: p("ios.permission.MOTION", "android.permission.ACTIVITY_RECOGNITION"),
|
|
86
|
+
NOTIFICATIONS: "notifications",
|
|
87
|
+
// iOS-only
|
|
88
|
+
IOS: {
|
|
89
|
+
APP_TRACKING_TRANSPARENCY: "ios.permission.APP_TRACKING_TRANSPARENCY",
|
|
90
|
+
FACE_ID: "ios.permission.FACE_ID",
|
|
91
|
+
REMINDERS: "ios.permission.REMINDERS",
|
|
92
|
+
SIRI: "ios.permission.SIRI",
|
|
93
|
+
STOREKIT: "ios.permission.STOREKIT"
|
|
94
|
+
},
|
|
95
|
+
// Android-only
|
|
96
|
+
ANDROID: {
|
|
97
|
+
ACCEPT_HANDOVER: "android.permission.ACCEPT_HANDOVER",
|
|
98
|
+
ACCESS_COARSE_LOCATION: "android.permission.ACCESS_COARSE_LOCATION",
|
|
99
|
+
ACCESS_MEDIA_LOCATION: "android.permission.ACCESS_MEDIA_LOCATION",
|
|
100
|
+
ADD_VOICEMAIL: "com.android.voicemail.permission.ADD_VOICEMAIL",
|
|
101
|
+
ANSWER_PHONE_CALLS: "android.permission.ANSWER_PHONE_CALLS",
|
|
102
|
+
BLUETOOTH_ADVERTISE: "android.permission.BLUETOOTH_ADVERTISE",
|
|
103
|
+
BLUETOOTH_SCAN: "android.permission.BLUETOOTH_SCAN",
|
|
104
|
+
BODY_SENSORS: "android.permission.BODY_SENSORS",
|
|
105
|
+
BODY_SENSORS_BACKGROUND: "android.permission.BODY_SENSORS_BACKGROUND",
|
|
106
|
+
CALL_PHONE: "android.permission.CALL_PHONE",
|
|
107
|
+
GET_ACCOUNTS: "android.permission.GET_ACCOUNTS",
|
|
108
|
+
NEARBY_WIFI_DEVICES: "android.permission.NEARBY_WIFI_DEVICES",
|
|
109
|
+
PROCESS_OUTGOING_CALLS: "android.permission.PROCESS_OUTGOING_CALLS",
|
|
110
|
+
READ_CALL_LOG: "android.permission.READ_CALL_LOG",
|
|
111
|
+
READ_EXTERNAL_STORAGE: "android.permission.READ_EXTERNAL_STORAGE",
|
|
112
|
+
READ_MEDIA_AUDIO: "android.permission.READ_MEDIA_AUDIO",
|
|
113
|
+
READ_MEDIA_IMAGES: "android.permission.READ_MEDIA_IMAGES",
|
|
114
|
+
READ_MEDIA_VIDEO: "android.permission.READ_MEDIA_VIDEO",
|
|
115
|
+
READ_MEDIA_VISUAL_USER_SELECTED: "android.permission.READ_MEDIA_VISUAL_USER_SELECTED",
|
|
116
|
+
READ_PHONE_NUMBERS: "android.permission.READ_PHONE_NUMBERS",
|
|
117
|
+
READ_PHONE_STATE: "android.permission.READ_PHONE_STATE",
|
|
118
|
+
READ_SMS: "android.permission.READ_SMS",
|
|
119
|
+
RECEIVE_MMS: "android.permission.RECEIVE_MMS",
|
|
120
|
+
RECEIVE_SMS: "android.permission.RECEIVE_SMS",
|
|
121
|
+
RECEIVE_WAP_PUSH: "android.permission.RECEIVE_WAP_PUSH",
|
|
122
|
+
SEND_SMS: "android.permission.SEND_SMS",
|
|
123
|
+
USE_SIP: "android.permission.USE_SIP",
|
|
124
|
+
UWB_RANGING: "android.permission.UWB_RANGING",
|
|
125
|
+
WRITE_CALL_LOG: "android.permission.WRITE_CALL_LOG",
|
|
126
|
+
WRITE_CONTACTS: "android.permission.WRITE_CONTACTS",
|
|
127
|
+
WRITE_EXTERNAL_STORAGE: "android.permission.WRITE_EXTERNAL_STORAGE"
|
|
128
|
+
}
|
|
83
129
|
};
|
|
84
130
|
}
|
|
85
131
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engines/rnp.ts","../src/index.ts","../src/engines/resolve.ts","../src/core/state-machine.ts","../src/hooks/use-permission-handler.ts","../src/core/debug-logger.ts","../src/core/with-timeout.ts","../src/engines/rnp-fallback.ts","../src/engines/use-engine.ts","../src/hooks/use-multiple-permissions.ts","../src/components/default-blocked-prompt.tsx","../src/components/default-pre-prompt.tsx","../src/components/permission-gate.tsx"],"sourcesContent":["import { Platform } from \"react-native\";\nimport {\n type Permission,\n check,\n checkNotifications,\n openSettings,\n request,\n requestNotifications,\n} from \"react-native-permissions\";\nimport type { PermissionEngine, PermissionStatus } from \"../types\";\n\nfunction p(ios: string, android: string): string {\n return Platform.select({ ios, android, default: ios }) ?? ios;\n}\n\n/**\n * Cross-platform permission constants for use with the RNP engine.\n * Each resolves to the correct platform-specific string at runtime.\n */\nexport const Permissions = {\n CAMERA: p(\"ios.permission.CAMERA\", \"android.permission.CAMERA\"),\n MICROPHONE: p(\"ios.permission.MICROPHONE\", \"android.permission.RECORD_AUDIO\"),\n CONTACTS: p(\"ios.permission.CONTACTS\", \"android.permission.READ_CONTACTS\"),\n CALENDARS: p(\"ios.permission.CALENDARS\", \"android.permission.READ_CALENDAR\"),\n CALENDARS_WRITE_ONLY: p(\n \"ios.permission.CALENDARS_WRITE_ONLY\",\n \"android.permission.WRITE_CALENDAR\",\n ),\n LOCATION_WHEN_IN_USE: p(\n \"ios.permission.LOCATION_WHEN_IN_USE\",\n \"android.permission.ACCESS_FINE_LOCATION\",\n ),\n LOCATION_ALWAYS: p(\n \"ios.permission.LOCATION_ALWAYS\",\n \"android.permission.ACCESS_BACKGROUND_LOCATION\",\n ),\n PHOTO_LIBRARY: p(\"ios.permission.PHOTO_LIBRARY\", \"android.permission.READ_MEDIA_IMAGES\"),\n PHOTO_LIBRARY_ADD_ONLY: p(\n \"ios.permission.PHOTO_LIBRARY_ADD_ONLY\",\n \"android.permission.WRITE_EXTERNAL_STORAGE\",\n ),\n BLUETOOTH: p(\"ios.permission.BLUETOOTH\", \"android.permission.BLUETOOTH_CONNECT\"),\n NOTIFICATIONS: \"notifications\",\n} as const;\n\nexport function createRNPEngine(): PermissionEngine {\n return {\n async check(permission: string): Promise<PermissionStatus> {\n if (permission === \"notifications\") {\n const result = await checkNotifications();\n return result.status as PermissionStatus;\n }\n return (await check(permission as Permission)) as PermissionStatus;\n },\n\n async request(permission: string): Promise<PermissionStatus> {\n if (permission === \"notifications\") {\n const result = await requestNotifications([\"alert\", \"badge\", \"sound\"]);\n return result.status as PermissionStatus;\n }\n return (await request(permission as Permission)) as PermissionStatus;\n },\n\n async openSettings(): Promise<void> {\n await openSettings();\n },\n };\n}\n","export type {\n BlockedPromptConfig,\n MultiPermissionEntry,\n MultiplePermissionsConfig,\n MultiplePermissionsResult,\n PermissionCallbacks,\n PermissionEngine,\n PermissionFlowEvent,\n PermissionFlowState,\n PermissionHandlerConfig,\n PermissionHandlerResult,\n PermissionStatus,\n PrePromptConfig,\n} from \"./types\";\n\nexport { setDefaultEngine } from \"./engines/resolve\";\nexport { transition } from \"./core/state-machine\";\nexport { usePermissionHandler } from \"./hooks/use-permission-handler\";\nexport { useMultiplePermissions } from \"./hooks/use-multiple-permissions\";\nexport { PermissionGate } from \"./components/permission-gate\";\nexport type { PermissionGateProps } from \"./components/permission-gate\";\nexport { DefaultPrePrompt } from \"./components/default-pre-prompt\";\nexport type { DefaultPrePromptProps } from \"./components/default-pre-prompt\";\nexport { DefaultBlockedPrompt } from \"./components/default-blocked-prompt\";\nexport type { DefaultBlockedPromptProps } from \"./components/default-blocked-prompt\";\n","import type { PermissionEngine } from \"../types\";\n\nlet defaultEngine: PermissionEngine | null = null;\n\nexport function setDefaultEngine(engine: PermissionEngine): void {\n defaultEngine = engine;\n}\n\nexport function getDefaultEngine(): PermissionEngine | null {\n return defaultEngine;\n}\n","import type { PermissionFlowEvent, PermissionFlowState } from \"../types\";\n\nexport function transition(\n state: PermissionFlowState,\n event: PermissionFlowEvent,\n): PermissionFlowState {\n switch (state) {\n case \"idle\":\n if (event.type === \"CHECK\") return \"checking\";\n return state;\n\n case \"checking\":\n if (event.type === \"CHECK_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"denied\":\n return \"prePrompt\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"unavailable\":\n return \"unavailable\";\n default:\n return state;\n }\n }\n return state;\n\n case \"prePrompt\":\n if (event.type === \"PRE_PROMPT_CONFIRM\") return \"requesting\";\n if (event.type === \"PRE_PROMPT_DISMISS\") return \"denied\";\n return state;\n\n case \"requesting\":\n if (event.type === \"REQUEST_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"denied\":\n return \"denied\";\n case \"blocked\":\n return \"blockedPrompt\";\n default:\n return state;\n }\n }\n return state;\n\n case \"blockedPrompt\":\n if (event.type === \"OPEN_SETTINGS\") return \"openingSettings\";\n return state;\n\n case \"openingSettings\":\n if (event.type === \"SETTINGS_RETURN\") return \"recheckingAfterSettings\";\n return state;\n\n case \"recheckingAfterSettings\":\n if (event.type === \"RECHECK_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"denied\":\n return \"blockedPrompt\";\n default:\n return state;\n }\n }\n return state;\n\n case \"granted\":\n case \"denied\":\n case \"unavailable\":\n if (event.type === \"CHECK\") return \"checking\";\n return state;\n\n case \"blocked\":\n return state;\n\n default:\n return state;\n }\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AppState } from \"react-native\";\nimport { createDebugLogger } from \"../core/debug-logger\";\nimport { transition } from \"../core/state-machine\";\nimport { PermissionTimeoutError, withTimeout } from \"../core/with-timeout\";\nimport { resolveEngine } from \"../engines/use-engine\";\nimport type {\n PermissionFlowState,\n PermissionHandlerConfig,\n PermissionHandlerResult,\n PermissionStatus,\n} from \"../types\";\n\nexport function usePermissionHandler(config: PermissionHandlerConfig): PermissionHandlerResult {\n const engine = resolveEngine(config.engine);\n const [flowState, setFlowState] = useState<PermissionFlowState>(\"idle\");\n const [nativeStatus, setNativeStatus] = useState<PermissionStatus | null>(null);\n const isRequesting = useRef(false);\n const waitingForSettings = useRef(false);\n const appStateRef = useRef(AppState.currentState);\n\n const {\n permission,\n autoCheck = true,\n requestTimeout,\n onTimeout,\n debug,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n } = config;\n\n const logger = createDebugLogger(debug, permission);\n\n const checkPermission = useCallback(async () => {\n setFlowState((s) => {\n const next = transition(s, { type: \"CHECK\" });\n logger.transition(s, next, \"CHECK\");\n return next;\n });\n try {\n const status = await engine.check(permission);\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"CHECK_RESULT\", status });\n logger.transition(s, next, `CHECK_RESULT:${status}`);\n if (next === \"granted\" && s !== \"granted\") onGrant?.();\n return next;\n });\n } catch {\n setFlowState(\"idle\");\n }\n }, [engine, permission, logger, onGrant]);\n\n const requestPermission = useCallback(async () => {\n if (isRequesting.current) return;\n isRequesting.current = true;\n\n setFlowState((s) => {\n const next = transition(s, { type: \"PRE_PROMPT_CONFIRM\" });\n logger.transition(s, next, \"PRE_PROMPT_CONFIRM\");\n return next;\n });\n try {\n const requestPromise = engine.request(permission);\n const status = requestTimeout\n ? await withTimeout(requestPromise, requestTimeout, permission)\n : await requestPromise;\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"REQUEST_RESULT\", status });\n logger.transition(s, next, `REQUEST_RESULT:${status}`);\n if (next === \"granted\") onGrant?.();\n if (next === \"denied\") onDeny?.();\n if (next === \"blockedPrompt\") onBlock?.();\n return next;\n });\n } catch (err) {\n if (err instanceof PermissionTimeoutError) {\n logger.info(`request timed out after ${requestTimeout}ms`);\n onTimeout?.();\n setFlowState(\"blockedPrompt\");\n } else {\n setFlowState(\"denied\");\n }\n } finally {\n isRequesting.current = false;\n }\n }, [engine, permission, requestTimeout, onTimeout, logger, onGrant, onDeny, onBlock]);\n\n const dismiss = useCallback(() => {\n setFlowState((s) => {\n const next = transition(s, { type: \"PRE_PROMPT_DISMISS\" });\n logger.transition(s, next, \"PRE_PROMPT_DISMISS\");\n return next;\n });\n onDeny?.();\n }, [logger, onDeny]);\n\n const goToSettings = useCallback(async () => {\n setFlowState((s) => {\n const next = transition(s, { type: \"OPEN_SETTINGS\" });\n logger.transition(s, next, \"OPEN_SETTINGS\");\n return next;\n });\n waitingForSettings.current = true;\n try {\n await engine.openSettings();\n } catch {\n waitingForSettings.current = false;\n setFlowState(\"blockedPrompt\");\n }\n }, [engine, logger]);\n\n const recheckAfterSettings = useCallback(async () => {\n setFlowState((s) => {\n const next = transition(s, { type: \"SETTINGS_RETURN\" });\n logger.transition(s, next, \"SETTINGS_RETURN\");\n return next;\n });\n try {\n const status = await engine.check(permission);\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"RECHECK_RESULT\", status });\n logger.transition(s, next, `RECHECK_RESULT:${status}`);\n if (next === \"granted\") onGrant?.();\n onSettingsReturn?.(next === \"granted\");\n return next;\n });\n } catch {\n setFlowState(\"blockedPrompt\");\n }\n }, [engine, permission, logger, onGrant, onSettingsReturn]);\n\n // Auto-check on mount\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect\n useEffect(() => {\n if (autoCheck) {\n checkPermission();\n }\n }, []);\n\n // AppState listener for settings return\n useEffect(() => {\n const subscription = AppState.addEventListener(\"change\", (nextAppState) => {\n if (\n appStateRef.current.match(/inactive|background/) &&\n nextAppState === \"active\" &&\n waitingForSettings.current\n ) {\n waitingForSettings.current = false;\n recheckAfterSettings();\n }\n appStateRef.current = nextAppState;\n });\n return () => subscription.remove();\n }, [recheckAfterSettings]);\n\n return {\n state: flowState,\n nativeStatus,\n isGranted: flowState === \"granted\",\n isDenied: flowState === \"denied\",\n isBlocked:\n flowState === \"blocked\" || flowState === \"blockedPrompt\" || flowState === \"openingSettings\",\n isChecking: flowState === \"checking\" || flowState === \"recheckingAfterSettings\",\n isUnavailable: flowState === \"unavailable\",\n request: requestPermission,\n check: checkPermission,\n dismiss,\n openSettings: goToSettings,\n };\n}\n","const PREFIX = \"[permission-handler]\";\n\ninterface DebugLogger {\n transition(from: string, to: string, event?: string): void;\n info(msg: string): void;\n}\n\nconst NOOP_LOGGER: DebugLogger = {\n transition: () => {},\n info: () => {},\n};\n\nexport function createDebugLogger(\n debug: boolean | ((msg: string) => void) | undefined,\n permission: string,\n): DebugLogger {\n if (!debug) return NOOP_LOGGER;\n\n const log = typeof debug === \"function\" ? debug : (msg: string) => console.log(msg);\n\n return {\n transition(from: string, to: string, event?: string) {\n log(`${PREFIX} ${permission}: ${from} → ${to}${event ? ` (${event})` : \"\"}`);\n },\n info(msg: string) {\n log(`${PREFIX} ${permission}: ${msg}`);\n },\n };\n}\n","export class PermissionTimeoutError extends Error {\n readonly permission: string;\n readonly timeoutMs: number;\n\n constructor(permission: string, timeoutMs: number) {\n super(`Permission request for \"${permission}\" timed out after ${timeoutMs}ms`);\n this.name = \"PermissionTimeoutError\";\n this.permission = permission;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n permission: string,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new PermissionTimeoutError(permission, timeoutMs)),\n timeoutMs,\n );\n promise.then(\n (val) => {\n clearTimeout(timer);\n resolve(val);\n },\n (err) => {\n clearTimeout(timer);\n reject(err);\n },\n );\n });\n}\n","import type { PermissionEngine } from \"../types\";\n\nlet cachedFallback: PermissionEngine | null = null;\n\nexport function getRNPFallbackEngine(): PermissionEngine {\n if (cachedFallback) return cachedFallback;\n\n try {\n // Dynamic require to avoid hard dependency — only resolves if\n // react-native-permissions is installed by the consumer.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require(\"./rnp\") as { createRNPEngine: () => PermissionEngine };\n const { createRNPEngine } = mod;\n cachedFallback = createRNPEngine();\n return cachedFallback;\n } catch {\n throw new Error(\n \"react-native-permission-handler: No permission engine configured. \" +\n \"Either pass an `engine` in your hook config, call setDefaultEngine(), \" +\n \"or install react-native-permissions as a peer dependency.\",\n );\n }\n}\n","import type { PermissionEngine } from \"../types\";\nimport { getDefaultEngine } from \"./resolve\";\nimport { getRNPFallbackEngine } from \"./rnp-fallback\";\n\nexport function resolveEngine(configEngine?: PermissionEngine): PermissionEngine {\n if (configEngine) return configEngine;\n const global = getDefaultEngine();\n if (global) return global;\n return getRNPFallbackEngine();\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createDebugLogger } from \"../core/debug-logger\";\nimport { PermissionTimeoutError, withTimeout } from \"../core/with-timeout\";\nimport { resolveEngine } from \"../engines/use-engine\";\nimport type {\n MultiPermissionEntry,\n MultiplePermissionsConfig,\n MultiplePermissionsResult,\n PermissionEngine,\n PermissionFlowState,\n PermissionStatus,\n} from \"../types\";\n\nfunction permissionKey(entry: MultiPermissionEntry): string {\n return String(entry.permission);\n}\n\nfunction isGrantedStatus(status: PermissionStatus): boolean {\n return status === \"granted\" || status === \"limited\";\n}\n\nfunction statusToFlowState(status: PermissionStatus): PermissionFlowState {\n switch (status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"unavailable\":\n return \"unavailable\";\n case \"denied\":\n return \"prePrompt\";\n default:\n return \"idle\";\n }\n}\n\nexport function useMultiplePermissions(\n config: MultiplePermissionsConfig,\n): MultiplePermissionsResult {\n const engine = resolveEngine(config.engine);\n const {\n permissions,\n strategy,\n autoCheck = true,\n requestTimeout,\n onTimeout,\n debug,\n onAllGranted,\n } = config;\n const logger = createDebugLogger(debug, \"multi\");\n const [statuses, setStatuses] = useState<Record<string, PermissionFlowState>>(() => {\n const initial: Record<string, PermissionFlowState> = {};\n for (const entry of permissions) {\n initial[permissionKey(entry)] = \"idle\";\n }\n return initial;\n });\n const isRunning = useRef(false);\n\n const allGranted = permissions.every((entry) => statuses[permissionKey(entry)] === \"granted\");\n\n const requestAll = useCallback(async () => {\n if (isRunning.current) return;\n isRunning.current = true;\n\n const update = (key: string, state: PermissionFlowState) => {\n setStatuses((prev) => {\n logger.transition(prev[key] ?? \"idle\", state, key);\n return { ...prev, [key]: state };\n });\n };\n\n try {\n if (strategy === \"sequential\") {\n await runSequential(permissions, engine, update, requestTimeout, onTimeout);\n } else {\n await runParallel(permissions, engine, update, requestTimeout, onTimeout);\n }\n\n // Final check: are all granted?\n let allDone = true;\n for (const entry of permissions) {\n const finalStatus = await engine.check(entry.permission);\n if (!isGrantedStatus(finalStatus)) {\n allDone = false;\n break;\n }\n }\n if (allDone) {\n onAllGranted?.();\n }\n } finally {\n isRunning.current = false;\n }\n }, [permissions, strategy, engine, requestTimeout, onTimeout, logger, onAllGranted]);\n\n // Auto-check on mount\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect\n useEffect(() => {\n if (!autoCheck) return;\n\n let cancelled = false;\n async function checkAll() {\n for (const entry of permissions) {\n const key = permissionKey(entry);\n const status = await engine.check(entry.permission);\n if (cancelled) return;\n setStatuses((prev) => ({ ...prev, [key]: statusToFlowState(status) }));\n }\n }\n checkAll();\n return () => {\n cancelled = true;\n };\n }, []);\n\n return {\n statuses,\n allGranted,\n request: requestAll,\n };\n}\n\nasync function runSequential(\n permissions: MultiPermissionEntry[],\n engine: PermissionEngine,\n updateStatus: (key: string, state: PermissionFlowState) => void,\n requestTimeout?: number,\n onTimeout?: () => void,\n): Promise<void> {\n for (const entry of permissions) {\n const key = permissionKey(entry);\n\n updateStatus(key, \"checking\");\n const checkStatus = await engine.check(entry.permission);\n\n if (isGrantedStatus(checkStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n continue;\n }\n\n if (checkStatus === \"unavailable\") {\n updateStatus(key, \"unavailable\");\n continue;\n }\n\n if (checkStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n break;\n }\n\n // Denied — request it\n updateStatus(key, \"requesting\");\n try {\n const requestPromise = engine.request(entry.permission);\n const requestStatus = requestTimeout\n ? await withTimeout(requestPromise, requestTimeout, entry.permission)\n : await requestPromise;\n\n if (isGrantedStatus(requestStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (requestStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n break;\n } else {\n updateStatus(key, \"denied\");\n entry.onDeny?.();\n break;\n }\n } catch (err) {\n if (err instanceof PermissionTimeoutError) {\n onTimeout?.();\n updateStatus(key, \"blockedPrompt\");\n break;\n }\n throw err;\n }\n }\n}\n\nasync function runParallel(\n permissions: MultiPermissionEntry[],\n engine: PermissionEngine,\n updateStatus: (key: string, state: PermissionFlowState) => void,\n requestTimeout?: number,\n onTimeout?: () => void,\n): Promise<void> {\n // Check all in parallel\n const checkResults = await Promise.all(\n permissions.map(async (entry) => {\n const key = permissionKey(entry);\n updateStatus(key, \"checking\");\n const status = await engine.check(entry.permission);\n return { entry, key, status };\n }),\n );\n\n // Update granted/unavailable immediately\n for (const { entry, key, status } of checkResults) {\n if (isGrantedStatus(status)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (status === \"unavailable\") {\n updateStatus(key, \"unavailable\");\n }\n }\n\n // Request denied/blocked ones sequentially (system dialogs are sequential)\n const needsAction = checkResults.filter(\n ({ status }) => status === \"denied\" || status === \"blocked\",\n );\n\n for (const { entry, key, status } of needsAction) {\n if (status === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n continue;\n }\n\n updateStatus(key, \"requesting\");\n try {\n const requestPromise = engine.request(entry.permission);\n const requestStatus = requestTimeout\n ? await withTimeout(requestPromise, requestTimeout, entry.permission)\n : await requestPromise;\n\n if (isGrantedStatus(requestStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (requestStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n } else {\n updateStatus(key, \"denied\");\n entry.onDeny?.();\n }\n } catch (err) {\n if (err instanceof PermissionTimeoutError) {\n onTimeout?.();\n updateStatus(key, \"blockedPrompt\");\n } else {\n throw err;\n }\n }\n }\n}\n","import React from \"react\";\nimport { Modal, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport type { BlockedPromptConfig } from \"../types\";\n\nexport interface DefaultBlockedPromptProps extends BlockedPromptConfig {\n visible: boolean;\n onOpenSettings: () => void;\n}\n\nexport function DefaultBlockedPrompt({\n visible,\n title,\n message,\n settingsLabel = \"Open Settings\",\n onOpenSettings,\n}: DefaultBlockedPromptProps) {\n return (\n <Modal visible={visible} transparent animationType=\"fade\">\n <View style={styles.overlay}>\n <View style={styles.modal}>\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.message}>{message}</Text>\n <TouchableOpacity\n style={styles.settingsButton}\n onPress={onOpenSettings}\n accessibilityRole=\"button\"\n >\n <Text style={styles.settingsText}>{settingsLabel}</Text>\n </TouchableOpacity>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: \"rgba(0,0,0,0.5)\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n modal: {\n backgroundColor: \"white\",\n borderRadius: 16,\n padding: 24,\n width: \"85%\",\n alignItems: \"center\",\n },\n title: {\n fontSize: 20,\n fontWeight: \"600\",\n marginBottom: 12,\n textAlign: \"center\",\n },\n message: {\n fontSize: 15,\n color: \"#666\",\n textAlign: \"center\",\n marginBottom: 24,\n lineHeight: 22,\n },\n settingsButton: {\n backgroundColor: \"#007AFF\",\n borderRadius: 12,\n paddingVertical: 14,\n paddingHorizontal: 32,\n width: \"100%\",\n alignItems: \"center\",\n },\n settingsText: {\n color: \"white\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n});\n","import React from \"react\";\nimport { Modal, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport type { PrePromptConfig } from \"../types\";\n\nexport interface DefaultPrePromptProps extends PrePromptConfig {\n visible: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function DefaultPrePrompt({\n visible,\n title,\n message,\n confirmLabel = \"Continue\",\n cancelLabel = \"Not Now\",\n onConfirm,\n onCancel,\n}: DefaultPrePromptProps) {\n return (\n <Modal visible={visible} transparent animationType=\"fade\">\n <View style={styles.overlay}>\n <View style={styles.modal}>\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.message}>{message}</Text>\n <TouchableOpacity\n style={styles.confirmButton}\n onPress={onConfirm}\n accessibilityRole=\"button\"\n >\n <Text style={styles.confirmText}>{confirmLabel}</Text>\n </TouchableOpacity>\n <TouchableOpacity onPress={onCancel} accessibilityRole=\"button\">\n <Text style={styles.cancelText}>{cancelLabel}</Text>\n </TouchableOpacity>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: \"rgba(0,0,0,0.5)\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n modal: {\n backgroundColor: \"white\",\n borderRadius: 16,\n padding: 24,\n width: \"85%\",\n alignItems: \"center\",\n },\n title: {\n fontSize: 20,\n fontWeight: \"600\",\n marginBottom: 12,\n textAlign: \"center\",\n },\n message: {\n fontSize: 15,\n color: \"#666\",\n textAlign: \"center\",\n marginBottom: 24,\n lineHeight: 22,\n },\n confirmButton: {\n backgroundColor: \"#007AFF\",\n borderRadius: 12,\n paddingVertical: 14,\n paddingHorizontal: 32,\n width: \"100%\",\n alignItems: \"center\",\n marginBottom: 12,\n },\n confirmText: {\n color: \"white\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n cancelText: {\n color: \"#007AFF\",\n fontSize: 15,\n },\n});\n","import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport { usePermissionHandler } from \"../hooks/use-permission-handler\";\nimport type {\n BlockedPromptConfig,\n PermissionCallbacks,\n PermissionEngine,\n PrePromptConfig,\n} from \"../types\";\nimport { DefaultBlockedPrompt } from \"./default-blocked-prompt\";\nimport { DefaultPrePrompt } from \"./default-pre-prompt\";\n\nexport interface PermissionGateProps extends PermissionCallbacks {\n permission: string;\n engine?: PermissionEngine;\n prePrompt: PrePromptConfig;\n blockedPrompt: BlockedPromptConfig;\n children: ReactNode;\n fallback?: ReactNode;\n renderPrePrompt?: (props: {\n config: PrePromptConfig;\n onConfirm: () => void;\n onCancel: () => void;\n }) => ReactNode;\n renderBlockedPrompt?: (props: {\n config: BlockedPromptConfig;\n onOpenSettings: () => void;\n }) => ReactNode;\n}\n\nexport function PermissionGate({\n permission,\n engine,\n prePrompt,\n blockedPrompt,\n children,\n fallback = null,\n renderPrePrompt,\n renderBlockedPrompt,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n}: PermissionGateProps) {\n const handler = usePermissionHandler({\n permission,\n engine,\n prePrompt,\n blockedPrompt,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n });\n\n if (handler.isGranted) {\n return <>{children}</>;\n }\n\n if (handler.isChecking || handler.isUnavailable) {\n return <>{fallback}</>;\n }\n\n if (handler.state === \"prePrompt\") {\n if (renderPrePrompt) {\n return (\n <>\n {renderPrePrompt({\n config: prePrompt,\n onConfirm: handler.request,\n onCancel: handler.dismiss,\n })}\n </>\n );\n }\n return (\n <DefaultPrePrompt\n visible\n title={prePrompt.title}\n message={prePrompt.message}\n confirmLabel={prePrompt.confirmLabel}\n cancelLabel={prePrompt.cancelLabel}\n onConfirm={handler.request}\n onCancel={handler.dismiss}\n />\n );\n }\n\n if (handler.state === \"blockedPrompt\") {\n if (renderBlockedPrompt) {\n return (\n <>\n {renderBlockedPrompt({\n config: blockedPrompt,\n onOpenSettings: handler.openSettings,\n })}\n </>\n );\n }\n return (\n <DefaultBlockedPrompt\n visible\n title={blockedPrompt.title}\n message={blockedPrompt.message}\n settingsLabel={blockedPrompt.settingsLabel}\n onOpenSettings={handler.openSettings}\n />\n );\n }\n\n return <>{fallback}</>;\n}\n"],"mappings":"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","names":["import_react_native","createRNPEngine","import_react","import_react_native","import_react_native","import_jsx_runtime","styles","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/engines/rnp.ts","../src/index.ts","../src/engines/resolve.ts","../src/core/state-machine.ts","../src/hooks/use-permission-handler.ts","../src/core/debug-logger.ts","../src/core/with-timeout.ts","../src/engines/rnp-fallback.ts","../src/engines/use-engine.ts","../src/hooks/use-multiple-permissions.ts","../src/components/default-blocked-prompt.tsx","../src/components/default-pre-prompt.tsx","../src/components/permission-gate.tsx"],"sourcesContent":["import { Platform } from \"react-native\";\nimport {\n type Permission,\n check,\n checkNotifications,\n openSettings,\n request,\n requestNotifications,\n} from \"react-native-permissions\";\nimport type { PermissionEngine, PermissionStatus } from \"../types\";\n\nfunction p(ios: string, android: string): string {\n return Platform.select({ ios, android, default: ios }) ?? ios;\n}\n\n/**\n * Cross-platform permission constants that resolve to the correct\n * platform-specific string at runtime via Platform.select.\n */\nexport const Permissions = {\n // Cross-platform\n CAMERA: p(\"ios.permission.CAMERA\", \"android.permission.CAMERA\"),\n MICROPHONE: p(\"ios.permission.MICROPHONE\", \"android.permission.RECORD_AUDIO\"),\n CONTACTS: p(\"ios.permission.CONTACTS\", \"android.permission.READ_CONTACTS\"),\n CALENDARS: p(\"ios.permission.CALENDARS\", \"android.permission.READ_CALENDAR\"),\n CALENDARS_WRITE_ONLY: p(\n \"ios.permission.CALENDARS_WRITE_ONLY\",\n \"android.permission.WRITE_CALENDAR\",\n ),\n LOCATION_WHEN_IN_USE: p(\n \"ios.permission.LOCATION_WHEN_IN_USE\",\n \"android.permission.ACCESS_FINE_LOCATION\",\n ),\n LOCATION_ALWAYS: p(\n \"ios.permission.LOCATION_ALWAYS\",\n \"android.permission.ACCESS_BACKGROUND_LOCATION\",\n ),\n PHOTO_LIBRARY: p(\"ios.permission.PHOTO_LIBRARY\", \"android.permission.READ_MEDIA_IMAGES\"),\n PHOTO_LIBRARY_ADD_ONLY: p(\n \"ios.permission.PHOTO_LIBRARY_ADD_ONLY\",\n \"android.permission.WRITE_EXTERNAL_STORAGE\",\n ),\n MEDIA_LIBRARY: p(\"ios.permission.MEDIA_LIBRARY\", \"android.permission.READ_MEDIA_AUDIO\"),\n BLUETOOTH: p(\"ios.permission.BLUETOOTH\", \"android.permission.BLUETOOTH_CONNECT\"),\n SPEECH_RECOGNITION: p(\"ios.permission.SPEECH_RECOGNITION\", \"android.permission.RECORD_AUDIO\"),\n MOTION: p(\"ios.permission.MOTION\", \"android.permission.ACTIVITY_RECOGNITION\"),\n NOTIFICATIONS: \"notifications\",\n\n // iOS-only\n IOS: {\n APP_TRACKING_TRANSPARENCY: \"ios.permission.APP_TRACKING_TRANSPARENCY\",\n FACE_ID: \"ios.permission.FACE_ID\",\n REMINDERS: \"ios.permission.REMINDERS\",\n SIRI: \"ios.permission.SIRI\",\n STOREKIT: \"ios.permission.STOREKIT\",\n },\n\n // Android-only\n ANDROID: {\n ACCEPT_HANDOVER: \"android.permission.ACCEPT_HANDOVER\",\n ACCESS_COARSE_LOCATION: \"android.permission.ACCESS_COARSE_LOCATION\",\n ACCESS_MEDIA_LOCATION: \"android.permission.ACCESS_MEDIA_LOCATION\",\n ADD_VOICEMAIL: \"com.android.voicemail.permission.ADD_VOICEMAIL\",\n ANSWER_PHONE_CALLS: \"android.permission.ANSWER_PHONE_CALLS\",\n BLUETOOTH_ADVERTISE: \"android.permission.BLUETOOTH_ADVERTISE\",\n BLUETOOTH_SCAN: \"android.permission.BLUETOOTH_SCAN\",\n BODY_SENSORS: \"android.permission.BODY_SENSORS\",\n BODY_SENSORS_BACKGROUND: \"android.permission.BODY_SENSORS_BACKGROUND\",\n CALL_PHONE: \"android.permission.CALL_PHONE\",\n GET_ACCOUNTS: \"android.permission.GET_ACCOUNTS\",\n NEARBY_WIFI_DEVICES: \"android.permission.NEARBY_WIFI_DEVICES\",\n PROCESS_OUTGOING_CALLS: \"android.permission.PROCESS_OUTGOING_CALLS\",\n READ_CALL_LOG: \"android.permission.READ_CALL_LOG\",\n READ_EXTERNAL_STORAGE: \"android.permission.READ_EXTERNAL_STORAGE\",\n READ_MEDIA_AUDIO: \"android.permission.READ_MEDIA_AUDIO\",\n READ_MEDIA_IMAGES: \"android.permission.READ_MEDIA_IMAGES\",\n READ_MEDIA_VIDEO: \"android.permission.READ_MEDIA_VIDEO\",\n READ_MEDIA_VISUAL_USER_SELECTED: \"android.permission.READ_MEDIA_VISUAL_USER_SELECTED\",\n READ_PHONE_NUMBERS: \"android.permission.READ_PHONE_NUMBERS\",\n READ_PHONE_STATE: \"android.permission.READ_PHONE_STATE\",\n READ_SMS: \"android.permission.READ_SMS\",\n RECEIVE_MMS: \"android.permission.RECEIVE_MMS\",\n RECEIVE_SMS: \"android.permission.RECEIVE_SMS\",\n RECEIVE_WAP_PUSH: \"android.permission.RECEIVE_WAP_PUSH\",\n SEND_SMS: \"android.permission.SEND_SMS\",\n USE_SIP: \"android.permission.USE_SIP\",\n UWB_RANGING: \"android.permission.UWB_RANGING\",\n WRITE_CALL_LOG: \"android.permission.WRITE_CALL_LOG\",\n WRITE_CONTACTS: \"android.permission.WRITE_CONTACTS\",\n WRITE_EXTERNAL_STORAGE: \"android.permission.WRITE_EXTERNAL_STORAGE\",\n },\n} as const;\n\nexport function createRNPEngine(): PermissionEngine {\n return {\n async check(permission: string): Promise<PermissionStatus> {\n if (permission === \"notifications\") {\n const result = await checkNotifications();\n return result.status as PermissionStatus;\n }\n return (await check(permission as Permission)) as PermissionStatus;\n },\n\n async request(permission: string): Promise<PermissionStatus> {\n if (permission === \"notifications\") {\n const result = await requestNotifications([\"alert\", \"badge\", \"sound\"]);\n return result.status as PermissionStatus;\n }\n return (await request(permission as Permission)) as PermissionStatus;\n },\n\n async openSettings(): Promise<void> {\n await openSettings();\n },\n };\n}\n","export type {\n BlockedPromptConfig,\n MultiPermissionEntry,\n MultiplePermissionsConfig,\n MultiplePermissionsResult,\n PermissionCallbacks,\n PermissionEngine,\n PermissionFlowEvent,\n PermissionFlowState,\n PermissionHandlerConfig,\n PermissionHandlerResult,\n PermissionStatus,\n PrePromptConfig,\n} from \"./types\";\n\nexport { setDefaultEngine } from \"./engines/resolve\";\nexport { transition } from \"./core/state-machine\";\nexport { usePermissionHandler } from \"./hooks/use-permission-handler\";\nexport { useMultiplePermissions } from \"./hooks/use-multiple-permissions\";\nexport { PermissionGate } from \"./components/permission-gate\";\nexport type { PermissionGateProps } from \"./components/permission-gate\";\nexport { DefaultPrePrompt } from \"./components/default-pre-prompt\";\nexport type { DefaultPrePromptProps } from \"./components/default-pre-prompt\";\nexport { DefaultBlockedPrompt } from \"./components/default-blocked-prompt\";\nexport type { DefaultBlockedPromptProps } from \"./components/default-blocked-prompt\";\n","import type { PermissionEngine } from \"../types\";\n\nlet defaultEngine: PermissionEngine | null = null;\n\nexport function setDefaultEngine(engine: PermissionEngine): void {\n defaultEngine = engine;\n}\n\nexport function getDefaultEngine(): PermissionEngine | null {\n return defaultEngine;\n}\n","import type { PermissionFlowEvent, PermissionFlowState } from \"../types\";\n\nexport function transition(\n state: PermissionFlowState,\n event: PermissionFlowEvent,\n): PermissionFlowState {\n switch (state) {\n case \"idle\":\n if (event.type === \"CHECK\") return \"checking\";\n return state;\n\n case \"checking\":\n if (event.type === \"CHECK_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"denied\":\n return \"prePrompt\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"unavailable\":\n return \"unavailable\";\n default:\n return state;\n }\n }\n return state;\n\n case \"prePrompt\":\n if (event.type === \"PRE_PROMPT_CONFIRM\") return \"requesting\";\n if (event.type === \"PRE_PROMPT_DISMISS\") return \"denied\";\n return state;\n\n case \"requesting\":\n if (event.type === \"REQUEST_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"denied\":\n return \"denied\";\n case \"blocked\":\n return \"blockedPrompt\";\n default:\n return state;\n }\n }\n return state;\n\n case \"blockedPrompt\":\n if (event.type === \"OPEN_SETTINGS\") return \"openingSettings\";\n return state;\n\n case \"openingSettings\":\n if (event.type === \"SETTINGS_RETURN\") return \"recheckingAfterSettings\";\n return state;\n\n case \"recheckingAfterSettings\":\n if (event.type === \"RECHECK_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"denied\":\n return \"blockedPrompt\";\n default:\n return state;\n }\n }\n return state;\n\n case \"granted\":\n case \"denied\":\n case \"unavailable\":\n if (event.type === \"CHECK\") return \"checking\";\n return state;\n\n case \"blocked\":\n return state;\n\n default:\n return state;\n }\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AppState } from \"react-native\";\nimport { createDebugLogger } from \"../core/debug-logger\";\nimport { transition } from \"../core/state-machine\";\nimport { PermissionTimeoutError, withTimeout } from \"../core/with-timeout\";\nimport { resolveEngine } from \"../engines/use-engine\";\nimport type {\n PermissionFlowState,\n PermissionHandlerConfig,\n PermissionHandlerResult,\n PermissionStatus,\n} from \"../types\";\n\nexport function usePermissionHandler(config: PermissionHandlerConfig): PermissionHandlerResult {\n const engine = resolveEngine(config.engine);\n const [flowState, setFlowState] = useState<PermissionFlowState>(\"idle\");\n const [nativeStatus, setNativeStatus] = useState<PermissionStatus | null>(null);\n const isRequesting = useRef(false);\n const waitingForSettings = useRef(false);\n const appStateRef = useRef(AppState.currentState);\n\n const {\n permission,\n autoCheck = true,\n requestTimeout,\n onTimeout,\n debug,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n } = config;\n\n const logger = createDebugLogger(debug, permission);\n\n const checkPermission = useCallback(async () => {\n setFlowState((s) => {\n const next = transition(s, { type: \"CHECK\" });\n logger.transition(s, next, \"CHECK\");\n return next;\n });\n try {\n const status = await engine.check(permission);\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"CHECK_RESULT\", status });\n logger.transition(s, next, `CHECK_RESULT:${status}`);\n if (next === \"granted\" && s !== \"granted\") onGrant?.();\n return next;\n });\n } catch {\n setFlowState(\"idle\");\n }\n }, [engine, permission, logger, onGrant]);\n\n const requestPermission = useCallback(async () => {\n if (isRequesting.current) return;\n isRequesting.current = true;\n\n setFlowState((s) => {\n const next = transition(s, { type: \"PRE_PROMPT_CONFIRM\" });\n logger.transition(s, next, \"PRE_PROMPT_CONFIRM\");\n return next;\n });\n try {\n const requestPromise = engine.request(permission);\n const status = requestTimeout\n ? await withTimeout(requestPromise, requestTimeout, permission)\n : await requestPromise;\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"REQUEST_RESULT\", status });\n logger.transition(s, next, `REQUEST_RESULT:${status}`);\n if (next === \"granted\") onGrant?.();\n if (next === \"denied\") onDeny?.();\n if (next === \"blockedPrompt\") onBlock?.();\n return next;\n });\n } catch (err) {\n if (err instanceof PermissionTimeoutError) {\n logger.info(`request timed out after ${requestTimeout}ms`);\n onTimeout?.();\n setFlowState(\"blockedPrompt\");\n } else {\n setFlowState(\"denied\");\n }\n } finally {\n isRequesting.current = false;\n }\n }, [engine, permission, requestTimeout, onTimeout, logger, onGrant, onDeny, onBlock]);\n\n const dismiss = useCallback(() => {\n setFlowState((s) => {\n const next = transition(s, { type: \"PRE_PROMPT_DISMISS\" });\n logger.transition(s, next, \"PRE_PROMPT_DISMISS\");\n return next;\n });\n onDeny?.();\n }, [logger, onDeny]);\n\n const goToSettings = useCallback(async () => {\n setFlowState((s) => {\n const next = transition(s, { type: \"OPEN_SETTINGS\" });\n logger.transition(s, next, \"OPEN_SETTINGS\");\n return next;\n });\n waitingForSettings.current = true;\n try {\n await engine.openSettings();\n } catch {\n waitingForSettings.current = false;\n setFlowState(\"blockedPrompt\");\n }\n }, [engine, logger]);\n\n const recheckAfterSettings = useCallback(async () => {\n setFlowState((s) => {\n const next = transition(s, { type: \"SETTINGS_RETURN\" });\n logger.transition(s, next, \"SETTINGS_RETURN\");\n return next;\n });\n try {\n const status = await engine.check(permission);\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"RECHECK_RESULT\", status });\n logger.transition(s, next, `RECHECK_RESULT:${status}`);\n if (next === \"granted\") onGrant?.();\n onSettingsReturn?.(next === \"granted\");\n return next;\n });\n } catch {\n setFlowState(\"blockedPrompt\");\n }\n }, [engine, permission, logger, onGrant, onSettingsReturn]);\n\n // Auto-check on mount\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect\n useEffect(() => {\n if (autoCheck) {\n checkPermission();\n }\n }, []);\n\n // AppState listener for settings return\n useEffect(() => {\n const subscription = AppState.addEventListener(\"change\", (nextAppState) => {\n if (\n appStateRef.current.match(/inactive|background/) &&\n nextAppState === \"active\" &&\n waitingForSettings.current\n ) {\n waitingForSettings.current = false;\n recheckAfterSettings();\n }\n appStateRef.current = nextAppState;\n });\n return () => subscription.remove();\n }, [recheckAfterSettings]);\n\n return {\n state: flowState,\n nativeStatus,\n isGranted: flowState === \"granted\",\n isDenied: flowState === \"denied\",\n isBlocked:\n flowState === \"blocked\" || flowState === \"blockedPrompt\" || flowState === \"openingSettings\",\n isChecking: flowState === \"checking\" || flowState === \"recheckingAfterSettings\",\n isUnavailable: flowState === \"unavailable\",\n request: requestPermission,\n check: checkPermission,\n dismiss,\n openSettings: goToSettings,\n };\n}\n","const PREFIX = \"[permission-handler]\";\n\ninterface DebugLogger {\n transition(from: string, to: string, event?: string): void;\n info(msg: string): void;\n}\n\nconst NOOP_LOGGER: DebugLogger = {\n transition: () => {},\n info: () => {},\n};\n\nexport function createDebugLogger(\n debug: boolean | ((msg: string) => void) | undefined,\n permission: string,\n): DebugLogger {\n if (!debug) return NOOP_LOGGER;\n\n const log = typeof debug === \"function\" ? debug : (msg: string) => console.log(msg);\n\n return {\n transition(from: string, to: string, event?: string) {\n log(`${PREFIX} ${permission}: ${from} → ${to}${event ? ` (${event})` : \"\"}`);\n },\n info(msg: string) {\n log(`${PREFIX} ${permission}: ${msg}`);\n },\n };\n}\n","export class PermissionTimeoutError extends Error {\n readonly permission: string;\n readonly timeoutMs: number;\n\n constructor(permission: string, timeoutMs: number) {\n super(`Permission request for \"${permission}\" timed out after ${timeoutMs}ms`);\n this.name = \"PermissionTimeoutError\";\n this.permission = permission;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n permission: string,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new PermissionTimeoutError(permission, timeoutMs)),\n timeoutMs,\n );\n promise.then(\n (val) => {\n clearTimeout(timer);\n resolve(val);\n },\n (err) => {\n clearTimeout(timer);\n reject(err);\n },\n );\n });\n}\n","import type { PermissionEngine } from \"../types\";\n\nlet cachedFallback: PermissionEngine | null = null;\n\nexport function getRNPFallbackEngine(): PermissionEngine {\n if (cachedFallback) return cachedFallback;\n\n try {\n // Dynamic require to avoid hard dependency — only resolves if\n // react-native-permissions is installed by the consumer.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require(\"./rnp\") as { createRNPEngine: () => PermissionEngine };\n const { createRNPEngine } = mod;\n cachedFallback = createRNPEngine();\n return cachedFallback;\n } catch {\n throw new Error(\n \"react-native-permission-handler: No permission engine configured. \" +\n \"Either pass an `engine` in your hook config, call setDefaultEngine(), \" +\n \"or install react-native-permissions as a peer dependency.\",\n );\n }\n}\n","import type { PermissionEngine } from \"../types\";\nimport { getDefaultEngine } from \"./resolve\";\nimport { getRNPFallbackEngine } from \"./rnp-fallback\";\n\nexport function resolveEngine(configEngine?: PermissionEngine): PermissionEngine {\n if (configEngine) return configEngine;\n const global = getDefaultEngine();\n if (global) return global;\n return getRNPFallbackEngine();\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createDebugLogger } from \"../core/debug-logger\";\nimport { PermissionTimeoutError, withTimeout } from \"../core/with-timeout\";\nimport { resolveEngine } from \"../engines/use-engine\";\nimport type {\n MultiPermissionEntry,\n MultiplePermissionsConfig,\n MultiplePermissionsResult,\n PermissionEngine,\n PermissionFlowState,\n PermissionStatus,\n} from \"../types\";\n\nfunction permissionKey(entry: MultiPermissionEntry): string {\n return String(entry.permission);\n}\n\nfunction isGrantedStatus(status: PermissionStatus): boolean {\n return status === \"granted\" || status === \"limited\";\n}\n\nfunction statusToFlowState(status: PermissionStatus): PermissionFlowState {\n switch (status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"unavailable\":\n return \"unavailable\";\n case \"denied\":\n return \"prePrompt\";\n default:\n return \"idle\";\n }\n}\n\nexport function useMultiplePermissions(\n config: MultiplePermissionsConfig,\n): MultiplePermissionsResult {\n const engine = resolveEngine(config.engine);\n const {\n permissions,\n strategy,\n autoCheck = true,\n requestTimeout,\n onTimeout,\n debug,\n onAllGranted,\n } = config;\n const logger = createDebugLogger(debug, \"multi\");\n const [statuses, setStatuses] = useState<Record<string, PermissionFlowState>>(() => {\n const initial: Record<string, PermissionFlowState> = {};\n for (const entry of permissions) {\n initial[permissionKey(entry)] = \"idle\";\n }\n return initial;\n });\n const isRunning = useRef(false);\n\n const allGranted = permissions.every((entry) => statuses[permissionKey(entry)] === \"granted\");\n\n const requestAll = useCallback(async () => {\n if (isRunning.current) return;\n isRunning.current = true;\n\n const update = (key: string, state: PermissionFlowState) => {\n setStatuses((prev) => {\n logger.transition(prev[key] ?? \"idle\", state, key);\n return { ...prev, [key]: state };\n });\n };\n\n try {\n if (strategy === \"sequential\") {\n await runSequential(permissions, engine, update, requestTimeout, onTimeout);\n } else {\n await runParallel(permissions, engine, update, requestTimeout, onTimeout);\n }\n\n // Final check: are all granted?\n let allDone = true;\n for (const entry of permissions) {\n const finalStatus = await engine.check(entry.permission);\n if (!isGrantedStatus(finalStatus)) {\n allDone = false;\n break;\n }\n }\n if (allDone) {\n onAllGranted?.();\n }\n } finally {\n isRunning.current = false;\n }\n }, [permissions, strategy, engine, requestTimeout, onTimeout, logger, onAllGranted]);\n\n // Auto-check on mount\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect\n useEffect(() => {\n if (!autoCheck) return;\n\n let cancelled = false;\n async function checkAll() {\n for (const entry of permissions) {\n const key = permissionKey(entry);\n const status = await engine.check(entry.permission);\n if (cancelled) return;\n setStatuses((prev) => ({ ...prev, [key]: statusToFlowState(status) }));\n }\n }\n checkAll();\n return () => {\n cancelled = true;\n };\n }, []);\n\n return {\n statuses,\n allGranted,\n request: requestAll,\n };\n}\n\nasync function runSequential(\n permissions: MultiPermissionEntry[],\n engine: PermissionEngine,\n updateStatus: (key: string, state: PermissionFlowState) => void,\n requestTimeout?: number,\n onTimeout?: () => void,\n): Promise<void> {\n for (const entry of permissions) {\n const key = permissionKey(entry);\n\n updateStatus(key, \"checking\");\n const checkStatus = await engine.check(entry.permission);\n\n if (isGrantedStatus(checkStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n continue;\n }\n\n if (checkStatus === \"unavailable\") {\n updateStatus(key, \"unavailable\");\n continue;\n }\n\n if (checkStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n break;\n }\n\n // Denied — request it\n updateStatus(key, \"requesting\");\n try {\n const requestPromise = engine.request(entry.permission);\n const requestStatus = requestTimeout\n ? await withTimeout(requestPromise, requestTimeout, entry.permission)\n : await requestPromise;\n\n if (isGrantedStatus(requestStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (requestStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n break;\n } else {\n updateStatus(key, \"denied\");\n entry.onDeny?.();\n break;\n }\n } catch (err) {\n if (err instanceof PermissionTimeoutError) {\n onTimeout?.();\n updateStatus(key, \"blockedPrompt\");\n break;\n }\n throw err;\n }\n }\n}\n\nasync function runParallel(\n permissions: MultiPermissionEntry[],\n engine: PermissionEngine,\n updateStatus: (key: string, state: PermissionFlowState) => void,\n requestTimeout?: number,\n onTimeout?: () => void,\n): Promise<void> {\n // Check all in parallel\n const checkResults = await Promise.all(\n permissions.map(async (entry) => {\n const key = permissionKey(entry);\n updateStatus(key, \"checking\");\n const status = await engine.check(entry.permission);\n return { entry, key, status };\n }),\n );\n\n // Update granted/unavailable immediately\n for (const { entry, key, status } of checkResults) {\n if (isGrantedStatus(status)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (status === \"unavailable\") {\n updateStatus(key, \"unavailable\");\n }\n }\n\n // Request denied/blocked ones sequentially (system dialogs are sequential)\n const needsAction = checkResults.filter(\n ({ status }) => status === \"denied\" || status === \"blocked\",\n );\n\n for (const { entry, key, status } of needsAction) {\n if (status === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n continue;\n }\n\n updateStatus(key, \"requesting\");\n try {\n const requestPromise = engine.request(entry.permission);\n const requestStatus = requestTimeout\n ? await withTimeout(requestPromise, requestTimeout, entry.permission)\n : await requestPromise;\n\n if (isGrantedStatus(requestStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (requestStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n } else {\n updateStatus(key, \"denied\");\n entry.onDeny?.();\n }\n } catch (err) {\n if (err instanceof PermissionTimeoutError) {\n onTimeout?.();\n updateStatus(key, \"blockedPrompt\");\n } else {\n throw err;\n }\n }\n }\n}\n","import React from \"react\";\nimport { Modal, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport type { BlockedPromptConfig } from \"../types\";\n\nexport interface DefaultBlockedPromptProps extends BlockedPromptConfig {\n visible: boolean;\n onOpenSettings: () => void;\n}\n\nexport function DefaultBlockedPrompt({\n visible,\n title,\n message,\n settingsLabel = \"Open Settings\",\n onOpenSettings,\n}: DefaultBlockedPromptProps) {\n return (\n <Modal visible={visible} transparent animationType=\"fade\">\n <View style={styles.overlay}>\n <View style={styles.modal}>\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.message}>{message}</Text>\n <TouchableOpacity\n style={styles.settingsButton}\n onPress={onOpenSettings}\n accessibilityRole=\"button\"\n >\n <Text style={styles.settingsText}>{settingsLabel}</Text>\n </TouchableOpacity>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: \"rgba(0,0,0,0.5)\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n modal: {\n backgroundColor: \"white\",\n borderRadius: 16,\n padding: 24,\n width: \"85%\",\n alignItems: \"center\",\n },\n title: {\n fontSize: 20,\n fontWeight: \"600\",\n marginBottom: 12,\n textAlign: \"center\",\n },\n message: {\n fontSize: 15,\n color: \"#666\",\n textAlign: \"center\",\n marginBottom: 24,\n lineHeight: 22,\n },\n settingsButton: {\n backgroundColor: \"#007AFF\",\n borderRadius: 12,\n paddingVertical: 14,\n paddingHorizontal: 32,\n width: \"100%\",\n alignItems: \"center\",\n },\n settingsText: {\n color: \"white\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n});\n","import React from \"react\";\nimport { Modal, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport type { PrePromptConfig } from \"../types\";\n\nexport interface DefaultPrePromptProps extends PrePromptConfig {\n visible: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function DefaultPrePrompt({\n visible,\n title,\n message,\n confirmLabel = \"Continue\",\n cancelLabel = \"Not Now\",\n onConfirm,\n onCancel,\n}: DefaultPrePromptProps) {\n return (\n <Modal visible={visible} transparent animationType=\"fade\">\n <View style={styles.overlay}>\n <View style={styles.modal}>\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.message}>{message}</Text>\n <TouchableOpacity\n style={styles.confirmButton}\n onPress={onConfirm}\n accessibilityRole=\"button\"\n >\n <Text style={styles.confirmText}>{confirmLabel}</Text>\n </TouchableOpacity>\n <TouchableOpacity onPress={onCancel} accessibilityRole=\"button\">\n <Text style={styles.cancelText}>{cancelLabel}</Text>\n </TouchableOpacity>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: \"rgba(0,0,0,0.5)\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n modal: {\n backgroundColor: \"white\",\n borderRadius: 16,\n padding: 24,\n width: \"85%\",\n alignItems: \"center\",\n },\n title: {\n fontSize: 20,\n fontWeight: \"600\",\n marginBottom: 12,\n textAlign: \"center\",\n },\n message: {\n fontSize: 15,\n color: \"#666\",\n textAlign: \"center\",\n marginBottom: 24,\n lineHeight: 22,\n },\n confirmButton: {\n backgroundColor: \"#007AFF\",\n borderRadius: 12,\n paddingVertical: 14,\n paddingHorizontal: 32,\n width: \"100%\",\n alignItems: \"center\",\n marginBottom: 12,\n },\n confirmText: {\n color: \"white\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n cancelText: {\n color: \"#007AFF\",\n fontSize: 15,\n },\n});\n","import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport { usePermissionHandler } from \"../hooks/use-permission-handler\";\nimport type {\n BlockedPromptConfig,\n PermissionCallbacks,\n PermissionEngine,\n PrePromptConfig,\n} from \"../types\";\nimport { DefaultBlockedPrompt } from \"./default-blocked-prompt\";\nimport { DefaultPrePrompt } from \"./default-pre-prompt\";\n\nexport interface PermissionGateProps extends PermissionCallbacks {\n permission: string;\n engine?: PermissionEngine;\n prePrompt: PrePromptConfig;\n blockedPrompt: BlockedPromptConfig;\n children: ReactNode;\n fallback?: ReactNode;\n renderPrePrompt?: (props: {\n config: PrePromptConfig;\n onConfirm: () => void;\n onCancel: () => void;\n }) => ReactNode;\n renderBlockedPrompt?: (props: {\n config: BlockedPromptConfig;\n onOpenSettings: () => void;\n }) => ReactNode;\n}\n\nexport function PermissionGate({\n permission,\n engine,\n prePrompt,\n blockedPrompt,\n children,\n fallback = null,\n renderPrePrompt,\n renderBlockedPrompt,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n}: PermissionGateProps) {\n const handler = usePermissionHandler({\n permission,\n engine,\n prePrompt,\n blockedPrompt,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n });\n\n if (handler.isGranted) {\n return <>{children}</>;\n }\n\n if (handler.isChecking || handler.isUnavailable) {\n return <>{fallback}</>;\n }\n\n if (handler.state === \"prePrompt\") {\n if (renderPrePrompt) {\n return (\n <>\n {renderPrePrompt({\n config: prePrompt,\n onConfirm: handler.request,\n onCancel: handler.dismiss,\n })}\n </>\n );\n }\n return (\n <DefaultPrePrompt\n visible\n title={prePrompt.title}\n message={prePrompt.message}\n confirmLabel={prePrompt.confirmLabel}\n cancelLabel={prePrompt.cancelLabel}\n onConfirm={handler.request}\n onCancel={handler.dismiss}\n />\n );\n }\n\n if (handler.state === \"blockedPrompt\") {\n if (renderBlockedPrompt) {\n return (\n <>\n {renderBlockedPrompt({\n config: blockedPrompt,\n onOpenSettings: handler.openSettings,\n })}\n </>\n );\n }\n return (\n <DefaultBlockedPrompt\n visible\n title={blockedPrompt.title}\n message={blockedPrompt.message}\n settingsLabel={blockedPrompt.settingsLabel}\n onOpenSettings={handler.openSettings}\n />\n );\n }\n\n return <>{fallback}</>;\n}\n"],"mappings":"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","names":["import_react_native","createRNPEngine","import_react","import_react_native","import_react_native","import_jsx_runtime","styles","import_jsx_runtime"]}
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-permission-handler",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Smart permission UX flows for React Native — pre-prompts, blocked handling, settings redirect & foreground re-check. Pluggable engine: works with react-native-permissions, Expo, or your own.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
package/src/engines/expo.test.ts
CHANGED
|
@@ -119,4 +119,80 @@ describe("createExpoEngine", () => {
|
|
|
119
119
|
expect(Linking.openSettings).toHaveBeenCalled();
|
|
120
120
|
});
|
|
121
121
|
});
|
|
122
|
+
|
|
123
|
+
describe("non-standard module names (ExpoPermissionFunctions)", () => {
|
|
124
|
+
it("works with explicit get/request functions", async () => {
|
|
125
|
+
const getFn = vi.fn().mockResolvedValue({ status: "granted", canAskAgain: true });
|
|
126
|
+
const requestFn = vi.fn().mockResolvedValue({ status: "denied", canAskAgain: false });
|
|
127
|
+
|
|
128
|
+
const engine = createExpoEngine({
|
|
129
|
+
permissions: {
|
|
130
|
+
camera: { get: getFn, request: requestFn },
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(await engine.check("camera")).toBe("granted");
|
|
135
|
+
expect(getFn).toHaveBeenCalled();
|
|
136
|
+
|
|
137
|
+
expect(await engine.request("camera")).toBe("blocked");
|
|
138
|
+
expect(requestFn).toHaveBeenCalled();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("simulates expo-camera with getCameraPermissionsAsync", async () => {
|
|
142
|
+
// This is how users would wire up expo-camera
|
|
143
|
+
const mockCamera = {
|
|
144
|
+
getCameraPermissionsAsync: vi
|
|
145
|
+
.fn()
|
|
146
|
+
.mockResolvedValue({ status: "denied", canAskAgain: true }),
|
|
147
|
+
requestCameraPermissionsAsync: vi
|
|
148
|
+
.fn()
|
|
149
|
+
.mockResolvedValue({ status: "granted", canAskAgain: true }),
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const engine = createExpoEngine({
|
|
153
|
+
permissions: {
|
|
154
|
+
camera: {
|
|
155
|
+
get: () => mockCamera.getCameraPermissionsAsync(),
|
|
156
|
+
request: () => mockCamera.requestCameraPermissionsAsync(),
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
expect(await engine.check("camera")).toBe("denied");
|
|
162
|
+
expect(await engine.request("camera")).toBe("granted");
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("simulates expo-location foreground + background as separate entries", async () => {
|
|
166
|
+
const mockLocation = {
|
|
167
|
+
getForegroundPermissionsAsync: vi
|
|
168
|
+
.fn()
|
|
169
|
+
.mockResolvedValue({ status: "granted", canAskAgain: true }),
|
|
170
|
+
requestForegroundPermissionsAsync: vi
|
|
171
|
+
.fn()
|
|
172
|
+
.mockResolvedValue({ status: "granted", canAskAgain: true }),
|
|
173
|
+
getBackgroundPermissionsAsync: vi
|
|
174
|
+
.fn()
|
|
175
|
+
.mockResolvedValue({ status: "denied", canAskAgain: false }),
|
|
176
|
+
requestBackgroundPermissionsAsync: vi
|
|
177
|
+
.fn()
|
|
178
|
+
.mockResolvedValue({ status: "denied", canAskAgain: false }),
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const engine = createExpoEngine({
|
|
182
|
+
permissions: {
|
|
183
|
+
locationForeground: {
|
|
184
|
+
get: () => mockLocation.getForegroundPermissionsAsync(),
|
|
185
|
+
request: () => mockLocation.requestForegroundPermissionsAsync(),
|
|
186
|
+
},
|
|
187
|
+
locationBackground: {
|
|
188
|
+
get: () => mockLocation.getBackgroundPermissionsAsync(),
|
|
189
|
+
request: () => mockLocation.requestBackgroundPermissionsAsync(),
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(await engine.check("locationForeground")).toBe("granted");
|
|
195
|
+
expect(await engine.check("locationBackground")).toBe("blocked");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
122
198
|
});
|
package/src/engines/expo.ts
CHANGED
|
@@ -1,19 +1,48 @@
|
|
|
1
1
|
import { Linking } from "react-native";
|
|
2
2
|
import type { PermissionEngine, PermissionStatus } from "../types";
|
|
3
3
|
|
|
4
|
+
type ExpoPermissionResponse = { status: string; canAskAgain: boolean };
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* An Expo module with standard permission methods (getPermissionsAsync/requestPermissionsAsync).
|
|
8
|
+
* Works with: expo-media-library, expo-notifications, expo-contacts, expo-brightness,
|
|
9
|
+
* expo-screen-capture, expo-cellular, expo-av, expo-sensors, expo-maps.
|
|
10
|
+
*/
|
|
4
11
|
export interface ExpoPermissionModule {
|
|
5
|
-
getPermissionsAsync: () => Promise<
|
|
6
|
-
requestPermissionsAsync: () => Promise<
|
|
12
|
+
getPermissionsAsync: () => Promise<ExpoPermissionResponse>;
|
|
13
|
+
requestPermissionsAsync: () => Promise<ExpoPermissionResponse>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Explicit get/request function pair for modules with non-standard method names.
|
|
18
|
+
* Use this for: expo-camera, expo-location, expo-calendar, expo-image-picker,
|
|
19
|
+
* expo-tracking-transparency, expo-audio.
|
|
20
|
+
*/
|
|
21
|
+
export interface ExpoPermissionFunctions {
|
|
22
|
+
get: () => Promise<ExpoPermissionResponse>;
|
|
23
|
+
request: () => Promise<ExpoPermissionResponse>;
|
|
7
24
|
}
|
|
8
25
|
|
|
26
|
+
export type ExpoPermissionEntry = ExpoPermissionModule | ExpoPermissionFunctions;
|
|
27
|
+
|
|
9
28
|
export interface ExpoEngineConfig {
|
|
10
|
-
permissions: Record<string,
|
|
29
|
+
permissions: Record<string, ExpoPermissionEntry>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveEntry(entry: ExpoPermissionEntry): {
|
|
33
|
+
get: () => Promise<ExpoPermissionResponse>;
|
|
34
|
+
request: () => Promise<ExpoPermissionResponse>;
|
|
35
|
+
} {
|
|
36
|
+
if ("get" in entry && "request" in entry) {
|
|
37
|
+
return entry;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
get: () => entry.getPermissionsAsync(),
|
|
41
|
+
request: () => entry.requestPermissionsAsync(),
|
|
42
|
+
};
|
|
11
43
|
}
|
|
12
44
|
|
|
13
|
-
function mapExpoStatus(result: {
|
|
14
|
-
status: string;
|
|
15
|
-
canAskAgain: boolean;
|
|
16
|
-
}): PermissionStatus {
|
|
45
|
+
function mapExpoStatus(result: ExpoPermissionResponse): PermissionStatus {
|
|
17
46
|
if (result.status === "granted") return "granted";
|
|
18
47
|
if (result.status === "undetermined") return "denied";
|
|
19
48
|
if (result.status === "denied") {
|
|
@@ -25,17 +54,17 @@ function mapExpoStatus(result: {
|
|
|
25
54
|
export function createExpoEngine(config: ExpoEngineConfig): PermissionEngine {
|
|
26
55
|
return {
|
|
27
56
|
async check(permission: string): Promise<PermissionStatus> {
|
|
28
|
-
const
|
|
29
|
-
if (!
|
|
30
|
-
const
|
|
31
|
-
return mapExpoStatus(
|
|
57
|
+
const entry = config.permissions[permission];
|
|
58
|
+
if (!entry) return "unavailable";
|
|
59
|
+
const { get } = resolveEntry(entry);
|
|
60
|
+
return mapExpoStatus(await get());
|
|
32
61
|
},
|
|
33
62
|
|
|
34
63
|
async request(permission: string): Promise<PermissionStatus> {
|
|
35
|
-
const
|
|
36
|
-
if (!
|
|
37
|
-
const
|
|
38
|
-
return mapExpoStatus(
|
|
64
|
+
const entry = config.permissions[permission];
|
|
65
|
+
if (!entry) return "unavailable";
|
|
66
|
+
const { request } = resolveEntry(entry);
|
|
67
|
+
return mapExpoStatus(await request());
|
|
39
68
|
},
|
|
40
69
|
|
|
41
70
|
async openSettings(): Promise<void> {
|