From 435db835e91588519341d1c025efcc7b9a430509 Mon Sep 17 00:00:00 2001 From: "Tanner Collin (aider)" Date: Thu, 14 Aug 2025 21:18:09 +0000 Subject: [PATCH] refactor: unify map view logic to fix centering and data bugs --- mapper/src/App.js | 80 +++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 48 deletions(-) diff --git a/mapper/src/App.js b/mapper/src/App.js index 1a874b9..33563f7 100644 --- a/mapper/src/App.js +++ b/mapper/src/App.js @@ -38,7 +38,7 @@ const parseSlider = (end, duration, slider) => { //async function sha256(source) { // const sourceBytes = new TextEncoder().encode(source); -// const digest = await crypto.subtle.digest('SHA-256', sourceBytes); +// const digest = await crypto.subtle.digest('SHA-26', sourceBytes); // const resultBytes = [...new Uint8Array(digest)]; // return resultBytes.map(x => x.toString(16).padStart(2, '0')).join(''); //} @@ -70,21 +70,17 @@ function useSensor(measurement, name, end, duration) { return [data, loading]; }; - -function ChangeView({ center, zoom }) { +function MapViewManager({ coords, mapState, setMapState, loading }) { const map = useMap(); - map.setView(center, zoom); - return null; -} -function MapEvents({ onMapChange }) { - const map = useMapEvents({ + // Effect 1: Handle map events (pan/zoom) from the user + useMapEvents({ moveend: () => { const center = map.getCenter(); const newZoom = map.getZoom(); const newCenter = [center.lat, center.lng]; - onMapChange(prevState => { + setMapState(prevState => { // A small tolerance for floating point comparisons const tolerance = 1e-5; if (!prevState.center) { @@ -104,49 +100,29 @@ function MapEvents({ onMapChange }) { }); }, }); - return null; -} -function FitBounds({ coords, mapState, end, duration, loading }) { - const map = useMap(); - const prevEndRef = useRef(); - const prevDurationRef = useRef(); - const refitNeeded = useRef(false); - const isInitialLoad = useRef(mapState.center === null); - - // Effect 1: Flag the need for a refit when end/duration changes. + // Effect 2: Handle programmatic view changes (refitting or setting from state) useEffect(() => { - // Don't run on the very first render, wait until refs are populated. - if (prevEndRef.current && prevDurationRef.current) { - const endChanged = end.unix() !== prevEndRef.current.unix(); - const durationChanged = duration.id !== prevDurationRef.current.id; + // Don't do anything while loading new data + if (loading) return; - if (endChanged || durationChanged) { - refitNeeded.current = true; - } - } - prevEndRef.current = end; - prevDurationRef.current = duration; - }, [end, duration]); - - // Effect 2: Perform the fit when conditions are right. - useEffect(() => { - // Don't do anything while new data is being fetched. - if (loading) { - return; - } - - // Perform fit on initial load OR if a refit has been flagged. - if ((isInitialLoad.current || refitNeeded.current) && coords.length > 0) { + // Case A: A refit is needed (signaled by null center) + if (mapState.center === null && coords.length > 0) { const bounds = leaflet.latLngBounds(coords); if (bounds.isValid()) { map.fitBounds(bounds); + // After fitting, the 'moveend' event will fire and update the state naturally. } - // Reset flags after fitting. - refitNeeded.current = false; - isInitialLoad.current = false; } - }, [coords, loading, map]); // Dependencies: run when data is ready. + // Case B: A center is set in the state, ensure map is synced + else if (mapState.center) { + const currentCenter = map.getCenter(); + const currentZoom = map.getZoom(); + if (currentCenter.lat !== mapState.center[0] || currentCenter.lng !== mapState.center[1] || currentZoom !== mapState.zoom) { + map.setView(mapState.center, mapState.zoom); + } + } + }, [coords, mapState, loading, map, setMapState]); return null; } @@ -179,7 +155,7 @@ function Map({end, duration, slider, mapState, setMapState}) { continue; } - // 5. Guard against invalid coordinates + // 5. Guard against invalid coordinates (null, undefined, NaN, non-number) if (typeof lat !== 'number' || typeof lon !== 'number' || !isFinite(lat) || !isFinite(lon)) { continue; } @@ -206,9 +182,7 @@ function Map({end, duration, slider, mapState, setMapState}) { coords.length ? ( - {mapState.center && } - - + { + if (isInitialMount.current) { + isInitialMount.current = false; + } else { + // Reset map center to trigger a refit when new data arrives + setMapState(prev => ({ ...prev, center: null })); + } + }, [end, duration]); + useEffect(() => { const handler = setTimeout(() => { const params = new URLSearchParams();