feat(maps): remembered views for the FT and grid maps, and no wasted first paint
The world map was the only one that remembered anything. Panning and zooming a map is the operator saying which part of the world they work, and on the FT decodes map and the grid-square map that was thrown away on every tab switch. Both now keep centre and zoom, through one shared helper (lib/mapView) that the world map uses too, and the keys are portable so a copied data folder brings the views with it. The world map also waits for the station's square before it paints. It drew the world at 0 degrees and then moved to the operator's longitude — a screenful of Esri tiles fetched and discarded on every first run. It is now built once, knowing where it is looking; a profile with no locator gets the default view after two seconds rather than a blank panel.
This commit is contained in:
@@ -8,6 +8,7 @@ import { useI18n } from '@/lib/i18n';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { BASEMAPS, addBasemap, loadBasemap, type BasemapKey } from '@/components/MainMap';
|
||||
import { writeUiPref } from '@/lib/uiPref';
|
||||
import { loadMapView, saveMapView, MAP_VIEW_GRIDS } from '@/lib/mapView';
|
||||
|
||||
// GridSquareMap — every Maidenhead square in the log, drawn on a world map.
|
||||
//
|
||||
@@ -131,8 +132,16 @@ export function GridSquareMap({ myGrid, className }: { myGrid?: string; classNam
|
||||
|
||||
}).setView([20, 0], 2);
|
||||
// The whole world, once, whatever the window is shaped like — computed by
|
||||
// Leaflet from the container rather than guessed with a zoom number.
|
||||
m.fitWorld({ animate: false });
|
||||
// Leaflet from the container rather than guessed with a zoom number. Unless
|
||||
// the operator has already chosen a view: theirs is the answer, and fitting
|
||||
// the world over it would undo the choice on every tab switch.
|
||||
const saved = loadMapView(MAP_VIEW_GRIDS);
|
||||
if (saved) m.setView([saved.lat, saved.lon], saved.zoom);
|
||||
else m.fitWorld({ animate: false });
|
||||
m.on('moveend', () => {
|
||||
const c = m.getCenter();
|
||||
saveMapView(MAP_VIEW_GRIDS, c.lat, c.lng, m.getZoom());
|
||||
});
|
||||
mapRef.current = m;
|
||||
layerRef.current = L.layerGroup().addTo(m);
|
||||
// Leaflet measures its container ONCE, when the map is created, and never
|
||||
@@ -144,7 +153,7 @@ export function GridSquareMap({ myGrid, className }: { myGrid?: string; classNam
|
||||
// fitWorld above ran against a container that may still have had no size —
|
||||
// the tab is mounted hidden. Fit ONCE more the first time it really has one,
|
||||
// and never again: after that the view belongs to the operator.
|
||||
let fitted = false;
|
||||
let fitted = !!saved; // a remembered view is already the right size
|
||||
const ro = new ResizeObserver(() => {
|
||||
m.invalidateSize({ animate: false });
|
||||
const el = hostRef.current;
|
||||
|
||||
Reference in New Issue
Block a user