diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 490362d..8f53962 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,11 @@ jobs: - name: Restore dependencies run: dotnet restore + - name: Test + shell: bash + run: | + dotnet test --no-restore --configuration ${{ matrix.configuration }} + - name: Build shell: bash run: | diff --git a/PostCodeGUI.sln b/PostCodeGUI.sln index e3aa5f5..d47f62e 100644 --- a/PostCodeGUI.sln +++ b/PostCodeGUI.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostCodeSerialMonitor", "PostCodeSerialMonitor\PostCodeSerialMonitor.csproj", "{EBB8E46D-05A6-46CF-9C53-7DF64086F492}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostCodeSerialMonitor.Tests", "PostCodeSerialMonitor.Tests\PostCodeSerialMonitor.Tests.csproj", "{D629C06E-3323-47AF-83C1-B7A21D978ED2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,18 @@ Global {EBB8E46D-05A6-46CF-9C53-7DF64086F492}.Release|x64.Build.0 = Release|Any CPU {EBB8E46D-05A6-46CF-9C53-7DF64086F492}.Release|x86.ActiveCfg = Release|Any CPU {EBB8E46D-05A6-46CF-9C53-7DF64086F492}.Release|x86.Build.0 = Release|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Debug|x64.ActiveCfg = Debug|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Debug|x64.Build.0 = Debug|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Debug|x86.ActiveCfg = Debug|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Debug|x86.Build.0 = Debug|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Release|Any CPU.Build.0 = Release|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Release|x64.ActiveCfg = Release|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Release|x64.Build.0 = Release|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Release|x86.ActiveCfg = Release|Any CPU + {D629C06E-3323-47AF-83C1-B7A21D978ED2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PostCodeSerialMonitor.Tests/PostCodeSerialMonitor.Tests.csproj b/PostCodeSerialMonitor.Tests/PostCodeSerialMonitor.Tests.csproj index f09e311..2bdb604 100644 --- a/PostCodeSerialMonitor.Tests/PostCodeSerialMonitor.Tests.csproj +++ b/PostCodeSerialMonitor.Tests/PostCodeSerialMonitor.Tests.csproj @@ -4,7 +4,9 @@ net9.0 enable enable + true false + false diff --git a/PostCodeSerialMonitor.Tests/SemanticVersionTests.cs b/PostCodeSerialMonitor.Tests/SemanticVersionTests.cs new file mode 100644 index 0000000..aa4faa9 --- /dev/null +++ b/PostCodeSerialMonitor.Tests/SemanticVersionTests.cs @@ -0,0 +1,93 @@ +using System.Collections; +using PostCodeSerialMonitor.Models; + +namespace PostCodeSerialMonitor.Tests; +public class SemanticVersionTestDataGenerator : IEnumerable +{ + private readonly List _data = new List + { + new object[] {"0.2.0.0", "0.2.1.0", true}, + new object[] {"0.2.0.0", "0.2.10.0", true}, + new object[] {"0.2.0.0", "0.2.0.1", true}, + new object[] {"0.2.0.0", "0.3.0", true}, + new object[] {"0.2.0.0", "0.1.99", false}, + new object[] {"0.2.0.0", "0.1.33.0", false}, + new object[] {"0.3.0", "0.3.1", true}, + new object[] {"0.3.1.0", "0.3.11.0", true}, + new object[] {"0.3.2.0", "0.3.20.0", true}, + new object[] {"0.3.11.0", "0.3.1.0", false}, + + new object[] {"1.0.0", "1.0.1", true}, + new object[] {"1.0.0", "1.1.0", true}, + new object[] {"1.0.0", "2.0.0", true}, + new object[] {"2.0.0", "1.9.9", false}, + new object[] {"1.2.3", "1.2.4", true}, + new object[] {"1.2.3", "1.3.0", true}, + new object[] {"1.2.3", "2.0.0", true}, + new object[] {"1.2.3", "1.2.3", false}, + new object[] {"10.0.0", "9.99.99", false}, + new object[] {"0.0.1", "0.0.2", true}, + new object[] {"0.0.1", "0.1.0", true}, + new object[] {"0.0.1", "1.0.0", true}, + + new object[] {"v0.2.0.0", "v0.2.1.0", true}, + new object[] {"v0.2.0.0", "0.2.1.0", true}, + new object[] {"0.2.0.0", "v0.2.1.0", true}, + new object[] {"v1.0.0", "v1.0.1", true}, + new object[] {"v1.0.0", "1.0.1", true}, + new object[] {"1.0.0", "v1.0.1", true}, + new object[] {"v2.3.4", "v2.3.5", true}, + new object[] {"v2.3.4", "2.3.5", true}, + new object[] {"2.3.4", "v2.3.5", true}, + new object[] {"v10.20.30", "v10.20.31", true}, + new object[] {"v10.20.30", "10.20.31", true}, + new object[] {"10.20.30", "v10.20.31", true}, + + new object[] {"v0.0.1", "v0.0.2", true}, + new object[] {"v0.0.1", "0.0.2", true}, + new object[] {"0.0.1", "v0.0.2", true}, + new object[] {"v1.2.3", "v1.2.3", false}, + new object[] {"v1.2.3", "1.2.3", false}, + new object[] {"1.2.3", "v1.2.3", false}, + + new object[] {"0.1.0", "v0.2.0", true}, + new object[] {"v0.1.0", "0.2.0", true}, + new object[] {"0.1.0.0", "v0.2.0", true}, + new object[] {"v0.1.0.0", "0.2.0", true}, + new object[] {"1.0.0.0", "v1.1.0", true}, + new object[] {"v1.0.0.0", "1.1.0", true}, + + new object[] {"0.9.9.9", "v1.0.0.0", true}, + new object[] {"v0.9.9.9", "1.0.0.0", true}, + new object[] {"1.99.99.99", "v2.0.0.0", true}, + new object[] {"v1.99.99.99", "2.0.0.0", true}, + new object[] {"0.0.0.1", "v0.0.0.2", true}, + new object[] {"v0.0.0.1", "0.0.0", false}, + }; + + public IEnumerator GetEnumerator() => _data.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} + +public class SemanticVersionTests +{ + [Fact] + public void TestParsing() + { + Assert.Equal([0, 1, 2, 3], new SemanticVersion("v0.1.2.3").VersionParts); + Assert.Equal([0, 1, 2, 3], new SemanticVersion("0.1.2.3").VersionParts); + Assert.Equal([0, 1, 2, 0], new SemanticVersion("v0.1.2").VersionParts); + Assert.Equal([0, 1, 2, 0], new SemanticVersion("0.1.2").VersionParts); + } + + [Theory] + [ClassData(typeof(SemanticVersionTestDataGenerator))] + public void TestComparison(string localVersion, string remoteVersion, bool isNewer) + { + var local = new SemanticVersion(localVersion); + var remote = new SemanticVersion(remoteVersion); + + Assert.Equal(isNewer, remote > local); + } +} \ No newline at end of file diff --git a/PostCodeSerialMonitor.Tests/SerialDecoderTests.cs b/PostCodeSerialMonitor.Tests/SerialDecoderTests.cs index 5fb82a8..27a0e16 100644 --- a/PostCodeSerialMonitor.Tests/SerialDecoderTests.cs +++ b/PostCodeSerialMonitor.Tests/SerialDecoderTests.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Text.Json; +using Moq; namespace PostCodeSerialMonitor.Tests; public class TestDataGenerator : IEnumerable @@ -41,14 +42,17 @@ public SerialDecoderTests() // Create configuration var config = new AppConfiguration(); - var options = Options.Create(config); + var optionsMonitor = new Mock>(); + optionsMonitor.Setup(m => m.CurrentValue).Returns(config); // Create logger factory var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); + var loggerMeta = new Mock>().Object; + var loggerDecoder = new Mock>().Object; // Create configuration service var configService = new ConfigurationService( - options, + optionsMonitor.Object, loggerFactory.CreateLogger(), Path.GetDirectoryName(_testDataPath) ?? "." ); @@ -69,17 +73,17 @@ public SerialDecoderTests() ); // Create MetaDefinitionService - var metaDefinitionService = new MetaDefinitionService(configService, metaUpdateService); + var metaDefinitionService = new MetaDefinitionService(configService, metaUpdateService, loggerMeta); metaDefinitionService.RefreshMetaDefinitionsAsync().GetAwaiter().GetResult(); - _decoder = new SerialLineDecoder(metaDefinitionService); + _decoder = new SerialLineDecoder(metaDefinitionService, loggerDecoder); } [Theory] [ClassData(typeof(TestDataGenerator))] public void TestDecoding(string input, DecodedCode expected) { - var result = _decoder.DecodeLine(input, ConsoleType.XboxOne); + var result = _decoder.DecodeLine(input, ConsoleType.XboxOnePhat); Assert.NotNull(result); Assert.Equal(expected.Flavor, result.Flavor); Assert.Equal(expected.Index, result.Index); diff --git a/PostCodeSerialMonitor/Assets/Resources.Designer.cs b/PostCodeSerialMonitor/Assets/Resources.Designer.cs index 755ef01..03b363c 100644 --- a/PostCodeSerialMonitor/Assets/Resources.Designer.cs +++ b/PostCodeSerialMonitor/Assets/Resources.Designer.cs @@ -176,7 +176,25 @@ public static string FailedDownloadMetaDefinition { return ResourceManager.GetString("FailedDownloadMetaDefinition", resourceCulture); } } + + /// + /// In Services/MetaUpdateService.cs + /// + public static string FailedDeserializingReleaseDefinition { + get { + return ResourceManager.GetString("FailedDeserializingReleaseDefinition", resourceCulture); + } + } + /// + /// In Services/MetaUpdateService.cs + /// + public static string FailedDownloadReleaseDefinition { + get { + return ResourceManager.GetString("FailedDownloadReleaseDefinition", resourceCulture); + } + } + /// /// In Services/SerialLineDecoder.cs /// @@ -302,7 +320,25 @@ public static string FailedUpdateMetadata { return ResourceManager.GetString("FailedUpdateMetadata", resourceCulture); } } - + + /// + /// In ViewModels/MainWindowViewModel.cs + /// + public static string NewAppReleaseAvailable { + get { + return ResourceManager.GetString("NewAppReleaseAvailable", resourceCulture); + } + } + + /// + /// In ViewModels/MainWindowViewModel.cs + /// + public static string NewFirmwareReleaseAvailable { + get { + return ResourceManager.GetString("NewFirmwareReleaseAvailable", resourceCulture); + } + } + /// /// In ViewModels/MainWindowViewModel.cs /// diff --git a/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx b/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx index 8195cca..9afb5d7 100644 --- a/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx +++ b/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx @@ -169,6 +169,14 @@ Falha ao baixar MetaDefinition de {0} In Services/MetaUpdateService.cs + + Falha ao deserializar ReleaseDefinition + In Services/MetaUpdateService.cs + + + Falha ao baixar o último lançamento de {0} + In Services/MetaUpdateService.cs + Decodificador: Ignorando linha {0} In Services/SerialLineDecoder.cs @@ -225,6 +233,14 @@ Falha ao ataulizar o metadata In ViewModels/MainWindowViewModel.cs + + Uma nova versão do aplicativo está disponível em {0}. + In ViewModels/MainWindowViewModel.cs + + + Uma nova versão do firmware está disponível em {0}. + In ViewModels/MainWindowViewModel.cs + Erro In ViewModels/MainWindowViewModel.cs diff --git a/PostCodeSerialMonitor/Assets/Resources.resx b/PostCodeSerialMonitor/Assets/Resources.resx index 0336470..ca22351 100644 --- a/PostCodeSerialMonitor/Assets/Resources.resx +++ b/PostCodeSerialMonitor/Assets/Resources.resx @@ -169,6 +169,14 @@ Failed to download MetaDefinition from {0} In Services/MetaUpdateService.cs + + Failed deserializing ReleaseDefinition + In Services/MetaUpdateService.cs + + + Failed to download latest release from {0} + In Services/MetaUpdateService.cs + Decoder: Ignoring line {0} In Services/SerialLineDecoder.cs @@ -225,6 +233,14 @@ Failed to update metadata In ViewModels/MainWindowViewModel.cs + + A new app release is available at {0}. + In ViewModels/MainWindowViewModel.cs + + + A new firmware release is available at {0}. + In ViewModels/MainWindowViewModel.cs + Error In ViewModels/MainWindowViewModel.cs diff --git a/PostCodeSerialMonitor/Models/ReleaseDefinition.cs b/PostCodeSerialMonitor/Models/ReleaseDefinition.cs new file mode 100644 index 0000000..2298b2a --- /dev/null +++ b/PostCodeSerialMonitor/Models/ReleaseDefinition.cs @@ -0,0 +1,5 @@ +namespace PostCodeSerialMonitor.Models; +public class ReleaseDefinition +{ + public string tag_name { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/PostCodeSerialMonitor/Models/SemanticVersion.cs b/PostCodeSerialMonitor/Models/SemanticVersion.cs new file mode 100644 index 0000000..e84c352 --- /dev/null +++ b/PostCodeSerialMonitor/Models/SemanticVersion.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +namespace PostCodeSerialMonitor.Models; + +public partial class SemanticVersion +{ + public const int MIN_PARTS = 3; + public const int EXPECTED_PARTS = 4; + public string Version { get; } = string.Empty; + + // Format: Major.Minor.Patch. + public List VersionParts { get; } = []; + + [GeneratedRegex(@"^(?:v)?(\d+)\.(\d+)\.(\d+)\.?(\d+)?", RegexOptions.IgnoreCase | RegexOptions.Compiled, "en-US")] + private static partial Regex VersionPartsRegex(); + + public SemanticVersion(string version) + { + var match = VersionPartsRegex().Match(version); + + VersionParts = match.Groups.Values + // Skip first entry (the full matched string!) + .Skip(1) + .Select(x => x.Success ? int.Parse(x.Value) : 0) + .ToList(); + + if (VersionParts.Count < MIN_PARTS) + { + throw new InvalidDataException("Expecting at least 3 numbers in SemanticVersion"); + } + + //Ignore the 'v' at the beginning of the version string + if (version.StartsWith("v")) + { + Version = version.Substring(1); + } + else + { + Version = version; + } + } + + /// Override greater-than operator for SemanticVersion + public static bool operator >(SemanticVersion left, SemanticVersion right) + { + for (int i = 0; i < EXPECTED_PARTS; i++) + { + if (left.VersionParts[i] > right.VersionParts[i]) return true; + if (left.VersionParts[i] < right.VersionParts[i]) return false; + } + return false; + } + + /// Override less-than operator for SemanticVersion + public static bool operator <(SemanticVersion left, SemanticVersion right) + { + for (int i = 0; i < EXPECTED_PARTS; i++) + { + if (left.VersionParts[i] < right.VersionParts[i]) return true; + if (left.VersionParts[i] > right.VersionParts[i]) return false; + } + return false; + } +} \ No newline at end of file diff --git a/PostCodeSerialMonitor/ServiceCollectionExtensions.cs b/PostCodeSerialMonitor/ServiceCollectionExtensions.cs index dceb8e2..adaea03 100644 --- a/PostCodeSerialMonitor/ServiceCollectionExtensions.cs +++ b/PostCodeSerialMonitor/ServiceCollectionExtensions.cs @@ -58,6 +58,7 @@ public static void AddCommonServices(this IServiceCollection collection) collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(); + collection.AddSingleton(); // Register ViewModels collection.AddTransient(); diff --git a/PostCodeSerialMonitor/Services/GithubUpdateService.cs b/PostCodeSerialMonitor/Services/GithubUpdateService.cs new file mode 100644 index 0000000..f6f6210 --- /dev/null +++ b/PostCodeSerialMonitor/Services/GithubUpdateService.cs @@ -0,0 +1,78 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using PostCodeSerialMonitor.Models; +using Microsoft.Extensions.Logging; + +namespace PostCodeSerialMonitor.Services; + +public class GithubUpdateService +{ + private readonly ConfigurationService _configurationService; + private readonly JsonSerializerOptions _jsonSerializeOptions; + private readonly string _localPath; + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + public AppConfiguration Config => _configurationService.Config; + + public GithubUpdateService( + ConfigurationService configurationService, + JsonSerializerOptions jsonOptions, + ILogger logger) + { + _configurationService = configurationService ?? throw new ArgumentNullException(nameof(configurationService)); + _jsonSerializeOptions = jsonOptions ?? throw new ArgumentNullException(nameof(jsonOptions)); + _localPath = _configurationService.Config.MetaStoragePath + ?? throw new ArgumentNullException(nameof(_configurationService.Config.MetaStoragePath)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _httpClient = new HttpClient(); + + //All GitHub's API requests must include a valid User-Agent header. + //@see https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api?apiVersion=2022-11-28#user-agent + _httpClient.DefaultRequestHeaders.Add("User-Agent", "XboxPostcodeMonitor"); + } + + public async Task CheckForAppUpdatesAsync(string localVersion) + { + // Get the latest release from GitHub repo. + var remoteRelease = await GetRepositoryLatestReleaseAsync("xboxoneresearch", "XboxPostcodeMonitor"); + var remoteVersion = remoteRelease?.tag_name ?? string.Empty; + + SemanticVersion local = new SemanticVersion(localVersion); + SemanticVersion remote = new SemanticVersion(remoteVersion); + + return remote > local; + } + + public async Task CheckForFirmwareUpdatesAsync(string localVersion) + { + // Get the latest release from GitHub repo. + var remoteRelease = await GetRepositoryLatestReleaseAsync("xboxoneresearch", "PicoDurangoPOST"); + var remoteVersion = remoteRelease?.tag_name ?? string.Empty; + + SemanticVersion local = new SemanticVersion(localVersion); + SemanticVersion remote = new SemanticVersion(remoteVersion); + + return remote > local; + } + + private async Task GetRepositoryLatestReleaseAsync(string owner, string repo) + { + var gitHubApiReleasesLatest = new Uri($"https://api.github.com/repos/{owner}/{repo}/releases/latest"); + + try + { + var response = await _httpClient.GetAsync(gitHubApiReleasesLatest); + response.EnsureSuccessStatusCode(); + + var json = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(json, _jsonSerializeOptions); + } + catch (Exception ex) + { + _logger.LogError(ex, Assets.Resources.FailedDownloadReleaseDefinition, gitHubApiReleasesLatest); + return null; + } + } +} \ No newline at end of file diff --git a/PostCodeSerialMonitor/Services/MetaUpdateService.cs b/PostCodeSerialMonitor/Services/MetaUpdateService.cs index 0204cd9..c2c87bb 100644 --- a/PostCodeSerialMonitor/Services/MetaUpdateService.cs +++ b/PostCodeSerialMonitor/Services/MetaUpdateService.cs @@ -1,13 +1,16 @@ using System; using System.IO; using System.Net.Http; +using System.Reflection; using System.Text.Json; using System.Threading.Tasks; using System.Collections.Generic; using PostCodeSerialMonitor.Models; +using PostCodeSerialMonitor.Utils; using Microsoft.Extensions.Logging; namespace PostCodeSerialMonitor.Services; + public class MetaUpdateService { private readonly ConfigurationService _configurationService; @@ -24,8 +27,8 @@ public class MetaUpdateService public AppConfiguration Config => _configurationService.Config; public MetaUpdateService( - ConfigurationService configurationService, - JsonSerializerOptions jsonOptions, + ConfigurationService configurationService, + JsonSerializerOptions jsonOptions, ILogger logger) { _configurationService = configurationService ?? throw new ArgumentNullException(nameof(configurationService)); @@ -50,7 +53,7 @@ public async Task CheckForMetaDefinitionUpdatesAsync() { var localMeta = await GetLocalMetaDefinitionAsync(); var remoteMeta = await GetRemoteMetaDefinitionAsync(); - + if (localMeta == null || remoteMeta == null) { // Update required @@ -75,7 +78,7 @@ public async Task UpdateMetaDefinitionAsync() // Ensure directory exists Directory.CreateDirectory(_localPath); - + // Save the new meta definition await File.WriteAllTextAsync(LocalMetaPath, metaContentStr); @@ -143,7 +146,7 @@ private async Task DownloadMetaFilesAsync() { var response = await _httpClient.GetAsync(Config.MetaJsonUrl); response.EnsureSuccessStatusCode(); - + var json = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(json, _jsonSerializeOptions); } diff --git a/PostCodeSerialMonitor/ViewModels/MainWindowViewModel.cs b/PostCodeSerialMonitor/ViewModels/MainWindowViewModel.cs index aa01310..0228d03 100644 --- a/PostCodeSerialMonitor/ViewModels/MainWindowViewModel.cs +++ b/PostCodeSerialMonitor/ViewModels/MainWindowViewModel.cs @@ -28,6 +28,7 @@ public partial class MainWindowViewModel : ViewModelBase private SerialLineDecoder _serialLineDecoder; private MetaUpdateService _metaUpdateService; private MetaDefinitionService _metaDefinitionService; + private GithubUpdateService _githubUpdateService; private IStorageProvider? _storageProvider; public ObservableCollection SerialPorts { get; } = new(); @@ -87,6 +88,7 @@ public MainWindowViewModel( MetaUpdateService metaUpdateService, MetaDefinitionService metaDefinitionService, SerialLineDecoder serialLineDecoder, + GithubUpdateService githubUpdateService, ILogger logger) { _serialService = serialService ?? throw new ArgumentNullException(nameof(serialService)); @@ -94,6 +96,7 @@ public MainWindowViewModel( _metaUpdateService = metaUpdateService ?? throw new ArgumentNullException(nameof(metaUpdateService)); _metaDefinitionService = metaDefinitionService ?? throw new ArgumentNullException(nameof(metaDefinitionService)); _serialLineDecoder = serialLineDecoder ?? throw new ArgumentNullException(nameof(serialLineDecoder)); + _githubUpdateService = githubUpdateService ?? throw new ArgumentNullException(nameof(githubUpdateService)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); // Get version from assembly @@ -174,6 +177,19 @@ await MessageBoxManager ButtonEnum.Ok) .ShowAsync(); } + + if (_configurationService.Config.CheckForAppUpdates) + { + updateAvailable = await _githubUpdateService.CheckForAppUpdatesAsync(AppVersion); + if (updateAvailable) + { + var box = MessageBoxManager + .GetMessageBoxStandard(Assets.Resources.Warning, + string.Format(Assets.Resources.NewAppReleaseAvailable, "https://github.com/xboxoneresearch/XboxPostcodeMonitor/releases"), ButtonEnum.Ok); + + await box.ShowAsync(); + } + } } [RelayCommand] @@ -267,10 +283,23 @@ private async Task ConnectAsync() { _logger.LogError(ex, Assets.Resources.ErrorConection); await MessageBoxManager - .GetMessageBoxStandard(Assets.Resources.Error, string.Format(Assets.Resources.ErrorConectionMessageBoxError,ex.Message), + .GetMessageBoxStandard(Assets.Resources.Error, string.Format(Assets.Resources.ErrorConectionMessageBoxError, ex.Message), ButtonEnum.Ok) .ShowAsync(); } + + if (IsConnected && _configurationService.Config.CheckForFwUpdates) + { + var updateAvailable = await _githubUpdateService.CheckForFirmwareUpdatesAsync(_serialService.FirmwareVersion); + if (updateAvailable) + { + var box = MessageBoxManager + .GetMessageBoxStandard(Assets.Resources.Warning, + string.Format(Assets.Resources.NewFirmwareReleaseAvailable, "https://github.com/xboxoneresearch/PicoDurangoPOST/releases"), ButtonEnum.Ok); + + await box.ShowAsync(); + } + } } }