fix(ux): Batch C part 1 — Near Me timing & reachability
- geolocation: cap the overall deadline at 15s (was 25s) and shorten the native plugin attempt to 8s, so a failed fix no longer hangs ~25-40s - MapPage: only warm the location cache when permission is ALREADY granted, so opening /map no longer fires the browser's 'Allow location?' prompt - MapPage: add a desktop Near Me control (it was mobile-only) - MapPage: on native, a denial is now retryable instead of permanently opening the browser-only help sheet
This commit is contained in:
parent
8e35859188
commit
dca0c0ede1
2 changed files with 57 additions and 10 deletions
|
|
@ -228,7 +228,7 @@ async function getNativePosition(native: CapGeolocationPlugin): Promise<GeoCoord
|
|||
// it defensively and fall back to navigator.geolocation only if it fails.
|
||||
try {
|
||||
const pos = await safeCall(() =>
|
||||
native.getCurrentPosition({ enableHighAccuracy: false, timeout: 15000, maximumAge: 60000 }),
|
||||
native.getCurrentPosition({ enableHighAccuracy: false, timeout: 8000, maximumAge: 60000 }),
|
||||
);
|
||||
const lat = pos?.coords?.latitude;
|
||||
const lng = pos?.coords?.longitude;
|
||||
|
|
@ -340,7 +340,7 @@ function getWebPosition(): Promise<GeoCoords> {
|
|||
settled = true;
|
||||
cleanup();
|
||||
reject(new GeolocationError('timeout', 'Location request timed out.'));
|
||||
}, 25000);
|
||||
}, 15000);
|
||||
|
||||
// 1) watchPosition — first update wins (fast network fix).
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -804,13 +804,29 @@ export default function MapPage() {
|
|||
useEffect(() => {
|
||||
if (isNativeGeolocation()) return;
|
||||
let cancelled = false;
|
||||
getCurrentPosition()
|
||||
.then(({ lat, lng }) => {
|
||||
if (!cancelled) setUserLocation({ lat, lon: lng });
|
||||
})
|
||||
.catch(() => {
|
||||
// Silent — user hasn't asked to be located yet.
|
||||
});
|
||||
|
||||
const warm = () =>
|
||||
getCurrentPosition()
|
||||
.then(({ lat, lng }) => {
|
||||
if (!cancelled) setUserLocation({ lat, lon: lng });
|
||||
})
|
||||
.catch(() => {
|
||||
// Silent — user hasn't asked to be located yet.
|
||||
});
|
||||
|
||||
// Only warm up when permission is ALREADY granted — otherwise this fires the
|
||||
// browser's "Allow location?" prompt the moment someone opens /map.
|
||||
if (typeof navigator !== 'undefined' && navigator.permissions?.query) {
|
||||
navigator.permissions
|
||||
.query({ name: 'geolocation' as PermissionName })
|
||||
.then((status) => {
|
||||
if (!cancelled && status.state === 'granted') warm();
|
||||
})
|
||||
.catch(() => {
|
||||
/* permissions API unavailable — don't prompt */
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
|
|
@ -1432,6 +1448,29 @@ export default function MapPage() {
|
|||
compact
|
||||
/>
|
||||
|
||||
{/* Near Me — desktop parity (mobile has the floating control) */}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
if (nearMeError === 'denied' && !isNativeGeolocation()) {
|
||||
setShowLocationHelp(true);
|
||||
return;
|
||||
}
|
||||
handleNearMe();
|
||||
}}
|
||||
disabled={nearMeLoading}
|
||||
title={nearMeError === 'denied' ? 'Enable location access' : 'Find my location'}
|
||||
className="hidden md:inline-flex h-8 gap-1.5 border-white/20 flex-shrink-0 touch-manipulation"
|
||||
>
|
||||
{nearMeError === 'denied' ? (
|
||||
<LocateOff className="h-4 w-4 text-red-400" />
|
||||
) : (
|
||||
<LocateFixed className={cn('h-4 w-4', userLocation ? 'text-[#ccff00]' : 'text-gray-300')} />
|
||||
)}
|
||||
<span className="hidden lg:inline">Near Me</span>
|
||||
</Button>
|
||||
|
||||
{/* Clear filters */}
|
||||
{hasActiveFilters && (
|
||||
<Button
|
||||
|
|
@ -1723,7 +1762,15 @@ export default function MapPage() {
|
|||
>
|
||||
{/* Near Me */}
|
||||
<button
|
||||
onClick={nearMeError === 'denied' ? () => setShowLocationHelp(true) : handleNearMe}
|
||||
onClick={() => {
|
||||
// On native a denial is an OS permission the user can grant
|
||||
// and retry; only the web needs the browser re-enable sheet.
|
||||
if (nearMeError === 'denied' && !isNativeGeolocation()) {
|
||||
setShowLocationHelp(true);
|
||||
return;
|
||||
}
|
||||
handleNearMe();
|
||||
}}
|
||||
disabled={nearMeLoading}
|
||||
className={cn(
|
||||
'h-11 w-11 rounded-full flex items-center justify-center shadow-lg border backdrop-blur transition-all touch-manipulation active:scale-90',
|
||||
|
|
|
|||
Loading…
Reference in a new issue