Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions components/calendar-notepad.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"use client"

"use client"

import type React from "react"
import { useState, useEffect } from "react"
import { ChevronLeft, ChevronRight, MapPin } from "lucide-react"
Expand All @@ -23,11 +21,21 @@ export function CalendarNotepad({ chatId }: CalendarNotepadProps) {
const [taggedLocation, setTaggedLocation] = useState<any | null>(null)

useEffect(() => {
let isMounted = true;
const fetchNotes = async () => {
const fetchedNotes = await getNotes(selectedDate, chatId ?? null)
setNotes(fetchedNotes)
try {
const fetchedNotes = await getNotes(selectedDate, chatId ?? null)
if (isMounted) {
setNotes(fetchedNotes)
}
} catch (error) {
console.error('Failed to fetch notes:', error);
}
}
fetchNotes()
return () => {
isMounted = false;
};
}, [selectedDate, chatId])

const generateDateRange = (offset: number) => {
Expand Down
19 changes: 12 additions & 7 deletions components/map/geojson-layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,24 @@ export function GeoJsonLayer({ id, data }: GeoJsonLayerProps) {
}
}

if (map.isStyleLoaded()) {
const isStyleLoaded = map.isStyleLoaded();
if (isStyleLoaded) {
onMapLoad()
} else {
map.on('load', onMapLoad)
map.once('load', onMapLoad)
}

// Cleanup function
return () => {
map.off('load', onMapLoad);
if (map.isStyleLoaded()) {
if (map.getLayer(pointLayerId)) map.removeLayer(pointLayerId)
if (map.getLayer(polygonLayerId)) map.removeLayer(polygonLayerId)
if (map.getLayer(polygonOutlineLayerId)) map.removeLayer(polygonOutlineLayerId)
if (map.getSource(sourceId)) map.removeSource(sourceId)
try {
if (map.getLayer(pointLayerId)) map.removeLayer(pointLayerId)
if (map.getLayer(polygonLayerId)) map.removeLayer(polygonLayerId)
if (map.getLayer(polygonOutlineLayerId)) map.removeLayer(polygonOutlineLayerId)
if (map.getSource(sourceId)) map.removeSource(sourceId)
} catch (e) {
console.warn('Error during GeoJsonLayer cleanup:', e);
}
}
}
}, [map, id, data])
Expand Down
42 changes: 23 additions & 19 deletions components/map/map-query-handler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,30 @@ export const MapQueryHandler: React.FC<MapQueryHandlerProps> = ({ toolOutput })
const { latitude, longitude, place_name } = toolOutput.mcp_response.location;

if (typeof latitude === 'number' && typeof longitude === 'number') {
console.log(`MapQueryHandler: Received data from geospatialTool. Place: ${place_name}, Lat: ${latitude}, Lng: ${longitude}`);
setMapData(prevData => ({
...prevData,
// Ensure coordinates are in [lng, lat] format for MapboxGL
targetPosition: [longitude, latitude],
// Optionally store more info from mcp_response if needed by MapboxMap component later
mapFeature: {
place_name,
// Potentially add mapUrl or other details from toolOutput.mcp_response
mapUrl: toolOutput.mcp_response?.mapUrl
}
}));
setMapData(prevData => {
const isSamePosition = Array.isArray(prevData.targetPosition) &&
prevData.targetPosition[0] === longitude &&
prevData.targetPosition[1] === latitude;
if (isSamePosition) return prevData;

return {
...prevData,
targetPosition: [longitude, latitude],
mapFeature: {
place_name,
mapUrl: toolOutput.mcp_response?.mapUrl
}
};
});
} else {
console.warn("MapQueryHandler: Invalid latitude/longitude in toolOutput.mcp_response:", toolOutput.mcp_response.location);
// Clear target position if data is invalid
setMapData(prevData => ({
...prevData,
targetPosition: null,
mapFeature: null
}));
setMapData(prevData => {
if (prevData.targetPosition === null && prevData.mapFeature === null) return prevData;
return {
...prevData,
targetPosition: null,
mapFeature: null
};
});
Comment on lines +54 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard condition may not match initial state.

Per map-data-context.tsx, targetPosition and mapFeature are typed as ... | null | undefined. The initial state may have these as undefined rather than null. The check on Line 55 only matches null, so if the initial state uses undefined, this guard won't prevent the first redundant update.

🔎 Suggested fix
 setMapData(prevData => {
-  if (prevData.targetPosition === null && prevData.mapFeature === null) return prevData;
+  if (!prevData.targetPosition && !prevData.mapFeature) return prevData;
   return {
     ...prevData,
     targetPosition: null,
     mapFeature: null
   };
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setMapData(prevData => {
if (prevData.targetPosition === null && prevData.mapFeature === null) return prevData;
return {
...prevData,
targetPosition: null,
mapFeature: null
};
});
setMapData(prevData => {
if (!prevData.targetPosition && !prevData.mapFeature) return prevData;
return {
...prevData,
targetPosition: null,
mapFeature: null
};
});
🤖 Prompt for AI Agents
In components/map/map-query-handler.tsx around lines 54 to 61, the guard only
checks for strict null which misses undefined (initial state allows null |
undefined); change the condition to check for both null and undefined (e.g., use
loose equality null check: if (prevData.targetPosition == null &&
prevData.mapFeature == null) return prevData;) so the redundant state update is
avoided for both null and undefined initial values.

}
} else {
// This case handles when toolOutput or its critical parts are missing.
Expand Down
76 changes: 17 additions & 59 deletions components/map/mapbox-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,12 @@ export const Mapbox: React.FC<{ position?: { latitude: number; longitude: number
}
})

setMapData(prevData => ({ ...prevData, drawnFeatures: currentDrawnFeatures }))
setMapData(prevData => {
// Only update if drawnFeatures actually changed to prevent infinite loops
const isChanged = JSON.stringify(prevData.drawnFeatures) !== JSON.stringify(currentDrawnFeatures);
if (!isChanged) return prevData;
return { ...prevData, drawnFeatures: currentDrawnFeatures };
});
}, [formatMeasurement, setMapData])

