import * as Location from 'expo-location' import * as TaskManager from 'expo-task-manager' import { Platform } from 'react-native' import { PlayerLocation, setLastLocation } from './features/location/locationSlice' import store from './store' import { useEffect } from 'react' import { socket } from './socket' import { useSettings } from '@/hooks/useGame' import { useAuth } from '@/hooks/useAuth' import { isAuthValid } from './features/auth/authSlice' const LOCATION_TASK = "TRAINTRAPE_MOI_GEOLOCATION" TaskManager.defineTask(LOCATION_TASK, async ({ data, error }: any) => { if (error) { console.error(error) return } const { locations } = data const lastLoc: Location.LocationObject = locations.at(-1) if (__DEV__) console.log("Localisation reçue :", lastLoc) store.dispatch(setLastLocation(lastLoc)) const playerId = store.getState().game.playerId if (socket.active && playerId) { const lastLocToSend: PlayerLocation = { playerId: playerId, longitude: lastLoc.coords.longitude, latitude: lastLoc.coords.latitude, speed: lastLoc.coords.speed ?? 0, accuracy: lastLoc.coords.accuracy ?? 0, altitude: lastLoc.coords.altitude ?? 0, altitudeAccuracy: lastLoc.coords.altitudeAccuracy ?? 0, timestamp: new Date(lastLoc.timestamp).toISOString(), } socket.emit('last-location', lastLocToSend) } }) export async function startGeolocationService(locationAccuracy: Location.Accuracy | null): Promise void)> { if (Platform.OS !== "web" && await Location.hasStartedLocationUpdatesAsync(LOCATION_TASK)) await Location.stopLocationUpdatesAsync(LOCATION_TASK) if (locationAccuracy === null) return await Location.enableNetworkProviderAsync().catch(error => alert(error)) const { status: foregroundStatus } = await Location.requestForegroundPermissionsAsync() if (foregroundStatus !== 'granted') alert("Vous devez activer votre géolocalisation pour utiliser l'application.") const { status: backgroundStatus } = await Location.requestBackgroundPermissionsAsync() if (backgroundStatus !== 'granted') alert("Vous devez activer votre géolocalisation en arrière-plan pour utiliser l'application.") if (Platform.OS !== "web") { await Location.startLocationUpdatesAsync(LOCATION_TASK, { accuracy: locationAccuracy, activityType: Location.ActivityType.OtherNavigation, distanceInterval: 10, timeInterval: 1000, foregroundService: { killServiceOnDestroy: false, notificationBody: "Géolocalisation activée pour « Traintrape-moi »", notificationTitle: "Traintrape-moi", notificationColor: "#FFFF00", } }) return async () => await Location.stopLocationUpdatesAsync(LOCATION_TASK) } else { const locationSubscription = await Location.watchPositionAsync({ accuracy: locationAccuracy }, location_nouveau => store.dispatch(setLastLocation(location_nouveau))) return locationSubscription.remove } } export const useStartGeolocationServiceEffect = () => { const auth = useAuth() const settings = useSettings() return useEffect(() => { if (!isAuthValid(auth)) return let cleanup: void | (() => void) = () => {} startGeolocationService(settings.locationAccuracy).then(result => cleanup = result) return cleanup }, [auth, settings.locationAccuracy]) }