();
-
- // Set map position when map is available or location gets updated
- useEffect(() => {
- function updateNodeMarker(lat, lon) {
- setNodeMarker([lat, lon]);
- }
- const mapInstance = mapRef.current;
-
- if (!loading && mapInstance && stationLat) {
- mapInstance.setView([+stationLat, +stationLon], 13);
- updateNodeMarker(stationLat, stationLon);
- }
- }, [stationLat, stationLon, loading]);
-
- // Center the map on the node also when editting is turned on
- useEffect(() => {
- const map = mapRef.current;
- if (map && stationLat) {
- editting && map.setView([+stationLat, +stationLon], 13);
- }
- }, [mapRef, editting, stationLat, stationLon]);
-
- function onConfirmLocation() {
- const position = mapRef.current.getCenter();
- changeLocation({ lat: position.lat, lon: position.lng });
- if (communityLayer) {
- // Hide the community view, to avoid outdated links
- toogleCommunityLayer();
- }
- }
-
- function toogleCommunityLayer() {
- if (communityLayer) {
- mapRef.current.removeLayer(communityLayer);
- setCommunityLayer(null);
- } else {
- const layer = getCommunityLayer(
- boardData.hostname,
- stationLat,
- stationLon,
- nodesData
- );
- layer.addTo(mapRef.current);
- setCommunityLayer(layer);
- }
- }
-
- function isReady() {
- return !loading && typeof stationLat !== "undefined";
- }
-
- function toogleEdition() {
- setEditting(!editting);
- }
-
- if (isAssetError) {
- return (
-
- Cannot load map, check your internet connection
-
- );
- }
-
- return (
- <>
- {(!isReady() || submitting) && (
-
-
-
- )}
- {isReady() && (
-
-
-
-
-
-
-
-
-
-
-
-
- {nodeMarker && (
-
- )}
- {editting && (
-
- )}
-
- )}
- {isReady() && (
-
- {editting && (
-
- )}
- {!editting && (
-
- )}
-
-
-
- )}
- >
- );
-};
-
-export default LocatePage;
diff --git a/plugins/lime-plugin-mesh-wide/src/containers/LocateNode.tsx b/plugins/lime-plugin-mesh-wide/src/containers/LocateNode.tsx
new file mode 100644
index 000000000..2fb75164d
--- /dev/null
+++ b/plugins/lime-plugin-mesh-wide/src/containers/LocateNode.tsx
@@ -0,0 +1,109 @@
+import { Trans } from "@lingui/macro";
+import { useMemo, useState } from "preact/hooks";
+
+import Loading from "components/loading";
+import { usePublishAll } from "components/shared-state/SharedStateQueries";
+import { sharedStateQueries } from "components/shared-state/SharedStateQueriesKeys";
+
+import style from "plugins/lime-plugin-mesh-wide/src/containers/style.less";
+import { useLocateNode } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocateNode";
+import {
+ getLocationQueryKey,
+ useChangeLocation,
+ useLocation,
+} from "plugins/lime-plugin-mesh-wide/src/locateNodeQueries";
+import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries";
+import { useNodeStatus } from "plugins/lime-plugin-rx/src/rxQueries";
+
+import queryCache from "utils/queryCache";
+
+const LocateNode = ({}) => {
+ const { editingLocation, setEditingLocation, mapRef } = useLocateNode();
+ const { data: selectedMapFeature } = useSelectedMapFeature();
+ const { data: nodeLocation, isLoading: isLoadingNodeLocation } =
+ useLocation({});
+ const [isLoading, setIsLoading] = useState(false);
+
+ // Code to force to update shared state with new location
+ const { data: node } = useNodeStatus();
+ const ip = useMemo(() => {
+ if (!node) return null;
+ return node?.ips
+ .find((ip) => ip.version === "4")
+ ?.address?.split("/")[0];
+ }, [node]);
+ const { mutateAsync: publishAll } = usePublishAll({
+ ip,
+ });
+
+ const onNewLocationSet = async () => {
+ try {
+ await queryCache.invalidateQueries(getLocationQueryKey);
+ await publishAll({ ip });
+ await queryCache.invalidateQueries(
+ sharedStateQueries.getFromSharedState("node_info")
+ );
+ } finally {
+ toogleEdition();
+ setIsLoading(false);
+ }
+ };
+
+ const { mutate: changeLocation } = useChangeLocation({
+ onSettled: onNewLocationSet,
+ });
+
+ let stationLat = null;
+ if (nodeLocation.location.lat !== "FIXME")
+ stationLat = nodeLocation.location.lat;
+ let stationLon = null;
+ if (nodeLocation.location.lon !== "FIXME") {
+ stationLon = nodeLocation.location.lon;
+ }
+
+ const hasLocation = stationLat && stationLon;
+ const loaded = !isLoadingNodeLocation && typeof stationLat !== "undefined";
+
+ const toogleEdition = () => {
+ setEditingLocation((prev) => !prev);
+ };
+
+ const confirmLocation = async () => {
+ setIsLoading(true);
+ const position = mapRef.current.getCenter();
+ changeLocation({ lat: position.lat, lon: position.lng });
+ };
+
+ if (!loaded || selectedMapFeature) {
+ return null;
+ }
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+ {editingLocation && (
+
+ )}
+
+
+ );
+};
+
+export default LocateNode;
diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx
index 2da02c117..973162ddd 100644
--- a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx
@@ -1,6 +1,5 @@
-import L from "leaflet";
import { ComponentChildren } from "preact";
-import { useEffect, useRef } from "preact/hooks";
+import { useEffect } from "preact/hooks";
import {
LayerGroup,
LayersControl,
@@ -10,22 +9,29 @@ import {
import { MeshWideMapTypes } from "components/shared-state/SharedStateTypes";
-import {
- useLoadLeaflet,
- useLocation,
-} from "plugins/lime-plugin-locate/src/locateQueries";
+import LocateNode from "plugins/lime-plugin-mesh-wide/src/containers/LocateNode";
import {
BabelLinksLayer,
BatmanLinksLayer,
WifiLinksLayer,
} from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers";
import NodesLayer from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer";
+import style from "plugins/lime-plugin-mesh-wide/src/containers/style.less";
+import { useLocateNode } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocateNode";
+import {
+ useLoadLeaflet,
+ useLocation,
+} from "plugins/lime-plugin-mesh-wide/src/locateNodeQueries";
import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries";
const openStreetMapTileString = "https://{s}.tile.osm.org/{z}/{x}/{y}.png";
const openStreetMapAttribution =
'© OpenStreetMap contributors';
+const gmSatellite = "https://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}";
+const gmHybrid = "https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}";
+const gmSubdomains = ["mt0", "mt1", "mt2", "mt3"];
+
interface ILayersChecked {
nodes?: boolean;
wifiLinks?: boolean;
@@ -33,12 +39,7 @@ interface ILayersChecked {
babelLinks?: boolean;
}
-export const MeshWideMap = ({
- nodes = true,
- wifiLinks = true,
- batmanLinks = false,
- babelLinks = false,
-}: ILayersChecked) => {
+export const MeshWideMap = (layers: ILayersChecked) => {
const { data: selectedMapFeature, setData: setSelectedMapFeature } =
useSelectedMapFeature();
@@ -50,7 +51,8 @@ export const MeshWideMap = ({
enabled: !!leafletData,
});
- const mapRef = useRef();
+ const { mapRef, editingLocation } = useLocateNode();
+
const loading = assetsLoading || isLoadingLocation;
useEffect(() => {
@@ -81,6 +83,34 @@ export const MeshWideMap = ({
}
}, [loading, nodeLocation]);
+ return (
+
+
+
+
+
+ {editingLocation && (
+
+ )}
+
+ );
+};
+
+const LayersControlMeshWide = ({
+ nodes = true,
+ wifiLinks = true,
+ batmanLinks = false,
+ babelLinks = false,
+}: ILayersChecked) => {
// @ts-ignore
const mapSupportedLayers: Record<
keyof MeshWideMapTypes,
@@ -105,30 +135,35 @@ export const MeshWideMap = ({
};
return (
-
+
+ {Object.values(mapSupportedLayers).map(
+ ({ name, layer, checked }, k) => (
+
+ {layer}
+
+ )
+ )}
+
+ );
+};
+
+const LayersControlMaps = () => (
+
+
-
- {Object.values(mapSupportedLayers).map(
- ({ name, layer, checked }, k) => (
-
- {layer}
-
- )
- )}
-
-
- );
-};
+
+
+
+
+
+
+
+
+);
diff --git a/plugins/lime-plugin-locate/src/style.less b/plugins/lime-plugin-mesh-wide/src/containers/style.less
similarity index 89%
rename from plugins/lime-plugin-locate/src/style.less
rename to plugins/lime-plugin-mesh-wide/src/containers/style.less
index 5a6fc9ec4..d5d965405 100644
--- a/plugins/lime-plugin-locate/src/style.less
+++ b/plugins/lime-plugin-mesh-wide/src/containers/style.less
@@ -1,8 +1,4 @@
-.mapContainer {
- width: 100vw;
- height: ~"calc(100vh - 56px)";
-}
-
+// Styles for locate node. Inherited from old implementation
.locationMarker {
width: 10px;
height: 10px;
@@ -27,6 +23,7 @@
button {
min-width: 60%;
background-color: white;
+ font-size: 15px;
}
}
diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useLocateNode.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useLocateNode.tsx
new file mode 100644
index 000000000..9d067eb54
--- /dev/null
+++ b/plugins/lime-plugin-mesh-wide/src/hooks/useLocateNode.tsx
@@ -0,0 +1,38 @@
+import L from "leaflet";
+import { ComponentChildren, createContext } from "preact";
+import { useContext, useRef, useState } from "preact/hooks";
+
+const LocateNodeContext = createContext<
+ ReturnType | undefined
+>(undefined);
+
+export const LocateNodeProvider = ({
+ children,
+}: {
+ children: ComponentChildren;
+}) => {
+ const locateNode = useLocateNodeProvider();
+ return (
+
+ {children}
+
+ );
+};
+
+const useLocateNodeProvider = () => {
+ const [editingLocation, setEditingLocation] = useState(false);
+ // MapRef is stored on here but should be moved to a more general place if used further
+ const mapRef = useRef();
+
+ return { editingLocation, setEditingLocation, mapRef };
+};
+
+export const useLocateNode = () => {
+ const context = useContext(LocateNodeContext);
+ if (context === null) {
+ throw new Error(
+ "useLocateNode must be used within a LocateNodeProvider"
+ );
+ }
+ return context;
+};
diff --git a/plugins/lime-plugin-locate/src/leafletUtils.ts b/plugins/lime-plugin-mesh-wide/src/lib/leafletUtils.ts
similarity index 98%
rename from plugins/lime-plugin-locate/src/leafletUtils.ts
rename to plugins/lime-plugin-mesh-wide/src/lib/leafletUtils.ts
index e0aa70f07..7022b75b0 100644
--- a/plugins/lime-plugin-locate/src/leafletUtils.ts
+++ b/plugins/lime-plugin-mesh-wide/src/lib/leafletUtils.ts
@@ -1,4 +1,4 @@
-import { DivIconOptions, IconOptions } from "leaflet";
+import { IconOptions } from "leaflet";
const leafletVersion = "1.9.3";
diff --git a/plugins/lime-plugin-locate/src/locateApi.js b/plugins/lime-plugin-mesh-wide/src/locateApi.js
similarity index 74%
rename from plugins/lime-plugin-locate/src/locateApi.js
rename to plugins/lime-plugin-mesh-wide/src/locateApi.js
index 3e2d54288..3a61484aa 100644
--- a/plugins/lime-plugin-locate/src/locateApi.js
+++ b/plugins/lime-plugin-mesh-wide/src/locateApi.js
@@ -2,9 +2,6 @@ import api from "utils/uhttpd.service";
export const getLocation = () => api.call("lime-location", "get", {});
-export const getNodesandlinks = async () =>
- api.call("lime-location", "all_nodes_and_links", {});
-
export const changeLocation = async (location) => {
return await api.call("lime-location", "set", {
lat: location.lat.toFixed(5),
diff --git a/plugins/lime-plugin-locate/src/locateQueries.tsx b/plugins/lime-plugin-mesh-wide/src/locateNodeQueries.tsx
similarity index 77%
rename from plugins/lime-plugin-locate/src/locateQueries.tsx
rename to plugins/lime-plugin-mesh-wide/src/locateNodeQueries.tsx
index 45c1f399a..c4a9e4d44 100644
--- a/plugins/lime-plugin-locate/src/locateQueries.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/locateNodeQueries.tsx
@@ -1,11 +1,10 @@
import { useMutation, useQuery } from "@tanstack/react-query";
-import { loadLeafLet } from "plugins/lime-plugin-locate/src/leafletUtils";
+import { loadLeafLet } from "plugins/lime-plugin-mesh-wide/src/lib/leafletUtils";
import {
changeLocation,
getLocation,
- getNodesandlinks,
-} from "plugins/lime-plugin-locate/src/locateApi";
+} from "plugins/lime-plugin-mesh-wide/src/locateApi";
import queryCache from "utils/queryCache";
@@ -17,8 +16,9 @@ export interface INodeLocation {
default: boolean;
}
+export const getLocationQueryKey = ["lime-location", "get"];
export function useLocation(params) {
- return useQuery(["lime-location", "get"], getLocation, {
+ return useQuery(getLocationQueryKey, getLocation, {
placeholderData: {
default: false,
location: {
@@ -30,16 +30,6 @@ export function useLocation(params) {
});
}
-export function useNodesandlinks(params) {
- return useQuery(
- ["lime-location", "all_nodes_and_links"],
- getNodesandlinks,
- {
- ...params,
- }
- );
-}
-
interface IChangeUserParams {
lat: number;
lon: number;
diff --git a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx
index 27e368f2b..88038e406 100644
--- a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx
@@ -3,16 +3,17 @@ import React from "react";
import Loading from "components/loading";
-import { useLoadLeaflet } from "plugins/lime-plugin-locate/src/locateQueries";
import { FloatingAlert } from "plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert";
import { MeshWideMap } from "plugins/lime-plugin-mesh-wide/src/containers/Map";
import { SelectedFeatureBottomSheet } from "plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet";
+import { LocateNodeProvider } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocateNode";
import {
BabelLinksProvider,
BatmanLinksProvider,
MeshWideLinksProvider,
} from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks";
import { NodesProvider } from "plugins/lime-plugin-mesh-wide/src/hooks/useNodes";
+import { useLoadLeaflet } from "plugins/lime-plugin-mesh-wide/src/locateNodeQueries";
const MeshWide = () => {
const {
@@ -53,13 +54,15 @@ const MeshWide = () => {
const MeshWidePage = () => {
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
);
};
diff --git a/plugins/lime-plugin-rx/src/sections/internetPath.tsx b/plugins/lime-plugin-rx/src/sections/internetPath.tsx
index 6d51cf256..57c9875c4 100644
--- a/plugins/lime-plugin-rx/src/sections/internetPath.tsx
+++ b/plugins/lime-plugin-rx/src/sections/internetPath.tsx
@@ -124,7 +124,7 @@ export const InternetPath = () => {
-