1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
import type { LngLatLike } from "maplibre-gl";
import { useCallback, useState } from "react";
import { useMap } from "../contexts/MapContext";
export interface UseGeolocationResult {
userLocation: { latitude: number; longitude: number } | null;
hasLocationPermission: boolean;
isLoading: boolean;
requestLocation: () => void;
}
function lngLatToCoords(loc: LngLatLike): {
latitude: number;
longitude: number;
} {
if (Array.isArray(loc)) {
// This codebase stores location as [latitude, longitude] (not the standard
// MapLibre [lng, lat] GeoJSON order). See MapContext.tsx where arrays are
// set as [position.coords.latitude, position.coords.longitude], and AppMap.tsx
// where getLatitude(center) returns center[0].
return { latitude: loc[0], longitude: loc[1] };
}
if ("lat" in loc) {
return {
latitude: loc.lat,
longitude: "lng" in loc ? (loc as any).lng : (loc as any).lon,
};
}
return { latitude: 0, longitude: 0 };
}
/**
* Provides the current user location from the global MapContext.
* Location updates are driven by the MapContext's watchPosition subscription
* (started automatically when geolocation permission is granted).
*
* Call `requestLocation()` to prompt the user for permission and start tracking.
*/
export function useGeolocation(): UseGeolocationResult {
const { mapState, setUserLocation, setLocationPermission } = useMap();
const [isLoading, setIsLoading] = useState(false);
const requestLocation = useCallback(() => {
if (typeof window === "undefined" || !("geolocation" in navigator)) return;
setIsLoading(true);
navigator.geolocation.getCurrentPosition(
(pos) => {
setUserLocation([pos.coords.latitude, pos.coords.longitude]);
setLocationPermission(true);
setIsLoading(false);
},
() => {
setLocationPermission(false);
setIsLoading(false);
},
{ enableHighAccuracy: false, maximumAge: 60000, timeout: 10000 }
);
}, [setUserLocation, setLocationPermission]);
const rawLoc = mapState.userLocation;
const userLocation = rawLoc ? lngLatToCoords(rawLoc) : null;
return {
userLocation,
hasLocationPermission: mapState.hasLocationPermission,
isLoading,
requestLocation,
};
}
|