CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-unimodules--core

Deprecated compatibility wrapper that provides backward compatibility for applications migrating from legacy Unimodules infrastructure to Expo Modules API

Pending
Overview
Eval results
Files

permissions.mddocs/

Permission Management

Complete permission system with React hooks for managing app permissions, providing standardized interfaces for requesting and checking permission status across platforms.

Capabilities

PermissionStatus Enum

Standard permission status values used across all permission types.

/**
 * Standard permission status values
 */
enum PermissionStatus {
  GRANTED = 'granted',
  UNDETERMINED = 'undetermined',
  DENIED = 'denied'
}

PermissionResponse Interface

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;
  }
}

createPermissionHook Function

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 />;
}

Advanced Permission Hooks

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>
  );
}

Multiple Permission Management

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>
  );
}

Advanced Usage

Permission State Management

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>;

Custom Permission Types

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();
  }
});

Permission Flow Patterns

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>;

Types

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

docs

error-handling.md

event-management.md

index.md

native-modules.md

native-views.md

permissions.md

platform-utilities.md

utilities.md

tile.json