fix: Add fallback to low-accuracy geolocation when GPS times out
- After 2 consecutive timeouts with high accuracy mode, automatically switch to low accuracy mode (WiFi/cell-based location) - Increased maxAge from 5s to 30s to accept older cached positions - Reduced timeout from 30s to 15s for faster fallback - Low accuracy mode uses 60s maxAge and 60s timeout for reliability This helps indoor users who can't get GPS signal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2284f94ee3
commit
007a7e877f
|
|
@ -38,8 +38,8 @@ export function useLocationSharing(
|
||||||
onLocationUpdate,
|
onLocationUpdate,
|
||||||
updateInterval = 5000,
|
updateInterval = 5000,
|
||||||
highAccuracy = true,
|
highAccuracy = true,
|
||||||
maxAge = 5000, // Allow cached position up to 5 seconds old
|
maxAge = 30000, // Allow cached position up to 30 seconds old
|
||||||
timeout = 30000,
|
timeout = 15000, // 15 second timeout before fallback
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const [isSharing, setIsSharing] = useState(false);
|
const [isSharing, setIsSharing] = useState(false);
|
||||||
|
|
@ -49,6 +49,8 @@ export function useLocationSharing(
|
||||||
|
|
||||||
const watchIdRef = useRef<number | null>(null);
|
const watchIdRef = useRef<number | null>(null);
|
||||||
const onLocationUpdateRef = useRef(onLocationUpdate);
|
const onLocationUpdateRef = useRef(onLocationUpdate);
|
||||||
|
const timeoutCountRef = useRef(0);
|
||||||
|
const usingLowAccuracyRef = useRef(false);
|
||||||
|
|
||||||
// Keep callback ref updated
|
// Keep callback ref updated
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -73,6 +75,9 @@ export function useLocationSharing(
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handlePosition = useCallback((position: GeolocationPosition) => {
|
const handlePosition = useCallback((position: GeolocationPosition) => {
|
||||||
|
// Reset timeout counter on successful position
|
||||||
|
timeoutCountRef.current = 0;
|
||||||
|
|
||||||
const location: ParticipantLocation = {
|
const location: ParticipantLocation = {
|
||||||
latitude: position.coords.latitude,
|
latitude: position.coords.latitude,
|
||||||
longitude: position.coords.longitude,
|
longitude: position.coords.longitude,
|
||||||
|
|
@ -90,12 +95,50 @@ export function useLocationSharing(
|
||||||
onLocationUpdateRef.current?.(location);
|
onLocationUpdateRef.current?.(location);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Restart watcher with low accuracy mode
|
||||||
|
const restartWithLowAccuracy = useCallback(() => {
|
||||||
|
if (watchIdRef.current !== null) {
|
||||||
|
navigator.geolocation.clearWatch(watchIdRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Switching to low accuracy mode for faster location');
|
||||||
|
usingLowAccuracyRef.current = true;
|
||||||
|
|
||||||
|
const geoOptions: PositionOptions = {
|
||||||
|
enableHighAccuracy: false,
|
||||||
|
maximumAge: 60000, // Accept positions up to 1 minute old
|
||||||
|
timeout: 60000, // Longer timeout for low accuracy
|
||||||
|
};
|
||||||
|
|
||||||
|
watchIdRef.current = navigator.geolocation.watchPosition(
|
||||||
|
handlePosition,
|
||||||
|
(err) => {
|
||||||
|
setError(err);
|
||||||
|
console.warn('Geolocation warning (low accuracy):', err.message, '(code:', err.code, ')');
|
||||||
|
},
|
||||||
|
geoOptions
|
||||||
|
);
|
||||||
|
}, [handlePosition]);
|
||||||
|
|
||||||
const handleError = useCallback((err: GeolocationPositionError) => {
|
const handleError = useCallback((err: GeolocationPositionError) => {
|
||||||
setError(err);
|
setError(err);
|
||||||
|
|
||||||
|
// Count consecutive timeouts
|
||||||
|
if (err.code === 3) { // TIMEOUT
|
||||||
|
timeoutCountRef.current++;
|
||||||
|
console.warn('Geolocation timeout', timeoutCountRef.current, '/', 3);
|
||||||
|
|
||||||
|
// After 2 timeouts, switch to low accuracy mode
|
||||||
|
if (timeoutCountRef.current >= 2 && !usingLowAccuracyRef.current && highAccuracy) {
|
||||||
|
restartWithLowAccuracy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only log as warning, not error - timeouts are common indoors
|
// Only log as warning, not error - timeouts are common indoors
|
||||||
console.warn('Geolocation warning:', err.message, '(code:', err.code, ')');
|
console.warn('Geolocation warning:', err.message, '(code:', err.code, ')');
|
||||||
// Don't stop sharing on errors - keep trying
|
// Don't stop sharing on errors - keep trying
|
||||||
}, []);
|
}, [highAccuracy, restartWithLowAccuracy]);
|
||||||
|
|
||||||
const startSharing = useCallback(() => {
|
const startSharing = useCallback(() => {
|
||||||
if (!('geolocation' in navigator)) {
|
if (!('geolocation' in navigator)) {
|
||||||
|
|
@ -107,6 +150,10 @@ export function useLocationSharing(
|
||||||
return; // Already watching
|
return; // Already watching
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset fallback flags
|
||||||
|
timeoutCountRef.current = 0;
|
||||||
|
usingLowAccuracyRef.current = false;
|
||||||
|
|
||||||
const geoOptions: PositionOptions = {
|
const geoOptions: PositionOptions = {
|
||||||
enableHighAccuracy: highAccuracy,
|
enableHighAccuracy: highAccuracy,
|
||||||
maximumAge: maxAge,
|
maximumAge: maxAge,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue