diff --git a/app/components/map/useDraggableMap.ts b/app/components/map/useDraggableMap.ts index 97a597f9..8bff1cc1 100644 --- a/app/components/map/useDraggableMap.ts +++ b/app/components/map/useDraggableMap.ts @@ -46,6 +46,29 @@ export type DraggableMap = { // Matches the legacy TraditionalController's isDragging() cooldown (mapper.js:1618-1646). const DRAG_END_COOLDOWN_MS = 500; +// The user's last zoom level per map kind is persisted to localStorage so it survives reloads and +// remounts (switching planets/entering star mode remounts the map, see app/components/menu/map.tsx). +const zoomStorageKey = (kind: MapKind) => `tlecommunity.map.${kind}.zoom`; + +const readStoredZoom = (kind: MapKind): number | undefined => { + try { + const raw = window.localStorage.getItem(zoomStorageKey(kind)); + if (raw === null) return undefined; + const parsed = Number(raw); + return Number.isFinite(parsed) ? parsed : undefined; + } catch { + return undefined; + } +}; + +const writeStoredZoom = (kind: MapKind, zoom: number): void => { + try { + window.localStorage.setItem(zoomStorageKey(kind), String(zoom)); + } catch { + // Ignore - storage may be unavailable (private mode, quota); zoom just won't persist. + } +}; + // Anything smaller than this is treated as a click, not a drag, so a slightly-jittery click isn't // swallowed as a drag-release. const DRAG_THRESHOLD_PX = 3; @@ -70,7 +93,9 @@ export const useDraggableMap = ({ kind, initialZoom = 0 }: Options): DraggableMa // The public setter is the `setZoom` wrapper defined below (it clamps); this raw setter is // deliberately kept private, hence the non-standard name. // eslint-disable-next-line react/hook-use-state - const [zoom, setZoomState] = useState(() => clampZoom(kind, initialZoom)); + const [zoom, setZoomState] = useState(() => + clampZoom(kind, readStoredZoom(kind) ?? initialZoom) + ); const [offsetPx, setOffsetPx] = useState({ x: 0, y: 0 }); const [viewportSize, setViewportSize] = useState({ width: 0, height: 0 }); @@ -157,7 +182,11 @@ export const useDraggableMap = ({ kind, initialZoom = 0 }: Options): DraggableMa }, []); const setZoom = useCallback( - (nextZoom: number) => setZoomState(clampZoom(kind, nextZoom)), + (nextZoom: number) => { + const clamped = clampZoom(kind, nextZoom); + writeStoredZoom(kind, clamped); + setZoomState(clamped); + }, [kind] );