From 1fc72aa7be0b6cdaa4c89e159dc7a99ce73fed39 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 8 Feb 2025 08:32:29 -0500 Subject: [PATCH 1/3] fix: keep existing zoom on map ndoe click --- src/pages/Map.tsx | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index 12a8e884..b2da0e69 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -44,7 +44,7 @@ const MapPage = (): JSX.Element => { } if (nodesWithPosition.length === 1) { map.easeTo({ - zoom: 12, + zoom: map.getZoom(), center: [ (nodesWithPosition[0].position?.longitudeI ?? 0) / 1e7, (nodesWithPosition[0].position?.latitudeI ?? 0) / 1e7, @@ -118,19 +118,6 @@ const MapPage = (): JSX.Element => { > { - // const waypoint = new Protobuf.Waypoint({ - // name: "test", - // description: "test description", - // latitudeI: Math.trunc(e.lngLat.lat * 1e7), - // longitudeI: Math.trunc(e.lngLat.lng * 1e7) - // }); - // addWaypoint(waypoint); - // connection?.sendWaypoint(waypoint, "broadcast"); - // }} - - // @ts-ignore - attributionControl={false} renderWorldCopies={false} maxPitch={0} @@ -163,11 +150,6 @@ const MapPage = (): JSX.Element => { ))} - {/* {rasterSources.map((source, index) => ( - - - - ))} */} {allNodes.map((node) => { if (node.position?.latitudeI && node.num !== selectedNode?.num) { return ( @@ -175,12 +157,11 @@ const MapPage = (): JSX.Element => { key={node.num} longitude={(node.position.longitudeI ?? 0) / 1e7} latitude={(node.position.latitudeI ?? 0) / 1e7} - // style={{ filter: darkMode ? "invert(1)" : "" }} anchor="bottom" onClick={() => { setSelectedNode(node); map?.easeTo({ - zoom: 12, + zoom: map.getZoom(), center: [ (node.position?.longitudeI ?? 0) / 1e7, (node.position?.latitudeI ?? 0) / 1e7, From d9aff939930952585444a416e765369b34c7ac26 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 8 Feb 2025 21:49:17 -0500 Subject: [PATCH 2/3] fix: removed map zoom on marker click. feat: lined up popup with map marker --- .../PageComponents/Map/NodeDetail.tsx | 2 +- src/pages/Map.tsx | 206 +++++++++--------- 2 files changed, 102 insertions(+), 106 deletions(-) diff --git a/src/components/PageComponents/Map/NodeDetail.tsx b/src/components/PageComponents/Map/NodeDetail.tsx index 5203d077..6b33318d 100644 --- a/src/components/PageComponents/Map/NodeDetail.tsx +++ b/src/components/PageComponents/Map/NodeDetail.tsx @@ -30,7 +30,7 @@ export const NodeDetail = ({ node }: NodeDetailProps) => { ].replaceAll("_", " "); return ( -
+
diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index b2da0e69..910de059 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -1,59 +1,94 @@ import { NodeDetail } from "@app/components/PageComponents/Map/NodeDetail"; import { Avatar } from "@app/components/UI/Avatar"; -import { Subtle } from "@app/components/UI/Typography/Subtle.tsx"; -import { cn } from "@app/core/utils/cn.ts"; import { PageLayout } from "@components/PageLayout.tsx"; import { Sidebar } from "@components/Sidebar.tsx"; -import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx"; -import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.tsx"; import { useAppStore } from "@core/stores/appStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts"; import type { Protobuf } from "@meshtastic/js"; -import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { bbox, lineString } from "@turf/turf"; -import { - BoxSelectIcon, - MapPinIcon, - ZoomInIcon, - ZoomOutIcon, -} from "lucide-react"; +import { MapPinIcon } from "lucide-react"; import { type JSX, useCallback, useEffect, useMemo, useState } from "react"; -import { AttributionControl, Marker, Popup, useMap } from "react-map-gl"; +import { + AttributionControl, + GeolocateControl, + Marker, + MarkerEvent, + NavigationControl, + Popup, + ScaleControl, + useMap, +} from "react-map-gl"; import MapGl from "react-map-gl/maplibre"; +type NodePosition = { + latitude: number; + longitude: number; +}; + +const convertToLatLng = (position: { + latitudeI?: number; + longitudeI?: number; +}): NodePosition => ({ + latitude: (position.latitudeI ?? 0) / 1e7, + longitude: (position.longitudeI ?? 0) / 1e7, +}); + const MapPage = (): JSX.Element => { const { nodes, waypoints } = useDevice(); - const { rasterSources, darkMode } = useAppStore(); + const { darkMode } = useAppStore(); const { default: map } = useMap(); - const [zoom, setZoom] = useState(0); const [selectedNode, setSelectedNode] = useState(null); - const allNodes = useMemo(() => Array.from(nodes.values()), [nodes]); + // Filter out nodes without a valid position + const validNodes = useMemo( + () => + Array.from(nodes.values()).filter( + (node): node is Protobuf.Mesh.NodeInfo => + Boolean(node.position?.latitudeI), + ), + [nodes], + ); + + const handleMarkerClick = useCallback( + (node: Protobuf.Mesh.NodeInfo, event: { originalEvent: MouseEvent }) => { + event?.originalEvent?.stopPropagation(); + + setSelectedNode(node); + + if (map) { + const position = convertToLatLng(node.position); + map.easeTo({ + center: [position.longitude, position.latitude], + zoom: map?.getZoom(), + }); + } + }, + [map], + ); - const getBBox = useCallback(() => { + // Get the bounds of the map based on the nodes furtherest away from center + const getMapBounds = useCallback(() => { if (!map) { return; } - const nodesWithPosition = allNodes.filter( - (node) => node.position?.latitudeI, - ); - if (!nodesWithPosition.length) { + + if (!validNodes.length) { return; } - if (nodesWithPosition.length === 1) { + if (validNodes.length === 1) { map.easeTo({ zoom: map.getZoom(), center: [ - (nodesWithPosition[0].position?.longitudeI ?? 0) / 1e7, - (nodesWithPosition[0].position?.latitudeI ?? 0) / 1e7, + (validNodes[0].position?.longitudeI ?? 0) / 1e7, + (validNodes[0].position?.latitudeI ?? 0) / 1e7, ], }); return; } const line = lineString( - nodesWithPosition.map((n) => [ + validNodes.map((n) => [ (n.position?.latitudeI ?? 0) / 1e7, (n.position?.longitudeI ?? 0) / 1e7, ]), @@ -69,65 +104,53 @@ const MapPage = (): JSX.Element => { if (center) { map.easeTo(center); } - }, [allNodes, map]); + }, [validNodes, map]); - useEffect(() => { - map?.on("zoom", () => { - setZoom(map?.getZoom() ?? 0); - }); - }, [map]); + // Generate all markers + const markers = useMemo( + () => + validNodes.map((node) => { + const position = convertToLatLng(node.position); + return ( + handleMarkerClick(node, e)} + > + + + ); + }), + [validNodes, handleMarkerClick], + ); useEffect(() => { map?.on("load", () => { - getBBox(); + getMapBounds(); }); - }, [map, getBBox]); + }, [map, getMapBounds]); return ( <> - - - {rasterSources.map((source) => ( - - ))} - - - + + { color: darkMode ? "black" : "", }} /> + + + + {waypoints.map((wp) => ( {
))} - {allNodes.map((node) => { - if (node.position?.latitudeI && node.num !== selectedNode?.num) { - return ( - { - setSelectedNode(node); - map?.easeTo({ - zoom: map.getZoom(), - center: [ - (node.position?.longitudeI ?? 0) / 1e7, - (node.position?.latitudeI ?? 0) / 1e7, - ], - }); - }} - > -
- - - {node.user?.longName || - `!${numberToHexUnpadded(node.num)}`} - -
-
- ); - } - })} - {selectedNode?.position && ( + {markers} + {selectedNode ? ( setSelectedNode(null)} > - )} + ) : null} From 5cc24fd6abbda8b814fe687c04420f865d97d35c Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Fri, 14 Feb 2025 11:41:06 -0500 Subject: [PATCH 3/3] fix: added border around markers --- src/pages/Map.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index 910de059..606f5be6 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -12,7 +12,6 @@ import { AttributionControl, GeolocateControl, Marker, - MarkerEvent, NavigationControl, Popup, ScaleControl, @@ -121,6 +120,7 @@ const MapPage = (): JSX.Element => { > ); @@ -145,7 +145,7 @@ const MapPage = (): JSX.Element => { maxPitch={0} antialias={true} style={{ - filter: darkMode ? "brightness(0.8)" : "", + filter: darkMode ? "brightness(0.9)" : "", }} dragRotate={false} touchZoomRotate={false}