0
# Permission Management
1
2
Complete permission system with React hooks for managing app permissions, providing standardized interfaces for requesting and checking permission status across platforms.
3
4
## Capabilities
5
6
### PermissionStatus Enum
7
8
Standard permission status values used across all permission types.
9
10
```typescript { .api }
11
/**
12
* Standard permission status values
13
*/
14
enum PermissionStatus {
15
GRANTED = 'granted',
16
UNDETERMINED = 'undetermined',
17
DENIED = 'denied'
18
}
19
```
20
21
### PermissionResponse Interface
22
23
Standard response format for all permission operations.
24
25
```typescript { .api }
26
/**
27
* Standard permission response interface
28
*/
29
interface PermissionResponse {
30
/**
31
* Current permission status
32
*/
33
status: PermissionStatus;
34
35
/**
36
* When the permission expires ('never' for permanent permissions)
37
*/
38
expires: PermissionExpiration;
39
40
/**
41
* Whether permission is currently granted (convenience property)
42
*/
43
granted: boolean;
44
45
/**
46
* Whether the system will show permission dialog if requested
47
*/
48
canAskAgain: boolean;
49
}
50
51
type PermissionExpiration = 'never' | number;
52
```
53
54
**Usage Examples:**
55
56
```typescript
57
import { PermissionResponse, PermissionStatus } from "@unimodules/core";
58
59
// Check permission response
60
function handlePermissionResponse(response: PermissionResponse) {
61
console.log('Status:', response.status);
62
console.log('Granted:', response.granted);
63
console.log('Can ask again:', response.canAskAgain);
64
65
switch (response.status) {
66
case PermissionStatus.GRANTED:
67
console.log('Permission granted');
68
break;
69
case PermissionStatus.DENIED:
70
if (response.canAskAgain) {
71
console.log('Permission denied, but can ask again');
72
} else {
73
console.log('Permission permanently denied');
74
}
75
break;
76
case PermissionStatus.UNDETERMINED:
77
console.log('Permission not yet requested');
78
break;
79
}
80
}
81
```
82
83
### createPermissionHook Function
84
85
Factory function for creating permission-specific React hooks with built-in state management.
86
87
```typescript { .api }
88
/**
89
* Create a permission hook with built-in methods
90
*/
91
function createPermissionHook<Permission extends PermissionResponse, Options extends object>(
92
methods: PermissionHookMethods<Permission, Options>
93
): (options?: PermissionHookOptions<Options>) => [
94
Permission | null, // Current permission status
95
() => Promise<Permission>, // Request permission function
96
() => Promise<Permission> // Get permission function
97
];
98
99
/**
100
* Methods required for permission hook
101
*/
102
interface PermissionHookMethods<Permission extends PermissionResponse, Options = never> {
103
/**
104
* Request permission from user
105
*/
106
requestMethod: (options?: Options) => Promise<Permission>;
107
108
/**
109
* Get current permission status without requesting
110
*/
111
getMethod: (options?: Options) => Promise<Permission>;
112
}
113
114
/**
115
* Options for permission hook behavior
116
*/
117
interface PermissionHookBehavior {
118
/**
119
* Automatically fetch permission status on mount
120
*/
121
get?: boolean;
122
123
/**
124
* Automatically request permission on mount
125
*/
126
request?: boolean;
127
}
128
129
type PermissionHookOptions<Options extends object> = PermissionHookBehavior & Options;
130
```
131
132
**Usage Examples:**
133
134
```typescript
135
import { createPermissionHook, PermissionResponse } from "@unimodules/core";
136
137
// Define custom permission interface
138
interface CameraPermission extends PermissionResponse {
139
accessPrivileges?: 'full' | 'limited';
140
}
141
142
// Create camera permission hook
143
const useCameraPermission = createPermissionHook<CameraPermission, {}>({
144
requestMethod: async () => {
145
const result = await NativeModulesProxy.Camera.requestPermissionsAsync();
146
return result;
147
},
148
getMethod: async () => {
149
const result = await NativeModulesProxy.Camera.getPermissionsAsync();
150
return result;
151
}
152
});
153
154
// Use in React component
155
function CameraComponent() {
156
// Hook returns [status, requestFn, getFn]
157
const [cameraPermission, requestCameraPermission, getCameraPermission] = useCameraPermission({
158
get: true, // Automatically get status on mount
159
request: false // Don't auto-request
160
});
161
162
const handleRequestPermission = async () => {
163
try {
164
const result = await requestCameraPermission();
165
if (result.granted) {
166
console.log('Camera permission granted');
167
} else {
168
console.log('Camera permission denied');
169
}
170
} catch (error) {
171
console.error('Failed to request permission:', error);
172
}
173
};
174
175
if (!cameraPermission) {
176
return <Text>Loading permission status...</Text>;
177
}
178
179
if (!cameraPermission.granted) {
180
return (
181
<View>
182
<Text>Camera permission required</Text>
183
<Button title="Grant Permission" onPress={handleRequestPermission} />
184
</View>
185
);
186
}
187
188
return <CameraView />;
189
}
190
```
191
192
### Advanced Permission Hooks
193
194
Create permission hooks with options and complex behaviors.
195
196
**Usage Examples:**
197
198
```typescript
199
import { createPermissionHook, PermissionResponse } from "@unimodules/core";
200
201
// Location permission with options
202
interface LocationPermission extends PermissionResponse {
203
accuracy?: 'fine' | 'coarse';
204
}
205
206
interface LocationOptions {
207
accuracy?: 'fine' | 'coarse';
208
background?: boolean;
209
}
210
211
const useLocationPermission = createPermissionHook<LocationPermission, LocationOptions>({
212
requestMethod: async (options) => {
213
return await NativeModulesProxy.Location.requestPermissionsAsync(options);
214
},
215
getMethod: async (options) => {
216
return await NativeModulesProxy.Location.getPermissionsAsync(options);
217
}
218
});
219
220
// Usage with options
221
function LocationComponent() {
222
const [locationPermission, requestLocation] = useLocationPermission({
223
get: true,
224
accuracy: 'fine',
225
background: false
226
});
227
228
const requestBackgroundLocation = async () => {
229
await requestLocation({ accuracy: 'fine', background: true });
230
};
231
232
return (
233
<View>
234
<Text>Location: {locationPermission?.status}</Text>
235
<Button title="Request Background" onPress={requestBackgroundLocation} />
236
</View>
237
);
238
}
239
```
240
241
### Multiple Permission Management
242
243
Handle multiple permissions in a single component.
244
245
**Usage Examples:**
246
247
```typescript
248
import { createPermissionHook } from "@unimodules/core";
249
250
// Create multiple permission hooks
251
const useCameraPermission = createPermissionHook(/* camera methods */);
252
const useMicrophonePermission = createPermissionHook(/* microphone methods */);
253
const useLocationPermission = createPermissionHook(/* location methods */);
254
255
function MultiPermissionComponent() {
256
const [cameraPermission, requestCamera] = useCameraPermission({ get: true });
257
const [micPermission, requestMic] = useMicrophonePermission({ get: true });
258
const [locationPermission, requestLocation] = useLocationPermission({ get: true });
259
260
const requestAllPermissions = async () => {
261
const results = await Promise.allSettled([
262
requestCamera(),
263
requestMic(),
264
requestLocation()
265
]);
266
267
results.forEach((result, index) => {
268
const permissionName = ['Camera', 'Microphone', 'Location'][index];
269
if (result.status === 'fulfilled' && result.value.granted) {
270
console.log(`${permissionName} permission granted`);
271
} else {
272
console.log(`${permissionName} permission failed`);
273
}
274
});
275
};
276
277
const allPermissionsGranted =
278
cameraPermission?.granted &&
279
micPermission?.granted &&
280
locationPermission?.granted;
281
282
return (
283
<View>
284
<Text>Camera: {cameraPermission?.status}</Text>
285
<Text>Microphone: {micPermission?.status}</Text>
286
<Text>Location: {locationPermission?.status}</Text>
287
288
{!allPermissionsGranted && (
289
<Button title="Request All Permissions" onPress={requestAllPermissions} />
290
)}
291
</View>
292
);
293
}
294
```
295
296
## Advanced Usage
297
298
### Permission State Management
299
300
```typescript
301
import { createPermissionHook, PermissionResponse, PermissionStatus } from "@unimodules/core";
302
303
class PermissionManager {
304
private static permissionCache = new Map<string, PermissionResponse>();
305
306
static async checkPermission(key: string, getMethod: () => Promise<PermissionResponse>) {
307
const cached = this.permissionCache.get(key);
308
if (cached && Date.now() - cached.expires < 5 * 60 * 1000) { // 5 minute cache
309
return cached;
310
}
311
312
const permission = await getMethod();
313
this.permissionCache.set(key, permission);
314
return permission;
315
}
316
317
static async requestWithRationale(
318
requestMethod: () => Promise<PermissionResponse>,
319
rationale: string
320
): Promise<PermissionResponse> {
321
// Show rationale before requesting
322
const shouldRequest = await showPermissionRationale(rationale);
323
if (!shouldRequest) {
324
return {
325
status: PermissionStatus.DENIED,
326
expires: 'never',
327
granted: false,
328
canAskAgain: true
329
};
330
}
331
332
return await requestMethod();
333
}
334
}
335
336
// Declare this function elsewhere
337
declare function showPermissionRationale(message: string): Promise<boolean>;
338
```
339
340
### Custom Permission Types
341
342
```typescript
343
import { PermissionResponse, PermissionStatus, createPermissionHook } from "@unimodules/core";
344
345
// Custom permission for app-specific features
346
interface NotificationPermission extends PermissionResponse {
347
allowsAlert?: boolean;
348
allowsBadge?: boolean;
349
allowsSound?: boolean;
350
allowsCriticalAlerts?: boolean;
351
}
352
353
interface MediaLibraryPermission extends PermissionResponse {
354
accessPrivileges?: 'all' | 'limited' | 'none';
355
selectedAssets?: string[];
356
}
357
358
// Create hooks for custom permissions
359
const useNotificationPermission = createPermissionHook<NotificationPermission, {}>({
360
requestMethod: async () => {
361
const result = await NativeModulesProxy.Notifications.requestPermissionsAsync();
362
return result;
363
},
364
getMethod: async () => {
365
return await NativeModulesProxy.Notifications.getPermissionsAsync();
366
}
367
});
368
369
const useMediaLibraryPermission = createPermissionHook<MediaLibraryPermission, {}>({
370
requestMethod: async () => {
371
return await NativeModulesProxy.MediaLibrary.requestPermissionsAsync();
372
},
373
getMethod: async () => {
374
return await NativeModulesProxy.MediaLibrary.getPermissionsAsync();
375
}
376
});
377
```
378
379
### Permission Flow Patterns
380
381
```typescript
382
import { PermissionStatus } from "@unimodules/core";
383
384
class PermissionFlow {
385
static async requestWithFallback<T extends PermissionResponse>(
386
requestMethod: () => Promise<T>,
387
fallbackAction: () => void
388
): Promise<T | null> {
389
const result = await requestMethod();
390
391
if (result.status === PermissionStatus.DENIED && !result.canAskAgain) {
392
// Permission permanently denied, show settings prompt
393
const shouldOpenSettings = await showSettingsPrompt();
394
if (shouldOpenSettings) {
395
await openAppSettings();
396
} else {
397
fallbackAction();
398
}
399
return null;
400
}
401
402
return result;
403
}
404
405
static async ensurePermission<T extends PermissionResponse>(
406
getMethod: () => Promise<T>,
407
requestMethod: () => Promise<T>
408
): Promise<T> {
409
let permission = await getMethod();
410
411
if (permission.status === PermissionStatus.UNDETERMINED) {
412
permission = await requestMethod();
413
}
414
415
return permission;
416
}
417
}
418
419
// Declare these functions elsewhere
420
declare function showSettingsPrompt(): Promise<boolean>;
421
declare function openAppSettings(): Promise<void>;
422
```
423
424
## Types
425
426
```typescript { .api }
427
type RequestPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;
428
type GetPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;
429
430
interface PermissionHook<Permission extends PermissionResponse> {
431
(options?: PermissionHookOptions<any>): [
432
Permission | null,
433
RequestPermissionMethod<Permission>,
434
GetPermissionMethod<Permission>
435
];
436
}
437
438
type PermissionHookReturnType<Permission extends PermissionResponse> = [
439
Permission | null,
440
RequestPermissionMethod<Permission>,
441
GetPermissionMethod<Permission>
442
];
443
```