From c8b9d2b8bd958a93971904d13ac2facc403fce99 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Sun, 17 Aug 2025 19:02:13 +0000 Subject: [PATCH] feat: Cycle included area segments by recency Co-authored-by: aider (gemini/gemini-2.5-pro) --- mapper/src/App.js | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/mapper/src/App.js b/mapper/src/App.js index 72fb6bd..a79223a 100644 --- a/mapper/src/App.js +++ b/mapper/src/App.js @@ -314,6 +314,8 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm const scrollPositionRef = useRef(0); const [lastDrawnItemsForExclusion, setLastDrawnItemsForExclusion] = useState(null); const [exclusionCycleIndex, setExclusionCycleIndex] = useState(0); + const [lastDrawnItemsForInclusion, setLastDrawnItemsForInclusion] = useState(null); + const [inclusionCycleIndex, setInclusionCycleIndex] = useState(0); useEffect(() => { const container = scrollContainerRef.current; @@ -497,8 +499,8 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm return false; }; - let minTime = null; - let maxTime = null; + const goodSegments = []; + let currentSegment = null; for (const point of data) { if (!point || typeof point.lat !== 'number' || typeof point.lon !== 'number' || !point.time) { @@ -508,23 +510,45 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm const isInside = isInsideInclusionZone(point.lat, point.lon); if (isInside) { - if (minTime === null || point.time < minTime) { - minTime = point.time; + if (!currentSegment) { + currentSegment = { start: point.time, end: point.time }; + } else { + currentSegment.end = point.time; } - if (maxTime === null || point.time > maxTime) { - maxTime = point.time; + } else { + if (currentSegment) { + goodSegments.push(currentSegment); + currentSegment = null; } } } - if (minTime === null) { + if (currentSegment) { + goodSegments.push(currentSegment); + } + + if (!goodSegments.length) { alert("No data points found inside the selected area(s)."); setSubmenu(false); return; } - const startUnix = moment(minTime).unix(); - const endUnix = moment(maxTime).unix(); + goodSegments.sort((a, b) => moment(b.end).diff(moment(a.end))); + + const drawnItemsKey = JSON.stringify(drawnItems.map(item => item.bounds.toBBoxString()).sort()); + + let newIndex = 0; + if (lastDrawnItemsForInclusion === drawnItemsKey) { + newIndex = (inclusionCycleIndex + 1) % goodSegments.length; + } + + setLastDrawnItemsForInclusion(drawnItemsKey); + setInclusionCycleIndex(newIndex); + + const segmentToSelect = goodSegments[newIndex]; + + const startUnix = moment(segmentToSelect.start).unix(); + const endUnix = moment(segmentToSelect.end).unix(); const endOfWindowUnix = end.unix(); const newSliderStart = Math.floor((startUnix - endOfWindowUnix) / duration.secs + duration.num);