From e1bb7d93204cd6b6e1f054b6610e0a03e64f9e44 Mon Sep 17 00:00:00 2001 From: livio Date: Tue, 22 Sep 2026 15:47:54 +0200 Subject: [PATCH] =?UTF-8?q?Correggi=20visibilit=C3=A0=20oggetti=20durante?= =?UTF-8?q?=20refresh=20GPS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LMEMappeCatastaliApp.csproj | 4 +- Services/AzureMapsService.cs | 2 +- Services/NetworkLocationService.cs | 2 +- wwwroot/css/app.css | 25 +++++- wwwroot/js/lme-map.js | 133 ++++++++++++++++++++++++----- 5 files changed, 141 insertions(+), 25 deletions(-) diff --git a/LMEMappeCatastaliApp.csproj b/LMEMappeCatastaliApp.csproj index 242c53d..3c823c8 100644 --- a/LMEMappeCatastaliApp.csproj +++ b/LMEMappeCatastaliApp.csproj @@ -28,8 +28,8 @@ com.companyname.lmemappecatastaliapp - 0.2.18 - 22 + 0.2.19 + 23 None diff --git a/Services/AzureMapsService.cs b/Services/AzureMapsService.cs index 4ad80f3..734efb2 100644 --- a/Services/AzureMapsService.cs +++ b/Services/AzureMapsService.cs @@ -13,7 +13,7 @@ public sealed class AzureMapsService public AzureMapsService() { - _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.18"); + _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.19"); _httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json"); } diff --git a/Services/NetworkLocationService.cs b/Services/NetworkLocationService.cs index f573df6..c789f6f 100644 --- a/Services/NetworkLocationService.cs +++ b/Services/NetworkLocationService.cs @@ -13,7 +13,7 @@ public sealed class NetworkLocationService public NetworkLocationService() { - httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.18"); + httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.19"); } public async Task GetApproximateLocationAsync( diff --git a/wwwroot/css/app.css b/wwwroot/css/app.css index c5f0cb0..65f06da 100644 --- a/wwwroot/css/app.css +++ b/wwwroot/css/app.css @@ -274,7 +274,7 @@ input[type="checkbox"] { .layer-manager-block > summary, .layer-manager-object > summary { display: grid; - grid-template-columns: 28px 20px minmax(0, 1fr) auto; + grid-template-columns: 28px 20px minmax(0, 1fr) auto auto; align-items: center; gap: 6px; min-height: 38px; @@ -302,6 +302,29 @@ input[type="checkbox"] { cursor: grab; } +.layer-move-buttons { + display: inline-grid; + grid-template-columns: 24px 24px; + gap: 2px; +} + +.layer-move-buttons button { + width: 24px; + height: 28px; + padding: 0; + border: 1px solid #cbd5da; + border-radius: 4px; + background: #f6f8f9; + color: var(--ink); + font-size: 16px; + font-weight: 800; + line-height: 1; +} + +.layer-move-buttons button:active { + background: #dce8ec; +} + .layer-manager-title { min-width: 0; overflow-wrap: anywhere; diff --git a/wwwroot/js/lme-map.js b/wwwroot/js/lme-map.js index 5db60b4..0ac3f42 100644 --- a/wwwroot/js/lme-map.js +++ b/wwwroot/js/lme-map.js @@ -49,6 +49,8 @@ const lmeState = { azureMapsKey: null, azureAttribution: null, managerHighlight: null, + managerHighlightedObjectId: null, + managerHighlightedCategoryKey: null, managerHiddenObjects: new Map(), managerHiddenObjectIds: new Set(), managerHiddenCategories: new Set(), @@ -1181,6 +1183,7 @@ function refreshLayerManager() { }); applyManagedVisualOrder(container); bindLayerManagerDrag(container); + bindLayerManagerMoveButtons(container); } function renderLayerManagerCategory(category, records) { @@ -1188,10 +1191,13 @@ function renderLayerManagerCategory(category, records) { group.className = "layer-manager-group"; group.dataset.dragType = "category"; group.dataset.categoryKey = category.key; - const visible = !lmeState.managerHiddenCategories.has(category.key) - && (!category.roots.length || category.roots.every(layer => lmeState.map.hasLayer(layer))); - group.innerHTML = `${escapeHtml(category.label)}${records.length}
`; + const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length; + const categoryVisible = !lmeState.managerHiddenCategories.has(category.key) + && (!category.roots.length || category.roots.some(layer => lmeState.map.hasLayer(layer))); + const visible = categoryVisible; + group.innerHTML = `${escapeHtml(category.label)}${layerManagerMoveButtons("gruppo")}${records.length}
`; const checkbox = group.querySelector("input"); + checkbox.indeterminate = categoryVisible && records.length > 0 && visibleCount < records.length; checkbox.addEventListener("click", event => event.stopPropagation()); checkbox.addEventListener("change", () => setManagedCategoryVisible(category, checkbox.checked)); const children = group.querySelector(".layer-manager-children"); @@ -1217,7 +1223,7 @@ function renderLayerManagerBlock(category, source, records) { block.dataset.blockKey = source; const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length; const visible = visibleCount === records.length; - block.innerHTML = `${escapeHtml(source)}${records.length}
`; + block.innerHTML = `${escapeHtml(source)}${layerManagerMoveButtons("blocco")}${records.length}
`; const checkbox = block.querySelector("input"); checkbox.indeterminate = visibleCount > 0 && !visible; checkbox.addEventListener("click", event => event.stopPropagation()); @@ -1236,7 +1242,7 @@ function renderLayerManagerObject(record, index) { object.dataset.dragType = "object"; object.dataset.objectId = record.id; const visible = !lmeState.managerHiddenObjectIds.has(record.id); - object.innerHTML = `${escapeHtml(managedObjectLabel(record, index))}›
`; + object.innerHTML = `${escapeHtml(managedObjectLabel(record, index))}${layerManagerMoveButtons("oggetto")}›
`; const checkbox = object.querySelector("input"); checkbox.addEventListener("click", event => event.stopPropagation()); checkbox.addEventListener("change", () => setManagedObjectVisible(record, checkbox.checked, true)); @@ -1267,7 +1273,10 @@ function setManagedCategoryVisible(category, visible) { if (visible) { lmeState.managerHiddenCategories.delete(category.key); category.roots.forEach(layer => { - if (layer && !lmeState.map.hasLayer(layer)) { + const objectId = managedLayerId(layer, category.key); + if (layer + && !lmeState.managerHiddenObjectIds.has(objectId) + && !lmeState.map.hasLayer(layer)) { layer.addTo(lmeState.map); } }); @@ -1278,15 +1287,23 @@ function setManagedCategoryVisible(category, visible) { lmeState.map.removeLayer(layer); } }); + if (lmeState.managerHighlightedCategoryKey === category.key) { + clearManagerHighlight(); + } } saveLayerManagerState(); + refreshImportedMeasurements(); + refreshDrawingMeasurements(); + refreshLayerManager(); } function setManagedObjectVisible(record, visible, refresh = true) { if (visible) { const hidden = lmeState.managerHiddenObjects.get(record.id); if (hidden) { - hidden.parent.addLayer(hidden.layer); + if (hidden.parent !== lmeState.map || managedCategoryEnabled(record.categoryKey)) { + hidden.parent.addLayer(hidden.layer); + } lmeState.managerHiddenObjects.delete(record.id); } lmeState.managerHiddenObjectIds.delete(record.id); @@ -1294,6 +1311,9 @@ function setManagedObjectVisible(record, visible, refresh = true) { lmeState.managerHiddenObjects.set(record.id, record); lmeState.managerHiddenObjectIds.add(record.id); record.parent.removeLayer(record.layer); + if (lmeState.managerHighlightedObjectId === record.id) { + clearManagerHighlight(); + } } saveLayerManagerState(); refreshImportedMeasurements(); @@ -1303,8 +1323,29 @@ function setManagedObjectVisible(record, visible, refresh = true) { } } +function managedCategoryEnabled(categoryKey) { + if (lmeState.managerHiddenCategories.has(categoryKey)) { + return false; + } + if (categoryKey === "gpsPosition") { + return lmeState.gpsPositionVisible; + } + if (categoryKey === "imported") { + return lmeState.importedVisible; + } + if (categoryKey === "importedSheets") { + return lmeState.importedSheetsVisible; + } + if (categoryKey === "selectedParcels") { + return lmeState.selectedParcelsVisible; + } + return true; +} + function highlightManagedObject(record) { lmeState.managerHighlight.clearLayers(); + lmeState.managerHighlightedObjectId = record.id; + lmeState.managerHighlightedCategoryKey = record.categoryKey; const geojson = record.layer.toGeoJSON?.(); if (geojson) { L.geoJSON(geojson, { @@ -1325,6 +1366,16 @@ function highlightManagedObject(record) { fitLayer(record.layer); } +function clearManagerHighlight() { + lmeState.managerHighlight?.clearLayers(); + lmeState.managerHighlightedObjectId = null; + lmeState.managerHighlightedCategoryKey = null; +} + +function layerManagerMoveButtons(label) { + return ``; +} + function bindLayerManagerDrag(container) { container.querySelectorAll(".layer-drag-handle").forEach(handle => { handle.addEventListener("pointerdown", event => { @@ -1335,6 +1386,7 @@ function bindLayerManagerDrag(container) { row.classList.add("layer-manager-dragging"); handle.setPointerCapture?.(event.pointerId); const move = moveEvent => { + moveEvent.preventDefault(); const target = document.elementFromPoint(moveEvent.clientX, moveEvent.clientY)?.closest(`[data-drag-type="${row.dataset.dragType}"]`); if (!target || target === row || target.parentElement !== list) { return; @@ -1344,14 +1396,37 @@ function bindLayerManagerDrag(container) { }; const end = () => { row.classList.remove("layer-manager-dragging"); - handle.removeEventListener("pointermove", move); - handle.removeEventListener("pointerup", end); - handle.removeEventListener("pointercancel", end); + handle.releasePointerCapture?.(event.pointerId); + document.removeEventListener("pointermove", move); + document.removeEventListener("pointerup", end); + document.removeEventListener("pointercancel", end); applyLayerManagerDomOrder(container); }; - handle.addEventListener("pointermove", move); - handle.addEventListener("pointerup", end); - handle.addEventListener("pointercancel", end); + document.addEventListener("pointermove", move, { passive: false }); + document.addEventListener("pointerup", end); + document.addEventListener("pointercancel", end); + }); + }); +} + +function bindLayerManagerMoveButtons(container) { + container.querySelectorAll(".layer-move-up, .layer-move-down").forEach(button => { + button.addEventListener("click", event => { + event.preventDefault(); + event.stopPropagation(); + const row = button.closest("[data-drag-type]"); + const sibling = button.classList.contains("layer-move-up") + ? row.previousElementSibling + : row.nextElementSibling; + if (!sibling || sibling.dataset.dragType !== row.dataset.dragType) { + return; + } + if (button.classList.contains("layer-move-up")) { + row.parentElement.insertBefore(row, sibling); + } else { + row.parentElement.insertBefore(sibling, row); + } + applyLayerManagerDomOrder(container); }); }); } @@ -1785,7 +1860,7 @@ function renderMeasurements(sourceGroup, targetGroup, visible, sourceType) { return; } targetGroup.clearLayers(); - if (!visible) { + if (!visible || !lmeState.map.hasLayer(sourceGroup)) { return; } @@ -2343,7 +2418,7 @@ function resetLayerManagerProjectState() { lmeState.managerHiddenObjectIds.clear(); lmeState.managerHiddenCategories.clear(); lmeState.managerObjectOrder = {}; - lmeState.managerHighlight?.clearLayers(); + clearManagerHighlight(); } function clearManagedCategoryState(categoryKey) { @@ -2809,11 +2884,11 @@ function onGpsPosition(position) { } function updateGpsPositionLayers(latlng, accuracy) { - if (!lmeState.gpsPositionVisible) { - return; - } + let created = false; if (!lmeState.gpsMarker) { lmeState.gpsMarker = L.marker(latlng, { pane: "gpsPositionPane", title: "La tua posizione" }); + lmeState.gpsMarker.lmeManagerId = "gps-position-marker"; + lmeState.gpsMarker.lmeManagerLabel = "Posizione GPS"; lmeState.gpsAccuracy = L.circle(latlng, { pane: "gpsPositionPane", radius: accuracy, @@ -2822,15 +2897,33 @@ function updateGpsPositionLayers(latlng, accuracy) { fillColor: "#60a5fa", fillOpacity: 0.16 }); + lmeState.gpsAccuracy.lmeManagerId = "gps-accuracy-circle"; + lmeState.gpsAccuracy.lmeManagerLabel = "Cerchio precisione GPS"; + created = true; } else { lmeState.gpsMarker.setLatLng(latlng); lmeState.gpsAccuracy.setLatLng(latlng).setRadius(accuracy); } - if (!lmeState.map.hasLayer(lmeState.gpsMarker)) { + const categoryVisible = lmeState.gpsPositionVisible + && !lmeState.managerHiddenCategories.has("gpsPosition"); + if (categoryVisible + && !lmeState.managerHiddenObjectIds.has("gps-position-marker") + && !lmeState.map.hasLayer(lmeState.gpsMarker)) { lmeState.gpsMarker.addTo(lmeState.map); + } else if ((!categoryVisible || lmeState.managerHiddenObjectIds.has("gps-position-marker")) + && lmeState.map.hasLayer(lmeState.gpsMarker)) { + lmeState.map.removeLayer(lmeState.gpsMarker); } - if (!lmeState.map.hasLayer(lmeState.gpsAccuracy)) { + if (categoryVisible + && !lmeState.managerHiddenObjectIds.has("gps-accuracy-circle") + && !lmeState.map.hasLayer(lmeState.gpsAccuracy)) { lmeState.gpsAccuracy.addTo(lmeState.map); + } else if ((!categoryVisible || lmeState.managerHiddenObjectIds.has("gps-accuracy-circle")) + && lmeState.map.hasLayer(lmeState.gpsAccuracy)) { + lmeState.map.removeLayer(lmeState.gpsAccuracy); + } + if (created) { + refreshLayerManager(); } }