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.