89 lines
3.3 KiB
TypeScript
89 lines
3.3 KiB
TypeScript
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 | (() => 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])
|
|
}
|