// Handle map rotation
Expand Down Expand Up @@ -513,22 +518,17 @@ export const Mapbox: React.FC<{ position?: { latitude: number; longitude: number
// Effect to handle map updates from MapDataContext
useEffect(() => {
if (mapData.targetPosition && map.current) {
// console.log("Mapbox.tsx: Received new targetPosition from context:", mapData.targetPosition);
// targetPosition is LngLatLike, which can be [number, number]
// updateMapPosition expects (latitude, longitude)
const [lng, lat] = mapData.targetPosition as [number, number]; // Assuming LngLatLike is [lng, lat]
const [lng, lat] = mapData.targetPosition as [number, number];
if (typeof lat === 'number' && typeof lng === 'number') {
updateMapPosition(lat, lng);
} else {
// console.error("Mapbox.tsx: Invalid targetPosition format in mapData", mapData.targetPosition);
// Check if the map is already at this position to avoid redundant flyTo
const center = map.current.getCenter();
const distance = Math.sqrt(Math.pow(center.lat - lat, 2) + Math.pow(center.lng - lng, 2));
if (distance > 0.0001) {
updateMapPosition(lat, lng);
}
}
}
// TODO: Handle mapData.mapFeature for drawing routes, polygons, etc. in a future step.
// For example:
// if (mapData.mapFeature && mapData.mapFeature.route_geometry && typeof drawRoute === 'function') {
// drawRoute(mapData.mapFeature.route_geometry); // Implement drawRoute function if needed
// }
}, [mapData.targetPosition, mapData.mapFeature, updateMapPosition]);
}, [mapData.targetPosition, updateMapPosition]);

// Long-press handlers
const handleMouseDown = useCallback(() => {
Expand All @@ -555,57 +555,15 @@ export const Mapbox: React.FC<{ position?: { latitude: number; longitude: number
}
}, []);

// Cleanup for the main useEffect
// Cleanup for long press timer
useEffect(() => {
// ... existing useEffect logic ...
return () => {
// ... existing cleanup logic ...
if (longPressTimerRef.current) { // Cleanup timer on component unmount
if (longPressTimerRef.current) {
clearTimeout(longPressTimerRef.current);
longPressTimerRef.current = null;
}
// ... existing cleanup logic for map and geolocation ...
if (map.current) {
map.current.off('moveend', captureMapCenter)

if (drawRef.current) {
try {
map.current.off('draw.create', updateMeasurementLabels)
map.current.off('draw.delete', updateMeasurementLabels)
map.current.off('draw.update', updateMeasurementLabels)
map.current.removeControl(drawRef.current)
} catch (e) {
console.log('Draw control already removed')
}
}

Object.values(polygonLabelsRef.current).forEach(marker => marker.remove())
Object.values(lineLabelsRef.current).forEach(marker => marker.remove())

stopRotation()
setIsMapLoaded(false)
setMap(null)
map.current.remove()
map.current = null
}

if (geolocationWatchIdRef.current !== null) {
navigator.geolocation.clearWatch(geolocationWatchIdRef.current)
geolocationWatchIdRef.current = null
}
};
}, [
handleUserInteraction,
startRotation,
stopRotation,
mapType, // mapType is already here, good.
updateMeasurementLabels,
setupGeolocationWatcher,
captureMapCenter,
setupDrawingTools,
setIsMapLoaded,
setMap
]);
}, []);


return (
Expand Down
Loading