mirror of
https://github.com/dpup/meshstream.git
synced 2026-03-28 17:42:37 +01:00
Lazy load maps
This commit is contained in:
@@ -11,7 +11,12 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;300;400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Roboto+Mono:wght@400;500&family=Share+Tech+Mono&family=Space+Mono:wght@400;700&family=VT323&display=swap"
|
||||
rel="stylesheet">
|
||||
<!-- Google Maps API with environment variable API key -->
|
||||
<script async defer src="https://maps.googleapis.com/maps/api/js?key=%VITE_GOOGLE_MAPS_API_KEY%"></script>
|
||||
<script>
|
||||
function gmapsCallback() {
|
||||
window.dispatchEvent(new Event('google-maps-loaded'));
|
||||
}
|
||||
</script>
|
||||
<script async src="https://maps.googleapis.com/maps/api/js?key=%VITE_GOOGLE_MAPS_API_KEY%&loading=async&callback=gmapsCallback"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -31,8 +31,17 @@ export const GoogleMap: React.FC<GoogleMapProps> = ({
|
||||
// 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<GoogleMapProps> = ({
|
||||
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 (
|
||||
|
||||
@@ -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<MeshCardProps> = ({
|
||||
// Get icon based on type
|
||||
const getIcon = () => {
|
||||
return type === "gateway" ? (
|
||||
<Signal className="w-4 h-4" />
|
||||
<Network className="w-4 h-4" />
|
||||
) : (
|
||||
<Radio className="w-4 h-4" />
|
||||
);
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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<NodeDetailProps> = ({ nodeId }) => {
|
||||
)}
|
||||
>
|
||||
{node.isGateway ? (
|
||||
<Signal className="w-4 h-4" />
|
||||
<Network className="w-4 h-4" />
|
||||
) : (
|
||||
<Radio className="w-4 h-4" />
|
||||
)}
|
||||
@@ -267,7 +268,7 @@ export const NodeDetail: React.FC<NodeDetailProps> = ({ nodeId }) => {
|
||||
<div className="mt-4 pt-3 border-t border-neutral-700 space-y-3">
|
||||
<div className="flex justify-between items-center mb-2 p-2 rounded effect-inset bg-neutral-700/50 ">
|
||||
<span className="flex items-center">
|
||||
<Signal className="w-4 h-4 mr-1.5" />
|
||||
<Network className="w-4 h-4 mr-1.5" />
|
||||
Gateway Node
|
||||
</span>
|
||||
{node.observedNodeCount !== undefined && (
|
||||
@@ -391,7 +392,7 @@ export const NodeDetail: React.FC<NodeDetailProps> = ({ nodeId }) => {
|
||||
|
||||
<div className="flex justify-between items-center bg-neutral-700/50 p-2 rounded effect-inset">
|
||||
<span className="text-neutral-400 flex items-center text-sm">
|
||||
<Signal className="w-3 h-3 mr-2 text-neutral-300" />
|
||||
<Network className="w-3 h-3 mr-2 text-neutral-300" />
|
||||
Gateways
|
||||
</span>
|
||||
<div className="flex flex-col items-end">
|
||||
|
||||
@@ -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<MapReportPacketProps> = ({ packet }) => {
|
||||
mapReport.modemPreset) && (
|
||||
<div className="p-3 bg-neutral-800/50 rounded border border-neutral-700">
|
||||
<h3 className="text-sm font-medium text-neutral-300 mb-3 flex items-center">
|
||||
<Signal className="w-4 h-4 mr-2 text-cyan-400" />
|
||||
<Network className="w-4 h-4 mr-2 text-cyan-400" />
|
||||
Report Source
|
||||
</h3>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user