backsplash-app
Version:
An AI powered wallpaper app.
99 lines (88 loc) • 3.55 kB
text/typescript
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 };
}