diff --git a/apps/client/src/widgets/floating_buttons/geo_map_button.ts b/apps/client/src/widgets/floating_buttons/geo_map_button.ts index 945be41d1..7e59eeaf2 100644 --- a/apps/client/src/widgets/floating_buttons/geo_map_button.ts +++ b/apps/client/src/widgets/floating_buttons/geo_map_button.ts @@ -23,7 +23,9 @@ const TPL = /*html*/`\ export default class GeoMapButtons extends NoteContextAwareWidget { isEnabled() { - return super.isEnabled() && this.note?.getLabelValue("viewType") === "geoMap"; + return super.isEnabled() + && this.note?.getLabelValue("viewType") === "geoMap" + && !this.note.hasLabel("readOnly"); } doRender() { diff --git a/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts b/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts index f436c820c..571e99017 100644 --- a/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts +++ b/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts @@ -39,10 +39,20 @@ export default class ToggleReadOnlyButton extends OnClickButtonWidget { } isEnabled() { - return super.isEnabled() - && this.note?.type === "mermaid" - && this.note?.isContentAvailable() - && this.noteContext?.viewScope?.viewMode === "default"; + if (!super.isEnabled()) { + return false; + } + + if (!this?.note?.isContentAvailable()) { + return false; + } + + if (this.noteContext?.viewScope?.viewMode !== "default") { + return false; + } + + return this.note.type === "mermaid" || + (this.note.getLabelValue("viewType") === "geoMap"); } } diff --git a/apps/client/src/widgets/view_widgets/geo_view/context_menu.ts b/apps/client/src/widgets/view_widgets/geo_view/context_menu.ts index 768a17d10..c2b405ecf 100644 --- a/apps/client/src/widgets/view_widgets/geo_view/context_menu.ts +++ b/apps/client/src/widgets/view_widgets/geo_view/context_menu.ts @@ -1,22 +1,31 @@ import type { LatLng, LeafletMouseEvent } from "leaflet"; -import appContext from "../../../components/app_context.js"; -import contextMenu from "../../../menus/context_menu.js"; +import appContext, { type CommandMappings } from "../../../components/app_context.js"; +import contextMenu, { type MenuItem } from "../../../menus/context_menu.js"; import linkContextMenu from "../../../menus/link_context_menu.js"; import { t } from "../../../services/i18n.js"; import { createNewNote } from "./editing.js"; import { copyTextWithToast } from "../../../services/clipboard_ext.js"; import link from "../../../services/link.js"; -export default function openContextMenu(noteId: string, e: LeafletMouseEvent) { +export default function openContextMenu(noteId: string, e: LeafletMouseEvent, isEditable: boolean) { + let items: MenuItem[] = [ + ...buildGeoLocationItem(e), + { title: "----" }, + ...linkContextMenu.getItems(), + ]; + + if (isEditable) { + items = [ + ...items, + { title: "----" }, + { title: t("geo-map-context.remove-from-map"), command: "deleteFromMap", uiIcon: "bx bx-trash" } + ]; + } + contextMenu.show({ x: e.originalEvent.pageX, y: e.originalEvent.pageY, - items: [ - ...buildGeoLocationItem(e), - ...linkContextMenu.getItems(), - { title: "----" }, - { title: t("geo-map-context.remove-from-map"), command: "deleteFromMap", uiIcon: "bx bx-trash" } - ], + items, selectMenuItemHandler: ({ command }, e) => { if (command === "deleteFromMap") { appContext.triggerCommand(command, { noteId }); @@ -29,14 +38,23 @@ export default function openContextMenu(noteId: string, e: LeafletMouseEvent) { }); } -export function openMapContextMenu(noteId: string, e: LeafletMouseEvent) { +export function openMapContextMenu(noteId: string, e: LeafletMouseEvent, isEditable: boolean) { + let items: MenuItem[] = [ + ...buildGeoLocationItem(e) + ]; + + if (isEditable) { + items = [ + ...items, + { title: "----" }, + { title: t("geo-map-context.add-note"), command: "addNoteToMap", uiIcon: "bx bx-plus" } + ] + } + contextMenu.show({ x: e.originalEvent.pageX, y: e.originalEvent.pageY, - items: [ - ...buildGeoLocationItem(e), - { title: t("geo-map-context.add-note"), command: "addNoteToMap", uiIcon: "bx bx-plus" } - ], + items, selectMenuItemHandler: ({ command }) => { switch (command) { case "addNoteToMap": @@ -64,9 +82,6 @@ function buildGeoLocationItem(e: LeafletMouseEvent) { title: t("geo-map-context.open-location"), uiIcon: "bx bx-map-alt", handler: () => link.goToLinkExt(null, `geo:${e.latlng.lat},${e.latlng.lng}`) - }, - { - title: "----" } ]; } 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 4af9b47cb..00db8be25 100644 --- a/apps/client/src/widgets/view_widgets/geo_view/index.ts +++ b/apps/client/src/widgets/view_widgets/geo_view/index.ts @@ -152,12 +152,16 @@ export default class GeoView extends ViewMode { this.#restoreViewportAndZoom(); + const isEditable = !this.isReadOnly; const updateFn = () => this.spacedUpdate.scheduleUpdate(); map.on("moveend", updateFn); map.on("zoomend", updateFn); map.on("click", (e) => this.#onMapClicked(e)) - map.on("contextmenu", (e) => openMapContextMenu(this.parentNote.noteId, e)); - setupDragging(this.$container, map, this.parentNote.noteId); + map.on("contextmenu", (e) => openMapContextMenu(this.parentNote.noteId, e, isEditable)); + + if (isEditable) { + setupDragging(this.$container, map, this.parentNote.noteId); + } this.#reloadMarkers(); @@ -219,6 +223,7 @@ export default class GeoView extends ViewMode { // Add the new markers. this.currentMarkerData = {}; const notes = await this.parentNote.getChildNotes(); + const draggable = !this.isReadOnly; for (const childNote of notes) { if (childNote.mime === "application/gpx+xml") { const track = await processNoteWithGpxTrack(this.map, childNote); @@ -228,7 +233,7 @@ export default class GeoView extends ViewMode { const latLng = childNote.getAttributeValue("label", LOCATION_ATTRIBUTE); if (latLng) { - const marker = processNoteWithMarker(this.map, childNote, latLng); + const marker = processNoteWithMarker(this.map, childNote, latLng, draggable); this.currentMarkerData[childNote.noteId] = marker; } } diff --git a/apps/client/src/widgets/view_widgets/geo_view/markers.ts b/apps/client/src/widgets/view_widgets/geo_view/markers.ts index 8853734ec..10a7fae65 100644 --- a/apps/client/src/widgets/view_widgets/geo_view/markers.ts +++ b/apps/client/src/widgets/view_widgets/geo_view/markers.ts @@ -9,20 +9,23 @@ import { moveMarker } from "./editing.js"; let gpxLoaded = false; -export default function processNoteWithMarker(map: Map, note: FNote, location: string) { +export default function processNoteWithMarker(map: Map, note: FNote, location: string, isEditable: boolean) { const [lat, lng] = location.split(",", 2).map((el) => parseFloat(el)); const icon = buildIcon(note.getIcon(), note.getColorClass(), note.title); const newMarker = marker(latLng(lat, lng), { icon, - draggable: true, + draggable: isEditable, autoPan: true, autoPanSpeed: 5 - }) - .addTo(map) - .on("moveend", (e) => { + }).addTo(map); + + if (isEditable) { + newMarker.on("moveend", (e) => { moveMarker(note.noteId, (e.target as Marker).getLatLng()); }); + } + newMarker.on("mousedown", ({ originalEvent }) => { // Middle click to open in new tab if (originalEvent.button === 1) { @@ -33,7 +36,7 @@ export default function processNoteWithMarker(map: Map, note: FNote, location: s } }); newMarker.on("contextmenu", (e) => { - openContextMenu(note.noteId, e); + openContextMenu(note.noteId, e, isEditable); }); const el = newMarker.getElement(); diff --git a/apps/client/src/widgets/view_widgets/view_mode.ts b/apps/client/src/widgets/view_widgets/view_mode.ts index d8c4314eb..f3706da4a 100644 --- a/apps/client/src/widgets/view_widgets/view_mode.ts +++ b/apps/client/src/widgets/view_widgets/view_mode.ts @@ -44,6 +44,10 @@ export default abstract class ViewMode extends Component { return false; } + get isReadOnly() { + return this.parentNote.hasLabel("readOnly"); + } + get viewStorage() { if (this._viewStorage) { return this._viewStorage;