diff --git a/Directory.Build.props b/Directory.Build.props index 7d6d9de5..ff71f1ba 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,8 +2,8 @@ Vladimir Khil Khil-soft - 7.11.3 - 6.0.0 + 7.11.10 + 6.0.2 2.15.0 diff --git a/SIGame.sln b/SIGame.sln index 7ba93dc1..20fd3b0f 100644 --- a/SIGame.sln +++ b/SIGame.sln @@ -59,8 +59,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SI.GameServer.Client", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "src\Common\Utils\Utils.csproj", "{49D06BD3-C088-4E5A-888E-697D78417ABF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppService.Client", "src\Common\AppService.Client\AppService.Client.csproj", "{26C59ADA-8AE7-467B-8D03-404725CCFC53}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIStorageService.ViewModel", "src\Common\SIStorageService.ViewModel\SIStorageService.ViewModel.csproj", "{AFF2B73A-0BA3-4152-82D0-9573C05FDC98}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{0D6E84B6-C90C-4FA8-A932-1DA7179E9F1D}" @@ -530,26 +528,6 @@ Global {49D06BD3-C088-4E5A-888E-697D78417ABF}.Release|x64.Build.0 = Release|Any CPU {49D06BD3-C088-4E5A-888E-697D78417ABF}.Release|x86.ActiveCfg = Release|Any CPU {49D06BD3-C088-4E5A-888E-697D78417ABF}.Release|x86.Build.0 = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|ARM.ActiveCfg = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|ARM.Build.0 = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|ARM64.Build.0 = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|x64.ActiveCfg = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|x64.Build.0 = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|x86.ActiveCfg = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Debug|x86.Build.0 = Debug|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|Any CPU.Build.0 = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|ARM.ActiveCfg = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|ARM.Build.0 = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|ARM64.ActiveCfg = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|ARM64.Build.0 = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|x64.ActiveCfg = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|x64.Build.0 = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|x86.ActiveCfg = Release|Any CPU - {26C59ADA-8AE7-467B-8D03-404725CCFC53}.Release|x86.Build.0 = Release|Any CPU {AFF2B73A-0BA3-4152-82D0-9573C05FDC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFF2B73A-0BA3-4152-82D0-9573C05FDC98}.Debug|Any CPU.Build.0 = Debug|Any CPU {AFF2B73A-0BA3-4152-82D0-9573C05FDC98}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -700,7 +678,6 @@ Global {8D528C21-F673-4CE0-A430-3F23F5B6A346} = {3E07412F-2F9C-458E-B897-E07E86BF682A} {35AD14FA-7BDC-42CB-8501-1EC446805C99} = {98AD9562-11D8-4547-B71E-56BDAC94A39C} {49D06BD3-C088-4E5A-888E-697D78417ABF} = {98AD9562-11D8-4547-B71E-56BDAC94A39C} - {26C59ADA-8AE7-467B-8D03-404725CCFC53} = {98AD9562-11D8-4547-B71E-56BDAC94A39C} {AFF2B73A-0BA3-4152-82D0-9573C05FDC98} = {98AD9562-11D8-4547-B71E-56BDAC94A39C} {9D7B6E42-82F0-491E-9E7C-F36086715D50} = {98AD9562-11D8-4547-B71E-56BDAC94A39C} {8C805CF1-39A5-461D-BB30-09E520FF3C78} = {3E07412F-2F9C-458E-B897-E07E86BF682A} diff --git a/SIQuester.sln b/SIQuester.sln index cce552f6..2803f86a 100644 --- a/SIQuester.sln +++ b/SIQuester.sln @@ -31,8 +31,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{29A5EB8A-6B8 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "src\Common\Utils\Utils.csproj", "{DB37734A-E865-4E1E-8CB9-3A9EB3D6BDF4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppService.Client", "src\Common\AppService.Client\AppService.Client.csproj", "{85ABCE10-858E-44F8-A1C1-5CAA9E84F484}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIPackages.Tests", "test\Common\SIPackages.Tests\SIPackages.Tests.csproj", "{3B650F1B-FA32-4C3C-A79E-6C386DF9977E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIStorageService.ViewModel", "src\Common\SIStorageService.ViewModel\SIStorageService.ViewModel.csproj", "{C3B297B7-6782-473B-B908-42458A636100}" @@ -43,6 +41,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIEngine.Core", "src\Common EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils.Wpf", "src\Common\Utils.Wpf\Utils.Wpf.csproj", "{F7AF5912-E7B2-43A2-8E3E-DE5CC75243A6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{1293FEFC-100A-4F00-8B73-1660DBF26F3F}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -119,14 +122,6 @@ Global {DB37734A-E865-4E1E-8CB9-3A9EB3D6BDF4}.Release|Any CPU.Build.0 = Release|Any CPU {DB37734A-E865-4E1E-8CB9-3A9EB3D6BDF4}.Release|x86.ActiveCfg = Release|Any CPU {DB37734A-E865-4E1E-8CB9-3A9EB3D6BDF4}.Release|x86.Build.0 = Release|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Debug|Any CPU.Build.0 = Debug|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Debug|x86.ActiveCfg = Debug|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Debug|x86.Build.0 = Debug|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Release|Any CPU.ActiveCfg = Release|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Release|Any CPU.Build.0 = Release|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Release|x86.ActiveCfg = Release|Any CPU - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484}.Release|x86.Build.0 = Release|Any CPU {3B650F1B-FA32-4C3C-A79E-6C386DF9977E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B650F1B-FA32-4C3C-A79E-6C386DF9977E}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B650F1B-FA32-4C3C-A79E-6C386DF9977E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -183,7 +178,6 @@ Global {191BE083-3920-4C18-8130-4D6B2BF0AB59} = {9BD30589-9C99-4E58-8447-2DDB33A7F0FC} {80E6576A-4906-4D07-B473-A994EDDD13AC} = {9BD30589-9C99-4E58-8447-2DDB33A7F0FC} {DB37734A-E865-4E1E-8CB9-3A9EB3D6BDF4} = {D8DC2EF3-36A3-475B-A88F-861AB1E112F6} - {85ABCE10-858E-44F8-A1C1-5CAA9E84F484} = {D8DC2EF3-36A3-475B-A88F-861AB1E112F6} {3B650F1B-FA32-4C3C-A79E-6C386DF9977E} = {03BB87B1-7EA0-49F8-B8A5-46A64E7A6E0C} {C3B297B7-6782-473B-B908-42458A636100} = {D8DC2EF3-36A3-475B-A88F-861AB1E112F6} {64E4E20D-318F-404F-B7D4-1039FD67F84B} = {03BB87B1-7EA0-49F8-B8A5-46A64E7A6E0C} diff --git a/SImulator.sln b/SImulator.sln index 7ce3ecda..fb0cd6c1 100644 --- a/SImulator.sln +++ b/SImulator.sln @@ -27,8 +27,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SImulator", "src\SImulator\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "src\Common\Utils\Utils.csproj", "{349CBBC7-36F8-4ED6-B45B-7B34D5B970DD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppService.Client", "src\Common\AppService.Client\AppService.Client.csproj", "{56112D6B-FD5A-4918-982D-4D3724375CF9}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EDF0B6AF-1972-47A9-B812-533BD079C701}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIStorageService.ViewModel", "src\Common\SIStorageService.ViewModel\SIStorageService.ViewModel.csproj", "{9CE7BB4E-0C76-4B89-9249-49369580C25B}" @@ -41,6 +39,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIEngine.Tests", "test\Comm EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils.Wpf", "src\Common\Utils.Wpf\Utils.Wpf.csproj", "{4C678CED-354B-432E-BB67-700E669EE0E7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{B368E16F-622F-4C82-97CE-DFF0F750A473}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -235,26 +238,6 @@ Global {349CBBC7-36F8-4ED6-B45B-7B34D5B970DD}.Release|x64.Build.0 = Release|Any CPU {349CBBC7-36F8-4ED6-B45B-7B34D5B970DD}.Release|x86.ActiveCfg = Release|Any CPU {349CBBC7-36F8-4ED6-B45B-7B34D5B970DD}.Release|x86.Build.0 = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|ARM.ActiveCfg = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|ARM.Build.0 = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|ARM64.Build.0 = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|x64.ActiveCfg = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|x64.Build.0 = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|x86.ActiveCfg = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Debug|x86.Build.0 = Debug|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|Any CPU.Build.0 = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|ARM.ActiveCfg = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|ARM.Build.0 = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|ARM64.ActiveCfg = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|ARM64.Build.0 = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|x64.ActiveCfg = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|x64.Build.0 = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|x86.ActiveCfg = Release|Any CPU - {56112D6B-FD5A-4918-982D-4D3724375CF9}.Release|x86.Build.0 = Release|Any CPU {9CE7BB4E-0C76-4B89-9249-49369580C25B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9CE7BB4E-0C76-4B89-9249-49369580C25B}.Debug|Any CPU.Build.0 = Debug|Any CPU {9CE7BB4E-0C76-4B89-9249-49369580C25B}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -371,7 +354,6 @@ Global {CB2B8CE7-876C-4D16-BFA4-E1F67F949280} = {F7CE4B38-4286-47BA-B5BA-0E4FA77E594E} {7BF7F1CE-2187-4372-9A31-CC0048031E09} = {117739F8-28CD-4CC4-950C-E3513265A87D} {349CBBC7-36F8-4ED6-B45B-7B34D5B970DD} = {069B16F1-8F70-4CFC-8651-E4763D225B60} - {56112D6B-FD5A-4918-982D-4D3724375CF9} = {069B16F1-8F70-4CFC-8651-E4763D225B60} {9CE7BB4E-0C76-4B89-9249-49369580C25B} = {069B16F1-8F70-4CFC-8651-E4763D225B60} {D960F7D2-7575-46DA-A2E4-A315A50B9863} = {069B16F1-8F70-4CFC-8651-E4763D225B60} {72F8EAE3-CBAD-45A5-A1BC-0FDA0C363DD2} = {F7CE4B38-4286-47BA-B5BA-0E4FA77E594E} diff --git a/deploy/SIGame.Setup/Product.wxs b/deploy/SIGame.Setup/Product.wxs index 0c458977..c5b475cb 100644 --- a/deploy/SIGame.Setup/Product.wxs +++ b/deploy/SIGame.Setup/Product.wxs @@ -345,9 +345,6 @@ - - - diff --git a/deploy/SIQuester.Setup/Product.wxs b/deploy/SIQuester.Setup/Product.wxs index d3442e2c..26ba6061 100644 --- a/deploy/SIQuester.Setup/Product.wxs +++ b/deploy/SIQuester.Setup/Product.wxs @@ -161,9 +161,6 @@ - - - diff --git a/src/Common/AppService.Client/AppService.Client.csproj b/src/Common/AppService.Client/AppService.Client.csproj deleted file mode 100644 index b66e6ec9..00000000 --- a/src/Common/AppService.Client/AppService.Client.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - net6.0 - enable - enable - True - key.snk - Khil-soft - Copyright © Khil-soft 2022 - 2024 - - - none - false - - - - - - - - - - diff --git a/src/Common/AppService.Client/AppServiceClient.cs b/src/Common/AppService.Client/AppServiceClient.cs deleted file mode 100644 index 15bc5538..00000000 --- a/src/Common/AppService.Client/AppServiceClient.cs +++ /dev/null @@ -1,81 +0,0 @@ -using AppService.Client.Models; -using Newtonsoft.Json; -using System.Reflection; -using System.Text; - -namespace AppService.Client -{ - /// - public sealed class AppServiceClient : IAppServiceClient - { - private static readonly JsonSerializer Serializer = new(); - - private readonly HttpClient _client; - - public AppServiceClient(HttpClient client) - { - _client = client; - } - - public async Task GetProductAsync(string name, CancellationToken cancellationToken = default) - { - var appInfo = await CallAsync("Product?name=" + name + "&osVersion=" + Environment.OSVersion.Version, cancellationToken); - - if (appInfo == null) - { - throw new Exception($"Product {name} not found"); - } - - if (!appInfo.Uri.IsAbsoluteUri) - { - appInfo.Uri = new Uri("https://vladimirkhil.com/" + appInfo.Uri.OriginalString); - } - - return appInfo; - } - - public async Task SendErrorReportAsync( - string application, - string errorMessage, - Version? appVersion = null, - DateTime? time = null, - CancellationToken cancellationToken = default) - { - var version = appVersion ?? Assembly.GetEntryAssembly()?.GetName().Version; - - var errorInfo = new ErrorInfo - { - Application = application, - Error = errorMessage, - Version = version?.ToString() ?? "", - Time = time ?? DateTime.UtcNow, - OSVersion = Environment.OSVersion.Version.ToString() - }; - - var sb = new StringBuilder(); - - using (var writer = new StringWriter(sb)) - { - Serializer.Serialize(writer, errorInfo); - } - - var content = new StringContent(sb.ToString(), Encoding.UTF8, "application/json"); - - using var response = await _client.PostAsync("SendErrorReport2", content, cancellationToken); - using var stream = await response.Content.ReadAsStreamAsync(cancellationToken); - using var reader = new StreamReader(stream); - - return (ErrorStatus?)Serializer.Deserialize(reader, typeof(ErrorStatus)); - } - - private async Task CallAsync(string request, CancellationToken cancellationToken = default) - { - using var stream = await _client.GetStreamAsync(request, cancellationToken); - using var reader = new StreamReader(stream); - - return (T?)Serializer.Deserialize(reader, typeof(T)); - } - - public void Dispose() => _client.Dispose(); - } -} diff --git a/src/Common/AppService.Client/AppServiceClientOptions.cs b/src/Common/AppService.Client/AppServiceClientOptions.cs deleted file mode 100644 index 0ad8ec20..00000000 --- a/src/Common/AppService.Client/AppServiceClientOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace AppService.Client -{ - /// - /// Provides options for . - /// - public sealed class AppServiceClientOptions - { - public const string ConfigurationSectionName = "AppServiceClient"; - - /// - /// AppService address. - /// - public Uri? ServiceUri { get; set; } - } -} diff --git a/src/Common/AppService.Client/IAppServiceClient.cs b/src/Common/AppService.Client/IAppServiceClient.cs deleted file mode 100644 index ea8d4ccf..00000000 --- a/src/Common/AppService.Client/IAppServiceClient.cs +++ /dev/null @@ -1,34 +0,0 @@ -using AppService.Client.Models; - -namespace AppService.Client -{ - /// - /// Provides API for working with published products. - /// - public interface IAppServiceClient : IDisposable - { - /// - /// Gets product info. - /// - /// Product name. - /// Cancellation token. - /// Product info. - Task GetProductAsync(string name, CancellationToken cancellationToken = default); - - /// - /// Sends product execution error information. - /// - /// Application name. - /// Error message. - /// Application version. - /// Error time. - /// Cancellation token. - /// Current status of this error. - Task SendErrorReportAsync( - string application, - string errorMessage, - Version? appVersion = null, - DateTime? time = null, - CancellationToken cancellationToken = default); - } -} diff --git a/src/Common/AppService.Client/Models/AppInfo.cs b/src/Common/AppService.Client/Models/AppInfo.cs deleted file mode 100644 index f4d3d7a0..00000000 --- a/src/Common/AppService.Client/Models/AppInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace AppService.Client.Models -{ - /// - /// Defines an application info. - /// - public sealed class AppInfo - { - /// - /// Current application version. - /// - public Version Version { get; set; } - - /// - /// Application setup uri. - /// - public Uri Uri { get; set; } - } -} diff --git a/src/Common/AppService.Client/Models/ErrorInfo.cs b/src/Common/AppService.Client/Models/ErrorInfo.cs deleted file mode 100644 index 5977314f..00000000 --- a/src/Common/AppService.Client/Models/ErrorInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace AppService.Client.Models -{ - /// - /// Contains information about application error. - /// - public sealed class ErrorInfo - { - /// - /// Application name. - /// - public string Application { get; set; } - - /// - /// Application version. - /// - public string Version { get; set; } - - /// - /// Error time. - /// - public DateTime Time { get; set; } - - /// - /// Error text. - /// - public string Error { get; set; } - - /// - /// Operation system version. - /// - public string OSVersion { get; set; } - } -} diff --git a/src/Common/AppService.Client/Models/ErrorStatus.cs b/src/Common/AppService.Client/Models/ErrorStatus.cs deleted file mode 100644 index 200349ec..00000000 --- a/src/Common/AppService.Client/Models/ErrorStatus.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace AppService.Client.Models -{ - /// - /// Defines an application error current status. - /// - public enum ErrorStatus - { - /// - /// The error has not been fixed yet. - /// - NotFixed, - /// - /// The error has been fixed in current application version. - /// - Fixed, - /// - /// The error can not be reproduced by the application author. - /// - CannotReproduce - } -} \ No newline at end of file diff --git a/src/Common/AppService.Client/NoOpAppServiceClient.cs b/src/Common/AppService.Client/NoOpAppServiceClient.cs deleted file mode 100644 index 5684bd13..00000000 --- a/src/Common/AppService.Client/NoOpAppServiceClient.cs +++ /dev/null @@ -1,24 +0,0 @@ -using AppService.Client.Models; - -namespace AppService.Client -{ - /// - /// Provides a no-op implementation for . - /// It is used when AppSerive Uri has not been specified. - /// - /// - internal sealed class NoOpAppServiceClient : IAppServiceClient - { - public Task GetProductAsync(string name, CancellationToken cancellationToken = default) => Task.FromResult(null); - - public Task SendErrorReportAsync( - string application, - string errorMessage, - Version? appVersion = null, - DateTime? time = null, - CancellationToken cancellationToken = default) => - Task.FromResult(ErrorStatus.NotFixed); - - public void Dispose() { } - } -} diff --git a/src/Common/AppService.Client/ServiceCollectionExtensions.cs b/src/Common/AppService.Client/ServiceCollectionExtensions.cs deleted file mode 100644 index 854fcb8f..00000000 --- a/src/Common/AppService.Client/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using System.Net; - -namespace AppService.Client -{ - /// - /// Provides an extension method for adding implementation to service collection. - /// - public static class ServiceCollectionExtensions - { - /// - /// Adds implementation to service collection. - /// - /// - /// When no gameresult service Uri has been provided, ads no-op implementation. - /// - /// Service collection. - /// App configuration. - public static IServiceCollection AddAppServiceClient(this IServiceCollection services, IConfiguration configuration) - { - var optionsSection = configuration.GetSection(AppServiceClientOptions.ConfigurationSectionName); - services.Configure(optionsSection); - - var options = optionsSection.Get(); - - if (options?.ServiceUri != null) - { - services.AddHttpClient( - client => - { - client.BaseAddress = options?.ServiceUri; - client.DefaultRequestVersion = HttpVersion.Version20; - }); - } - else - { - services.AddSingleton(); - } - - return services; - } - } -} diff --git a/src/Common/AppService.Client/key.snk b/src/Common/AppService.Client/key.snk deleted file mode 100644 index 53c34449..00000000 Binary files a/src/Common/AppService.Client/key.snk and /dev/null differ diff --git a/src/Common/SI.GameServer.Client/GameServerClient.cs b/src/Common/SI.GameServer.Client/GameServerClient.cs index 8a8bddcb..d6ecf90c 100644 --- a/src/Common/SI.GameServer.Client/GameServerClient.cs +++ b/src/Common/SI.GameServer.Client/GameServerClient.cs @@ -6,11 +6,8 @@ using SIData; using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Http.Handlers; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -115,7 +112,7 @@ public Task GetLatestChatMessagesAsync(CancellationToken cancella public Task GetUsersAsync(CancellationToken cancellationToken = default) => _connection.InvokeAsync("GetUsers", cancellationToken); - private async Task AuthenticateUserAsync( + private async Task AuthenticateUserAsync( string user, string password, CancellationToken cancellationToken = default) @@ -133,7 +130,7 @@ private async Task AuthenticateUserAsync( if (response.IsSuccessStatusCode) { - return await response.Content.ReadAsStringAsync(cancellationToken); + return; } throw response.StatusCode switch @@ -151,14 +148,15 @@ public async Task OpenAsync(string userName, CancellationToken cancellationToken throw new InvalidOperationException("Client has been already opened"); } - var token = await AuthenticateUserAsync(userName, "", cancellationToken); + await AuthenticateUserAsync(userName, "", cancellationToken); _connection = new HubConnectionBuilder() .WithUrl( - $"{ServiceUri}sionline?token={token}", + $"{ServiceUri}sionline", options => { options.AccessTokenProvider = () => Task.FromResult(Convert.ToBase64String(Encoding.UTF8.GetBytes(userName))); + options.Cookies = _cookieContainer; }) .WithAutomaticReconnect(new ReconnectPolicy()) .AddMessagePackProtocol() @@ -206,24 +204,6 @@ public async Task OpenAsync(string userName, CancellationToken cancellationToken public Task SayAsync(string message) => _connection.InvokeAsync("Say", message); - private static async Task GetErrorMessageAsync(HttpResponseMessage response, CancellationToken cancellationToken) - { - var serverError = await response.Content.ReadAsStringAsync(cancellationToken); - - if (response.StatusCode == HttpStatusCode.RequestEntityTooLarge || - response.StatusCode == HttpStatusCode.BadRequest && serverError == "Request body too large.") - { - return Resources.FileTooLarge; - } - - if (response.StatusCode == HttpStatusCode.BadGateway) - { - return $"{response.StatusCode}: Bad Gateway"; - } - - return $"{response.StatusCode}: {serverError}"; - } - private Task OnConnectionClosedAsync(Exception? exc) => Closed != null ? Closed(exc) : Task.CompletedTask; private void OnUI(Action action) diff --git a/src/Common/SIPackages/GlobalData.cs b/src/Common/SIPackages/GlobalData.cs index 5b37e8d4..3fc9291c 100644 --- a/src/Common/SIPackages/GlobalData.cs +++ b/src/Common/SIPackages/GlobalData.cs @@ -1,6 +1,5 @@ using SIPackages.Models; using System.Xml; -using System.Xml.Schema; namespace SIPackages; diff --git a/src/Common/Utils/UI.cs b/src/Common/Utils/UI.cs index 0dbe4920..e11619ac 100644 --- a/src/Common/Utils/UI.cs +++ b/src/Common/Utils/UI.cs @@ -7,6 +7,9 @@ public static class UI { public static TaskScheduler? Scheduler { get; private set; } // TODO: -> private + /// + /// Captures UI thread task scheduler. + /// public static void Initialize() { Scheduler = TaskScheduler.FromCurrentSynchronizationContext(); diff --git a/src/SICore/SICore/Clients/Other/SIReport.cs b/src/SICore/SICore/Clients/Other/SIReport.cs index 43177e9a..6adebaea 100644 --- a/src/SICore/SICore/Clients/Other/SIReport.cs +++ b/src/SICore/SICore/Clients/Other/SIReport.cs @@ -2,38 +2,41 @@ using System.Runtime.CompilerServices; using System.Windows.Input; -namespace SICore +namespace SICore; + +/// +/// Defines a user provided report. +/// +public sealed class SIReport : INotifyPropertyChanged { - public sealed class SIReport : INotifyPropertyChanged - { - private string _report = ""; + private string _report = ""; - public string Report - { - get { return _report; } - set { _report = value; OnPropertyChanged(); } - } + public string Report + { + get => _report; + set { _report = value; OnPropertyChanged(); } + } - private string _comment = ""; + private string _comment = ""; - public string Comment - { - get { return _comment; } - set { _comment = value; OnPropertyChanged(); } - } + public string Comment + { + get => _comment; + set { _comment = value; OnPropertyChanged(); } + } - public string Title { get; set; } + public string Title { get; set; } - public string Subtitle { get; set; } + public string Subtitle { get; set; } - public ICommand SendReport { get; set; } - public ICommand SendNoReport { get; set; } + public ICommand SendReport { get; set; } - private void OnPropertyChanged([CallerMemberName] string name = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); - } + public ICommand SendNoReport { get; set; } - public event PropertyChangedEventHandler PropertyChanged; + private void OnPropertyChanged([CallerMemberName] string? name = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } + + public event PropertyChangedEventHandler? PropertyChanged; } diff --git a/src/SIGame/SIGame.ViewModel/Settings/ErrorInfo.cs b/src/SIGame/SIGame.ViewModel/Settings/ErrorInfo.cs index 4e857f62..7dbee15a 100644 --- a/src/SIGame/SIGame.ViewModel/Settings/ErrorInfo.cs +++ b/src/SIGame/SIGame.ViewModel/Settings/ErrorInfo.cs @@ -1,10 +1,17 @@ namespace SIGame; +/// +/// Defines an error saved for sending to AppRegistry service. +/// public sealed class ErrorInfo { - public string Version { get; set; } + public string? Version { get; set; } + public DateTime Time { get; set; } - public string Error { get; set; } + + public string? Error { get; set; } + + public string? UserNotes { get; set; } } public sealed class ErrorInfoList : List { } diff --git a/src/SIGame/SIGame.ViewModel/ViewModel/MainViewModel.cs b/src/SIGame/SIGame.ViewModel/ViewModel/MainViewModel.cs index c461df75..d1ab2f6a 100644 --- a/src/SIGame/SIGame.ViewModel/ViewModel/MainViewModel.cs +++ b/src/SIGame/SIGame.ViewModel/ViewModel/MainViewModel.cs @@ -100,7 +100,7 @@ public bool IsSlideMenuOpen public ICommand CloseSlideMenu { get; private set; } - private string _startMenuPage; + private string _startMenuPage = "MainMenuView.xaml"; public string StartMenuPage { diff --git a/src/SIGame/SIGame/App.xaml.cs b/src/SIGame/SIGame/App.xaml.cs index 0a700a87..b91ae234 100644 --- a/src/SIGame/SIGame/App.xaml.cs +++ b/src/SIGame/SIGame/App.xaml.cs @@ -1,4 +1,4 @@ -using AppService.Client; +using AppRegistryService.Client; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -17,17 +17,21 @@ using SIStorage.Service.Client; using System; using System.ComponentModel; -using System.Diagnostics; using System.Net; using System.Threading; using System.Windows; using System.Windows.Threading; using Utils; + #if UPDATE -using AppService.Client.Models; +using AppRegistryService.Contract; +using AppRegistryService.Contract.Responses; +using AppRegistryService.Contract.Requests; using SICore; +using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using System.Net.Http; using System.Threading.Tasks; #endif @@ -39,6 +43,11 @@ namespace SIGame; /// public partial class App : Application { + /// + /// Unique application identifier. + /// + internal static readonly Guid AppId = Guid.Parse("4394ecaf-e377-4fee-aba8-303adc8cdc36"); + private IHost? _host; private ILogger? _logger; @@ -90,7 +99,7 @@ private void ConfigureServices(HostBuilderContext ctx, IServiceCollection servic { var configuration = ctx.Configuration; - services.AddAppServiceClient(configuration); + services.AddAppRegistryServiceClient(configuration); services.AddSIGameServerClient(configuration); services.AddSIStatisticsServiceClient(configuration); services.AddSIStorageServiceClient(configuration); @@ -163,8 +172,6 @@ protected override void OnStartup(StartupEventArgs e) } } - Trace.TraceInformation("Game launched"); - UserSettings.Default.UseSignalRConnection = UseSignalRConnection; UserSettings.Default.PropertyChanged += Default_PropertyChanged; @@ -218,7 +225,7 @@ protected override void OnStartup(StartupEventArgs e) } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) => - _logger.LogError("Common game error: {error}", e.ExceptionObject); + _logger?.LogError("Common game error: {error}", e.ExceptionObject); private void Default_PropertyChanged(object? sender, PropertyChangedEventArgs e) { @@ -236,7 +243,7 @@ private async void CheckUpdate() { try { - var updateInfo = await SearchForUpdatesAsync(); + var updateInfo = await TryFindUpdateAsync(); if (updateInfo != null) { @@ -245,7 +252,7 @@ private async void CheckUpdate() } catch (Exception exc) { - _logger.LogError(exc, "Update error: {error}", exc.Message); + _logger?.LogError(exc, "Update error: {error}", exc.Message); MessageBox.Show( string.Format(SIGame.Properties.Resources.UpdateException, exc.Message), @@ -256,38 +263,37 @@ private async void CheckUpdate() } /// - /// Произвести поиск обновлений + /// Tries to find a product update. /// - /// Нужно ли завершить приложение для выполнения обновления - private async Task SearchForUpdatesAsync() + private async Task TryFindUpdateAsync(CancellationToken cancellationToken = default) { - using var appService = _host.Services.GetRequiredService(); + EnsureThat.EnsureArg.IsNotNull(_host); - var assembly = Assembly.GetAssembly(typeof(MainViewModel)); + var assembly = Assembly.GetAssembly(typeof(MainViewModel)) ?? throw new Exception("Main assembly not found"); + var currentVersion = assembly.GetName().Version ?? throw new Exception("No app version found"); - if (assembly == null) - { - throw new Exception("assembly == null"); - } + var appRegistryClient = _host.Services.GetRequiredService(); - var currentVersion = assembly.GetName().Version; - var product = await appService.GetProductAsync("SI"); + var productInfo = await appRegistryClient.Apps.PostAppUsageAsync( + AppId, + new AppUsageInfo(currentVersion, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture), + cancellationToken); - if (product?.Version > currentVersion) + if (productInfo?.Release?.Version > currentVersion) { - return product; + return productInfo; } return null; } - private void SearchForUpdatesFinished(AppInfo updateInfo) + private void SearchForUpdatesFinished(AppInstallerReleaseInfoResponse updateInfo) { - var updateUri = updateInfo.Uri; + var updateUri = updateInfo.Installer?.Uri!; var mainViewModel = (MainViewModel)MainWindow.DataContext; - mainViewModel.StartMenu.UpdateVersion = updateInfo.Version; + mainViewModel.StartMenu.UpdateVersion = updateInfo.Release?.Version!; mainViewModel.StartMenu.Update = new CustomCommand(obj => Update_Executed(updateUri)); } @@ -351,6 +357,4 @@ protected override void OnExit(ExitEventArgs e) private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) => e.Handled = new ExceptionHandler(_host.Services.GetRequiredService()).Handle(e.Exception); - - } diff --git a/src/SIGame/SIGame/Implementation/ErrorManager.cs b/src/SIGame/SIGame/Implementation/ErrorManager.cs index 0822d7c8..8dc07fd1 100644 --- a/src/SIGame/SIGame/Implementation/ErrorManager.cs +++ b/src/SIGame/SIGame/Implementation/ErrorManager.cs @@ -1,6 +1,6 @@ -using AppService.Client; -using AppService.Client.Models; -using Microsoft.Extensions.Options; +using AppRegistryService.Contract; +using AppRegistryService.Contract.Models; +using AppRegistryService.Contract.Requests; using SICore; using SIGame.Contracts; using SIGame.Properties; @@ -9,6 +9,7 @@ using System; using System.Diagnostics; using System.Reflection; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows; @@ -19,29 +20,23 @@ namespace SIGame.Implementation; /// internal sealed class ErrorManager : IErrorManager { - private const string AppCode = "SI"; private static bool ErrorHappened = false; private static readonly object ErrorSync = new(); - private readonly IAppServiceClient _appServiceClient; + private readonly IAppRegistryServiceClient _appRegistryServiceClient; private readonly ISIStatisticsServiceClient _siStatisticsServiceClient; private readonly AppState _appState; - private readonly bool _useAppService; - public ErrorManager( - IAppServiceClient appServiceClient, + IAppRegistryServiceClient appRegistryServiceClient, ISIStatisticsServiceClient gameResultServiceClient, - AppState appState, - IOptions appServiceClientOptions) + AppState appState) { - _appServiceClient = appServiceClient; + _appRegistryServiceClient = appRegistryServiceClient; _siStatisticsServiceClient = gameResultServiceClient; _appState = appState; - - _useAppService = appServiceClientOptions.Value.ServiceUri != null; } public bool SendErrorReport(Exception e) @@ -96,12 +91,6 @@ public bool SendErrorReport(Exception e) private async void SendErrorMessage(string errorMessage, object sync) { - if (!_useAppService) - { - MessageBox.Show(errorMessage); - return; - } - try { var errorReport = new SIReport @@ -112,18 +101,24 @@ private async void SendErrorMessage(string errorMessage, object sync) Subtitle = Resources.ErrorDescribe }; - var reportView = new GameReportView { DataContext = errorReport }; + var reportView = new GameReportView { DataContext = errorReport, Foreground = Brushes.White, VerticalAlignment = VerticalAlignment.Center }; var mainWindow = Application.Current.MainWindow; errorReport.SendReport = new CustomCommand(async arg => { - var version = Assembly.GetExecutingAssembly().GetName().Version; - var message = errorMessage + Environment.NewLine + errorReport.Comment; + var version = Assembly.GetExecutingAssembly().GetName().Version ?? new Version(); try { - var result = await _appServiceClient.SendErrorReportAsync(AppCode, message, version, DateTime.Now); + var result = await _appRegistryServiceClient.Apps.SendAppErrorReportAsync( + App.AppId, + new AppErrorRequest(version, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = errorMessage, + ErrorTime = DateTimeOffset.UtcNow, + UserNotes = errorReport.Comment + }); switch (result) { @@ -145,17 +140,15 @@ private async void SendErrorMessage(string errorMessage, object sync) CommonSettings.Default.DelayedErrorsNew.Add( new ErrorInfo { - Error = message, + Error = errorMessage, Time = DateTime.Now, - Version = version.ToString() + Version = version.ToString(), + UserNotes = errorReport.Comment }); } } - if (mainWindow != null) - { - mainWindow.Close(); - } + mainWindow?.Close(); Application.Current.Dispatcher.Invoke(Application.Current.Shutdown); }); @@ -184,10 +177,17 @@ private async void SendErrorMessage(string errorMessage, object sync) { if (MessageBox.Show(Resources.FatalErrorMessage, CommonSettings.AppName, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - var version = Assembly.GetExecutingAssembly().GetName().Version; + var version = Assembly.GetExecutingAssembly().GetName().Version ?? new Version(); + try { - await _appServiceClient.SendErrorReportAsync(AppCode, errorMessage, version, DateTime.Now); + await _appRegistryServiceClient.Apps.SendAppErrorReportAsync( + App.AppId, + new AppErrorRequest(version, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = errorMessage, + ErrorTime = DateTimeOffset.UtcNow, + }); } catch (Exception) { @@ -219,15 +219,23 @@ public async void SendDelayedReports() return; } - if (_useAppService) + while (CommonSettings.Default.DelayedErrorsNew.Count > 0) { - while (CommonSettings.Default.DelayedErrorsNew.Count > 0) - { - var report = CommonSettings.Default.DelayedErrorsNew[0]; + var report = CommonSettings.Default.DelayedErrorsNew[0]; - await _appServiceClient.SendErrorReportAsync(AppCode, report.Error, Version.Parse(report.Version), report.Time); - CommonSettings.Default.DelayedErrorsNew.RemoveAt(0); + if (report.Version != null && report.Error != null) + { + await _appRegistryServiceClient.Apps.SendAppErrorReportAsync( + App.AppId, + new AppErrorRequest(Version.Parse(report.Version), Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = report.Error, + ErrorTime = report.Time, + UserNotes = report.UserNotes + }); } + + CommonSettings.Default.DelayedErrorsNew.RemoveAt(0); } while (_appState.DelayedReports.Count > 0) diff --git a/src/SIGame/SIGame/SIGame.csproj b/src/SIGame/SIGame/SIGame.csproj index 3da86874..56203fbc 100644 --- a/src/SIGame/SIGame/SIGame.csproj +++ b/src/SIGame/SIGame/SIGame.csproj @@ -6,7 +6,7 @@ Khil-soft SIGame Quizz game - Copyright © Khil-soft 2002-2023 + Copyright © Khil-soft 2002-2024 $(SIGameVersion) true true @@ -42,6 +42,7 @@ + @@ -51,9 +52,6 @@ - - PreserveNewest - @@ -124,7 +122,6 @@ - @@ -256,9 +253,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest diff --git a/src/SIGame/SIGame/appsettings.Production.json b/src/SIGame/SIGame/appsettings.Production.json deleted file mode 100644 index d30d08cc..00000000 --- a/src/SIGame/SIGame/appsettings.Production.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "AppServiceClient": { - "ServiceUri": "https://vladimirkhil.com/api/app/" - } -} \ No newline at end of file diff --git a/src/SIGame/SIGame/appsettings.json b/src/SIGame/SIGame/appsettings.json index 0e5f6e09..2c475897 100644 --- a/src/SIGame/SIGame/appsettings.json +++ b/src/SIGame/SIGame/appsettings.json @@ -1,6 +1,6 @@ { - "AppServiceClient": { - "ServiceUri": null + "AppRegistryServiceClient": { + "ServiceUri": "https://vladimirkhil.com/appregistry/" }, "SIStatisticsServiceClient": { "ServiceUri": "https://vladimirkhil.com/sistatistics/" diff --git a/src/SIGame/SIGame/licenses/Newtonsoft.Json.LICENSE.md b/src/SIGame/SIGame/licenses/Newtonsoft.Json.LICENSE.md deleted file mode 100644 index dfaadbe4..00000000 --- a/src/SIGame/SIGame/licenses/Newtonsoft.Json.LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2007 James Newton-King - -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. diff --git a/src/SIQuester/SIQuester.ViewModel/Workspaces/QDocument.cs b/src/SIQuester/SIQuester.ViewModel/Workspaces/QDocument.cs index e12af296..0f871e18 100644 --- a/src/SIQuester/SIQuester.ViewModel/Workspaces/QDocument.cs +++ b/src/SIQuester/SIQuester.ViewModel/Workspaces/QDocument.cs @@ -3179,7 +3179,10 @@ private void ConvertToCompTvSI_Executed(object? arg) atom.Model.Text = atom.Model.Text.ClearPoints(); } - questionViewModel.Right[0] = questionViewModel.Right[0].ClearPoints().GrowFirstLetter(); + if (questionViewModel.Right.Count > 0) + { + questionViewModel.Right[0] = questionViewModel.Right[0].ClearPoints().GrowFirstLetter(); + } } if (ind < allthemes.Count) diff --git a/src/SIQuester/SIQuester/App.xaml.cs b/src/SIQuester/SIQuester/App.xaml.cs index 7b3da2e9..ee1fa580 100644 --- a/src/SIQuester/SIQuester/App.xaml.cs +++ b/src/SIQuester/SIQuester/App.xaml.cs @@ -1,6 +1,4 @@ -using AppService.Client; -using AppService.Client.Models; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -26,8 +24,12 @@ using System.Windows; using System.Windows.Threading; using System.Xaml; +using AppRegistryService.Client; +using AppRegistryService.Contract; +using AppRegistryService.Contract.Requests; +using AppRegistryService.Contract.Models; -#if !DEBUG +#if UPDATE using Microsoft.WindowsAPICodePack.Dialogs; using System.Net; using System.Net.Http; @@ -40,9 +42,13 @@ namespace SIQuester; /// public partial class App : Application { + /// + /// Unique application identifier. + /// + internal static readonly Guid AppId = Guid.Parse("42813995-fe5a-4de1-827e-af543293884e"); + private IHost? _host; - private AppSettings _settings = SettingsHelper.LoadUserSettings() ?? AppSettings.Create(); - private bool _useAppService; + private readonly AppSettings _settings = SettingsHelper.LoadUserSettings() ?? AppSettings.Create(); private readonly Implementation.DesktopManager _manager = new(); @@ -99,10 +105,7 @@ private async void Application_Startup(object sender, StartupEventArgs e) _manager.ServiceProvider = _host.Services; - var appServiceClientOptions = _host.Services.GetRequiredService>().Value; - _useAppService = appServiceClientOptions.ServiceUri != null; - -#if !DEBUG +#if UPDATE if (_settings.SearchForUpdates) { SearchForUpdatesAsync(); @@ -167,7 +170,7 @@ protected override void OnStartup(StartupEventArgs e) private void ConfigureServices(HostBuilderContext ctx, IServiceCollection services) { - services.AddAppServiceClient(ctx.Configuration); + services.AddAppRegistryServiceClient(ctx.Configuration); services.AddSIStorageServiceClient(ctx.Configuration); services.AddChgkServiceClient(ctx.Configuration); @@ -179,24 +182,28 @@ private void ConfigureServices(HostBuilderContext ctx, IServiceCollection servic services.AddSIQuester(); } -#if !DEBUG +#if UPDATE private async void SendDelayedReports() { - if (!_useAppService || _host == null) - { - return; - } + EnsureThat.EnsureArg.IsNotNull(_host); - using var appService = _host.Services.GetRequiredService(); + var appRegistryClient = _host.Services.GetRequiredService(); try { while (_settings.DelayedErrors.Count > 0) { var error = _settings.DelayedErrors[0]; - var errorInfo = (Model.ErrorInfo)XamlServices.Load(error); + var report = (ErrorInfo)XamlServices.Load(error); + + await appRegistryClient.Apps.SendAppErrorReportAsync( + AppId, + new AppErrorRequest(report.Version, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = report.Error, + ErrorTime = report.Time + }); - await appService.SendErrorReportAsync("SIQuester", errorInfo.Error, errorInfo.Version, errorInfo.Time); _settings.DelayedErrors.RemoveAt(0); } } @@ -221,27 +228,28 @@ private async void SearchForUpdatesAsync() /// Should the app be closed for update installation. private async Task SearchForUpdatesNewAsync(CancellationToken cancellationToken = default) { - if (!_useAppService || _host == null) - { - return false; - } + EnsureThat.EnsureArg.IsNotNull(_host); - using var appService = _host.Services.GetRequiredService(); + var appRegistryClient = _host.Services.GetRequiredService(); try { - var currentVersion = Assembly.GetExecutingAssembly().GetName().Version; - var product = await appService.GetProductAsync("SIQuester", cancellationToken); + var currentVersion = Assembly.GetExecutingAssembly().GetName().Version ?? throw new Exception("No app version found"); + + var productInfo = await appRegistryClient.Apps.PostAppUsageAsync( + AppId, + new AppUsageInfo(currentVersion, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture), + cancellationToken); - if (product != null && product.Version > currentVersion) + if (productInfo != null && productInfo.Release?.Version > currentVersion) { + var updateUri = productInfo.Installer?.Uri!; + _logger?.LogInformation( "Update detected. Current version: {currentVersion}. Product version: {productVersion}. Product uri: {productUri}", currentVersion, - product.Version, - product.Uri); - - var updateUri = product.Uri; + productInfo.Release.Version, + updateUri); var localFile = Path.Combine(Path.GetTempPath(), "setup.exe"); @@ -287,6 +295,8 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa return; } + e.Handled = true; + _hasError = true; _logger?.LogError(e.Exception, "Application error: {message}", e.Exception.Message); @@ -374,7 +384,7 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa var exception = e.Exception; var message = new StringBuilder(); var systemMessage = new StringBuilder(); - var version = Assembly.GetExecutingAssembly().GetName().Version; + var version = Assembly.GetExecutingAssembly().GetName().Version ?? new Version(); while (exception != null) { @@ -388,7 +398,7 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa exception = exception.InnerException; } - var errorInfo = new Model.ErrorInfo { Time = DateTime.Now, Version = version, Error = systemMessage.ToString() }; + var errorInfo = new ErrorInfo { Time = DateTime.Now, Version = version, Error = systemMessage.ToString() }; #if !DEBUG var dialog = new TaskDialog { @@ -415,22 +425,24 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa #endif } - e.Handled = true; Shutdown(); } - private async Task SendMessageAsync(Model.ErrorInfo errorInfo) + private async Task SendMessageAsync(ErrorInfo errorInfo) { - if (!_useAppService || _host == null) - { - return; - } + EnsureThat.EnsureArg.IsNotNull(_host); - using var appService = _host.Services.GetRequiredService(); + var appRegistryServiceClient = _host.Services.GetRequiredService(); try { - var result = await appService.SendErrorReportAsync("SIQuester", errorInfo.Error, errorInfo.Version, errorInfo.Time); + var result = await appRegistryServiceClient.Apps.SendAppErrorReportAsync( + AppId, + new AppErrorRequest(errorInfo.Version, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = errorInfo.Error, + ErrorTime = errorInfo.Time, + }); switch (result) { diff --git a/src/SIQuester/SIQuester/SIQuester.csproj b/src/SIQuester/SIQuester/SIQuester.csproj index 089e1602..39b47b2a 100644 --- a/src/SIQuester/SIQuester/SIQuester.csproj +++ b/src/SIQuester/SIQuester/SIQuester.csproj @@ -20,6 +20,7 @@ none false + $(DefineConstants);UPDATE true @@ -32,7 +33,6 @@ - @@ -55,6 +55,7 @@ + @@ -65,15 +66,9 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest @@ -199,7 +194,6 @@ - diff --git a/src/SIQuester/SIQuester/appsettings.Production.json b/src/SIQuester/SIQuester/appsettings.Production.json deleted file mode 100644 index d30d08cc..00000000 --- a/src/SIQuester/SIQuester/appsettings.Production.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "AppServiceClient": { - "ServiceUri": "https://vladimirkhil.com/api/app/" - } -} \ No newline at end of file diff --git a/src/SIQuester/SIQuester/appsettings.json b/src/SIQuester/SIQuester/appsettings.json index 15dfc33d..d4972bf8 100644 --- a/src/SIQuester/SIQuester/appsettings.json +++ b/src/SIQuester/SIQuester/appsettings.json @@ -1,6 +1,6 @@ { - "AppServiceClient": { - "ServiceUri": null + "AppRegistryServiceClient": { + "ServiceUri": "https://vladimirkhil.com/appregistry/" }, "SIStorageServiceClient": { "ServiceUri": "https://vladimirkhil.com/sistorage/" diff --git a/src/SIQuester/SIQuester/licenses/Newtonsoft.Json.LICENSE.md b/src/SIQuester/SIQuester/licenses/Newtonsoft.Json.LICENSE.md deleted file mode 100644 index dfaadbe4..00000000 --- a/src/SIQuester/SIQuester/licenses/Newtonsoft.Json.LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2007 James Newton-King - -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. diff --git a/src/SImulator/SImulator/App.xaml.cs b/src/SImulator/SImulator/App.xaml.cs index 2e2b7d2b..19077f0e 100644 --- a/src/SImulator/SImulator/App.xaml.cs +++ b/src/SImulator/SImulator/App.xaml.cs @@ -1,5 +1,7 @@ -using AppService.Client; -using AppService.Client.Models; +using AppRegistryService.Client; +using AppRegistryService.Contract; +using AppRegistryService.Contract.Models; +using AppRegistryService.Contract.Requests; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -7,8 +9,8 @@ using NLog.Web; using SImulator.Implementation; using SImulator.ViewModel; +using SImulator.ViewModel.Core; using SIStorage.Service.Client; -using SIStorage.Service.Contract.Models; using SIStorageService.ViewModel; using System; using System.ComponentModel; @@ -23,6 +25,10 @@ using Utils; using Settings = SImulator.ViewModel.Model.AppSettings; +#if DEBUG +using SIStorage.Service.Contract.Models; +#endif + namespace SImulator; /// @@ -30,6 +36,11 @@ namespace SImulator; /// public partial class App : Application { + /// + /// Unique application identifier. + /// + internal static readonly Guid AppId = Guid.Parse("ea8635a0-183e-47d6-944c-50643e32d689"); + private IHost? _host; #pragma warning disable IDE0052 @@ -43,8 +54,6 @@ public partial class App : Application internal Settings Settings { get; } = LoadSettings(); - private bool _useAppService; - private async void Application_Startup(object sender, StartupEventArgs e) { _host = new HostBuilder() @@ -77,17 +86,12 @@ private void ConfigureServices(HostBuilderContext ctx, IServiceCollection servic { var configuration = ctx.Configuration; - services.AddAppServiceClient(configuration); + services.AddAppRegistryServiceClient(configuration); services.AddSIStorageServiceClient(configuration); services.AddSingleton(typeof(StorageViewModel)); services.AddTransient(); - - var options = configuration.GetSection(AppServiceClientOptions.ConfigurationSectionName); - var appServiceClientOptions = options.Get(); - - _useAppService = appServiceClientOptions?.ServiceUri != null; } protected override void OnStartup(StartupEventArgs e) @@ -200,24 +204,37 @@ public static Settings LoadSettings() } #if !DEBUG - private async void ProcessAsync() + private async void ProcessAsync(CancellationToken cancellationToken = default) { - if (!_useAppService) - { - return; - } + EnsureThat.EnsureArg.IsNotNull(_host); + + var appRegistryClient = _host.Services.GetRequiredService(); - using var appService = _host.Services.GetRequiredService(); try { + var currentVersion = Assembly.GetExecutingAssembly().GetName().Version ?? throw new Exception("No app version found"); + // Update application launch counter - await appService.GetProductAsync("SImulator"); + await appRegistryClient.Apps.PostAppUsageAsync( + AppId, + new AppUsageInfo(currentVersion, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture), + cancellationToken); var delayedErrors = Settings.DelayedErrors; + while (delayedErrors.Count > 0) { var error = delayedErrors[0]; - await appService.SendErrorReportAsync("SImulator", error.Error, Version.Parse(error.Version), error.Time); + + await appRegistryClient.Apps.SendAppErrorReportAsync( + AppId, + new AppErrorRequest(Version.Parse(error.Version), Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = error.Error, + ErrorTime = error.Time + }, + cancellationToken); + delayedErrors.RemoveAt(0); } } @@ -229,6 +246,8 @@ private async void ProcessAsync() private async void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { + e.Handled = true; + var msg = e.Exception.ToString(); if (msg.Contains("WmClose")) // Normal closing, it's ok @@ -282,21 +301,26 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa { // Do nothing } - else if (_useAppService - && _host != null + else if (_host != null && MessageBox.Show( string.Format(SImulator.Properties.Resources.ErrorSendConfirm, e.Exception.Message), MainViewModel.ProductName, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) { - using var appService = _host.Services.GetRequiredService(); - var version = Assembly.GetExecutingAssembly().GetName().Version; + var appRegistryServiceClient = _host.Services.GetRequiredService(); + var version = Assembly.GetExecutingAssembly().GetName().Version ?? new Version(); var errorMessage = e.Exception.ToStringDemystified(); try { - var result = await appService.SendErrorReportAsync("SImulator", errorMessage, version, DateTime.UtcNow); + var result = await appRegistryServiceClient.Apps.SendAppErrorReportAsync( + AppId, + new AppErrorRequest(version, Environment.OSVersion.Version, RuntimeInformation.OSArchitecture) + { + ErrorMessage = errorMessage, + ErrorTime = DateTimeOffset.UtcNow, + }); switch (result) { @@ -328,7 +352,7 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa if (Settings.DelayedErrors.Count < 10) { Settings.DelayedErrors.Add( - new ViewModel.Core.ErrorInfo + new ErrorInfo { Time = DateTime.Now, Error = errorMessage, @@ -346,7 +370,6 @@ private async void Application_DispatcherUnhandledException(object sender, Dispa MessageBoxImage.Error); } - e.Handled = true; Shutdown(); } diff --git a/src/SImulator/SImulator/SImulator.csproj b/src/SImulator/SImulator/SImulator.csproj index 4a623e6a..83f0f22e 100644 --- a/src/SImulator/SImulator/SImulator.csproj +++ b/src/SImulator/SImulator/SImulator.csproj @@ -58,7 +58,6 @@ - @@ -76,6 +75,7 @@ + @@ -88,18 +88,12 @@ - - PreserveNewest - PreserveNewest PreserveNewest - - PreserveNewest - PreserveNewest diff --git a/src/SImulator/SImulator/appsettings.Production.json b/src/SImulator/SImulator/appsettings.Production.json deleted file mode 100644 index d30d08cc..00000000 --- a/src/SImulator/SImulator/appsettings.Production.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "AppServiceClient": { - "ServiceUri": "https://vladimirkhil.com/api/app/" - } -} \ No newline at end of file diff --git a/src/SImulator/SImulator/appsettings.json b/src/SImulator/SImulator/appsettings.json index 2866ee6e..0c85934b 100644 --- a/src/SImulator/SImulator/appsettings.json +++ b/src/SImulator/SImulator/appsettings.json @@ -1,6 +1,6 @@ { - "AppServiceClient": { - "ServiceUri": null + "AppRegistryServiceClient": { + "ServiceUri": "https://vladimirkhil.com/appregistry/" }, "SIStorageServiceClient": { "ServiceUri": "https://vladimirkhil.com/sistorage/" diff --git a/src/SImulator/SImulator/licenses/Newtonsoft.Json.LICENSE.md b/src/SImulator/SImulator/licenses/Newtonsoft.Json.LICENSE.md deleted file mode 100644 index dfaadbe4..00000000 --- a/src/SImulator/SImulator/licenses/Newtonsoft.Json.LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2007 James Newton-King - -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.