Affichage des dernières positions sur la carte
This commit is contained in:
		| @@ -6,6 +6,7 @@ import { FAB, Surface, Text } from 'react-native-paper' | |||||||
| import { useGame } from '@/hooks/useGame' | import { useGame } from '@/hooks/useGame' | ||||||
| import { FontAwesome6 } from '@expo/vector-icons' | import { FontAwesome6 } from '@expo/vector-icons' | ||||||
| import FreeChaseBanner from '@/components/FreeChaseBanner' | import FreeChaseBanner from '@/components/FreeChaseBanner' | ||||||
|  | import { View } from 'react-native' | ||||||
|  |  | ||||||
| export default function MapScreen() { | export default function MapScreen() { | ||||||
|   const [backgroundStatus, requestBackgroundPermission] = useBackgroundPermissions() |   const [backgroundStatus, requestBackgroundPermission] = useBackgroundPermissions() | ||||||
| @@ -16,6 +17,7 @@ export default function MapScreen() { | |||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Surface style={styles.page}> |     <Surface style={styles.page}> | ||||||
|  |       <View style={styles.container}> | ||||||
|         {backgroundStatus?.granted ? <Map /> : <Text>La géolocalisation est requise pour utiliser la carte.</Text>} |         {backgroundStatus?.granted ? <Map /> : <Text>La géolocalisation est requise pour utiliser la carte.</Text>} | ||||||
|         <FAB |         <FAB | ||||||
|             style={styles.moneyBadge} |             style={styles.moneyBadge} | ||||||
| @@ -30,6 +32,7 @@ export default function MapScreen() { | |||||||
|             color='black' |             color='black' | ||||||
|             icon={game.currentRunner ? 'run-fast' : () => <FontAwesome6 name='cat' size={20} />} |             icon={game.currentRunner ? 'run-fast' : () => <FontAwesome6 name='cat' size={20} />} | ||||||
|             label={game.currentRunner ? "Coureuse" : "Poursuiveuse"} /> |             label={game.currentRunner ? "Coureuse" : "Poursuiveuse"} /> | ||||||
|  |       </View> | ||||||
|       <FreeChaseBanner /> |       <FreeChaseBanner /> | ||||||
|     </Surface> |     </Surface> | ||||||
|   ) |   ) | ||||||
| @@ -39,6 +42,11 @@ const styles = StyleSheet.create({ | |||||||
|   page: { |   page: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|   }, |   }, | ||||||
|  |   container: { | ||||||
|  |     flexGrow: 1, | ||||||
|  |     alignItems: 'center', | ||||||
|  |     justifyContent: 'center', | ||||||
|  |   }, | ||||||
|   map: { |   map: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|     alignSelf: 'stretch', |     alignSelf: 'stretch', | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| import { ReactNode, useEffect } from 'react' | import { ReactNode, useEffect } from 'react' | ||||||
| import { useAuth } from '@/hooks/useAuth' | import { useAuth } from '@/hooks/useAuth' | ||||||
| import { useQueuedLocations, useUnqueueLocation } from '@/hooks/useLocation' | import { useQueuedLocations, useSetLastPlayerLocations, useUnqueueLocation } from '@/hooks/useLocation' | ||||||
| import { useGeolocationMutation } from '@/hooks/mutations/useGeolocationMutation' | import { useGeolocationMutation } from '@/hooks/mutations/useGeolocationMutation' | ||||||
| import { useStartGeolocationServiceEffect } from '@/utils/geolocation' | import { useStartGeolocationServiceEffect } from '@/utils/geolocation' | ||||||
| import { Platform } from 'react-native' | import { Platform } from 'react-native' | ||||||
|  | import { useQuery } from '@tanstack/react-query' | ||||||
|  |  | ||||||
| export default function GeolocationProvider({ children }: { children: ReactNode }) { | export default function GeolocationProvider({ children }: { children: ReactNode }) { | ||||||
|   useStartGeolocationServiceEffect() |   useStartGeolocationServiceEffect() | ||||||
| @@ -11,6 +12,7 @@ export default function GeolocationProvider({ children }: { children: ReactNode | |||||||
|   const auth = useAuth() |   const auth = useAuth() | ||||||
|   const geolocationsQueue = useQueuedLocations() |   const geolocationsQueue = useQueuedLocations() | ||||||
|   const unqueueLocation = useUnqueueLocation() |   const unqueueLocation = useUnqueueLocation() | ||||||
|  |   const setLastPlayerLocations = useSetLastPlayerLocations() | ||||||
|   const geolocationMutation = useGeolocationMutation({ |   const geolocationMutation = useGeolocationMutation({ | ||||||
|     auth, |     auth, | ||||||
|     onPostSuccess: (data) => { |     onPostSuccess: (data) => { | ||||||
| @@ -27,6 +29,22 @@ export default function GeolocationProvider({ children }: { children: ReactNode | |||||||
|     geolocationMutation.mutate(locToSend) |     geolocationMutation.mutate(locToSend) | ||||||
|   }, [auth, geolocationsQueue]) |   }, [auth, geolocationsQueue]) | ||||||
|  |  | ||||||
|  |   const lastLocationsQuery = useQuery({ | ||||||
|  |     queryKey: ['get-last-locations', auth.token], | ||||||
|  |     queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/geolocations/last-locations/`, { | ||||||
|  |       method: "GET", | ||||||
|  |       headers: { | ||||||
|  |         "Authorization": `Bearer ${auth.token}`, | ||||||
|  |         "Content-Type": "application/json", | ||||||
|  |       }} | ||||||
|  |     ).then(resp => resp.json()), | ||||||
|  |     refetchInterval: 5000, | ||||||
|  |   }) | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (lastLocationsQuery.isSuccess && lastLocationsQuery.data) | ||||||
|  |       setLastPlayerLocations(lastLocationsQuery.data) | ||||||
|  |   }, [lastLocationsQuery.status, lastLocationsQuery.dataUpdatedAt]) | ||||||
|  |  | ||||||
|   return <> |   return <> | ||||||
|     {children} |     {children} | ||||||
|   </> |   </> | ||||||
|   | |||||||
| @@ -2,12 +2,14 @@ import { StyleSheet } from 'react-native' | |||||||
| import MapLibreGL, { Camera, FillLayer, LineLayer, MapView, PointAnnotation, RasterLayer, RasterSource, ShapeSource, UserLocation } from '@maplibre/maplibre-react-native' | import MapLibreGL, { Camera, FillLayer, LineLayer, MapView, PointAnnotation, RasterLayer, RasterSource, ShapeSource, UserLocation } from '@maplibre/maplibre-react-native' | ||||||
| import { FontAwesome5 } from '@expo/vector-icons' | import { FontAwesome5 } from '@expo/vector-icons' | ||||||
| import { circle } from '@turf/circle' | import { circle } from '@turf/circle' | ||||||
| import { useLastOwnLocation } from '@/hooks/useLocation' | import { useLastOwnLocation, useLastPlayerLocations } from '@/hooks/useLocation' | ||||||
|  | import { useMemo } from 'react' | ||||||
|  | import { PlayerLocation } from '@/utils/features/location/locationSlice' | ||||||
|  | import { useGame } from '@/hooks/useGame' | ||||||
|  |  | ||||||
| export default function Map() { | export default function Map() { | ||||||
|   const userLocation = useLastOwnLocation() |   const userLocation = useLastOwnLocation() | ||||||
|   MapLibreGL.setAccessToken(null) |   MapLibreGL.setAccessToken(null) | ||||||
|   const accuracyCircle = circle([userLocation?.coords.longitude ?? 0, userLocation?.coords.latitude ?? 0], userLocation?.coords.accuracy ?? 0, {steps: 64, units: 'meters'}) |  | ||||||
|   return ( |   return ( | ||||||
|     <MapView |     <MapView | ||||||
|       logoEnabled={false} |       logoEnabled={false} | ||||||
| @@ -16,21 +18,48 @@ export default function Map() { | |||||||
|       {/* FIXME Il faudra pouvoir avoir un bouton de suivi pour activer le suivi de la caméro */} |       {/* FIXME Il faudra pouvoir avoir un bouton de suivi pour activer le suivi de la caméro */} | ||||||
|       {userLocation && <Camera |       {userLocation && <Camera | ||||||
|           defaultSettings={{centerCoordinate: [userLocation?.coords.longitude, userLocation?.coords.latitude], zoomLevel: 15}} />} |           defaultSettings={{centerCoordinate: [userLocation?.coords.longitude, userLocation?.coords.latitude], zoomLevel: 15}} />} | ||||||
|  |        | ||||||
|       <RasterSource id="railwaymap-source" tileUrlTemplates={["https://a.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png"]}></RasterSource> |       <RasterSource id="railwaymap-source" tileUrlTemplates={["https://a.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png"]}></RasterSource> | ||||||
|       <RasterLayer id="railwaymap-layer" sourceID="railwaymap-source" style={{rasterOpacity: 0.7}} /> |       <RasterLayer id="railwaymap-layer" sourceID="railwaymap-source" style={{rasterOpacity: 0.7}} /> | ||||||
|  |  | ||||||
|       {/* FIXME Il faudra avoir uniquement les positions des autres personnes, puisque sa propre position peut être obtenue nativement */} |       <UserLocation animated={true} renderMode="native" androidRenderMode="compass" showsUserHeadingIndicator={true} /> | ||||||
|       <ShapeSource id="accuracy-radius" shape={accuracyCircle} /> |       <PlayerLocationsMarkers /> | ||||||
|       <FillLayer id="accuracy-radius-fill" sourceID="accuracy-radius" style={{fillOpacity: 0.4, fillColor: 'lightblue'}} aboveLayerID="railwaymap-layer" /> |  | ||||||
|       <LineLayer id="accuracy-radius-border" sourceID="accuracy-radius" style={{lineOpacity: 0.4, lineColor: 'blue'}} aboveLayerID="accuracy-radius-fill" /> |  | ||||||
|       <PointAnnotation id="current-location" coordinate={[userLocation?.coords.longitude ?? 2.9, userLocation?.coords.latitude ?? 46.5]}> |  | ||||||
|         <FontAwesome5 name="map-marker-alt" size={24} color="blue" /> |  | ||||||
|       </PointAnnotation> |  | ||||||
|       {/* <UserLocation animated={true} renderMode="native" androidRenderMode="compass" showsUserHeadingIndicator={true} /> */} |  | ||||||
|     </MapView> |     </MapView> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function PlayerLocationsMarkers() { | ||||||
|  |   const game = useGame() | ||||||
|  |   const lastPlayerLocations = useLastPlayerLocations() | ||||||
|  |   return lastPlayerLocations | ||||||
|  |     .filter(playerLoc => playerLoc.playerId !== game.playerId) | ||||||
|  |     .map(playerLoc => <PlayerLocationMarker key={`player-${playerLoc.playerId}-loc`} playerLocation={playerLoc} />) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function PlayerLocationMarker({ playerLocation }: { playerLocation: PlayerLocation }) { | ||||||
|  |   const accuracyCircle = useMemo(() => circle([playerLocation.longitude, playerLocation.latitude], playerLocation.accuracy, {steps: 64, units: 'meters'}), [playerLocation]) | ||||||
|  |   return <> | ||||||
|  |     <ShapeSource | ||||||
|  |         id={`accuracy-radius-${playerLocation.playerId}`} | ||||||
|  |         shape={accuracyCircle} /> | ||||||
|  |     <FillLayer | ||||||
|  |         id={`accuracy-radius-fill-${playerLocation.playerId}`} | ||||||
|  |         sourceID={`accuracy-radius-${playerLocation.playerId}`} | ||||||
|  |         style={{fillOpacity: 0.4, fillColor: 'pink'}} | ||||||
|  |         aboveLayerID="railwaymap-layer" /> | ||||||
|  |     <LineLayer | ||||||
|  |         id={`accuracy-radius-border-${playerLocation.playerId}`} | ||||||
|  |         sourceID={`accuracy-radius-${playerLocation.playerId}`} | ||||||
|  |         style={{lineOpacity: 0.4, lineColor: 'red'}} | ||||||
|  |         aboveLayerID={`accuracy-radius-fill-${playerLocation.playerId}`} /> | ||||||
|  |     <PointAnnotation id={`player-location-marker-${playerLocation.playerId}`} | ||||||
|  |         coordinate={[playerLocation.longitude, playerLocation.latitude]}> | ||||||
|  |       <FontAwesome5 name="map-marker-alt" size={24} color="red" /> | ||||||
|  |     </PointAnnotation> | ||||||
|  |   </> | ||||||
|  | } | ||||||
|  |  | ||||||
| const styles = StyleSheet.create({ | const styles = StyleSheet.create({ | ||||||
|   map: { |   map: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| import { useAuth } from "@/hooks/useAuth" | import { useGame } from "@/hooks/useGame" | ||||||
| import { useLastOwnLocation } from "@/hooks/useLocation" | import { useLastOwnLocation, useLastPlayerLocations } from "@/hooks/useLocation" | ||||||
| import { useQuery } from "@tanstack/react-query" | import { PlayerLocation } from "@/utils/features/location/locationSlice" | ||||||
| import { circle } from "@turf/circle" | import { circle } from "@turf/circle" | ||||||
| import { type Map as MaplibreGLMap } from "maplibre-gl" | import { type Map as MaplibreGLMap } from "maplibre-gl" | ||||||
| import { RLayer, RMap, RMarker, RNavigationControl, RSource, useMap } from "maplibre-react-components" | import { RLayer, RMap, RMarker, RNavigationControl, RSource, useMap } from "maplibre-react-components" | ||||||
| import { useEffect, useMemo, useState } from "react" | import { useMemo, useState } from "react" | ||||||
|  |  | ||||||
| export default function Map() { | export default function Map() { | ||||||
|   return ( |   return ( | ||||||
| @@ -18,7 +18,7 @@ export default function Map() { | |||||||
|       <RLayer id="railwaymap-layer" type="raster" source="railwaymap-source" paint={{"raster-opacity": 0.7}} /> |       <RLayer id="railwaymap-layer" type="raster" source="railwaymap-source" paint={{"raster-opacity": 0.7}} /> | ||||||
|  |  | ||||||
|       <UserLocation /> |       <UserLocation /> | ||||||
|       <DownloadedLocation /> |       <PlayerLocationsMarkers /> | ||||||
|     </RMap> |     </RMap> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
| @@ -34,43 +34,44 @@ function UserLocation() { | |||||||
|   const accuracyCircle = circle([userLocation?.coords.longitude ?? 0, userLocation?.coords.latitude ?? 0], userLocation?.coords.accuracy ?? 0, {steps: 64, units: 'meters'}) |   const accuracyCircle = circle([userLocation?.coords.longitude ?? 0, userLocation?.coords.latitude ?? 0], userLocation?.coords.accuracy ?? 0, {steps: 64, units: 'meters'}) | ||||||
|   const marker = userLocation ? <RMarker longitude={userLocation?.coords.longitude} latitude={userLocation?.coords.latitude} /> : <></> |   const marker = userLocation ? <RMarker longitude={userLocation?.coords.longitude} latitude={userLocation?.coords.latitude} /> : <></> | ||||||
|   return <> |   return <> | ||||||
|     <RSource id="accuracy-radius" type="geojson" data={accuracyCircle} /> |     <RSource id={'accuracy-radius-own'} type="geojson" data={accuracyCircle} /> | ||||||
|     <RLayer id="accuracy-radius-fill" type="fill" source="accuracy-radius" paint={{"fill-color": "lightblue", "fill-opacity": 0.4}} /> |     <RLayer id={'accuracy-radius-fill-own'} type="fill" source='accuracy-radius-own' paint={{"fill-color": "lightblue", "fill-opacity": 0.4}} /> | ||||||
|     <RLayer id="accuracy-radius-border" type="line" source="accuracy-radius" paint={{"line-color": "blue", "line-opacity": 0.4}} /> |     <RLayer id={'accuracy-radius-border'} type="line" source='accuracy-radius-own' paint={{"line-color": "blue", "line-opacity": 0.4}} /> | ||||||
|     {marker} |     {marker} | ||||||
|   </> |   </> | ||||||
| } | } | ||||||
|  |  | ||||||
| function DownloadedLocation() { | function PlayerLocationsMarkers() { | ||||||
|   const auth = useAuth() |   const game = useGame() | ||||||
|   const query = useQuery({ |   const lastPlayerLocations = useLastPlayerLocations() | ||||||
|     queryKey: ['get-last-locations'], |   return lastPlayerLocations | ||||||
|     queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/geolocations/last-locations/`, { |     // .filter(playerLoc => playerLoc.playerId !== game.playerId) | ||||||
|       method: "GET", |     .map(playerLoc => <PlayerLocationMarker key={`player-${playerLoc.playerId}-loc`} playerLocation={playerLoc} />) | ||||||
|       headers: { |  | ||||||
|         "Authorization": `Bearer ${auth.token}`, |  | ||||||
|         "Content-Type": "application/json", |  | ||||||
|       }} |  | ||||||
|     ).then(resp => resp.json()), |  | ||||||
|   }) |  | ||||||
|   useEffect(() => { |  | ||||||
|     const interval = setInterval(() => query.refetch(), 5000) |  | ||||||
|     return () => clearInterval(interval) |  | ||||||
|   }, []) |  | ||||||
|   console.log(query.data) |  | ||||||
|   const userLocation = query.isSuccess ? query.data[0] : { longitude: 0, latitude: 0, accuracy: 0 } |  | ||||||
|   const [firstUserPositionFetched, setFirstUserPositionFetched] = useState(false) |  | ||||||
|   const map: MaplibreGLMap = useMap() |  | ||||||
|   if (userLocation != null && !firstUserPositionFetched) { |  | ||||||
|     setFirstUserPositionFetched(true) |  | ||||||
|     map.flyTo({center: [userLocation.longitude, userLocation.latitude], zoom: 15}) |  | ||||||
| } | } | ||||||
|   const accuracyCircle = useMemo(() => circle([userLocation?.longitude ?? 0, userLocation?.latitude ?? 0], userLocation?.accuracy ?? 0, {steps: 64, units: 'meters'}), [userLocation]) |  | ||||||
|   const marker = userLocation ? <RMarker longitude={userLocation?.longitude} latitude={userLocation?.latitude} /> : <></> | function PlayerLocationMarker({ playerLocation }: { playerLocation: PlayerLocation }) { | ||||||
|  |   const map: MaplibreGLMap = useMap() | ||||||
|  |   const accuracyCircle = useMemo(() => circle( | ||||||
|  |     [playerLocation.longitude, playerLocation.latitude], | ||||||
|  |     playerLocation.accuracy, | ||||||
|  |     {steps: 64, units: 'meters'}), [playerLocation]) | ||||||
|   return <> |   return <> | ||||||
|     <RSource id="accuracy-radius-2" type="geojson" data={accuracyCircle} /> |     <RSource | ||||||
|     <RLayer id="accuracy-radius-fill-2" type="fill" source="accuracy-radius-2" paint={{"fill-color": "pink", "fill-opacity": 0.4}} /> |         id={`accuracy-radius-${playerLocation.playerId}`} | ||||||
|     <RLayer id="accuracy-radius-border-2" type="line" source="accuracy-radius-2" paint={{"line-color": "red", "line-opacity": 0.4}} /> |         type="geojson" | ||||||
|     {marker} |         data={accuracyCircle} /> | ||||||
|  |     <RLayer | ||||||
|  |         id={`accuracy-radius-fill-${playerLocation.playerId}`} | ||||||
|  |         type="fill" source={`accuracy-radius-${playerLocation.playerId}`} | ||||||
|  |         paint={{"fill-color": "pink", "fill-opacity": 0.4}} /> | ||||||
|  |     <RLayer | ||||||
|  |         id={`accuracy-radius-border-${playerLocation.playerId}`} | ||||||
|  |         type="line" | ||||||
|  |         source={`accuracy-radius-${playerLocation.playerId}`} | ||||||
|  |         paint={{"line-color": "red", "line-opacity": 0.4}} /> | ||||||
|  |     <RMarker | ||||||
|  |         key={`marker-player-${playerLocation.playerId}`} | ||||||
|  |         longitude={playerLocation.longitude} | ||||||
|  |         latitude={playerLocation.latitude} /> | ||||||
|   </> |   </> | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| import { LocationObject } from "expo-location" | import { LocationObject } from "expo-location" | ||||||
| import { useAppDispatch, useAppSelector } from "./useStore" | import { useAppDispatch, useAppSelector } from "./useStore" | ||||||
| import { setLastLocation, unqueueLocation } from "@/utils/features/location/locationSlice" | import { PlayerLocation, setLastLocation, setLastPlayerLocations, unqueueLocation } from "@/utils/features/location/locationSlice" | ||||||
|  |  | ||||||
| export const useLastOwnLocation = () => useAppSelector((state) => state.location.lastOwnLocation) | export const useLastOwnLocation = () => useAppSelector((state) => state.location.lastOwnLocation) | ||||||
| export const useQueuedLocations = () => useAppSelector((state) => state.location.queuedLocations) | export const useQueuedLocations = () => useAppSelector((state) => state.location.queuedLocations) | ||||||
|  | export const useLastPlayerLocations = () => useAppSelector((state) => state.location.lastPlayerLocations) | ||||||
|  |  | ||||||
| export const useSetLastLocation = () => { | export const useSetLastLocation = () => { | ||||||
|     const dispatch = useAppDispatch() |     const dispatch = useAppDispatch() | ||||||
| @@ -13,3 +14,7 @@ export const useUnqueueLocation = () => { | |||||||
|     const dispatch = useAppDispatch() |     const dispatch = useAppDispatch() | ||||||
|     return (location: LocationObject) => dispatch(unqueueLocation(location)) |     return (location: LocationObject) => dispatch(unqueueLocation(location)) | ||||||
| } | } | ||||||
|  | export const useSetLastPlayerLocations = () => { | ||||||
|  |     const dispatch = useAppDispatch() | ||||||
|  |     return (playerLocations: PlayerLocation[]) => dispatch(setLastPlayerLocations(playerLocations)) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -2,16 +2,30 @@ import { Constants } from '@/constants/Constants' | |||||||
| import { createSlice, PayloadAction } from '@reduxjs/toolkit' | import { createSlice, PayloadAction } from '@reduxjs/toolkit' | ||||||
| import { LocationObject } from 'expo-location' | import { LocationObject } from 'expo-location' | ||||||
|  |  | ||||||
|  | export type PlayerLocation = { | ||||||
|  |   id: number | ||||||
|  |   playerId: number | ||||||
|  |   longitude: number | ||||||
|  |   latitude: number | ||||||
|  |   speed: number | ||||||
|  |   accuracy: number | ||||||
|  |   altitude: number | ||||||
|  |   altitudeAccuracy: number | ||||||
|  |   timestamp: string | ||||||
|  | } | ||||||
|  |  | ||||||
| interface LocationState { | interface LocationState { | ||||||
|   lastOwnLocation: LocationObject | null |   lastOwnLocation: LocationObject | null | ||||||
|   lastSentLocation: LocationObject | null |   lastSentLocation: LocationObject | null | ||||||
|   queuedLocations: LocationObject[] |   queuedLocations: LocationObject[] | ||||||
|  |   lastPlayerLocations: PlayerLocation[] | ||||||
| } | } | ||||||
|  |  | ||||||
| const initialState: LocationState = { | const initialState: LocationState = { | ||||||
|   lastOwnLocation: null, |   lastOwnLocation: null, | ||||||
|   lastSentLocation: null, |   lastSentLocation: null, | ||||||
|   queuedLocations: [] |   queuedLocations: [], | ||||||
|  |   lastPlayerLocations: [] | ||||||
| } | } | ||||||
|  |  | ||||||
| export const locationSlice = createSlice({ | export const locationSlice = createSlice({ | ||||||
| @@ -33,9 +47,12 @@ export const locationSlice = createSlice({ | |||||||
|           || loc.coords.latitude !== sentLoc.coords.latitude |           || loc.coords.latitude !== sentLoc.coords.latitude | ||||||
|           || loc.coords.longitude !== sentLoc.coords.latitude) |           || loc.coords.longitude !== sentLoc.coords.latitude) | ||||||
|     }, |     }, | ||||||
|  |     setLastPlayerLocations: (state, action: PayloadAction<PlayerLocation[]>) => { | ||||||
|  |       state.lastPlayerLocations = action.payload | ||||||
|  |     } | ||||||
|   }, |   }, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| export const { setLastLocation, unqueueLocation } = locationSlice.actions | export const { setLastLocation, unqueueLocation, setLastPlayerLocations } = locationSlice.actions | ||||||
|  |  | ||||||
| export default locationSlice.reducer | export default locationSlice.reducer | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user