UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

83 lines (70 loc) 3.29 kB
import { useCallback, useEffect, useRef, useState } from 'react'; import { PermissionResponse } from './PermissionsInterface'; // These types are identical, but improves the readability for suggestions in editors type RequestPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>; type GetPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>; interface PermissionHookMethods<Permission extends PermissionResponse, Options = never> { /** The permission method that requests the user to grant permission. */ requestMethod: (options?: Options) => Promise<Permission>; /** The permission method that only fetches the current permission status. */ getMethod: (options?: Options) => Promise<Permission>; } interface PermissionHookBehavior { /** If the hook should automatically fetch the current permission status, without asking the user. */ get?: boolean; /** If the hook should automatically request the user to grant permission. */ request?: boolean; } export type PermissionHookOptions<Options extends object> = PermissionHookBehavior & Options; /** * Get or request permission for protected functionality within the app. * It uses separate permission requesters to interact with a single permission. * By default, the hook will only retrieve the permission status. */ function usePermission<Permission extends PermissionResponse, Options extends object>( methods: PermissionHookMethods<Permission, Options>, options?: PermissionHookOptions<Options> ): [Permission | null, RequestPermissionMethod<Permission>, GetPermissionMethod<Permission>] { const isMounted = useRef(true); const [status, setStatus] = useState<Permission | null>(null); const { get = true, request = false, ...permissionOptions } = options || {}; const getPermission = useCallback(async () => { const response = await methods.getMethod( Object.keys(permissionOptions).length > 0 ? (permissionOptions as Options) : undefined ); if (isMounted.current) setStatus(response); return response; }, [methods.getMethod]); const requestPermission = useCallback(async () => { const response = await methods.requestMethod( Object.keys(permissionOptions).length > 0 ? (permissionOptions as Options) : undefined ); if (isMounted.current) setStatus(response); return response; }, [methods.requestMethod]); useEffect( function runMethods() { if (request) requestPermission(); if (!request && get) getPermission(); }, [get, request, requestPermission, getPermission] ); // Workaround for unmounting components receiving state updates useEffect(function didMount() { isMounted.current = true; return () => { isMounted.current = false; }; }, []); return [status, requestPermission, getPermission]; } /** * Create a new permission hook with the permission methods built-in. * This can be used to quickly create specific permission hooks in every module. */ export function createPermissionHook<Permission extends PermissionResponse, Options extends object>( methods: PermissionHookMethods<Permission, Options> ) { return (options?: PermissionHookOptions<Options>) => usePermission<Permission, Options>(methods, options); }