UNPKG

backsplash-app

Version:
99 lines (88 loc) 3.55 kB
import { useState, useEffect, useCallback } from "react"; type GeolocationPermissionStatus = PermissionState | "checking" | "idle"; export function useLocationPermission() { const [permissionStatus, setPermissionStatus] = useState<GeolocationPermissionStatus>("idle"); const checkPermission = useCallback(async () => { if (!navigator.geolocation || !navigator.permissions) { console.warn("Geolocation or Permissions API not available."); setPermissionStatus("denied"); // Treat lack of API as denial return "denied"; } setPermissionStatus("checking"); try { const status = await navigator.permissions.query({ name: "geolocation" }); setPermissionStatus(status.state); return status.state; } catch (error) { console.error("Error checking geolocation permission:", error); setPermissionStatus("denied"); // Assume denied on error return "denied"; } }, []); const requestLocation = useCallback(async () => { const currentStatus = await checkPermission(); if (currentStatus === "granted") { console.log("Location permission already granted."); // Optionally trigger location fetch here if needed immediately return true; } if (currentStatus === "prompt") { return new Promise<boolean>((resolve) => { // Using getCurrentPosition to trigger the prompt navigator.geolocation.getCurrentPosition( () => { // Success callback (permission granted) setPermissionStatus("granted"); resolve(true); }, (error) => { // Error callback (permission denied or other error) console.warn("Geolocation permission denied or error:", error.message); // Check permission status again as the user might have explicitly denied checkPermission().then((status) => { // status will likely be 'denied' now setPermissionStatus(status); resolve(false); }); }, { enableHighAccuracy: false, timeout: 5000, maximumAge: 0 }, // Options can be adjusted ); }); } // If status is 'denied' or 'checking' or 'idle' (or anything else unexpected) console.log(`Cannot request location permission. Status: ${permissionStatus}`); return false; }, [checkPermission, permissionStatus]); // Effect to check permission status on mount useEffect(() => { checkPermission(); // Optional: Add listener for permission changes const checkAndSetStatus = async () => { if (navigator.permissions) { try { const status = await navigator.permissions.query({ name: "geolocation" }); setPermissionStatus(status.state); status.onchange = () => { setPermissionStatus(status.state); }; } catch (error) { console.error("Error setting up permission listener:", error); setPermissionStatus("denied"); } } }; checkAndSetStatus(); // Cleanup listener return () => { if (navigator.permissions) { navigator.permissions .query({ name: "geolocation" }) .then((status) => { status.onchange = null; }) .catch((err) => console.error("Error cleaning up permission listener:", err)); } }; }, [checkPermission]); // checkPermission dependency is stable due to useCallback return { permissionStatus, requestLocation, checkPermission }; }