'use client'; import { useEffect, useRef } from 'react'; import { useAuth } from '@/components/AuthProvider'; import { getSettings, saveDriverLocation, isAuthenticated } from '@/lib/pocketbase'; export default function LocationTracker() { const { isLoggedIn } = useAuth(); const watchRef = useRef(null); const intervalRef = useRef | null>(null); const wakeLockRef = useRef(null); useEffect(() => { // Skip entirely when not signed in — previously the watcher // was set up regardless of auth, which meant we requested a // GPS lock on the login screen (and ate battery doing nothing). if (!isLoggedIn) return; if (!('geolocation' in navigator)) return; const settings = getSettings(); const intervalMs = Math.max(30000, settings.locationInterval * 1000); const sendLocation = (position: GeolocationPosition) => { if (!isAuthenticated()) return; if (position.coords.accuracy > settings.minimumAccuracy) return; const auth = JSON.parse(localStorage.getItem('pocketbase_auth') || '{}'); const user = auth?.model; if (!user) return; saveDriverLocation({ // PB schema note: driver_locations stores the user relation under // `relation`, not `driver`. Using the wrong key here silently // 400'd inside a try/catch — see lib/types.ts DriverLocation. relation: user.id, latitude: position.coords.latitude, longitude: position.coords.longitude, accuracy: position.coords.accuracy || undefined, altitude: position.coords.altitude || undefined, speed: position.coords.speed || undefined, heading: position.coords.heading || undefined, timestamp: new Date().toISOString(), }); }; // 1. watchPosition keeps GPS active (helps Android stay alive longer) watchRef.current = navigator.geolocation.watchPosition( sendLocation, () => {}, { enableHighAccuracy: settings.enableHighAccuracy, maximumAge: 5000, // fresh GPS every 5s timeout: 30000, } ); // 2. Interval fallback (for when watchPosition is throttled) intervalRef.current = setInterval(() => { navigator.geolocation.getCurrentPosition( sendLocation, () => {}, { enableHighAccuracy: settings.enableHighAccuracy, maximumAge: intervalMs, timeout: 30000 } ); }, intervalMs); // 3. Screen Wake Lock — keeps phone awake while app is open if ('wakeLock' in navigator) { navigator.wakeLock.request('screen') .then((lock) => { wakeLockRef.current = lock; }) .catch(() => {}); // Re-acquire if page regains focus const onFocus = () => { if (!wakeLockRef.current) { navigator.wakeLock.request('screen') .then((lock) => { wakeLockRef.current = lock; }) .catch(() => {}); } }; document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') onFocus(); }); } return () => { if (watchRef.current !== null) { navigator.geolocation.clearWatch(watchRef.current); watchRef.current = null; } if (intervalRef.current !== null) { clearInterval(intervalRef.current); intervalRef.current = null; } if (wakeLockRef.current) { wakeLockRef.current.release(); wakeLockRef.current = null; } }; }, [isLoggedIn]); return null; }