diff --git a/web/index.html b/web/index.html index 310025b..1f321d8 100644 --- a/web/index.html +++ b/web/index.html @@ -11,7 +11,12 @@ - + + diff --git a/web/src/components/dashboard/GoogleMap.tsx b/web/src/components/dashboard/GoogleMap.tsx index 2a8da2a..f68454b 100644 --- a/web/src/components/dashboard/GoogleMap.tsx +++ b/web/src/components/dashboard/GoogleMap.tsx @@ -31,8 +31,17 @@ export const GoogleMap: React.FC = ({ // If zoom is not provided, calculate based on accuracy const effectiveZoom = zoom || calculateZoomFromAccuracy(accuracyMeters); - useEffect(() => { - if (mapRef.current && window.google && window.google.maps) { + // Track whether the map has been initialized + const isInitializedRef = useRef(false); + + const initializeMap = () => { + if ( + mapRef.current && + window.google && + window.google.maps && + !isInitializedRef.current + ) { + isInitializedRef.current = true; // Create map instance const mapOptions: google.maps.MapOptions = { center: { lat, lng }, @@ -119,6 +128,34 @@ export const GoogleMap: React.FC = ({ radius: accuracyMeters, }); } + }; + + useEffect(() => { + // Check if Google Maps API is already loaded + if (window.google && window.google.maps) { + initializeMap(); + } else { + // Set up a listener for when the API loads + const handleGoogleMapsLoaded = () => { + initializeMap(); + }; + + // Add event listener for Google Maps API loading + window.addEventListener('google-maps-loaded', handleGoogleMapsLoaded); + + // Also try initializing after a short delay (backup) + const timeoutId = setTimeout(() => { + if (window.google && window.google.maps) { + initializeMap(); + } + }, 1000); + + // Cleanup + return () => { + window.removeEventListener('google-maps-loaded', handleGoogleMapsLoaded); + clearTimeout(timeoutId); + }; + } }, [lat, lng, effectiveZoom, accuracyMeters, precisionBits]); return ( diff --git a/web/src/components/dashboard/MeshCard.tsx b/web/src/components/dashboard/MeshCard.tsx index 7a325d8..d77142f 100644 --- a/web/src/components/dashboard/MeshCard.tsx +++ b/web/src/components/dashboard/MeshCard.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Radio, Signal, Battery, MapPin, Thermometer } from "lucide-react"; +import { Radio, Battery, MapPin, Thermometer, Network } from "lucide-react"; import { Counter } from "../Counter"; import { NodeData } from "../../store/slices/aggregatorSlice"; import { getActivityLevel, getNodeColors, ActivityLevel } from "../../lib/activity"; @@ -35,7 +35,7 @@ export const MeshCard: React.FC = ({ // Get icon based on type const getIcon = () => { return type === "gateway" ? ( - + ) : ( ); diff --git a/web/src/components/dashboard/NetworkMap.tsx b/web/src/components/dashboard/NetworkMap.tsx index 1e4a119..b99dcb0 100644 --- a/web/src/components/dashboard/NetworkMap.tsx +++ b/web/src/components/dashboard/NetworkMap.tsx @@ -124,24 +124,52 @@ export const NetworkMap = React.forwardRef<{ resetAutoZoom: () => void }, Networ setNodesWithPosition(nodeArray); }, [nodes, gateways]); + // Check for Google Maps API and initialize + const tryInitializeMap = useCallback(() => { + if (mapRef.current && window.google && window.google.maps) { + // Initialize map if not already done + if (!mapInstanceRef.current) { + initializeMap(mapRef.current); + } + + // Create info window if not already done + if (!infoWindowRef.current) { + infoWindowRef.current = new google.maps.InfoWindow(); + } + + // Update markers and fit the map + updateNodeMarkers(nodesWithPosition, navigate); + return true; + } + return false; + }, [nodesWithPosition, navigate, updateNodeMarkers, initializeMap]); + // Handle map initialization and marker creation useEffect(() => { - if (!mapRef.current || !window.google || !window.google.maps) return; - - // Initialize map if not already done - if (!mapInstanceRef.current) { - initializeMap(mapRef.current); + // Try to initialize immediately if Google Maps is already loaded + if (tryInitializeMap()) { + return; } - - // Create info window if not already done - if (!infoWindowRef.current) { - infoWindowRef.current = new google.maps.InfoWindow(); - } - - // Update markers and fit the map - updateNodeMarkers(nodesWithPosition, navigate); - }, [nodesWithPosition, navigate, setupZoomListener]); + // Set up a listener for when the API loads + const handleGoogleMapsLoaded = () => { + tryInitializeMap(); + }; + + // Add event listener for Google Maps API loading + window.addEventListener('google-maps-loaded', handleGoogleMapsLoaded); + + // Also try initializing after a short delay (backup) + const timeoutId = setTimeout(() => { + tryInitializeMap(); + }, 1000); + + // Cleanup + return () => { + window.removeEventListener('google-maps-loaded', handleGoogleMapsLoaded); + clearTimeout(timeoutId); + }; + }, [nodesWithPosition, navigate, tryInitializeMap]); // Setup zoom listener when map is initialized useEffect(() => { diff --git a/web/src/components/dashboard/NodeDetail.tsx b/web/src/components/dashboard/NodeDetail.tsx index 61e371d..1c73658 100644 --- a/web/src/components/dashboard/NodeDetail.tsx +++ b/web/src/components/dashboard/NodeDetail.tsx @@ -13,7 +13,7 @@ import { Map, Zap, ChevronRight, - Signal, + Network, Wifi, Users, Earth, @@ -26,7 +26,7 @@ import { Separator } from "../Separator"; import { KeyValuePair } from "../ui/KeyValuePair"; import { Section } from "../ui/Section"; import { BatteryLevel } from "./BatteryLevel"; -import { SignalStrength } from "./SignalStrength"; +import { NetworkStrength } from "./NetworkStrength"; import { GoogleMap } from "./GoogleMap"; import { NodePositionData } from "./NodePositionData"; import { EnvironmentMetrics } from "./EnvironmentMetrics"; @@ -39,6 +39,7 @@ import { getRegionName, getModemPresetName, } from "../../utils/formatters"; +import { SignalStrength } from "./SignalStrength"; interface NodeDetailProps { nodeId: number; @@ -179,7 +180,7 @@ export const NodeDetail: React.FC = ({ nodeId }) => { )} > {node.isGateway ? ( - + ) : ( )} @@ -267,7 +268,7 @@ export const NodeDetail: React.FC = ({ nodeId }) => {
- + Gateway Node {node.observedNodeCount !== undefined && ( @@ -391,7 +392,7 @@ export const NodeDetail: React.FC = ({ nodeId }) => {
- + Gateways
diff --git a/web/src/components/packets/MapReportPacket.tsx b/web/src/components/packets/MapReportPacket.tsx index d402d0e..4cd9a21 100644 --- a/web/src/components/packets/MapReportPacket.tsx +++ b/web/src/components/packets/MapReportPacket.tsx @@ -6,7 +6,7 @@ import { RegionCode, ModemPreset, } from "../../lib/types"; -import { Map as MapIcon, Signal, MapPin } from "lucide-react"; +import { Map as MapIcon, MapPin, Network } from "lucide-react"; import { PacketCard } from "./PacketCard"; import { KeyValueGrid, KeyValuePair } from "../ui/KeyValuePair"; import { Map } from "../Map"; @@ -202,7 +202,7 @@ export const MapReportPacket: React.FC = ({ packet }) => { mapReport.modemPreset) && (

- + Report Source