54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
import * as Location from "expo-location";
|
|
import { Linking } from "react-native";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
|
|
export type LocationPermissionStatus =
|
|
/** Permission granted. */
|
|
| "granted"
|
|
/** The user denied but we can still ask again. */
|
|
| "denied"
|
|
/** The user denied permanently ("Don't ask again") — must go to Settings. */
|
|
| "blocked"
|
|
/** First read hasn't completed. */
|
|
| "unknown";
|
|
|
|
/**
|
|
* Reports the foreground location permission as it is right now, so the
|
|
* Settings screen can show the real state without re-running the request
|
|
* prompt. Call `refresh()` again on focus (e.g. with `useFocusEffect`) so the
|
|
* row updates when the user comes back from the system settings screen.
|
|
*/
|
|
export const useLocationPermission = () => {
|
|
const [status, setStatus] = useState<LocationPermissionStatus>("unknown");
|
|
|
|
const refresh = useCallback(async () => {
|
|
try {
|
|
const result = await Location.getForegroundPermissionsAsync();
|
|
|
|
if (result.granted) {
|
|
setStatus("granted");
|
|
} else if (result.canAskAgain) {
|
|
setStatus("denied");
|
|
} else {
|
|
setStatus("blocked");
|
|
}
|
|
} catch (error) {
|
|
console.warn("[LOCATION_PERMISSION]: ", error);
|
|
setStatus("unknown");
|
|
}
|
|
}, []);
|
|
|
|
const openSettings = useCallback(async () => {
|
|
try {
|
|
await Linking.openSettings();
|
|
} catch (error) {
|
|
console.warn("[OPEN_SETTINGS]: ", error);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
void refresh();
|
|
}, [refresh]);
|
|
|
|
return { status, refresh, openSettings };
|
|
}; |