Stockage de la géolocalisation en arrière-plan et utilisation sur la carte

This commit is contained in:
2024-12-06 21:49:28 +01:00
parent 91963e378d
commit d08dcb9720
11 changed files with 257 additions and 97 deletions

View File

@ -0,0 +1,24 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { LocationObject } from 'expo-location'
interface LocationState {
location: LocationObject | null
}
const initialState: LocationState = {
location: null
}
export const locationSlice = createSlice({
name: 'location',
initialState: initialState,
reducers: {
setLocation: (state, action: PayloadAction<LocationObject>) => {
state.location = action.payload
},
},
})
export const { setLocation } = locationSlice.actions
export default locationSlice.reducer

View File

@ -0,0 +1,60 @@
import * as Location from 'expo-location'
import * as TaskManager from 'expo-task-manager'
import { Platform } from 'react-native'
import { setLocation } from './features/location/locationSlice'
import store from './store'
import { useEffect } from 'react'
const LOCATION_TASK = "fetch-geolocation"
TaskManager.defineTask(LOCATION_TASK, async ({ data, error }: any) => {
if (error) {
console.error(error)
return
}
const { locations } = data
store.dispatch(setLocation(locations.at(-1)))
for (let location of locations) {
// TODO Envoyer les positions au serveur
}
})
export async function startGeolocationService(): Promise<void | (() => void)> {
if (Platform.OS !== "web" && await Location.hasStartedLocationUpdatesAsync(LOCATION_TASK))
return async () => await Location.stopLocationUpdatesAsync(LOCATION_TASK)
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: Location.Accuracy.BestForNavigation,
activityType: Location.ActivityType.OtherNavigation,
deferredUpdatesInterval: 100,
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: Location.Accuracy.BestForNavigation}, location_nouveau => store.dispatch(setLocation(location_nouveau)))
return locationSubscription.remove
}
}
export const useStartGeolocationServiceEffect = () => useEffect(() => {
let cleanup: void | (() => void) = () => {}
startGeolocationService().then(result => cleanup = result)
return cleanup
}, [])

13
client/utils/store.ts Normal file
View File

@ -0,0 +1,13 @@
import { configureStore } from '@reduxjs/toolkit'
import locationReducer from './features/location/locationSlice'
const store = configureStore({
reducer: {
location: locationReducer,
},
})
export default store
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch