This commit is contained in:
Jake Kasper
2025-09-05 13:29:45 -04:00
parent e85bf3256a
commit 174961ed19

View File

@@ -353,6 +353,9 @@ const PropertyDetail = () => {
const [gpsSamples, setGpsSamples] = useState([]); // recent raw samples for smoothing const [gpsSamples, setGpsSamples] = useState([]); // recent raw samples for smoothing
const [gpsDistance, setGpsDistance] = useState(0); const [gpsDistance, setGpsDistance] = useState(0);
const [gpsAccuracy, setGpsAccuracy] = useState(null); const [gpsAccuracy, setGpsAccuracy] = useState(null);
const [gpsFixAgeMs, setGpsFixAgeMs] = useState(null);
const [gpsReady, setGpsReady] = useState(false);
const [warmWatchId, setWarmWatchId] = useState(null);
const [isSnapPreview, setIsSnapPreview] = useState(false); const [isSnapPreview, setIsSnapPreview] = useState(false);
const [showAddMenu, setShowAddMenu] = useState(false); const [showAddMenu, setShowAddMenu] = useState(false);
// Modal picker to ensure options show reliably on mobile // Modal picker to ensure options show reliably on mobile
@@ -378,6 +381,28 @@ const PropertyDetail = () => {
fetchPropertyDetails(); fetchPropertyDetails();
}, [id]); // eslint-disable-line react-hooks/exhaustive-deps }, [id]); // eslint-disable-line react-hooks/exhaustive-deps
// Start a passive GPS watch when the page mounts to warm up the fix
useEffect(() => {
if (!navigator.geolocation) return;
if (warmWatchId) return; // already running
const id = navigator.geolocation.watchPosition(
(pos) => {
const { latitude, longitude, accuracy } = pos.coords;
addSampleAndSmooth(latitude, longitude, accuracy);
},
(err) => {
console.warn('Warm GPS watch error', err?.message);
},
{ enableHighAccuracy: true, maximumAge: 1000, timeout: 20000 }
);
setWarmWatchId(id);
return () => {
try { if (id) navigator.geolocation.clearWatch(id); } catch {}
setWarmWatchId(null);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Load recent history when property is available // Load recent history when property is available
useEffect(() => { useEffect(() => {
if (!property?.id) return; if (!property?.id) return;
@@ -997,7 +1022,10 @@ const PropertyDetail = () => {
<span className="font-semibold">GPS Points Mode</span> <span className="font-semibold">GPS Points Mode</span>
<span>Points: {gpsTracePoints.length}</span> <span>Points: {gpsTracePoints.length}</span>
<span>Distance: {(gpsDistance * 3.28084).toFixed(0)} ft</span> <span>Distance: {(gpsDistance * 3.28084).toFixed(0)} ft</span>
{gpsAccuracy != null && <span>Accuracy: ±{Math.round(gpsAccuracy)} m</span>} <span className="flex items-center gap-1">
<span className={`inline-block w-2.5 h-2.5 rounded-full ${gpsReady ? 'bg-green-600' : (gpsAccuracy && gpsAccuracy <= 20 ? 'bg-amber-500' : 'bg-red-600')}`}></span>
<span>Fix {gpsReady ? 'Good' : 'Improving'}{gpsAccuracy != null ? ` • ±${Math.round(gpsAccuracy)} m` : ''}</span>
</span>
</div> </div>
<div className="mt-3 flex gap-2 items-center"> <div className="mt-3 flex gap-2 items-center">
<button className="btn-primary" onClick={markCurrentPoint}>Mark Point</button> <button className="btn-primary" onClick={markCurrentPoint}>Mark Point</button>
@@ -1015,7 +1043,10 @@ const PropertyDetail = () => {
<span className="font-semibold">Trace Mode</span> <span className="font-semibold">Trace Mode</span>
<span>Points: {gpsTracePoints.length}</span> <span>Points: {gpsTracePoints.length}</span>
<span>Distance: {(gpsDistance * 3.28084).toFixed(0)} ft</span> <span>Distance: {(gpsDistance * 3.28084).toFixed(0)} ft</span>
{gpsAccuracy != null && <span>Accuracy: ±{Math.round(gpsAccuracy)} m</span>} <span className="flex items-center gap-1">
<span className={`inline-block w-2.5 h-2.5 rounded-full ${gpsReady ? 'bg-green-600' : (gpsAccuracy && gpsAccuracy <= 25 ? 'bg-amber-500' : 'bg-red-600')}`}></span>
<span>Fix {gpsReady ? 'Good' : 'Improving'}{gpsAccuracy != null ? ` • ±${Math.round(gpsAccuracy)} m` : ''}</span>
</span>
</div> </div>
<div className="mt-3 flex gap-2 items-center"> <div className="mt-3 flex gap-2 items-center">
{!isTracing ? ( {!isTracing ? (
@@ -1041,9 +1072,9 @@ const PropertyDetail = () => {
return next; return next;
}); });
}, (err)=>{ }, (err)=>{
console.warn('GPS error', err?.message); console.warn('GPS watch error', err?.message);
toast.error('GPS error: ' + (err?.message || 'unknown')); // non-intrusive: don't spam toasts while tracing
}, { enableHighAccuracy: true, maximumAge: 1000, timeout: 10000 }); }, { enableHighAccuracy: true, maximumAge: 500, timeout: 20000 });
setGpsWatchId(id); setGpsWatchId(id);
setIsTracing(true); setIsTracing(true);
}}>Start</button> }}>Start</button>
@@ -1178,18 +1209,7 @@ const PropertyDetail = () => {
if (gpsWatchId) { navigator.geolocation.clearWatch(gpsWatchId); setGpsWatchId(null); } if (gpsWatchId) { navigator.geolocation.clearWatch(gpsWatchId); setGpsWatchId(null); }
clearGpsPoints(); clearGpsPoints();
setIsGPSPointsMode(true); setIsGPSPointsMode(true);
// Start passive GPS watch to warm up accuracy for Points mode // Warm watch already runs globally on page mount
if (navigator.geolocation) {
const id = navigator.geolocation.watchPosition((pos)=>{
const { latitude, longitude, accuracy } = pos.coords;
setGpsAccuracy(accuracy || null);
// Populate smoothing buffer without adding a point yet
try { addSampleAndSmooth(latitude, longitude, accuracy); } catch {}
}, (err)=>{
console.warn('GPS warmup error', err?.message);
}, { enableHighAccuracy: true, maximumAge: 1000, timeout: 15000 });
setGpsWatchId(id);
}
}} }}
> >
<div className="font-medium">GPS Points (walk and mark)</div> <div className="font-medium">GPS Points (walk and mark)</div>