Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3aa4ff1564 | ||
|
|
74527638c1 | ||
|
|
a0e24fc925 | ||
|
|
8a8fc1dfe4 | ||
|
|
e70a30f7d7 | ||
|
|
47b58a9b0e | ||
|
|
fc1ee8f21a | ||
|
|
bb69b9fd0d | ||
|
|
260e0a3df5 | ||
|
|
a15c8e0b36 | ||
|
|
aa389f7581 | ||
|
|
812420b86a |
No files matched your search
@@ -24,6 +24,7 @@
|
||||
{
|
||||
"layers" => "Qui controlli visibilita, ordine, selezione e organizzazione di tutti gli oggetti presenti sulla mappa.",
|
||||
"cadastre" => "Trova una particella nel catalogo catastale e mostrane il confine ufficiale sulla mappa.",
|
||||
"fiducials" => "Ricerca i Punti Fiduciali di un foglio, consultali sulla mappa e scarica le monografie disponibili.",
|
||||
"data" => "Importa file GIS, crea disegni e misure oppure aggiungi punti di interesse.",
|
||||
"save" => "Esporta gli elementi della mappa in un file compatibile con altre applicazioni GIS e GPS.",
|
||||
"projects" => "Salva il lavoro completo, riaprilo, organizzalo e recupera revisioni o copie di sicurezza.",
|
||||
@@ -40,6 +41,7 @@
|
||||
"Gerarchia: premi la freccia accanto alla maniglia per aprire un gruppo. Il rientro, il carattere e la tonalita indicano se una riga e figlia, nipote o di livello successivo.",
|
||||
"Selezione multipla: attiva il flag sulle righe desiderate. Esempio: seleziona tre poligoni per esportare solo quelli oppure per bloccarli con una sola operazione.",
|
||||
"Rinomina e attributi: Rinomina modifica il nome mostrato e salvato nei progetti e nei file esportati; Attributi apre un editor multilinea per consultare o correggere i dati associati.",
|
||||
"Note: espandi un oggetto e premi Visualizza note per consultarne l'elenco. Con LME Pro, tramite abbonamento o licenza manuale, puoi aggiungere, modificare ed eliminare un numero qualsiasi di note; le vecchie note singole restano compatibili.",
|
||||
"Colori: espandi un padre o un figlio e usa gli editor di linea e riempimento. Puoi scegliere il colore, prelevarlo con il contagocce se supportato, oppure inserire e copiare i valori HEX, RGB e HSL; sul padre viene applicato a tutto il gruppo.",
|
||||
"Blocco: il lucchetto impedisce modifiche e spostamenti involontari. Sblocca l'oggetto prima di usare la matita o gli strumenti geometrici.",
|
||||
"Sposta nel gruppo cambia l'appartenenza. Esempio: trasferisci un poligono da Disegni e POI a Progetti e dati importati, oppure in un nuovo sottogruppo chiamato Rilievo nord.",
|
||||
@@ -56,6 +58,16 @@
|
||||
"Se un oggetto gia presente era nascosto, viene reso nuovamente visibile. La visibilita generale dei contorni evidenziati e dei dati importati resta controllabile dal pannello Layer.",
|
||||
"Quando il servizio ufficiale non restituisce subito il confine, attendi il completamento indicato nel pannello e riprova mantenendo gli stessi dati selezionati."
|
||||
],
|
||||
"fiducials" =>
|
||||
[
|
||||
"La funzione richiede LME Pro: sono validi sia l'abbonamento Google Play sia una licenza manuale attiva.",
|
||||
"Scegli Provincia, Comune catastale e Foglio, quindi premi Cerca Punti Fiduciali. Puoi anche usare il comando PF sulla mappa dopo aver selezionato una particella o un foglio, dalla particella individuata dal GPS oppure, in navigazione, mostrando il layer del foglio catastale corrente.",
|
||||
"Mantieni i PF dei fogli gia caricati conserva i risultati precedenti come sottogruppi distinti; disattivalo per sostituirli con il nuovo foglio.",
|
||||
"Il flag Mostra i PF sulla mappa controlla la visibilita generale. Nel pannello Layer puoi inoltre cambiare colore, ordine, visibilita o rimuovere il singolo gruppo del foglio.",
|
||||
"Tocca un punto rosso per vedere identificativo e coordinate. Quando disponibile, Scarica PDF monografia apre o salva il documento ufficiale dell'Agenzia delle Entrate.",
|
||||
"I PF caricati vengono salvati nel progetto con gruppi, popup e collegamenti alle monografie; riaprendo il progetto tornano disponibili come gli altri oggetti.",
|
||||
"Il posizionamento cartografico e sperimentale e non sostituisce un rilievo topografico o la verifica professionale sul posto."
|
||||
],
|
||||
"data" =>
|
||||
[
|
||||
"Importazione: premi Carica KML, KMZ o GeoJSON e scegli il file dal dispositivo. I nomi e gli attributi riconosciuti vengono mantenuti.",
|
||||
@@ -75,11 +87,11 @@
|
||||
"Attiva solo le categorie da includere. Esempio: per consegnare disegni e particelle importate senza la traccia GPS, lascia attive quelle due voci e disattiva Traccia GPS.",
|
||||
"Solo oggetti selezionati esporta esclusivamente le righe contrassegnate nel pannello Layer. Se non devi filtrare manualmente, lascia questa opzione disattivata.",
|
||||
"Premi Esporta e salva file e scegli la cartella o l'app di destinazione proposta dal dispositivo.",
|
||||
"Nomi rinominati e attributi vengono salvati in GeoJSON, KML e KMZ. Gli sfondi satellitari, stradali e WMS non vengono incorporati nei file vettoriali."
|
||||
"Nomi rinominati, attributi e note compatibili vengono salvati nei formati che supportano metadati. Gli sfondi satellitari, stradali e WMS non vengono incorporati nei file vettoriali."
|
||||
],
|
||||
"projects" =>
|
||||
[
|
||||
"Nuovo progetto: inserisci un nome, scegli se includere i contorni catastali evidenziati e premi Salva progetto. Vengono conservati oggetti, gruppi, nomi, attributi e opzioni di visualizzazione.",
|
||||
"Nuovo progetto: inserisci un nome, scegli se includere i contorni catastali evidenziati e premi Salva progetto. Vengono conservati oggetti, gruppi, nomi, attributi, note, Punti Fiduciali caricati e opzioni di visualizzazione.",
|
||||
"Aggiornamento: dopo aver aperto un progetto, usa di nuovo Salva progetto con lo stesso nome per aggiornarlo. Se nelle Impostazioni attivi Aggiorna automaticamente il progetto aperto, le modifiche vengono registrate dopo 3 secondi di inattivita.",
|
||||
"Cartelle: seleziona un progetto, scrivi per esempio Cantieri 2026 e premi Sposta per organizzarlo nell'archivio; questa operazione non sposta le geometrie sulla mappa.",
|
||||
"Rinomina cambia il nome del progetto selezionato senza alterarne contenuti e revisioni. Duplica crea invece una copia modificabile, utile prima di una variante importante o quando ricevi un progetto in sola lettura.",
|
||||
@@ -90,7 +102,8 @@
|
||||
],
|
||||
"tools" =>
|
||||
[
|
||||
"Tabella oggetti: apre una vista ordinata di particelle, file importati e disegni. Usa i flag per selezionare piu righe, il lucchetto per proteggerle e la matita per modificare i metadati.",
|
||||
"Tabella oggetti: apre una vista ordinata di particelle catastali, file importati e disegni. La selezione e bidirezionale con mappa e pannello Layer: Singola sostituisce la scelta, Multipla aggiunge o rimuove oggetti, Disattivata deseleziona tutto e blocca nuove selezioni. Cancella selezione toglie soltanto lo stato selezionato e non elimina geometrie.",
|
||||
"Colonna Note: il pulsante Note e sempre attivo e apre tutte le note dell'oggetto. La consultazione resta disponibile anche senza Pro; aggiunta, modifica ed eliminazione richiedono abbonamento o licenza manuale.",
|
||||
"Copia metadati: nella maschera Metadati oggetto scegli Copia da e l'oggetto sorgente. Attiva Importa anche i valori per copiare nomi e contenuti; disattivalo per creare soltanto gli stessi campi, lasciandoli vuoti o mantenendo i valori gia presenti.",
|
||||
"Coordinate WGS84 e UTM: scegli un punto sulla mappa per leggere latitudine e longitudine oppure le coordinate metriche UTM, utili per rilievi e confronti tecnici.",
|
||||
"Registro operazioni: mostra in ordine cronologico disegni, modifiche, rinomine, spostamenti ed eliminazioni, cosi puoi capire cosa e cambiato durante la sessione.",
|
||||
@@ -102,6 +115,8 @@
|
||||
"settings" =>
|
||||
[
|
||||
"Mappa e sfondo: scegli la cartografia di base e regola Trasparenza catasto per leggere meglio confini e immagini sottostanti. Esempio: riducila quando le linee coprono dettagli del terreno.",
|
||||
"Bussola: attiva Mostra bussola per visualizzare N, NE, E, SE, S, SW, W e NW. Puoi trascinarla nella posizione preferita. La modalita predefinita mantiene il nord della mappa fisso in alto e la lancetta indica il nord con movimento continuo; in modalita Navigatore la mappa segue l'orientamento del dispositivo.",
|
||||
"Messaggi mappa: scegli dopo quanti secondi devono chiudersi automaticamente; imposta 0 per mantenerli finche non premi la X.",
|
||||
"Autosalvataggio locale dopo ogni modifica: se attivo, ogni disegno, modifica, rinomina o eliminazione aggiorna immediatamente una copia di recupero nel dispositivo. Per usarla apri Dati e disegni e premi Recupera ultimo autosalvataggio.",
|
||||
"Aggiorna automaticamente il progetto aperto: funziona solo dopo aver aperto o salvato un progetto modificabile. Dopo una modifica attende 3 secondi senza altre operazioni e aggiorna quel progetto; un progetto in sola lettura non viene mai sovrascritto.",
|
||||
"Backup automatico: scegli Giornaliero o Settimanale. Alla successiva pressione di Salva progetto, se e trascorso l'intervallo, viene creata una copia interna di tutti i progetti; l'app conserva le 10 copie automatiche piu recenti. Disattivato non crea nuove copie programmate.",
|
||||
@@ -109,7 +124,8 @@
|
||||
"Aggancio ai vertici: avvicinando un nuovo vertice a uno esistente, l'app lo allinea entro la distanza in pixel scelta. Aumenta la distanza su schermi piccoli; riducila quando ci sono molti vertici ravvicinati.",
|
||||
"Centra e zooma quando seleziono un oggetto: attivalo per inquadrare automaticamente ogni elemento scelto; disattivalo se vuoi mantenere ferma la vista mentre lavori dall'elenco Layer.",
|
||||
"WebDAV: inserisci indirizzo, utente e password applicazione, salva la configurazione, poi usa Invia al cloud per caricare il backup o Scarica dal cloud per ripristinare quello remoto.",
|
||||
"GPS e percorso: Mostra punto visualizza posizione e precisione; Registra traccia memorizza il cammino; distanza e avvisi aiutano a controllare l'avvicinamento e l'attraversamento del confine selezionato.",
|
||||
"GPS e percorso: Mostra punto visualizza posizione e precisione; Registra traccia memorizza il cammino; distanza e avvisi aiutano a controllare l'avvicinamento e l'attraversamento del confine selezionato. Avvia/Ferma GPS e Centra sono disposti verticalmente e il riquadro puo essere compresso.",
|
||||
"Fogli catastali in navigazione: con Fogli catastali attivo nel pannello Layer, l'app carica il foglio anche senza particelle o progetti e lo mantiene visibile a zoom piu ampi senza duplicarlo se e gia presente.",
|
||||
"Google Maps e Azure Maps richiedono le rispettive chiavi solo quando scegli quegli sfondi. Controlla nuova versione confronta la versione installata con l'ultima pubblicata e mostra le relative modifiche."
|
||||
],
|
||||
_ => []
|
||||
|
||||
@@ -309,6 +309,7 @@
|
||||
<p>Elenco e PDF provengono dall'Agenzia delle Entrate; il posizionamento sperimentale usa il servizio cartografico GloboGIS. Le coordinate sono un ausilio: verificale prima di qualsiasi uso topografico o professionale.</p>
|
||||
</div>
|
||||
}
|
||||
<MenuHelp Topic="fiducials" />
|
||||
</section>
|
||||
}
|
||||
else if (ActiveTab == "data")
|
||||
@@ -673,6 +674,17 @@
|
||||
<input type="number" min="0" max="30" step="1" @bind="MapMessageTimeoutSeconds" @bind:after="ApplyMapMessageOptions" />
|
||||
</label>
|
||||
<small class="field-help">Imposta 0 per lasciare i messaggi visibili fino alla chiusura manuale.</small>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="ShowCompass" @bind:after="ApplyCompassOptions" />
|
||||
<span>Mostra bussola sulla mappa</span>
|
||||
</label>
|
||||
<label>
|
||||
Orientamento bussola
|
||||
<select @bind="CompassMode" @bind:after="ApplyCompassOptions" disabled="@(!ShowCompass)">
|
||||
<option value="fixed">Mappa: nord fisso in alto (predefinito)</option>
|
||||
<option value="heading">Navigatore: direzione del dispositivo in alto</option>
|
||||
</select>
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
@@ -877,6 +889,9 @@
|
||||
private bool GpsActive { get; set; }
|
||||
private bool GpsOverlayCollapsed { get; set; }
|
||||
private bool ShowGpsPosition { get; set; } = true;
|
||||
private bool ShowCompass { get; set; }
|
||||
private string CompassMode { get; set; } = "fixed";
|
||||
private bool CompassSensorSubscribed { get; set; }
|
||||
private bool ShowSelectedParcels { get; set; } = true;
|
||||
private bool ShowFiducialPoints { get; set; } = true;
|
||||
private bool KeepPreviousFiducialPoints { get; set; } = true;
|
||||
@@ -1788,6 +1803,15 @@
|
||||
return InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public async Task SetCompassFromLayerManager(bool enabled)
|
||||
{
|
||||
ShowCompass = enabled;
|
||||
SaveFlagPreferences();
|
||||
await ConfigureCompassSensorAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public Task<string> GetOfficialCadastralSheetsNear(double latitude, double longitude) =>
|
||||
OfficialCadastreService.GetSheetsNearAsync(latitude, longitude);
|
||||
@@ -2298,6 +2322,8 @@
|
||||
ShowDrawingMeasurements = options.ShowDrawingMeasurements;
|
||||
DrawToolsVisible = options.DrawToolsVisible;
|
||||
ShowGpsPosition = options.GpsPositionVisible;
|
||||
ShowCompass = options.CompassVisible;
|
||||
CompassMode = options.CompassMode is "heading" ? "heading" : "fixed";
|
||||
ShowSelectedParcels = options.SelectedParcelsVisible;
|
||||
TrailEnabled = options.TrailEnabled;
|
||||
|
||||
@@ -2307,6 +2333,7 @@
|
||||
layer.Enabled = activeLayers.Contains(layer.Key);
|
||||
}
|
||||
SaveFlagPreferences();
|
||||
_ = ConfigureCompassSensorAsync();
|
||||
}
|
||||
|
||||
private async Task DeleteProject()
|
||||
@@ -2512,6 +2539,7 @@
|
||||
{
|
||||
advancedGeometry = CanUse(AppFeatures.AdvancedGeometry),
|
||||
fiducialPoints = CanUse(AppFeatures.FiducialPoints),
|
||||
multipleNotes = CanUse(AppFeatures.MultipleNotes),
|
||||
maxDrawingObjects = Entitlements.HasProAccess ? (int?)null : EntitlementService.BaseDrawingObjectLimit,
|
||||
drawingLimitMessage = L("drawings.base.limit.reached")
|
||||
}).AsTask();
|
||||
@@ -2718,6 +2746,8 @@
|
||||
ShowDrawingMeasurements = GetFlagPreference("show_drawing_measurements", true);
|
||||
DrawToolsVisible = GetFlagPreference("draw_tools_visible", false);
|
||||
ShowGpsPosition = GetFlagPreference("show_gps_position", true);
|
||||
ShowCompass = GetFlagPreference("show_compass", false);
|
||||
CompassMode = Preferences.Default.Get($"{FlagPreferencePrefix}compass_mode", "fixed") is "heading" ? "heading" : "fixed";
|
||||
ShowSelectedParcels = GetFlagPreference("show_selected_parcels", true);
|
||||
ShowFiducialPoints = GetFlagPreference("show_fiducial_points", true);
|
||||
KeepPreviousFiducialPoints = GetFlagPreference("keep_previous_fiducials", true);
|
||||
@@ -2761,6 +2791,8 @@
|
||||
SetFlagPreference("show_drawing_measurements", ShowDrawingMeasurements);
|
||||
SetFlagPreference("draw_tools_visible", DrawToolsVisible);
|
||||
SetFlagPreference("show_gps_position", ShowGpsPosition);
|
||||
SetFlagPreference("show_compass", ShowCompass);
|
||||
Preferences.Default.Set($"{FlagPreferencePrefix}compass_mode", CompassMode);
|
||||
SetFlagPreference("show_selected_parcels", ShowSelectedParcels);
|
||||
SetFlagPreference("show_fiducial_points", ShowFiducialPoints);
|
||||
SetFlagPreference("keep_previous_fiducials", KeepPreviousFiducialPoints);
|
||||
@@ -2801,6 +2833,8 @@
|
||||
await JS.InvokeVoidAsync("lmeMap.setDrawingMeasurementsVisible", ShowDrawingMeasurements);
|
||||
await JS.InvokeVoidAsync("lmeMap.setDrawToolsVisible", DrawToolsVisible);
|
||||
await JS.InvokeVoidAsync("lmeMap.setGpsPositionVisible", ShowGpsPosition);
|
||||
await JS.InvokeVoidAsync("lmeMap.setCompassOptions", ShowCompass, CompassMode);
|
||||
await ConfigureCompassSensorAsync();
|
||||
await JS.InvokeVoidAsync("lmeMap.setSelectedParcelsVisible", ShowSelectedParcels);
|
||||
await JS.InvokeVoidAsync("lmeMap.setFiducialColor", FiducialColor);
|
||||
await JS.InvokeVoidAsync("lmeMap.setFiducialPointsVisible", ShowFiducialPoints);
|
||||
@@ -2819,6 +2853,68 @@
|
||||
await JS.InvokeVoidAsync("lmeMap.setInfoTimeout", MapMessageTimeoutSeconds);
|
||||
}
|
||||
|
||||
private async Task ApplyCompassOptions()
|
||||
{
|
||||
CompassMode = CompassMode is "heading" ? "heading" : "fixed";
|
||||
SaveFlagPreferences();
|
||||
await JS.InvokeVoidAsync("lmeMap.setCompassOptions", ShowCompass, CompassMode);
|
||||
await ConfigureCompassSensorAsync();
|
||||
}
|
||||
|
||||
private Task ConfigureCompassSensorAsync()
|
||||
{
|
||||
var compass = Microsoft.Maui.Devices.Sensors.Compass.Default;
|
||||
var shouldMonitor = ShowCompass && compass.IsSupported;
|
||||
try
|
||||
{
|
||||
if (shouldMonitor && !CompassSensorSubscribed)
|
||||
{
|
||||
compass.ReadingChanged += OnCompassReadingChanged;
|
||||
CompassSensorSubscribed = true;
|
||||
compass.Start(Microsoft.Maui.Devices.Sensors.SensorSpeed.Game, applyLowPassFilter: true);
|
||||
}
|
||||
else if (!shouldMonitor && CompassSensorSubscribed)
|
||||
{
|
||||
compass.ReadingChanged -= OnCompassReadingChanged;
|
||||
CompassSensorSubscribed = false;
|
||||
if (compass.IsMonitoring)
|
||||
{
|
||||
compass.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (CompassSensorSubscribed)
|
||||
{
|
||||
compass.ReadingChanged -= OnCompassReadingChanged;
|
||||
CompassSensorSubscribed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async void OnCompassReadingChanged(
|
||||
object? sender,
|
||||
Microsoft.Maui.Devices.Sensors.CompassChangedEventArgs args)
|
||||
{
|
||||
if (!MapReady || !ShowCompass)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await InvokeAsync(() => JS.InvokeVoidAsync(
|
||||
"lmeMap.setCompassHeading",
|
||||
args.Reading.HeadingMagneticNorth).AsTask());
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyAdvancedOptions()
|
||||
{
|
||||
SaveFlagPreferences();
|
||||
@@ -2893,6 +2989,8 @@
|
||||
public bool ShowDrawingMeasurements { get; init; } = true;
|
||||
public bool DrawToolsVisible { get; init; }
|
||||
public bool GpsPositionVisible { get; init; } = true;
|
||||
public bool CompassVisible { get; init; }
|
||||
public string CompassMode { get; init; } = "fixed";
|
||||
public bool SelectedParcelsVisible { get; init; } = true;
|
||||
public bool TrailEnabled { get; init; }
|
||||
}
|
||||
@@ -2922,6 +3020,16 @@
|
||||
GpsLookupCancellation?.Dispose();
|
||||
ProjectAutoSaveCancellation?.Cancel();
|
||||
ProjectAutoSaveCancellation?.Dispose();
|
||||
var compass = Microsoft.Maui.Devices.Sensors.Compass.Default;
|
||||
if (CompassSensorSubscribed)
|
||||
{
|
||||
compass.ReadingChanged -= OnCompassReadingChanged;
|
||||
if (compass.IsMonitoring)
|
||||
{
|
||||
compass.Stop();
|
||||
}
|
||||
CompassSensorSubscribed = false;
|
||||
}
|
||||
MapCallbackReference?.Dispose();
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
<ApplicationId>it.liviomerola.lmemappecatastali.pro</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>1.0.14</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>114</ApplicationVersion>
|
||||
<ApplicationDisplayVersion>1.0.25</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>125</ApplicationVersion>
|
||||
<Version>$(ApplicationDisplayVersion)</Version>
|
||||
|
||||
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||
|
||||
@@ -22,7 +22,8 @@ public sealed class EntitlementService(
|
||||
AppFeatures.OfflineMaps,
|
||||
AppFeatures.AdvancedGeometry,
|
||||
AppFeatures.GpsTrail,
|
||||
AppFeatures.FiducialPoints
|
||||
AppFeatures.FiducialPoints,
|
||||
AppFeatures.MultipleNotes
|
||||
};
|
||||
|
||||
public bool IsGoogleProActive { get; private set; }
|
||||
@@ -187,4 +188,5 @@ public static class AppFeatures
|
||||
public const string AdvancedGeometry = "advanced-geometry";
|
||||
public const string GpsTrail = "gps-trail";
|
||||
public const string FiducialPoints = "fiducial-points";
|
||||
public const string MultipleNotes = "multiple-notes";
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
param(
|
||||
[string]$Configuration = "Release"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$projectRoot = Split-Path -Parent $PSScriptRoot
|
||||
$dotnet = Join-Path $projectRoot "artifacts\tooling\dotnet10\dotnet.exe"
|
||||
$androidSdk = Join-Path $env:LOCALAPPDATA "Android\Sdk"
|
||||
$documentsDirectory = Split-Path -Parent (Split-Path -Parent $projectRoot)
|
||||
$privateDirectory = Join-Path $documentsDirectory "LMEMappeCatastali-Private\GooglePlay"
|
||||
$keyStore = Join-Path $privateDirectory "lme-mappe-catastali-pro-upload.jks"
|
||||
$recoveryFile = Join-Path $privateDirectory "UPLOAD-KEY-RECOVERY.txt"
|
||||
$outputDirectory = Join-Path $projectRoot "artifacts\play-store"
|
||||
$projectPath = Join-Path $projectRoot "LMEMappeCatastaliApp.csproj"
|
||||
|
||||
foreach ($requiredPath in @($dotnet, $androidSdk, $keyStore, $recoveryFile, $projectPath)) {
|
||||
if (-not (Test-Path -LiteralPath $requiredPath)) {
|
||||
throw "Componente richiesto non trovato: $requiredPath"
|
||||
}
|
||||
}
|
||||
|
||||
[xml]$projectXml = Get-Content -Raw -LiteralPath $projectPath
|
||||
$propertyGroup = $projectXml.Project.PropertyGroup |
|
||||
Where-Object { $_.ApplicationDisplayVersion -and $_.ApplicationVersion } |
|
||||
Select-Object -First 1
|
||||
$displayVersion = [string]$propertyGroup.ApplicationDisplayVersion
|
||||
$versionCode = [string]$propertyGroup.ApplicationVersion
|
||||
if ([string]::IsNullOrWhiteSpace($displayVersion) -or [string]::IsNullOrWhiteSpace($versionCode)) {
|
||||
throw "Versione applicazione non trovata nel progetto."
|
||||
}
|
||||
|
||||
$recovery = Get-Content -LiteralPath $recoveryFile
|
||||
function Read-RecoveryValue([string]$label) {
|
||||
$line = $recovery | Where-Object { $_ -like "${label}:*" } | Select-Object -First 1
|
||||
if ([string]::IsNullOrWhiteSpace($line)) {
|
||||
throw "Valore $label non trovato nel file di recupero."
|
||||
}
|
||||
return ($line -split ":", 2)[1].Trim()
|
||||
}
|
||||
|
||||
$storePassword = Read-RecoveryValue "Store password"
|
||||
$keyPassword = Read-RecoveryValue "Key password"
|
||||
$env:LME_ANDROID_UPLOAD_STORE_PASS = $storePassword
|
||||
$env:LME_ANDROID_UPLOAD_KEY_PASS = $keyPassword
|
||||
$packages = [System.Collections.Generic.List[System.IO.FileInfo]]::new()
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
|
||||
|
||||
& $dotnet restore $projectPath `
|
||||
-p:Configuration=$Configuration `
|
||||
-p:TargetFrameworks=net10.0-android `
|
||||
-p:AndroidSdkDirectory=$androidSdk `
|
||||
-p:UseDefaultPublishRuntimeIdentifier=false
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Ripristino delle dipendenze Android non riuscito."
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($format in @("aab", "apk")) {
|
||||
& $dotnet publish $projectPath `
|
||||
-f net10.0-android `
|
||||
-c $Configuration `
|
||||
--no-restore `
|
||||
-p:AndroidSdkDirectory=$androidSdk `
|
||||
-p:UseDefaultPublishRuntimeIdentifier=false `
|
||||
-p:AndroidPackageFormat=$format `
|
||||
-p:AndroidKeyStore=true `
|
||||
-p:AndroidSigningKeyStore=$keyStore `
|
||||
-p:AndroidSigningKeyAlias=lme-upload `
|
||||
-p:AndroidSigningStorePass=env:LME_ANDROID_UPLOAD_STORE_PASS `
|
||||
-p:AndroidSigningKeyPass=env:LME_ANDROID_UPLOAD_KEY_PASS
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Pubblicazione Android $format non riuscita."
|
||||
}
|
||||
|
||||
$publishDirectory = Join-Path $projectRoot "bin\$Configuration\net10.0-android\publish"
|
||||
$package = Get-ChildItem -LiteralPath $publishDirectory -Filter "*-Signed.$format" -File |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 1
|
||||
if ($null -eq $package) {
|
||||
throw "Nessun pacchetto $format firmato prodotto in $publishDirectory"
|
||||
}
|
||||
|
||||
$destination = Join-Path $outputDirectory "LME-Mappe-Catastali-Pro-$displayVersion-$versionCode.$format"
|
||||
Copy-Item -LiteralPath $package.FullName -Destination $destination -Force
|
||||
$packages.Add((Get-Item -LiteralPath $destination))
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Remove-Item Env:LME_ANDROID_UPLOAD_STORE_PASS -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:LME_ANDROID_UPLOAD_KEY_PASS -ErrorAction SilentlyContinue
|
||||
$storePassword = $null
|
||||
$keyPassword = $null
|
||||
}
|
||||
|
||||
$hashLines = $packages | ForEach-Object {
|
||||
$hash = Get-FileHash -Algorithm SHA256 -LiteralPath $_.FullName
|
||||
"$($hash.Hash.ToLowerInvariant()) $($_.Name)"
|
||||
}
|
||||
$hashFile = Join-Path $outputDirectory "LME-Mappe-Catastali-Pro-$displayVersion-$versionCode-SHA256SUMS.txt"
|
||||
$hashLines | Set-Content -LiteralPath $hashFile
|
||||
|
||||
$packages | Select-Object Name, Length, LastWriteTime
|
||||
Get-Item -LiteralPath $hashFile | Select-Object Name, Length, LastWriteTime
|
||||
@@ -906,6 +906,86 @@ input[type="checkbox"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.object-table-wrap .object-notes-button {
|
||||
width: auto;
|
||||
min-width: 70px;
|
||||
padding: 4px 8px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.object-table-wrap tr.object-table-selected td {
|
||||
background: #fce7f3;
|
||||
box-shadow: inset 0 1px 0 #f0abfc, inset 0 -1px 0 #f0abfc;
|
||||
}
|
||||
|
||||
.managed-notes-command {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.managed-notes-command small,
|
||||
.managed-note-pro-message {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.managed-notes-list {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.managed-note {
|
||||
padding: 10px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 6px;
|
||||
background: #f8fafb;
|
||||
}
|
||||
|
||||
.managed-note > header {
|
||||
padding: 0 0 7px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.managed-note time {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.managed-note p,
|
||||
.lme-popup-notes p {
|
||||
margin: 0 0 8px;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.managed-note-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.managed-note-actions button {
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
.managed-note-editor {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.managed-note-editor label {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.managed-note-editor textarea {
|
||||
min-height: 90px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.object-table-search,
|
||||
.coordinate-result {
|
||||
display: grid;
|
||||
@@ -1149,6 +1229,12 @@ input[type="checkbox"] {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.object-table-legend button {
|
||||
min-height: 28px;
|
||||
padding: 4px 9px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.object-table-wrap input[type="checkbox"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@@ -1196,6 +1282,69 @@ input[type="checkbox"] {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.lme-geometry-toolbar a.lme-selection-mode-button.is-active {
|
||||
background: #0f766e;
|
||||
color: #fff;
|
||||
box-shadow: inset 0 0 0 2px #99f6e4;
|
||||
}
|
||||
|
||||
.lme-geometry-toolbar a.lme-selection-mode-button.is-multiple {
|
||||
background: #a21caf;
|
||||
box-shadow: inset 0 0 0 2px #f5d0fe;
|
||||
}
|
||||
|
||||
.lme-geometry-toolbar {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.lme-comparison-actions,
|
||||
.lme-selection-actions {
|
||||
position: absolute;
|
||||
right: calc(100% + 6px);
|
||||
z-index: 1000;
|
||||
display: grid;
|
||||
min-width: 154px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #b8c1c8;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgb(0 0 0 / 22%);
|
||||
}
|
||||
|
||||
.lme-selection-actions {
|
||||
min-width: 205px;
|
||||
}
|
||||
|
||||
.lme-geometry-toolbar .lme-comparison-actions a,
|
||||
.lme-geometry-toolbar .lme-selection-actions a {
|
||||
display: flex !important;
|
||||
width: auto !important;
|
||||
height: 36px !important;
|
||||
padding: 0 10px;
|
||||
justify-content: flex-start;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #d7dde1;
|
||||
color: #1f2933;
|
||||
font-size: 13px !important;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.lme-geometry-toolbar .lme-comparison-actions a:last-child,
|
||||
.lme-geometry-toolbar .lme-selection-actions a:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.lme-geometry-toolbar .lme-comparison-actions a:hover,
|
||||
.lme-geometry-toolbar .lme-comparison-actions a:focus-visible,
|
||||
.lme-geometry-toolbar .lme-selection-actions a:hover,
|
||||
.lme-geometry-toolbar .lme-selection-actions a:focus-visible,
|
||||
.lme-geometry-toolbar .lme-selection-actions a.is-current {
|
||||
background: #e8f4f1;
|
||||
color: #075e54;
|
||||
}
|
||||
|
||||
.leaflet-help {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
@@ -1674,6 +1823,104 @@ label {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.map-compass {
|
||||
--compass-rotation: 0deg;
|
||||
--compass-radius: -31px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 12px;
|
||||
z-index: 810;
|
||||
width: 82px;
|
||||
height: 82px;
|
||||
transform: translateY(-50%);
|
||||
border: 2px solid rgba(255, 255, 255, 0.92);
|
||||
border-radius: 50%;
|
||||
background: rgba(22, 31, 38, 0.86);
|
||||
box-shadow: 0 2px 9px rgba(0, 0, 0, 0.3);
|
||||
color: #fff;
|
||||
cursor: grab;
|
||||
pointer-events: auto;
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.map-compass.is-dragging {
|
||||
cursor: grabbing;
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.42);
|
||||
}
|
||||
|
||||
.map-compass-rose {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.map-compass-direction {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 20px;
|
||||
height: 12px;
|
||||
transform: translate(-50%, -50%) rotate(var(--direction-angle)) translateY(var(--compass-radius));
|
||||
color: #f8fafc;
|
||||
font-size: 9px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.map-compass-direction > span {
|
||||
display: block;
|
||||
transform: rotate(var(--label-counter));
|
||||
}
|
||||
|
||||
.map-compass-direction.is-intermediate {
|
||||
color: #cbd5e1;
|
||||
font-size: 7px;
|
||||
}
|
||||
|
||||
.map-compass-direction.is-north {
|
||||
color: #fca5a5;
|
||||
font-size: 11px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.map-compass-needle {
|
||||
position: absolute;
|
||||
bottom: 50%;
|
||||
left: 50%;
|
||||
width: 4px;
|
||||
height: 23px;
|
||||
transform: translateX(-50%) rotate(var(--compass-rotation));
|
||||
transform-origin: 50% 100%;
|
||||
border-radius: 4px 4px 1px 1px;
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.map-compass-needle::after {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
transform: translateX(-50%);
|
||||
border-right: 5px solid transparent;
|
||||
border-bottom: 7px solid #ef4444;
|
||||
border-left: 5px solid transparent;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.map-compass-center {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
transform: translate(-50%, -50%);
|
||||
border: 2px solid #fff;
|
||||
border-radius: 50%;
|
||||
background: #17212b;
|
||||
}
|
||||
|
||||
.wms-preview[hidden] {
|
||||
display: none;
|
||||
}
|
||||
@@ -1948,6 +2195,13 @@ footer {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.map-compass {
|
||||
--compass-radius: -27px;
|
||||
left: 8px;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
.map-info-text {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
<script src="_framework/blazor.webview.js" autostart="false"></script>
|
||||
<script src="lib/leaflet/leaflet.js"></script>
|
||||
<script src="lib/leaflet-rotate/leaflet-rotate.umd.min.js"></script>
|
||||
<script src="lib/leaflet-draw/leaflet.draw.js"></script>
|
||||
<script src="lib/googlemutant/Leaflet.GoogleMutant.js"></script>
|
||||
<script src="lib/jszip/jszip.min.js"></script>
|
||||
|
||||
+1007
-129
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Grzegorz Tomicki
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! @tomickigrzegorz/leaflet-rotate v0.3.0 | MIT */
|
||||
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("leaflet")):"function"==typeof define&&define.amd?define(["leaflet"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).L)}(this,function(t){"use strict";t.Point.prototype.rotate=function(i){var e=Math.cos(i),o=Math.sin(i);return new t.Point(this.x*e-this.y*o,this.x*o+this.y*e)},t.Point.prototype.rotateFrom=function(t,i){return i?this.subtract(i).rotate(t).add(i):this.rotate(t)};const i=Math.PI/180,e=180/Math.PI;function o(t){return(t%360+360)%360}function a(t){return o(t+180)-180}function n(t){var i=2*Math.PI;return((t+Math.PI)%i+i)%i-Math.PI}const s=1e3/60;function r(t,i){return 1-Math.pow(1-t,i/s)}function h(){return"undefined"!=typeof performance&&performance.now?performance.now():Date.now()}var _=t.Map.prototype;t.Map.mergeOptions({rotate:!1,bearing:0,touchRotate:!1,shiftKeyRotate:!1,dragRotate:!0,rotateControl:!1,rotateClockwise:!0});var p=_.initialize;_.initialize=function(t,i){i&&i.rotate&&(this._rotate=!0,this._bearing=0,this._bearingRad=0),p.call(this,t,i),this._rotate&&this.setBearing(i.bearing||0)};var l=_._initPanes;_._initPanes=function(){if(l.call(this),this._rotate){var i=this._mapPane;this._rotatePane=t.DomUtil.create("div","leaflet-rotate-pane",i),this._norotatePane=t.DomUtil.create("div","leaflet-norotate-pane",i),this._rotatePane.appendChild(this._panes.tilePane),this._rotatePane.appendChild(this._panes.overlayPane),this._norotatePane.appendChild(this._panes.shadowPane),this._norotatePane.appendChild(this._panes.markerPane),this._norotatePane.appendChild(this._panes.tooltipPane),this._norotatePane.appendChild(this._panes.popupPane),t.DomUtil.addClass(this._rotatePane,"leaflet-proxy leaflet-zoom-animated")}},_.setBearing=function(e){if(!this._rotate||!isFinite(e))return this;var a=this._bearing||0,n=o(e);if(n===a)return this;if(this._commitRotatePan(),this._bearing=n,this._bearingRad=n*i,this._updateRotatePaneTransform(),0===a!=(0===n))for(var s in this._layers){var r=this._layers[s];r instanceof t.Renderer&&r._update()}return this.fire("rotate")},_.getBearing=function(){return this._bearing||0},_._updateRotatePaneTransform=function(){if(this._rotatePane){if(!this._bearing)return this._rotatePane.style[t.DomUtil.TRANSFORM]="",void(this._rotatePane.style[t.DomUtil.TRANSFORM+"Origin"]="");var i=this.getSize().divideBy(2);this._rotatePane.style[t.DomUtil.TRANSFORM+"Origin"]=i.x+"px "+i.y+"px",this._rotatePane.style[t.DomUtil.TRANSFORM]="rotate("+this._bearingRad+"rad)"}},_._commitRotatePan=function(){if(this._rotate&&!this._committingRotatePan){var t=this._getMapPanePos();!t||0===t.x&&0===t.y||(this._committingRotatePan=!0,this._resetView(this.getCenter(),this.getZoom(),!0),this._committingRotatePan=!1)}};var m=_.containerPointToLayerPoint;_.containerPointToLayerPoint=function(i){if(!this._rotate||!this._bearing)return m.call(this,i);var e=t.point(i),o=this._getMapPanePos(),a=this.getSize().divideBy(2);return e.subtract(o).subtract(a).rotate(-this._bearingRad).add(a)};var d=_.layerPointToContainerPoint;_.layerPointToContainerPoint=function(i){if(!this._rotate||!this._bearing)return d.call(this,i);var e=t.point(i),o=this._getMapPanePos(),a=this.getSize().divideBy(2);return e.subtract(a).rotate(this._bearingRad).add(a).add(o)},_.rotatedPointToMapPanePoint=function(i){if(!this._bearing)return t.point(i);var e=this.getSize().divideBy(2);return t.point(i).rotateFrom(this._bearingRad,e)},_.mapPanePointToRotatedPoint=function(i){if(!this._bearing)return t.point(i);var e=this.getSize().divideBy(2);return t.point(i).rotateFrom(-this._bearingRad,e)};var c=_._getCenterOffset;_._getCenterOffset=function(t){return this._rotate&&this._bearing?this.project(t).subtract(this.project(this.getCenter())).rotate(this._bearingRad):c.call(this,t)};var u=_.getBounds;_.getBounds=function(){if(!this._rotate||!this._bearing)return u.call(this);var i=this.getSize(),e=t.latLngBounds();return e.extend(this.containerPointToLatLng(t.point(0,0))),e.extend(this.containerPointToLatLng(t.point(i.x,0))),e.extend(this.containerPointToLatLng(t.point(i.x,i.y))),e.extend(this.containerPointToLatLng(t.point(0,i.y))),e},_.mapBoundsToContainerBounds=function(i){return t.bounds([this.latLngToContainerPoint(i.getNorthWest()),this.latLngToContainerPoint(i.getNorthEast()),this.latLngToContainerPoint(i.getSouthEast()),this.latLngToContainerPoint(i.getSouthWest())])};var g=_.getBoundsZoom;_.getBoundsZoom=function(i,e,o){if(!this._rotate||!this._bearing)return g.call(this,i,e,o);i=t.latLngBounds(i),o=t.point(o||[0,0]);var a=this.getZoom()||0,n=this.getMinZoom(),s=this.getMaxZoom(),r=this.getSize().subtract(o);if(r.x<=0||r.y<=0)return a;var h=this.mapBoundsToContainerBounds(i).getSize(),_=this.options.zoomSnap,p=r.x/h.x,l=r.y/h.y,m=e?Math.max(p,l):Math.min(p,l);return a=this.getScaleZoom(m,a),_&&(a=Math.round(a/_)*_),Math.max(n,Math.min(s,a))},_._animateZoomNoDelay=function(t,i,e){this._mapPane&&(e&&(this._animatingZoom=!0,this._animateToCenter=t,this._animLine truncated
|
||||
Reference in new issue
Block a user