Deprecated compatibility wrapper that provides backward compatibility for applications migrating from legacy Unimodules infrastructure to Expo Modules API
—
Complete permission system with React hooks for managing app permissions, providing standardized interfaces for requesting and checking permission status across platforms.
Standard permission status values used across all permission types.
/**
* Standard permission status values
*/
enum PermissionStatus {
GRANTED = 'granted',
UNDETERMINED = 'undetermined',
DENIED = 'denied'
}Standard response format for all permission operations.
/**
* Standard permission response interface
*/
interface PermissionResponse {
/**
* Current permission status
*/
status: PermissionStatus;
/**
* When the permission expires ('never' for permanent permissions)
*/
expires: PermissionExpiration;
/**
* Whether permission is currently granted (convenience property)
*/
granted: boolean;
/**
* Whether the system will show permission dialog if requested
*/
canAskAgain: boolean;
}
type PermissionExpiration = 'never' | number;Usage Examples:
import { PermissionResponse, PermissionStatus } from "@unimodules/core";
// Check permission response
function handlePermissionResponse(response: PermissionResponse) {
console.log('Status:', response.status);
console.log('Granted:', response.granted);
console.log('Can ask again:', response.canAskAgain);
switch (response.status) {
case PermissionStatus.GRANTED:
console.log('Permission granted');
break;
case PermissionStatus.DENIED:
if (response.canAskAgain) {
console.log('Permission denied, but can ask again');
} else {
console.log('Permission permanently denied');
}
break;
case PermissionStatus.UNDETERMINED:
console.log('Permission not yet requested');
break;
}
}Factory function for creating permission-specific React hooks with built-in state management.
/**
* Create a permission hook with built-in methods
*/
function createPermissionHook<Permission extends PermissionResponse, Options extends object>(
methods: PermissionHookMethods<Permission, Options>
): (options?: PermissionHookOptions<Options>) => [
Permission | null, // Current permission status
() => Promise<Permission>, // Request permission function
() => Promise<Permission> // Get permission function
];
/**
* Methods required for permission hook
*/
interface PermissionHookMethods<Permission extends PermissionResponse, Options = never> {
/**
* Request permission from user
*/
requestMethod: (options?: Options) => Promise<Permission>;
/**
* Get current permission status without requesting
*/
getMethod: (options?: Options) => Promise<Permission>;
}
/**
* Options for permission hook behavior
*/
interface PermissionHookBehavior {
/**
* Automatically fetch permission status on mount
*/
get?: boolean;
/**
* Automatically request permission on mount
*/
request?: boolean;
}
type PermissionHookOptions<Options extends object> = PermissionHookBehavior & Options;Usage Examples:
import { createPermissionHook, PermissionResponse } from "@unimodules/core";
// Define custom permission interface
interface CameraPermission extends PermissionResponse {
accessPrivileges?: 'full' | 'limited';
}
// Create camera permission hook
const useCameraPermission = createPermissionHook<CameraPermission, {}>({
requestMethod: async () => {
const result = await NativeModulesProxy.Camera.requestPermissionsAsync();
return result;
},
getMethod: async () => {
const result = await NativeModulesProxy.Camera.getPermissionsAsync();
return result;
}
});
// Use in React component
function CameraComponent() {
// Hook returns [status, requestFn, getFn]
const [cameraPermission, requestCameraPermission, getCameraPermission] = useCameraPermission({
get: true, // Automatically get status on mount
request: false // Don't auto-request
});
const handleRequestPermission = async () => {
try {
const result = await requestCameraPermission();
if (result.granted) {
console.log('Camera permission granted');
} else {
console.log('Camera permission denied');
}
} catch (error) {
console.error('Failed to request permission:', error);
}
};
if (!cameraPermission) {
return <Text>Loading permission status...</Text>;
}
if (!cameraPermission.granted) {
return (
<View>
<Text>Camera permission required</Text>
<Button title="Grant Permission" onPress={handleRequestPermission} />
</View>
);
}
return <CameraView />;
}Create permission hooks with options and complex behaviors.
Usage Examples:
import { createPermissionHook, PermissionResponse } from "@unimodules/core";
// Location permission with options
interface LocationPermission extends PermissionResponse {
accuracy?: 'fine' | 'coarse';
}
interface LocationOptions {
accuracy?: 'fine' | 'coarse';
background?: boolean;
}
const useLocationPermission = createPermissionHook<LocationPermission, LocationOptions>({
requestMethod: async (options) => {
return await NativeModulesProxy.Location.requestPermissionsAsync(options);
},
getMethod: async (options) => {
return await NativeModulesProxy.Location.getPermissionsAsync(options);
}
});
// Usage with options
function LocationComponent() {
const [locationPermission, requestLocation] = useLocationPermission({
get: true,
accuracy: 'fine',
background: false
});
const requestBackgroundLocation = async () => {
await requestLocation({ accuracy: 'fine', background: true });
};
return (
<View>
<Text>Location: {locationPermission?.status}</Text>
<Button title="Request Background" onPress={requestBackgroundLocation} />
</View>
);
}Handle multiple permissions in a single component.
Usage Examples:
import { createPermissionHook } from "@unimodules/core";
// Create multiple permission hooks
const useCameraPermission = createPermissionHook(/* camera methods */);
const useMicrophonePermission = createPermissionHook(/* microphone methods */);
const useLocationPermission = createPermissionHook(/* location methods */);
function MultiPermissionComponent() {
const [cameraPermission, requestCamera] = useCameraPermission({ get: true });
const [micPermission, requestMic] = useMicrophonePermission({ get: true });
const [locationPermission, requestLocation] = useLocationPermission({ get: true });
const requestAllPermissions = async () => {
const results = await Promise.allSettled([
requestCamera(),
requestMic(),
requestLocation()
]);
results.forEach((result, index) => {
const permissionName = ['Camera', 'Microphone', 'Location'][index];
if (result.status === 'fulfilled' && result.value.granted) {
console.log(`${permissionName} permission granted`);
} else {
console.log(`${permissionName} permission failed`);
}
});
};
const allPermissionsGranted =
cameraPermission?.granted &&
micPermission?.granted &&
locationPermission?.granted;
return (
<View>
<Text>Camera: {cameraPermission?.status}</Text>
<Text>Microphone: {micPermission?.status}</Text>
<Text>Location: {locationPermission?.status}</Text>
{!allPermissionsGranted && (
<Button title="Request All Permissions" onPress={requestAllPermissions} />
)}
</View>
);
}import { createPermissionHook, PermissionResponse, PermissionStatus } from "@unimodules/core";
class PermissionManager {
private static permissionCache = new Map<string, PermissionResponse>();
static async checkPermission(key: string, getMethod: () => Promise<PermissionResponse>) {
const cached = this.permissionCache.get(key);
if (cached && Date.now() - cached.expires < 5 * 60 * 1000) { // 5 minute cache
return cached;
}
const permission = await getMethod();
this.permissionCache.set(key, permission);
return permission;
}
static async requestWithRationale(
requestMethod: () => Promise<PermissionResponse>,
rationale: string
): Promise<PermissionResponse> {
// Show rationale before requesting
const shouldRequest = await showPermissionRationale(rationale);
if (!shouldRequest) {
return {
status: PermissionStatus.DENIED,
expires: 'never',
granted: false,
canAskAgain: true
};
}
return await requestMethod();
}
}
// Declare this function elsewhere
declare function showPermissionRationale(message: string): Promise<boolean>;import { PermissionResponse, PermissionStatus, createPermissionHook } from "@unimodules/core";
// Custom permission for app-specific features
interface NotificationPermission extends PermissionResponse {
allowsAlert?: boolean;
allowsBadge?: boolean;
allowsSound?: boolean;
allowsCriticalAlerts?: boolean;
}
interface MediaLibraryPermission extends PermissionResponse {
accessPrivileges?: 'all' | 'limited' | 'none';
selectedAssets?: string[];
}
// Create hooks for custom permissions
const useNotificationPermission = createPermissionHook<NotificationPermission, {}>({
requestMethod: async () => {
const result = await NativeModulesProxy.Notifications.requestPermissionsAsync();
return result;
},
getMethod: async () => {
return await NativeModulesProxy.Notifications.getPermissionsAsync();
}
});
const useMediaLibraryPermission = createPermissionHook<MediaLibraryPermission, {}>({
requestMethod: async () => {
return await NativeModulesProxy.MediaLibrary.requestPermissionsAsync();
},
getMethod: async () => {
return await NativeModulesProxy.MediaLibrary.getPermissionsAsync();
}
});import { PermissionStatus } from "@unimodules/core";
class PermissionFlow {
static async requestWithFallback<T extends PermissionResponse>(
requestMethod: () => Promise<T>,
fallbackAction: () => void
): Promise<T | null> {
const result = await requestMethod();
if (result.status === PermissionStatus.DENIED && !result.canAskAgain) {
// Permission permanently denied, show settings prompt
const shouldOpenSettings = await showSettingsPrompt();
if (shouldOpenSettings) {
await openAppSettings();
} else {
fallbackAction();
}
return null;
}
return result;
}
static async ensurePermission<T extends PermissionResponse>(
getMethod: () => Promise<T>,
requestMethod: () => Promise<T>
): Promise<T> {
let permission = await getMethod();
if (permission.status === PermissionStatus.UNDETERMINED) {
permission = await requestMethod();
}
return permission;
}
}
// Declare these functions elsewhere
declare function showSettingsPrompt(): Promise<boolean>;
declare function openAppSettings(): Promise<void>;type RequestPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;
type GetPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;
interface PermissionHook<Permission extends PermissionResponse> {
(options?: PermissionHookOptions<any>): [
Permission | null,
RequestPermissionMethod<Permission>,
GetPermissionMethod<Permission>
];
}
type PermissionHookReturnType<Permission extends PermissionResponse> = [
Permission | null,
RequestPermissionMethod<Permission>,
GetPermissionMethod<Permission>
];Install with Tessl CLI
npx tessl i tessl/npm-unimodules--core