react-native-permission-handler 0.2.1 → 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.
@@ -100,23 +100,53 @@ describe("createRNPEngine", () => {
100
100
  });
101
101
 
102
102
  describe("Permissions constants", () => {
103
- it("resolves to iOS strings (mocked platform)", () => {
103
+ it("resolves cross-platform permissions to iOS strings (mocked platform)", () => {
104
104
  expect(Permissions.CAMERA).toBe("ios.permission.CAMERA");
105
105
  expect(Permissions.MICROPHONE).toBe("ios.permission.MICROPHONE");
106
106
  expect(Permissions.LOCATION_WHEN_IN_USE).toBe("ios.permission.LOCATION_WHEN_IN_USE");
107
+ expect(Permissions.MEDIA_LIBRARY).toBe("ios.permission.MEDIA_LIBRARY");
108
+ expect(Permissions.SPEECH_RECOGNITION).toBe("ios.permission.SPEECH_RECOGNITION");
109
+ expect(Permissions.MOTION).toBe("ios.permission.MOTION");
107
110
  expect(Permissions.NOTIFICATIONS).toBe("notifications");
108
111
  });
109
112
 
110
- it("includes all expected cross-platform permissions", () => {
113
+ it("includes all cross-platform permissions", () => {
111
114
  const keys = Object.keys(Permissions);
112
- expect(keys).toContain("CAMERA");
113
- expect(keys).toContain("MICROPHONE");
114
- expect(keys).toContain("CONTACTS");
115
- expect(keys).toContain("CALENDARS");
116
- expect(keys).toContain("LOCATION_WHEN_IN_USE");
117
- expect(keys).toContain("LOCATION_ALWAYS");
118
- expect(keys).toContain("PHOTO_LIBRARY");
119
- expect(keys).toContain("BLUETOOTH");
120
- expect(keys).toContain("NOTIFICATIONS");
115
+ for (const key of [
116
+ "CAMERA",
117
+ "MICROPHONE",
118
+ "CONTACTS",
119
+ "CALENDARS",
120
+ "CALENDARS_WRITE_ONLY",
121
+ "LOCATION_WHEN_IN_USE",
122
+ "LOCATION_ALWAYS",
123
+ "PHOTO_LIBRARY",
124
+ "PHOTO_LIBRARY_ADD_ONLY",
125
+ "MEDIA_LIBRARY",
126
+ "BLUETOOTH",
127
+ "SPEECH_RECOGNITION",
128
+ "MOTION",
129
+ "NOTIFICATIONS",
130
+ ]) {
131
+ expect(keys).toContain(key);
132
+ }
133
+ });
134
+
135
+ it("includes iOS-only permissions", () => {
136
+ expect(Permissions.IOS.FACE_ID).toBe("ios.permission.FACE_ID");
137
+ expect(Permissions.IOS.APP_TRACKING_TRANSPARENCY).toBe(
138
+ "ios.permission.APP_TRACKING_TRANSPARENCY",
139
+ );
140
+ expect(Permissions.IOS.SIRI).toBe("ios.permission.SIRI");
141
+ expect(Permissions.IOS.REMINDERS).toBe("ios.permission.REMINDERS");
142
+ expect(Permissions.IOS.STOREKIT).toBe("ios.permission.STOREKIT");
143
+ });
144
+
145
+ it("includes Android-only permissions", () => {
146
+ expect(Permissions.ANDROID.BODY_SENSORS).toBe("android.permission.BODY_SENSORS");
147
+ expect(Permissions.ANDROID.CALL_PHONE).toBe("android.permission.CALL_PHONE");
148
+ expect(Permissions.ANDROID.READ_SMS).toBe("android.permission.READ_SMS");
149
+ expect(Permissions.ANDROID.BLUETOOTH_SCAN).toBe("android.permission.BLUETOOTH_SCAN");
150
+ expect(Permissions.ANDROID.READ_MEDIA_VIDEO).toBe("android.permission.READ_MEDIA_VIDEO");
121
151
  });
122
152
  });
@@ -14,10 +14,11 @@ function p(ios: string, android: string): string {
14
14
  }
15
15
 
16
16
  /**
17
- * Cross-platform permission constants for use with the RNP engine.
18
- * Each resolves to the correct platform-specific string at runtime.
17
+ * Cross-platform permission constants that resolve to the correct
18
+ * platform-specific string at runtime via Platform.select.
19
19
  */
20
20
  export const Permissions = {
21
+ // Cross-platform
21
22
  CAMERA: p("ios.permission.CAMERA", "android.permission.CAMERA"),
22
23
  MICROPHONE: p("ios.permission.MICROPHONE", "android.permission.RECORD_AUDIO"),
23
24
  CONTACTS: p("ios.permission.CONTACTS", "android.permission.READ_CONTACTS"),
@@ -39,8 +40,55 @@ export const Permissions = {
39
40
  "ios.permission.PHOTO_LIBRARY_ADD_ONLY",
40
41
  "android.permission.WRITE_EXTERNAL_STORAGE",
41
42
  ),
43
+ MEDIA_LIBRARY: p("ios.permission.MEDIA_LIBRARY", "android.permission.READ_MEDIA_AUDIO"),
42
44
  BLUETOOTH: p("ios.permission.BLUETOOTH", "android.permission.BLUETOOTH_CONNECT"),
45
+ SPEECH_RECOGNITION: p("ios.permission.SPEECH_RECOGNITION", "android.permission.RECORD_AUDIO"),
46
+ MOTION: p("ios.permission.MOTION", "android.permission.ACTIVITY_RECOGNITION"),
43
47
  NOTIFICATIONS: "notifications",
48
+
49
+ // iOS-only
50
+ IOS: {
51
+ APP_TRACKING_TRANSPARENCY: "ios.permission.APP_TRACKING_TRANSPARENCY",
52
+ FACE_ID: "ios.permission.FACE_ID",
53
+ REMINDERS: "ios.permission.REMINDERS",
54
+ SIRI: "ios.permission.SIRI",
55
+ STOREKIT: "ios.permission.STOREKIT",
56
+ },
57
+
58
+ // Android-only
59
+ ANDROID: {
60
+ ACCEPT_HANDOVER: "android.permission.ACCEPT_HANDOVER",
61
+ ACCESS_COARSE_LOCATION: "android.permission.ACCESS_COARSE_LOCATION",
62
+ ACCESS_MEDIA_LOCATION: "android.permission.ACCESS_MEDIA_LOCATION",
63
+ ADD_VOICEMAIL: "com.android.voicemail.permission.ADD_VOICEMAIL",
64
+ ANSWER_PHONE_CALLS: "android.permission.ANSWER_PHONE_CALLS",
65
+ BLUETOOTH_ADVERTISE: "android.permission.BLUETOOTH_ADVERTISE",
66
+ BLUETOOTH_SCAN: "android.permission.BLUETOOTH_SCAN",
67
+ BODY_SENSORS: "android.permission.BODY_SENSORS",
68
+ BODY_SENSORS_BACKGROUND: "android.permission.BODY_SENSORS_BACKGROUND",
69
+ CALL_PHONE: "android.permission.CALL_PHONE",
70
+ GET_ACCOUNTS: "android.permission.GET_ACCOUNTS",
71
+ NEARBY_WIFI_DEVICES: "android.permission.NEARBY_WIFI_DEVICES",
72
+ PROCESS_OUTGOING_CALLS: "android.permission.PROCESS_OUTGOING_CALLS",
73
+ READ_CALL_LOG: "android.permission.READ_CALL_LOG",
74
+ READ_EXTERNAL_STORAGE: "android.permission.READ_EXTERNAL_STORAGE",
75
+ READ_MEDIA_AUDIO: "android.permission.READ_MEDIA_AUDIO",
76
+ READ_MEDIA_IMAGES: "android.permission.READ_MEDIA_IMAGES",
77
+ READ_MEDIA_VIDEO: "android.permission.READ_MEDIA_VIDEO",
78
+ READ_MEDIA_VISUAL_USER_SELECTED: "android.permission.READ_MEDIA_VISUAL_USER_SELECTED",
79
+ READ_PHONE_NUMBERS: "android.permission.READ_PHONE_NUMBERS",
80
+ READ_PHONE_STATE: "android.permission.READ_PHONE_STATE",
81
+ READ_SMS: "android.permission.READ_SMS",
82
+ RECEIVE_MMS: "android.permission.RECEIVE_MMS",
83
+ RECEIVE_SMS: "android.permission.RECEIVE_SMS",
84
+ RECEIVE_WAP_PUSH: "android.permission.RECEIVE_WAP_PUSH",
85
+ SEND_SMS: "android.permission.SEND_SMS",
86
+ USE_SIP: "android.permission.USE_SIP",
87
+ UWB_RANGING: "android.permission.UWB_RANGING",
88
+ WRITE_CALL_LOG: "android.permission.WRITE_CALL_LOG",
89
+ WRITE_CONTACTS: "android.permission.WRITE_CONTACTS",
90
+ WRITE_EXTERNAL_STORAGE: "android.permission.WRITE_EXTERNAL_STORAGE",
91
+ },
44
92
  } as const;
45
93
 
46
94
  export function createRNPEngine(): PermissionEngine {
@@ -1,4 +1,6 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { createDebugLogger } from "../core/debug-logger";
3
+ import { PermissionTimeoutError, withTimeout } from "../core/with-timeout";
2
4
  import { resolveEngine } from "../engines/use-engine";
3
5
  import type {
4
6
  MultiPermissionEntry,
@@ -37,7 +39,16 @@ export function useMultiplePermissions(
37
39
  config: MultiplePermissionsConfig,
38
40
  ): MultiplePermissionsResult {
39
41
  const engine = resolveEngine(config.engine);
40
- const { permissions, strategy, autoCheck = true, onAllGranted } = config;
42
+ const {
43
+ permissions,
44
+ strategy,
45
+ autoCheck = true,
46
+ requestTimeout,
47
+ onTimeout,
48
+ debug,
49
+ onAllGranted,
50
+ } = config;
51
+ const logger = createDebugLogger(debug, "multi");
41
52
  const [statuses, setStatuses] = useState<Record<string, PermissionFlowState>>(() => {
42
53
  const initial: Record<string, PermissionFlowState> = {};
43
54
  for (const entry of permissions) {
@@ -54,14 +65,17 @@ export function useMultiplePermissions(
54
65
  isRunning.current = true;
55
66
 
56
67
  const update = (key: string, state: PermissionFlowState) => {
57
- setStatuses((prev) => ({ ...prev, [key]: state }));
68
+ setStatuses((prev) => {
69
+ logger.transition(prev[key] ?? "idle", state, key);
70
+ return { ...prev, [key]: state };
71
+ });
58
72
  };
59
73
 
60
74
  try {
61
75
  if (strategy === "sequential") {
62
- await runSequential(permissions, engine, update);
76
+ await runSequential(permissions, engine, update, requestTimeout, onTimeout);
63
77
  } else {
64
- await runParallel(permissions, engine, update);
78
+ await runParallel(permissions, engine, update, requestTimeout, onTimeout);
65
79
  }
66
80
 
67
81
  // Final check: are all granted?
@@ -79,7 +93,7 @@ export function useMultiplePermissions(
79
93
  } finally {
80
94
  isRunning.current = false;
81
95
  }
82
- }, [permissions, strategy, engine, onAllGranted]);
96
+ }, [permissions, strategy, engine, requestTimeout, onTimeout, logger, onAllGranted]);
83
97
 
84
98
  // Auto-check on mount
85
99
  // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect
@@ -112,6 +126,8 @@ async function runSequential(
112
126
  permissions: MultiPermissionEntry[],
113
127
  engine: PermissionEngine,
114
128
  updateStatus: (key: string, state: PermissionFlowState) => void,
129
+ requestTimeout?: number,
130
+ onTimeout?: () => void,
115
131
  ): Promise<void> {
116
132
  for (const entry of permissions) {
117
133
  const key = permissionKey(entry);
@@ -138,19 +154,31 @@ async function runSequential(
138
154
 
139
155
  // Denied — request it
140
156
  updateStatus(key, "requesting");
141
- const requestStatus = await engine.request(entry.permission);
142
-
143
- if (isGrantedStatus(requestStatus)) {
144
- updateStatus(key, "granted");
145
- entry.onGrant?.();
146
- } else if (requestStatus === "blocked") {
147
- updateStatus(key, "blockedPrompt");
148
- entry.onBlock?.();
149
- break;
150
- } else {
151
- updateStatus(key, "denied");
152
- entry.onDeny?.();
153
- break;
157
+ try {
158
+ const requestPromise = engine.request(entry.permission);
159
+ const requestStatus = requestTimeout
160
+ ? await withTimeout(requestPromise, requestTimeout, entry.permission)
161
+ : await requestPromise;
162
+
163
+ if (isGrantedStatus(requestStatus)) {
164
+ updateStatus(key, "granted");
165
+ entry.onGrant?.();
166
+ } else if (requestStatus === "blocked") {
167
+ updateStatus(key, "blockedPrompt");
168
+ entry.onBlock?.();
169
+ break;
170
+ } else {
171
+ updateStatus(key, "denied");
172
+ entry.onDeny?.();
173
+ break;
174
+ }
175
+ } catch (err) {
176
+ if (err instanceof PermissionTimeoutError) {
177
+ onTimeout?.();
178
+ updateStatus(key, "blockedPrompt");
179
+ break;
180
+ }
181
+ throw err;
154
182
  }
155
183
  }
156
184
  }
@@ -159,6 +187,8 @@ async function runParallel(
159
187
  permissions: MultiPermissionEntry[],
160
188
  engine: PermissionEngine,
161
189
  updateStatus: (key: string, state: PermissionFlowState) => void,
190
+ requestTimeout?: number,
191
+ onTimeout?: () => void,
162
192
  ): Promise<void> {
163
193
  // Check all in parallel
164
194
  const checkResults = await Promise.all(
@@ -193,17 +223,29 @@ async function runParallel(
193
223
  }
194
224
 
195
225
  updateStatus(key, "requesting");
196
- const requestStatus = await engine.request(entry.permission);
197
-
198
- if (isGrantedStatus(requestStatus)) {
199
- updateStatus(key, "granted");
200
- entry.onGrant?.();
201
- } else if (requestStatus === "blocked") {
202
- updateStatus(key, "blockedPrompt");
203
- entry.onBlock?.();
204
- } else {
205
- updateStatus(key, "denied");
206
- entry.onDeny?.();
226
+ try {
227
+ const requestPromise = engine.request(entry.permission);
228
+ const requestStatus = requestTimeout
229
+ ? await withTimeout(requestPromise, requestTimeout, entry.permission)
230
+ : await requestPromise;
231
+
232
+ if (isGrantedStatus(requestStatus)) {
233
+ updateStatus(key, "granted");
234
+ entry.onGrant?.();
235
+ } else if (requestStatus === "blocked") {
236
+ updateStatus(key, "blockedPrompt");
237
+ entry.onBlock?.();
238
+ } else {
239
+ updateStatus(key, "denied");
240
+ entry.onDeny?.();
241
+ }
242
+ } catch (err) {
243
+ if (err instanceof PermissionTimeoutError) {
244
+ onTimeout?.();
245
+ updateStatus(key, "blockedPrompt");
246
+ } else {
247
+ throw err;
248
+ }
207
249
  }
208
250
  }
209
251
  }
@@ -1,6 +1,8 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { AppState } from "react-native";
3
+ import { createDebugLogger } from "../core/debug-logger";
3
4
  import { transition } from "../core/state-machine";
5
+ import { PermissionTimeoutError, withTimeout } from "../core/with-timeout";
4
6
  import { resolveEngine } from "../engines/use-engine";
5
7
  import type {
6
8
  PermissionFlowState,
@@ -17,52 +19,91 @@ export function usePermissionHandler(config: PermissionHandlerConfig): Permissio
17
19
  const waitingForSettings = useRef(false);
18
20
  const appStateRef = useRef(AppState.currentState);
19
21
 
20
- const { permission, autoCheck = true, onGrant, onDeny, onBlock, onSettingsReturn } = config;
22
+ const {
23
+ permission,
24
+ autoCheck = true,
25
+ requestTimeout,
26
+ onTimeout,
27
+ debug,
28
+ onGrant,
29
+ onDeny,
30
+ onBlock,
31
+ onSettingsReturn,
32
+ } = config;
33
+
34
+ const logger = createDebugLogger(debug, permission);
21
35
 
22
36
  const checkPermission = useCallback(async () => {
23
- setFlowState((s) => transition(s, { type: "CHECK" }));
37
+ setFlowState((s) => {
38
+ const next = transition(s, { type: "CHECK" });
39
+ logger.transition(s, next, "CHECK");
40
+ return next;
41
+ });
24
42
  try {
25
43
  const status = await engine.check(permission);
26
44
  setNativeStatus(status);
27
45
  setFlowState((s) => {
28
46
  const next = transition(s, { type: "CHECK_RESULT", status });
47
+ logger.transition(s, next, `CHECK_RESULT:${status}`);
29
48
  if (next === "granted" && s !== "granted") onGrant?.();
30
49
  return next;
31
50
  });
32
51
  } catch {
33
52
  setFlowState("idle");
34
53
  }
35
- }, [engine, permission, onGrant]);
54
+ }, [engine, permission, logger, onGrant]);
36
55
 
37
56
  const requestPermission = useCallback(async () => {
38
57
  if (isRequesting.current) return;
39
58
  isRequesting.current = true;
40
59
 
41
- setFlowState((s) => transition(s, { type: "PRE_PROMPT_CONFIRM" }));
60
+ setFlowState((s) => {
61
+ const next = transition(s, { type: "PRE_PROMPT_CONFIRM" });
62
+ logger.transition(s, next, "PRE_PROMPT_CONFIRM");
63
+ return next;
64
+ });
42
65
  try {
43
- const status = await engine.request(permission);
66
+ const requestPromise = engine.request(permission);
67
+ const status = requestTimeout
68
+ ? await withTimeout(requestPromise, requestTimeout, permission)
69
+ : await requestPromise;
44
70
  setNativeStatus(status);
45
71
  setFlowState((s) => {
46
72
  const next = transition(s, { type: "REQUEST_RESULT", status });
73
+ logger.transition(s, next, `REQUEST_RESULT:${status}`);
47
74
  if (next === "granted") onGrant?.();
48
75
  if (next === "denied") onDeny?.();
49
76
  if (next === "blockedPrompt") onBlock?.();
50
77
  return next;
51
78
  });
52
- } catch {
53
- setFlowState("denied");
79
+ } catch (err) {
80
+ if (err instanceof PermissionTimeoutError) {
81
+ logger.info(`request timed out after ${requestTimeout}ms`);
82
+ onTimeout?.();
83
+ setFlowState("blockedPrompt");
84
+ } else {
85
+ setFlowState("denied");
86
+ }
54
87
  } finally {
55
88
  isRequesting.current = false;
56
89
  }
57
- }, [engine, permission, onGrant, onDeny, onBlock]);
90
+ }, [engine, permission, requestTimeout, onTimeout, logger, onGrant, onDeny, onBlock]);
58
91
 
59
92
  const dismiss = useCallback(() => {
60
- setFlowState((s) => transition(s, { type: "PRE_PROMPT_DISMISS" }));
93
+ setFlowState((s) => {
94
+ const next = transition(s, { type: "PRE_PROMPT_DISMISS" });
95
+ logger.transition(s, next, "PRE_PROMPT_DISMISS");
96
+ return next;
97
+ });
61
98
  onDeny?.();
62
- }, [onDeny]);
99
+ }, [logger, onDeny]);
63
100
 
64
101
  const goToSettings = useCallback(async () => {
65
- setFlowState((s) => transition(s, { type: "OPEN_SETTINGS" }));
102
+ setFlowState((s) => {
103
+ const next = transition(s, { type: "OPEN_SETTINGS" });
104
+ logger.transition(s, next, "OPEN_SETTINGS");
105
+ return next;
106
+ });
66
107
  waitingForSettings.current = true;
67
108
  try {
68
109
  await engine.openSettings();
@@ -70,15 +111,20 @@ export function usePermissionHandler(config: PermissionHandlerConfig): Permissio
70
111
  waitingForSettings.current = false;
71
112
  setFlowState("blockedPrompt");
72
113
  }
73
- }, [engine]);
114
+ }, [engine, logger]);
74
115
 
75
116
  const recheckAfterSettings = useCallback(async () => {
76
- setFlowState((s) => transition(s, { type: "SETTINGS_RETURN" }));
117
+ setFlowState((s) => {
118
+ const next = transition(s, { type: "SETTINGS_RETURN" });
119
+ logger.transition(s, next, "SETTINGS_RETURN");
120
+ return next;
121
+ });
77
122
  try {
78
123
  const status = await engine.check(permission);
79
124
  setNativeStatus(status);
80
125
  setFlowState((s) => {
81
126
  const next = transition(s, { type: "RECHECK_RESULT", status });
127
+ logger.transition(s, next, `RECHECK_RESULT:${status}`);
82
128
  if (next === "granted") onGrant?.();
83
129
  onSettingsReturn?.(next === "granted");
84
130
  return next;
@@ -86,7 +132,7 @@ export function usePermissionHandler(config: PermissionHandlerConfig): Permissio
86
132
  } catch {
87
133
  setFlowState("blockedPrompt");
88
134
  }
89
- }, [engine, permission, onGrant, onSettingsReturn]);
135
+ }, [engine, permission, logger, onGrant, onSettingsReturn]);
90
136
 
91
137
  // Auto-check on mount
92
138
  // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect
package/src/types.ts CHANGED
@@ -82,6 +82,9 @@ export interface PermissionHandlerConfig extends PermissionCallbacks {
82
82
  blockedPrompt: BlockedPromptConfig;
83
83
  autoCheck?: boolean;
84
84
  recheckOnForeground?: boolean;
85
+ requestTimeout?: number;
86
+ onTimeout?: () => void;
87
+ debug?: boolean | ((msg: string) => void);
85
88
  }
86
89
 
87
90
  /**
@@ -118,6 +121,9 @@ export interface MultiplePermissionsConfig {
118
121
  strategy: "sequential" | "parallel";
119
122
  engine?: PermissionEngine;
120
123
  autoCheck?: boolean;
124
+ requestTimeout?: number;
125
+ onTimeout?: () => void;
126
+ debug?: boolean | ((msg: string) => void);
121
127
  onAllGranted?: () => void;
122
128
  }
123
129
 
@@ -1,81 +0,0 @@
1
- import {
2
- __esm,
3
- __export
4
- } from "./chunk-NFEGQTCC.mjs";
5
-
6
- // src/engines/rnp.ts
7
- var rnp_exports = {};
8
- __export(rnp_exports, {
9
- Permissions: () => Permissions,
10
- createRNPEngine: () => createRNPEngine
11
- });
12
- import { Platform } from "react-native";
13
- import {
14
- check,
15
- checkNotifications,
16
- openSettings,
17
- request,
18
- requestNotifications
19
- } from "react-native-permissions";
20
- function p(ios, android) {
21
- return Platform.select({ ios, android, default: ios }) ?? ios;
22
- }
23
- function createRNPEngine() {
24
- return {
25
- async check(permission) {
26
- if (permission === "notifications") {
27
- const result = await checkNotifications();
28
- return result.status;
29
- }
30
- return await check(permission);
31
- },
32
- async request(permission) {
33
- if (permission === "notifications") {
34
- const result = await requestNotifications(["alert", "badge", "sound"]);
35
- return result.status;
36
- }
37
- return await request(permission);
38
- },
39
- async openSettings() {
40
- await openSettings();
41
- }
42
- };
43
- }
44
- var Permissions;
45
- var init_rnp = __esm({
46
- "src/engines/rnp.ts"() {
47
- Permissions = {
48
- CAMERA: p("ios.permission.CAMERA", "android.permission.CAMERA"),
49
- MICROPHONE: p("ios.permission.MICROPHONE", "android.permission.RECORD_AUDIO"),
50
- CONTACTS: p("ios.permission.CONTACTS", "android.permission.READ_CONTACTS"),
51
- CALENDARS: p("ios.permission.CALENDARS", "android.permission.READ_CALENDAR"),
52
- CALENDARS_WRITE_ONLY: p(
53
- "ios.permission.CALENDARS_WRITE_ONLY",
54
- "android.permission.WRITE_CALENDAR"
55
- ),
56
- LOCATION_WHEN_IN_USE: p(
57
- "ios.permission.LOCATION_WHEN_IN_USE",
58
- "android.permission.ACCESS_FINE_LOCATION"
59
- ),
60
- LOCATION_ALWAYS: p(
61
- "ios.permission.LOCATION_ALWAYS",
62
- "android.permission.ACCESS_BACKGROUND_LOCATION"
63
- ),
64
- PHOTO_LIBRARY: p("ios.permission.PHOTO_LIBRARY", "android.permission.READ_MEDIA_IMAGES"),
65
- PHOTO_LIBRARY_ADD_ONLY: p(
66
- "ios.permission.PHOTO_LIBRARY_ADD_ONLY",
67
- "android.permission.WRITE_EXTERNAL_STORAGE"
68
- ),
69
- BLUETOOTH: p("ios.permission.BLUETOOTH", "android.permission.BLUETOOTH_CONNECT"),
70
- NOTIFICATIONS: "notifications"
71
- };
72
- }
73
- });
74
-
75
- export {
76
- Permissions,
77
- createRNPEngine,
78
- rnp_exports,
79
- init_rnp
80
- };
81
- //# sourceMappingURL=chunk-EU3KPRTI.mjs.map
@@ -1 +0,0 @@
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 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"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,gBAAgB;AACzB;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,EAAE,KAAa,SAAyB;AAC/C,SAAO,SAAS,OAAO,EAAE,KAAK,SAAS,SAAS,IAAI,CAAC,KAAK;AAC5D;AAgCO,SAAS,kBAAoC;AAClD,SAAO;AAAA,IACL,MAAM,MAAM,YAA+C;AACzD,UAAI,eAAe,iBAAiB;AAClC,cAAM,SAAS,MAAM,mBAAmB;AACxC,eAAO,OAAO;AAAA,MAChB;AACA,aAAQ,MAAM,MAAM,UAAwB;AAAA,IAC9C;AAAA,IAEA,MAAM,QAAQ,YAA+C;AAC3D,UAAI,eAAe,iBAAiB;AAClC,cAAM,SAAS,MAAM,qBAAqB,CAAC,SAAS,SAAS,OAAO,CAAC;AACrE,eAAO,OAAO;AAAA,MAChB;AACA,aAAQ,MAAM,QAAQ,UAAwB;AAAA,IAChD;AAAA,IAEA,MAAM,eAA8B;AAClC,YAAM,aAAa;AAAA,IACrB;AAAA,EACF;AACF;AAnEA,IAmBa;AAnBb;AAAA;AAmBO,IAAM,cAAc;AAAA,MACzB,QAAQ,EAAE,yBAAyB,2BAA2B;AAAA,MAC9D,YAAY,EAAE,6BAA6B,iCAAiC;AAAA,MAC5E,UAAU,EAAE,2BAA2B,kCAAkC;AAAA,MACzE,WAAW,EAAE,4BAA4B,kCAAkC;AAAA,MAC3E,sBAAsB;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,MACA,sBAAsB;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,MACA,iBAAiB;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,MACA,eAAe,EAAE,gCAAgC,sCAAsC;AAAA,MACvF,wBAAwB;AAAA,QACtB;AAAA,QACA;AAAA,MACF;AAAA,MACA,WAAW,EAAE,4BAA4B,sCAAsC;AAAA,MAC/E,eAAe;AAAA,IACjB;AAAA;AAAA;","names":[]}