import { useCallback, useEffect, useState } from 'react'; import * as Location from 'expo-location'; import AsyncStorage from '@react-native-async-storage/async-storage'; export interface Coords { latitude: number; longitude: number; } const LAST_LOC_KEY = 'ps_last_location'; /** Persist the most recent fix so the "near my last location" button works cold. */ async function saveLastLocation(c: Coords) { await AsyncStorage.setItem(LAST_LOC_KEY, JSON.stringify(c)); } export async function getLastKnownSavedLocation(): Promise { const raw = await AsyncStorage.getItem(LAST_LOC_KEY); return raw ? (JSON.parse(raw) as Coords) : null; } /** * Foreground location. On GrapheneOS this uses the OS location provider directly * (no Google Play Services). We prefer a fast last-known fix, then refine. */ export function useLocation() { const [coords, setCoords] = useState(null); const [granted, setGranted] = useState(null); const [error, setError] = useState(null); const refresh = useCallback(async () => { try { const { status } = await Location.requestForegroundPermissionsAsync(); const ok = status === 'granted'; setGranted(ok); if (!ok) { setError('Location permission denied.'); return null; } const last = await Location.getLastKnownPositionAsync(); if (last) { const c = { latitude: last.coords.latitude, longitude: last.coords.longitude }; setCoords(c); void saveLastLocation(c); } const cur = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.Balanced, }); const c = { latitude: cur.coords.latitude, longitude: cur.coords.longitude }; setCoords(c); void saveLastLocation(c); return c; } catch (e: any) { setError(e?.message ?? 'Failed to get location.'); return null; } }, []); useEffect(() => { void refresh(); }, [refresh]); return { coords, granted, error, refresh }; }