Map tab: much bigger map with its own remembered view
Publish Container / publish (push) Successful in 2m12s

- Map fills the screen (was a 56vh strip); timeline and details sit below it
- No longer snaps back to the main-page radar's location/zoom on every refresh or tab switch;
  starts as a wider regional view, remembers pan/zoom, and recentres only when the location changes
- New 'My location' button

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Nate EmmertandClaude Sonnet 5.5 committed 2026-10-15 13:43:04 -04:00
1 parent acdcd6a2c5
commit 4f47d67a7e
4 files changed
+49 -5

No files matched your search

+14
View File
@@ -241,3 +241,17 @@ body:not([data-tab="conditions"]) #loading { display: none; }
.app { padding-left: calc(var(--gutter) + env(safe-area-inset-left, 0px)); padding-right: calc(var(--gutter) + env(safe-area-inset-right, 0px)); }
.topbar { margin-left: calc(-1 * (var(--gutter) + env(safe-area-inset-left, 0px))); margin-right: calc(-1 * (var(--gutter) + env(safe-area-inset-right, 0px))); }
.install-dialog { margin-top: max(1rem, env(safe-area-inset-top, 0px)); }
/* ── Map tab: the map is the page (not a 56vh strip); timeline and details sit below it ── */
body:not(.map-fs) #tab-unified-map .unified-map-wrap { height: auto; min-height: 0; padding: 0.7rem; gap: 0.6rem; border-radius: 16px; }
body:not(.map-fs) #tab-unified-map .unified-map-container {
height: max(540px, calc(100dvh - var(--topbar-h) - 250px)); border-radius: 12px;
}
@media (max-width: 640px) {
body:not(.map-fs) #tab-unified-map .unified-map-container {
height: max(460px, calc(100dvh - var(--topbar-h) - 58px - max(6px, env(safe-area-inset-bottom, 0px)) - 190px));
}
}
.map-controls-header { padding-bottom: 0.5rem; gap: 0.5rem; }
.map-recenter { font: inherit; font-size: 0.78rem; font-weight: 700; min-height: 40px; padding: 0 0.9rem; border-radius: 999px; border: 1px solid var(--border); background: var(--paper-dark); color: var(--ink); cursor: pointer; margin-left: auto; white-space: nowrap; }
.map-recenter:hover { border-color: var(--accent); color: var(--accent); }
+28
View File
@@ -378,6 +378,33 @@ function updateRadar(city, outlook) {
if (map.isStyleLoaded()) apply(); else map.once('idle', apply);
}
// ── Map tab: independent, remembered view (not tied to the main-page radar) ──
let mapCenteredFor = null;
const mapCityKey = (c) => `${(+c.latitude).toFixed(2)},${(+c.longitude).toFixed(2)}`;
function centerMap(city, force) {
const m = typeof mapsOverview !== 'undefined' ? mapsOverview?.map : null;
if (!m || city?.latitude == null) return;
const key = mapCityKey(city);
if (!force && mapCenteredFor === key) return; // keep wherever the user panned/zoomed to
let saved = null;
try { saved = JSON.parse(localStorage.getItem('mapView') || 'null'); } catch {}
if (!force && !mapCenteredFor && saved && saved.key === key && Number.isFinite(saved.zoom)) m.jumpTo({ center: [saved.lng, saved.lat], zoom: saved.zoom });
else mapsOverview.panTo(city.latitude, city.longitude, force ? 7 : 5); // wider regional view than the main-page radar
mapCenteredFor = key;
}
(() => {
const m = typeof mapsOverview !== 'undefined' ? mapsOverview?.map : null;
if (!m) return;
let t = 0;
m.on('moveend', () => {
if (!mapCenteredFor) return;
clearTimeout(t);
t = setTimeout(() => { try { const c = m.getCenter(); localStorage.setItem('mapView', JSON.stringify({ key: mapCenteredFor, lng: c.lng, lat: c.lat, zoom: m.getZoom() })); } catch {} }, 400);
});
$('map-recenter-btn')?.addEventListener('click', () => { if (state.currentCity) centerMap(state.currentCity, true); });
})();
// ── Public hooks ─────────────────────────────────────────────────────────────
let lastOutlook = null;
window.AppUI = {
@@ -399,6 +426,7 @@ window.AppUI = {
if (state.currentAir) renderAqi(state.currentAir);
if (stationFresh) renderStationContext();
},
centerMap,
onAir(air) { renderAqi(air); },
refreshFx() { const c = $('sky-fx'); if (c && fx.kind) { cancelAnimationFrame(fx.raf); fxResize(c); fxSeed(fx.kind); if (fx.parts.length) fxFrame(performance.now()); } },
onStation() { syncTopbarLocation(); renderStationContext(); },
+5 -4
View File
@@ -1281,8 +1281,9 @@ function refreshMapsOverview() {
if (!state.currentCity) return;
const zoom = mapsOverview.map.getZoom ? mapsOverview.map.getZoom() : 6;
mapsOverview.panTo(state.currentCity.latitude, state.currentCity.longitude, zoom || 6);
// Keep the user's own pan/zoom; only (re)centre when the location changes
if (window.AppUI && window.AppUI.centerMap) window.AppUI.centerMap(state.currentCity);
else mapsOverview.panTo(state.currentCity.latitude, state.currentCity.longitude, mapsOverview.map.getZoom ? mapsOverview.map.getZoom() : 6);
clearLightningMarkers();
clearWindArrows();
@@ -1599,8 +1600,8 @@ function renderWeather(data, city) {
radarEmbed.panTo(city.latitude, city.longitude, 6);
radarFull.panTo(city.latitude, city.longitude, 6);
const mapZoom = mapsOverview?.map?.getZoom ? mapsOverview.map.getZoom() : 6;
mapsOverview.panTo(city.latitude, city.longitude, mapZoom || 6);
if (window.AppUI && window.AppUI.centerMap) window.AppUI.centerMap(city);
else mapsOverview.panTo(city.latitude, city.longitude, (mapsOverview?.map?.getZoom ? mapsOverview.map.getZoom() : 6) || 6);
if (mapsWindEl) mapsWindEl.textContent = `${speedDisplay(c.wind_speed_10m)} ${speedUnit()} ${compassDir(c.wind_direction_10m)}`;
updateSourceLocation(city);
updateShareUrl(city);
+2 -1
View File
@@ -259,6 +259,7 @@
<option value="light">Light</option>
<option value="satellite">Satellite</option>
</select>
<button id="map-recenter-btn" class="map-recenter" type="button" title="Back to my location">📍 My location</button>
<button id="map-fullscreen-btn" class="radar-btn radar-fs-btn" title="Fullscreen">⛶</button>
</div>
@@ -351,7 +352,7 @@
<!-- Main Map -->
<div class="unified-map-shell">
<div id="unified-map" class="unified-map-container" style="height:56vh; min-height:420px;"></div>
<div id="unified-map" class="unified-map-container"></div>
<div class="map-overlay-readouts" id="map-overlay-readouts">
<span class="map-readout-chip" id="overlay-temp">Temp --</span>
<span class="map-readout-chip" id="overlay-aqi">AQI --</span>