using System.Net.Http.Json; using System.Text.Json.Serialization; using Microsoft.Maui.Networking; namespace LMEMappeCatastaliApp.Services; public sealed class NetworkLocationService { private readonly HttpClient httpClient = new() { Timeout = TimeSpan.FromSeconds(6) }; public NetworkLocationService() { httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.15"); } public async Task GetApproximateLocationAsync( CancellationToken cancellationToken = default) { if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet) { return null; } using var response = await httpClient.GetAsync("https://ipapi.co/json/", cancellationToken); if (!response.IsSuccessStatusCode) { return null; } var result = await response.Content.ReadFromJsonAsync(cancellationToken); if (result is null || result.Error == true || !result.Latitude.HasValue || !result.Longitude.HasValue || Math.Abs(result.Latitude.Value) > 90 || Math.Abs(result.Longitude.Value) > 180) { return null; } var labelParts = new[] { result.City, result.Region, result.CountryName } .Where(value => !string.IsNullOrWhiteSpace(value)); return new NetworkLocationSnapshot( result.Latitude.Value, result.Longitude.Value, string.Join(", ", labelParts)); } private sealed class IpLocationResponse { [JsonPropertyName("latitude")] public double? Latitude { get; init; } [JsonPropertyName("longitude")] public double? Longitude { get; init; } [JsonPropertyName("city")] public string? City { get; init; } [JsonPropertyName("region")] public string? Region { get; init; } [JsonPropertyName("country_name")] public string? CountryName { get; init; } [JsonPropertyName("error")] public bool? Error { get; init; } } } public sealed record NetworkLocationSnapshot(double Latitude, double Longitude, string Label);