import * as Location from 'expo-location'; import { Linking, Alert, Platform } from 'react-native'; import { LocationData } from '../types'; export async function checkLocationServicesEnabled(): Promise { const enabled = await Location.hasServicesEnabledAsync(); return enabled; } export async function requestLocationPermission(): Promise { const { status } = await Location.requestForegroundPermissionsAsync(); return status === 'granted'; } export async function ensureLocationEnabled(): Promise<{ enabled: boolean; permission: boolean }> { const enabled = await checkLocationServicesEnabled(); if (!enabled) { return { enabled: false, permission: false }; } const permission = await requestLocationPermission(); return { enabled: true, permission }; } export async function promptEnableLocation(): Promise { Alert.alert( 'Location Required', 'GPS must be enabled to report issues. This ensures accurate location data and prevents fraudulent reports.', [ { text: 'Cancel', style: 'cancel' }, { text: 'Open Settings', onPress: () => { if (Platform.OS === 'ios') { Linking.openURL('app-settings:'); } else { Linking.openSettings(); } } }, ] ); } export async function getCurrentLocation( minAccuracy: number = 20, timeout: number = 30000 ): Promise { const startTime = Date.now(); while (Date.now() - startTime < timeout) { const location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.BestForNavigation, }); if (location.coords.accuracy !== null && location.coords.accuracy <= minAccuracy) { return { latitude: location.coords.latitude, longitude: location.coords.longitude, accuracy: location.coords.accuracy, heading: location.coords.heading ?? undefined, altitude: location.coords.altitude ?? undefined, }; } await new Promise((resolve) => setTimeout(resolve, 1000)); } const location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High, }); return { latitude: location.coords.latitude, longitude: location.coords.longitude, accuracy: location.coords.accuracy ?? 999, heading: location.coords.heading ?? undefined, altitude: location.coords.altitude ?? undefined, }; } export function isLocationAccurate(accuracy: number, threshold: number = 15): boolean { return accuracy <= threshold; } export async function watchLocationWithGpsCheck( onLocationUpdate: (location: LocationData) => void, onGpsStatusChange: (enabled: boolean) => void, accuracyThreshold: number = 15 ): Promise<() => void> { let subscription: Location.LocationSubscription | null = null; let gpsCheckInterval: ReturnType | null = null; const checkGpsAndStart = async () => { const enabled = await checkLocationServicesEnabled(); onGpsStatusChange(enabled); if (enabled && !subscription) { subscription = await Location.watchPositionAsync( { accuracy: Location.Accuracy.BestForNavigation, timeInterval: 1000, distanceInterval: 1, }, (newLocation) => { const accuracy = newLocation.coords.accuracy ?? 999; onLocationUpdate({ latitude: newLocation.coords.latitude, longitude: newLocation.coords.longitude, accuracy: accuracy, heading: newLocation.coords.heading ?? undefined, altitude: newLocation.coords.altitude ?? undefined, }); } ); } else if (!enabled && subscription) { subscription.remove(); subscription = null; } }; await checkGpsAndStart(); gpsCheckInterval = setInterval(async () => { const enabled = await checkLocationServicesEnabled(); onGpsStatusChange(enabled); if (!enabled && subscription) { subscription.remove(); subscription = null; } else if (enabled && !subscription) { await checkGpsAndStart(); } }, 3000); return () => { if (subscription) { subscription.remove(); } if (gpsCheckInterval) { clearInterval(gpsCheckInterval); } }; }