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,
|
||||
updateInterval = 5000,
|
||||
highAccuracy = true,
|
||||
maxAge = 5000, // Allow cached position up to 5 seconds old
|
||||
timeout = 30000,
|
||||
maxAge = 30000, // Allow cached position up to 30 seconds old
|
||||
timeout = 15000, // 15 second timeout before fallback
|
||||
} = options;
|
||||
|
||||
const [isSharing, setIsSharing] = useState(false);
|
||||
|
|
@ -49,6 +49,8 @@ export function useLocationSharing(
|
|||
|
||||
const watchIdRef = useRef<number | null>(null);
|
||||
const onLocationUpdateRef = useRef(onLocationUpdate);
|
||||
const timeoutCountRef = useRef(0);
|
||||
const usingLowAccuracyRef = useRef(false);
|
||||
|
||||
// Keep callback ref updated
|
||||
useEffect(() => {
|
||||
|
|
@ -73,6 +75,9 @@ export function useLocationSharing(
|
|||
}, []);
|
||||
|
||||
const handlePosition = useCallback((position: GeolocationPosition) => {
|
||||
// Reset timeout counter on successful position
|
||||
timeoutCountRef.current = 0;
|
||||
|
||||
const location: ParticipantLocation = {
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
|
|
@ -90,12 +95,50 @@ export function useLocationSharing(
|
|||
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) => {
|
||||
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
|
||||
console.warn('Geolocation warning:', err.message, '(code:', err.code, ')');
|
||||
// Don't stop sharing on errors - keep trying
|
||||
}, []);
|
||||
}, [highAccuracy, restartWithLowAccuracy]);
|
||||
|
||||
const startSharing = useCallback(() => {
|
||||
if (!('geolocation' in navigator)) {
|
||||
|
|
@ -107,6 +150,10 @@ export function useLocationSharing(
|
|||
return; // Already watching
|
||||
}
|
||||
|
||||
// Reset fallback flags
|
||||
timeoutCountRef.current = 0;
|
||||
usingLowAccuracyRef.current = false;
|
||||
|
||||
const geoOptions: PositionOptions = {
|
||||
enableHighAccuracy: highAccuracy,
|
||||
maximumAge: maxAge,
|
||||
|
|
|
|||
Loading…
Reference in New Issue