Location: say why it failed, retry once, show permission status
Publish Container / publish (push) Successful in 2m15s
Publish Container / publish (push) Successful in 2m15s
The ⌖ button reported 'Location access denied' for every failure, including timeouts and no-GPS-fix errors that have nothing to do with permission. - Specific messages for denied / no fix / timeout, with the exact iPhone steps (Safari tab vs installed web app) and the error code for diagnosis - One patient high-accuracy retry for slow or cold GPS fixes (a real denial is not retried) - Live permission status line under the search row (allowed / not asked / blocked) - Mentions Safari content blockers as a possible cause Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0cbebfef2a
commit
eaff2f55c8
4 files changed
+83
-8
No files matched your search
+45
-8
@@ -2273,26 +2273,63 @@ searchBtn.addEventListener('click', doSearch);
|
||||
searchInput.addEventListener('keydown', e => { if (e.key === 'Enter') doSearch(); });
|
||||
|
||||
// ── Geolocation ───────────────────────────────────────────────────────────────
|
||||
locateBtn.addEventListener('click', () => {
|
||||
// Why a location request failed, in plain language (the browser tells us: 1 denied, 2 unavailable, 3 timeout)
|
||||
const IS_IOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
|
||||
const IS_STANDALONE = window.matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
|
||||
async function geoPermissionState() {
|
||||
try { return (await navigator.permissions.query({ name: 'geolocation' })).state; } catch { return 'unknown'; }
|
||||
}
|
||||
function geoErrorHelp(err, perm) {
|
||||
const code = err && err.code;
|
||||
const tag = ` (error ${code ?? '?'}${perm && perm !== 'unknown' ? ', permission: ' + perm : ''})`;
|
||||
if (code === 1) {
|
||||
if (IS_IOS) {
|
||||
const where = IS_STANDALONE
|
||||
? 'Settings → Privacy & Security → Location Services → "NeCloud Weather" → While Using the App'
|
||||
: 'Settings → Privacy & Security → Location Services → Safari Websites → While Using, then in Safari tap aA → Website Settings → Location → Allow';
|
||||
return `Your phone says location is off for ${IS_STANDALONE ? 'this app' : 'this site'}. Turn it on in ${where}. If you use a Safari content blocker, also try aA → Turn Off Content Blockers for this site.${tag}`;
|
||||
}
|
||||
return `Location is blocked for this site. Click the lock icon in the address bar → Location → Allow, then try again.${tag}`;
|
||||
}
|
||||
if (code === 2) return `Your device couldn't find your position yet (no GPS or Wi-Fi fix). Make sure Location Services is on, turn off Low Power Mode, and try again, ideally on Wi-Fi or outdoors.${tag}`;
|
||||
if (code === 3) return `Timed out waiting for your location. Try again in a moment.${tag}`;
|
||||
return `Could not get your location.${tag}`;
|
||||
}
|
||||
function geoOnce(opts) {
|
||||
return new Promise((resolve, reject) => navigator.geolocation.getCurrentPosition(resolve, reject, opts));
|
||||
}
|
||||
// A slow or cold GPS often times out the first time: retry once with a patient, high-accuracy request.
|
||||
// A real "denied" is final, so don't retry that.
|
||||
async function getPositionRobust() {
|
||||
try {
|
||||
return await geoOnce({ enableHighAccuracy: false, timeout: 12000, maximumAge: 5 * 60 * 1000 });
|
||||
} catch (e) {
|
||||
if (e && e.code === 1) throw e;
|
||||
return await geoOnce({ enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });
|
||||
}
|
||||
}
|
||||
|
||||
locateBtn.addEventListener('click', async () => {
|
||||
if (!navigator.geolocation) { showErr('Geolocation not supported.'); return; }
|
||||
clearErr();
|
||||
hide(weatherDiv);
|
||||
show(loadingEl);
|
||||
|
||||
navigator.geolocation.getCurrentPosition(async pos => {
|
||||
try {
|
||||
const pos = await getPositionRobust();
|
||||
const { latitude: lat, longitude: lon } = pos.coords;
|
||||
try {
|
||||
const city = await buildDetectedCity(lat, lon);
|
||||
await loadAll(city, 'gps-button');
|
||||
} catch {
|
||||
showErr('Could not fetch weather for your location.');
|
||||
} finally {
|
||||
hide(loadingEl);
|
||||
}
|
||||
}, () => {
|
||||
} catch (err) {
|
||||
if (state.currentWeather) show(weatherDiv);
|
||||
showErr(geoErrorHelp(err, await geoPermissionState()));
|
||||
} finally {
|
||||
hide(loadingEl);
|
||||
showErr('Location access denied.');
|
||||
});
|
||||
if (window.AppUI && window.AppUI.refreshGeoStatus) window.AppUI.refreshGeoStatus();
|
||||
}
|
||||
});
|
||||
|
||||
unitsBtn.addEventListener('click', () => {
|
||||
|
||||
Reference in new issue
Block a user