diff --git a/apps/client/src/widgets/collections/NoteList.tsx b/apps/client/src/widgets/collections/NoteList.tsx
index 3b10d831e..501944158 100644
--- a/apps/client/src/widgets/collections/NoteList.tsx
+++ b/apps/client/src/widgets/collections/NoteList.tsx
@@ -4,6 +4,7 @@ import FNote from "../../entities/fnote";
import "./NoteList.css";
import { ListView, GridView } from "./legacy/ListOrGridView";
import { useEffect, useRef, useState } from "preact/hooks";
+import GeoView from "./geomap";
interface NoteListProps {
note?: FNote | null;
@@ -67,6 +68,8 @@ function getComponentByViewType(note: FNote, noteIds: string[], viewType: ViewTy
return ;
case "grid":
return ;
+ case "geoMap":
+ return ;
}
}
diff --git a/apps/client/src/widgets/collections/geomap/index.css b/apps/client/src/widgets/collections/geomap/index.css
new file mode 100644
index 000000000..668962ff1
--- /dev/null
+++ b/apps/client/src/widgets/collections/geomap/index.css
@@ -0,0 +1,74 @@
+.geo-view {
+ overflow: hidden;
+ position: relative;
+ height: 100%;
+}
+
+.geo-map-container {
+ height: 100%;
+ overflow: hidden;
+}
+
+.leaflet-pane {
+ z-index: 1;
+}
+
+.leaflet-top,
+.leaflet-bottom {
+ z-index: 997;
+}
+
+.geo-map-container.placing-note {
+ cursor: crosshair;
+}
+
+.geo-map-container .marker-pin {
+ position: relative;
+}
+
+.geo-map-container .leaflet-div-icon {
+ position: relative;
+ background: transparent;
+ border: 0;
+ overflow: visible;
+}
+
+.geo-map-container .leaflet-div-icon .icon-shadow {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.geo-map-container .leaflet-div-icon .bx {
+ position: absolute;
+ top: 3px;
+ left: 2px;
+ background-color: white;
+ color: black;
+ padding: 2px;
+ border-radius: 50%;
+ font-size: 17px;
+}
+
+.geo-map-container .leaflet-div-icon .title-label {
+ display: block;
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ font-size: 0.75rem;
+ height: 1rem;
+ color: black;
+ width: 100px;
+ text-align: center;
+ text-overflow: ellipsis;
+ text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white;
+ white-space: no-wrap;
+ overflow: hidden;
+}
+
+.geo-map-container.dark .leaflet-div-icon .title-label {
+ color: white;
+ text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black;
+}
\ No newline at end of file
diff --git a/apps/client/src/widgets/collections/geomap/index.tsx b/apps/client/src/widgets/collections/geomap/index.tsx
new file mode 100644
index 000000000..c116ebd7a
--- /dev/null
+++ b/apps/client/src/widgets/collections/geomap/index.tsx
@@ -0,0 +1,16 @@
+import Map from "./map";
+import "./index.css";
+
+const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659];
+const DEFAULT_ZOOM = 2;
+
+export default function GeoView() {
+ return (
+
+
+
+ );
+}
diff --git a/apps/client/src/widgets/collections/geomap/map.tsx b/apps/client/src/widgets/collections/geomap/map.tsx
new file mode 100644
index 000000000..8a3dd97b1
--- /dev/null
+++ b/apps/client/src/widgets/collections/geomap/map.tsx
@@ -0,0 +1,70 @@
+import { useEffect, useRef, useState } from "preact/hooks";
+import L, { LatLng, Layer } from "leaflet";
+import "leaflet/dist/leaflet.css";
+import { useNoteContext, useNoteLabel } from "../../react/hooks";
+import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS } from "./map_layer";
+
+interface MapProps {
+ coordinates: LatLng | [number, number];
+ zoom: number;
+}
+
+export default function Map({ coordinates, zoom }: MapProps) {
+ const mapRef = useRef(null);
+ const containerRef = useRef(null);
+ const { note } = useNoteContext();
+ const [ layerName ] = useNoteLabel(note, "map:style");
+
+ useEffect(() => {
+ if (!containerRef.current) return;
+ mapRef.current = L.map(containerRef.current, {
+ worldCopyJump: true
+ });
+ }, []);
+
+ // Load the layer asynchronously.
+ const [ layer, setLayer ] = useState();
+ useEffect(() => {
+ async function load() {
+ const layerData = MAP_LAYERS[layerName ?? DEFAULT_MAP_LAYER_NAME];
+
+ if (layerData.type === "vector") {
+ const style = (typeof layerData.style === "string" ? layerData.style : await layerData.style());
+ await import("@maplibre/maplibre-gl-leaflet");
+
+ setLayer(L.maplibreGL({
+ style: style as any
+ }));
+ } else {
+ setLayer(L.tileLayer(layerData.url, {
+ attribution: layerData.attribution,
+ detectRetina: true
+ }));
+ }
+ }
+
+ load();
+ }, [ layerName ]);
+
+ // Attach layer to the map.
+ useEffect(() => {
+ const map = mapRef.current;
+ const layerToAdd = layer;
+ console.log("Add layer ", map, layerToAdd);
+ if (!map || !layerToAdd) return;
+ layerToAdd.addTo(map);
+ return () => layerToAdd.removeFrom(map);
+ }, [ mapRef, layer ]);
+
+ // React to coordinate changes.
+ useEffect(() => {
+ if (!mapRef.current) return;
+ mapRef.current.setView(coordinates, zoom);
+ }, [ mapRef, coordinates, zoom ]);
+
+ return (
+
+
+
+ );
+}
diff --git a/apps/client/src/widgets/view_widgets/geo_view/map_layer.ts b/apps/client/src/widgets/collections/geomap/map_layer.ts
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/map_layer.ts
rename to apps/client/src/widgets/collections/geomap/map_layer.ts
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/colorful/de.json b/apps/client/src/widgets/collections/geomap/styles/colorful/de.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/colorful/de.json
rename to apps/client/src/widgets/collections/geomap/styles/colorful/de.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/colorful/en.json b/apps/client/src/widgets/collections/geomap/styles/colorful/en.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/colorful/en.json
rename to apps/client/src/widgets/collections/geomap/styles/colorful/en.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/colorful/nolabel.json b/apps/client/src/widgets/collections/geomap/styles/colorful/nolabel.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/colorful/nolabel.json
rename to apps/client/src/widgets/collections/geomap/styles/colorful/nolabel.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/colorful/style.json b/apps/client/src/widgets/collections/geomap/styles/colorful/style.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/colorful/style.json
rename to apps/client/src/widgets/collections/geomap/styles/colorful/style.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/de.json b/apps/client/src/widgets/collections/geomap/styles/eclipse/de.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/de.json
rename to apps/client/src/widgets/collections/geomap/styles/eclipse/de.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/en.json b/apps/client/src/widgets/collections/geomap/styles/eclipse/en.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/en.json
rename to apps/client/src/widgets/collections/geomap/styles/eclipse/en.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/nolabel.json b/apps/client/src/widgets/collections/geomap/styles/eclipse/nolabel.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/nolabel.json
rename to apps/client/src/widgets/collections/geomap/styles/eclipse/nolabel.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/style.json b/apps/client/src/widgets/collections/geomap/styles/eclipse/style.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/eclipse/style.json
rename to apps/client/src/widgets/collections/geomap/styles/eclipse/style.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/de.json b/apps/client/src/widgets/collections/geomap/styles/graybeard/de.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/de.json
rename to apps/client/src/widgets/collections/geomap/styles/graybeard/de.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/en.json b/apps/client/src/widgets/collections/geomap/styles/graybeard/en.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/en.json
rename to apps/client/src/widgets/collections/geomap/styles/graybeard/en.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/nolabel.json b/apps/client/src/widgets/collections/geomap/styles/graybeard/nolabel.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/nolabel.json
rename to apps/client/src/widgets/collections/geomap/styles/graybeard/nolabel.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/style.json b/apps/client/src/widgets/collections/geomap/styles/graybeard/style.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/graybeard/style.json
rename to apps/client/src/widgets/collections/geomap/styles/graybeard/style.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/de.json b/apps/client/src/widgets/collections/geomap/styles/neutrino/de.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/de.json
rename to apps/client/src/widgets/collections/geomap/styles/neutrino/de.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/en.json b/apps/client/src/widgets/collections/geomap/styles/neutrino/en.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/en.json
rename to apps/client/src/widgets/collections/geomap/styles/neutrino/en.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/nolabel.json b/apps/client/src/widgets/collections/geomap/styles/neutrino/nolabel.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/nolabel.json
rename to apps/client/src/widgets/collections/geomap/styles/neutrino/nolabel.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/style.json b/apps/client/src/widgets/collections/geomap/styles/neutrino/style.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/neutrino/style.json
rename to apps/client/src/widgets/collections/geomap/styles/neutrino/style.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/shadow/de.json b/apps/client/src/widgets/collections/geomap/styles/shadow/de.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/shadow/de.json
rename to apps/client/src/widgets/collections/geomap/styles/shadow/de.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/shadow/en.json b/apps/client/src/widgets/collections/geomap/styles/shadow/en.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/shadow/en.json
rename to apps/client/src/widgets/collections/geomap/styles/shadow/en.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/shadow/nolabel.json b/apps/client/src/widgets/collections/geomap/styles/shadow/nolabel.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/shadow/nolabel.json
rename to apps/client/src/widgets/collections/geomap/styles/shadow/nolabel.json
diff --git a/apps/client/src/widgets/view_widgets/geo_view/styles/shadow/style.json b/apps/client/src/widgets/collections/geomap/styles/shadow/style.json
similarity index 100%
rename from apps/client/src/widgets/view_widgets/geo_view/styles/shadow/style.json
rename to apps/client/src/widgets/collections/geomap/styles/shadow/style.json
diff --git a/apps/client/src/widgets/ribbon/collection-properties-config.ts b/apps/client/src/widgets/ribbon/collection-properties-config.ts
index 6a0c74d04..d53513a43 100644
--- a/apps/client/src/widgets/ribbon/collection-properties-config.ts
+++ b/apps/client/src/widgets/ribbon/collection-properties-config.ts
@@ -2,7 +2,7 @@ import { t } from "i18next";
import FNote from "../../entities/fnote";
import attributes from "../../services/attributes";
import NoteContextAwareWidget from "../note_context_aware_widget";
-import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, type MapLayer } from "../view_widgets/geo_view/map_layer";
+import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, type MapLayer } from "../collections/geomap/map_layer";
import { ViewTypeOptions } from "../collections/interface";
interface BookConfig {
diff --git a/apps/client/src/widgets/view_widgets/geo_view/index.ts b/apps/client/src/widgets/view_widgets/geo_view/index.ts
index 9b194f9df..845df3813 100644
--- a/apps/client/src/widgets/view_widgets/geo_view/index.ts
+++ b/apps/client/src/widgets/view_widgets/geo_view/index.ts
@@ -1,7 +1,6 @@
import ViewMode, { ViewModeArgs } from "../view_mode.js";
import L from "leaflet";
import type { GPX, LatLng, Layer, LeafletMouseEvent, Map, Marker } from "leaflet";
-import "leaflet/dist/leaflet.css";
import SpacedUpdate from "../../../services/spaced_update.js";
import { t } from "../../../services/i18n.js";
import processNoteWithMarker, { processNoteWithGpxTrack } from "./markers.js";
@@ -13,88 +12,6 @@ import { openMapContextMenu } from "./context_menu.js";
import attributes from "../../../services/attributes.js";
import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS } from "./map_layer.js";
-const TPL = /*html*/`
-`;
-
interface MapData {
view?: {
center?: LatLng | [number, number];
@@ -102,8 +19,6 @@ interface MapData {
};
}
-const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659];
-const DEFAULT_ZOOM = 2;
export const LOCATION_ATTRIBUTE = "geolocation";
enum State {
@@ -142,27 +57,8 @@ export default class GeoView extends ViewMode {
}
async renderMap() {
- const map = L.map(this.$container[0], {
- worldCopyJump: true
- });
+ const layerName = this.parentNote.getLabelValue("map:style") ?? ;
- const layerName = this.parentNote.getLabelValue("map:style") ?? DEFAULT_MAP_LAYER_NAME;
- let layer: Layer;
- const layerData = MAP_LAYERS[layerName];
-
- if (layerData.type === "vector") {
- const style = (typeof layerData.style === "string" ? layerData.style : await layerData.style());
- await import("@maplibre/maplibre-gl-leaflet");
-
- layer = L.maplibreGL({
- style: style as any
- });
- } else {
- layer = L.tileLayer(layerData.url, {
- attribution: layerData.attribution,
- detectRetina: true
- });
- }
if (this.parentNote.hasLabel("map:scale")) {
L.control.scale().addTo(map);
@@ -220,7 +116,6 @@ export default class GeoView extends ViewMode {
// Restore viewport position & zoom
const center = parsedContent?.view?.center ?? DEFAULT_COORDINATES;
const zoom = parsedContent?.view?.zoom ?? DEFAULT_ZOOM;
- map.setView(center, zoom);
}
private onSave() {