diff --git a/apps/client/src/widgets/collections/geomap/Tooltips.tsx b/apps/client/src/widgets/collections/geomap/Tooltips.tsx
new file mode 100644
index 0000000000..329a00f5bd
--- /dev/null
+++ b/apps/client/src/widgets/collections/geomap/Tooltips.tsx
@@ -0,0 +1,42 @@
+import { MapMouseEvent, Popup } from "maplibre-gl";
+import { useContext, useEffect } from "preact/hooks";
+
+import { ParentMap } from "./map";
+import { MARKER_LAYER } from "./marker_data";
+
+export default function Tooltips() {
+ const map = useContext(ParentMap);
+
+ useEffect(() => {
+ if (!map) return;
+
+ const tooltip = new Popup({
+ closeButton: false,
+ closeOnClick: false,
+ offset: 12,
+ className: "marker-tooltip"
+ });
+
+ function onMouseEnter(e: MapMouseEvent) {
+ const feature = e.features[0];
+ tooltip
+ .setLngLat(feature.geometry.coordinates)
+ .setHTML(`${feature.properties.name}`)
+ .addTo(map);
+ }
+
+ function onMouseLeave() {
+ tooltip.remove();
+ }
+
+ map.on("mouseenter", MARKER_LAYER, onMouseEnter);
+ map.on("mouseleave", MARKER_LAYER, onMouseLeave);
+
+ return () => {
+ map.off("mouseenter", MARKER_LAYER, onMouseEnter);
+ map.off("mouseleave", MARKER_LAYER, onMouseLeave);
+ };
+ }, [ map ]);
+
+ return null;
+}
diff --git a/apps/client/src/widgets/collections/geomap/index.tsx b/apps/client/src/widgets/collections/geomap/index.tsx
index deb326ce4e..7076c08274 100644
--- a/apps/client/src/widgets/collections/geomap/index.tsx
+++ b/apps/client/src/widgets/collections/geomap/index.tsx
@@ -25,6 +25,7 @@ import Map, { GeoMouseEvent } from "./map";
import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, MapLayer } from "./map_layer";
import Marker, { GpxTrack } from "./marker";
import { MARKER_LAYER, MARKER_SVG, useMarkerData } from "./marker_data";
+import Tooltips from "./Tooltips";
const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659];
const DEFAULT_ZOOM = 2;
@@ -119,7 +120,6 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
const containerRef = useRef(null);
const apiRef = useRef(null);
useMarkerData(note, apiRef);
- useHoverTooltip(containerRef, apiRef);
useNoteTreeDrag(containerRef, {
dragEnabled: !isReadOnly,
dragNotEnabledMessage: {
@@ -178,7 +178,7 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
onContextMenu={onContextMenu}
scale={hasScale}
>
- {/* {notes.map(note => )} */}
+
}
@@ -207,40 +207,6 @@ function useLayerData(note: FNote) {
return layerData;
}
-function useHoverTooltip(containerRef: RefObject, mapRef: RefObject) {
- useEffect(() => {
- const map = mapRef.current;
- if (!map) return;
-
- const tooltip = new Popup({
- closeButton: false,
- closeOnClick: false,
- offset: 12,
- className: "marker-tooltip"
- });
-
- function onMouseEnter(e: MapMouseEvent) {
- const feature = e.features[0];
- tooltip
- .setLngLat(feature.geometry.coordinates)
- .setHTML(`${feature.properties.name}`)
- .addTo(map);
- }
-
- function onMouseLeave() {
- tooltip.remove();
- }
-
- map.on("mouseenter", MARKER_LAYER, onMouseEnter);
- map.on("mouseleave", MARKER_LAYER, onMouseLeave);
-
- return () => {
- map.off("mouseenter", MARKER_LAYER, onMouseEnter);
- map.off("mouseleave", MARKER_LAYER, onMouseLeave);
- };
- }, [ mapRef ]);
-}
-
function ToggleReadOnlyButton({ note }: { note: FNote }) {
const [ isReadOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly");
diff --git a/apps/client/src/widgets/collections/geomap/map.tsx b/apps/client/src/widgets/collections/geomap/map.tsx
index a79031e827..53d90e41ba 100644
--- a/apps/client/src/widgets/collections/geomap/map.tsx
+++ b/apps/client/src/widgets/collections/geomap/map.tsx
@@ -2,7 +2,7 @@ import "maplibre-gl/dist/maplibre-gl.css";
import maplibregl, { NavigationControl, type Point } from "maplibre-gl";
import { ComponentChildren, createContext, RefObject } from "preact";
-import { useEffect, useImperativeHandle, useRef } from "preact/hooks";
+import { useEffect, useImperativeHandle, useRef, useState } from "preact/hooks";
import { useElementSize, useSyncedRef } from "../../react/hooks";
import { MapLayer } from "./map_layer";
@@ -38,10 +38,10 @@ function toMapLibreEvent(e: maplibregl.MapMouseEvent): GeoMouseEvent {
}
export default function Map({ coordinates, zoom, layerData, viewportChanged, children, onClick, onContextMenu, scale, apiRef, containerRef: _containerRef, onZoom }: MapProps) {
- const mapRef = useRef(null);
+ const [ map, setMap ] = useState(null);
const containerRef = useSyncedRef(_containerRef);
- useImperativeHandle(apiRef ?? null, () => mapRef.current);
+ useImperativeHandle(apiRef ?? null, () => map);
// Initialize the map.
useEffect(() => {
@@ -93,7 +93,7 @@ export default function Map({ coordinates, zoom, layerData, viewportChanged, chi
showZoom: true
}), "top-left");
- mapRef.current = mapInstance;
+ setMap(mapInstance);
// Load async vector style if needed.
if (layerData.type === "vector" && typeof layerData.style !== "string") {
@@ -104,13 +104,12 @@ export default function Map({ coordinates, zoom, layerData, viewportChanged, chi
return () => {
mapInstance.remove();
- mapRef.current = null;
+ setMap(null);
};
}, []);
// React to layer changes.
useEffect(() => {
- const map = mapRef.current;
if (!map) return;
if (layerData.type === "vector") {
@@ -141,23 +140,21 @@ export default function Map({ coordinates, zoom, layerData, viewportChanged, chi
]
});
}
- }, [ layerData ]);
+ }, [ map, layerData ]);
// React to coordinate changes.
useEffect(() => {
- if (!mapRef.current) return;
-
+ if (!map) return;
const center = Array.isArray(coordinates)
? [coordinates[1], coordinates[0]] as [number, number]
: [coordinates.lng, coordinates.lat] as [number, number];
- mapRef.current.setCenter(center);
- mapRef.current.setZoom(zoom);
- }, [ coordinates, zoom ]);
+ map.setCenter(center);
+ map.setZoom(zoom);
+ }, [ map, coordinates, zoom ]);
// Viewport callback.
useEffect(() => {
- const map = mapRef.current;
if (!map) return;
const updateFn = () => {
@@ -169,19 +166,17 @@ export default function Map({ coordinates, zoom, layerData, viewportChanged, chi
return () => {
map.off("moveend", updateFn);
};
- }, [ viewportChanged ]);
+ }, [ map, viewportChanged ]);
useEffect(() => {
- const map = mapRef.current;
if (!onClick || !map) return;
const handler = (e: maplibregl.MapMouseEvent) => onClick(toMapLibreEvent(e));
map.on("click", handler);
return () => { map.off("click", handler); };
- }, [ onClick ]);
+ }, [ map, onClick ]);
useEffect(() => {
- const map = mapRef.current;
if (!onContextMenu || !map) return;
const handler = (e: maplibregl.MapMouseEvent) => {
@@ -190,37 +185,35 @@ export default function Map({ coordinates, zoom, layerData, viewportChanged, chi
};
map.on("contextmenu", handler);
return () => { map.off("contextmenu", handler); };
- }, [ onContextMenu ]);
+ }, [ map, onContextMenu ]);
useEffect(() => {
- const map = mapRef.current;
if (!onZoom || !map) return;
map.on("zoom", onZoom);
return () => { map.off("zoom", onZoom); };
- }, [ onZoom ]);
+ }, [ map, onZoom ]);
// Scale
useEffect(() => {
- const map = mapRef.current;
if (!scale || !map) return;
const scaleControl = new maplibregl.ScaleControl();
map.addControl(scaleControl);
return () => { map.removeControl(scaleControl); };
- }, [ scale ]);
+ }, [ map, scale ]);
// Adapt to container size changes.
const size = useElementSize(containerRef);
useEffect(() => {
- mapRef.current?.resize();
- }, [ size?.width, size?.height ]);
+ map?.resize();
+ }, [ map, size?.width, size?.height ]);
return (