using System.Net.Http.Json; using System.Reflection; using System.Text.Json.Serialization; namespace LMEMappeCatastaliApp.Services; public sealed class AppUpdateService { private const string LatestReleaseUrl = "https://gitea.lmcloud.it/api/v1/repos/livio/LMEMappeCatastaliApp/releases/latest"; private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(20) }; public static string CurrentVersion => typeof(AppUpdateService).Assembly .GetCustomAttribute()? .InformationalVersion.Split('+')[0] ?? AppInfo.Current.VersionString; public async Task CheckAsync(CancellationToken cancellationToken = default) { var release = await _httpClient.GetFromJsonAsync(LatestReleaseUrl, cancellationToken) ?? throw new InvalidDataException("Risposta aggiornamenti non valida."); var latestText = (release.TagName ?? string.Empty).TrimStart('v', 'V'); _ = Version.TryParse(CurrentVersion, out var current); _ = Version.TryParse(latestText, out var latest); var apk = release.Assets?.FirstOrDefault(item => item.Name?.EndsWith(".apk", StringComparison.OrdinalIgnoreCase) == true); return new(latest is not null && current is not null && latest > current, latestText, release.HtmlUrl ?? string.Empty, apk?.BrowserDownloadUrl ?? release.HtmlUrl ?? string.Empty, release.Body ?? string.Empty); } private sealed class GiteaRelease { [JsonPropertyName("tag_name")] public string? TagName { get; set; } [JsonPropertyName("html_url")] public string? HtmlUrl { get; set; } [JsonPropertyName("assets")] public GiteaAsset[]? Assets { get; set; } [JsonPropertyName("body")] public string? Body { get; set; } } private sealed class GiteaAsset { [JsonPropertyName("name")] public string? Name { get; set; } [JsonPropertyName("browser_download_url")] public string? BrowserDownloadUrl { get; set; } } } public sealed record AppUpdateResult(bool IsAvailable, string Version, string ReleaseUrl, string DownloadUrl, string ReleaseNotes);