85 lines
1.9 KiB
JavaScript
85 lines
1.9 KiB
JavaScript
import { useEffect, useState } from "react";
|
|
import { LAST_POS_KEY } from "./mapConfig";
|
|
import { fetchIpLocation } from "../../api/client";
|
|
|
|
export function useUserPosition(mapRef, hasLastView) {
|
|
const [userPosition, setUserPosition] = useState(null); // [lng, lat]
|
|
|
|
useEffect(() => {
|
|
const map = mapRef.current;
|
|
if (!map) return;
|
|
|
|
let cancelled = false;
|
|
|
|
function saveUserPos(lat, lon) {
|
|
if (cancelled) return;
|
|
const coords = [lon, lat];
|
|
setUserPosition(coords);
|
|
try {
|
|
localStorage.setItem(LAST_POS_KEY, JSON.stringify({ lat, lon }));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
|
|
if (!hasLastView) {
|
|
map.flyTo({
|
|
center: coords,
|
|
zoom: 9,
|
|
speed: 1.2,
|
|
curve: 1.5,
|
|
essential: true,
|
|
});
|
|
}
|
|
}
|
|
|
|
// 1) dernière position user
|
|
try {
|
|
const raw = localStorage.getItem(LAST_POS_KEY);
|
|
if (raw) {
|
|
const p = JSON.parse(raw);
|
|
if (typeof p.lat === "number" && typeof p.lon === "number") {
|
|
setUserPosition([p.lon, p.lat]);
|
|
}
|
|
}
|
|
} catch {
|
|
// ignore
|
|
}
|
|
|
|
// 2) GPS → 3) IP backend
|
|
function viaIpFallback() {
|
|
(async () => {
|
|
const ipCoords = await fetchIpLocation();
|
|
if (!ipCoords || cancelled) return;
|
|
const [lon, lat] = ipCoords;
|
|
saveUserPos(lat, lon);
|
|
})();
|
|
}
|
|
|
|
if ("geolocation" in navigator) {
|
|
navigator.geolocation.getCurrentPosition(
|
|
(pos) => {
|
|
if (cancelled) return;
|
|
saveUserPos(pos.coords.latitude, pos.coords.longitude);
|
|
},
|
|
() => {
|
|
if (cancelled) return;
|
|
viaIpFallback();
|
|
},
|
|
{
|
|
enableHighAccuracy: true,
|
|
timeout: 8000,
|
|
maximumAge: 30000,
|
|
}
|
|
);
|
|
} else {
|
|
viaIpFallback();
|
|
}
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [mapRef, hasLastView]);
|
|
|
|
return userPosition;
|
|
}
|