rework to have only 1 exe!

This commit is contained in:
Alex Bezdieniezhnykh
2024-12-04 20:51:26 +02:00
parent 3944df8efe
commit 60519461a1
25 changed files with 194 additions and 198 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ public partial class Annotator
Loaded += OnLoaded; Loaded += OnLoaded;
Closed += OnFormClosed; Closed += OnFormClosed;
Activated += (_, _) => _formState.ActiveWindow = WindowEnum.Annotator;
Editor.GetTimeFunc = () => TimeSpan.FromMilliseconds(_mediaPlayer.Time); Editor.GetTimeFunc = () => TimeSpan.FromMilliseconds(_mediaPlayer.Time);
} }
@@ -4,11 +4,12 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Azaion.Common.DTO.Config; using Azaion.Common.DTO.Config;
using LibVLCSharp.Shared; using LibVLCSharp.Shared;
using Microsoft.Extensions.Options;
using SkiaSharp; using SkiaSharp;
namespace Azaion.Annotator.Extensions; namespace Azaion.Annotator.Extensions;
public class VLCFrameExtractor(LibVLC libVLC, AIRecognitionConfig config) public class VLCFrameExtractor(LibVLC libVLC, IOptions<AIRecognitionConfig> config)
{ {
private const uint RGBA_BYTES = 4; private const uint RGBA_BYTES = 4;
private const int PLAYBACK_RATE = 4; private const int PLAYBACK_RATE = 4;
@@ -105,7 +106,7 @@ public class VLCFrameExtractor(LibVLC libVLC, AIRecognitionConfig config)
_lastFrameTimestamp = playerTime; _lastFrameTimestamp = playerTime;
} }
if (_frameCounter > 20 && _frameCounter % config.FramePeriodRecognition == 0) if (_frameCounter > 20 && _frameCounter % config.Value.FramePeriodRecognition == 0)
{ {
var msToAdd = (_frameCounter - _lastFrame) * (_lastFrame == 0 ? 0 : _lastFrameTimestamp.TotalMilliseconds / _lastFrame); var msToAdd = (_frameCounter - _lastFrame) * (_lastFrame == 0 ? 0 : _lastFrameTimestamp.TotalMilliseconds / _lastFrame);
var time = _lastFrameTimestamp.Add(TimeSpan.FromMilliseconds(msToAdd)); var time = _lastFrameTimestamp.Add(TimeSpan.FromMilliseconds(msToAdd));
+1 -1
View File
@@ -7,12 +7,12 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="MediatR" Version="12.4.1" /> <PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+5
View File
@@ -13,6 +13,11 @@ public class Constants
public const string DEFAULT_API_URL = "https://api.azaion.com/"; public const string DEFAULT_API_URL = "https://api.azaion.com/";
public const int DEFAULT_API_RETRY_COUNT = 3; public const int DEFAULT_API_RETRY_COUNT = 3;
public const int DEFAULT_API_TIMEOUT_SECONDS = 40; public const int DEFAULT_API_TIMEOUT_SECONDS = 40;
public const string CLAIM_NAME_ID = "nameid";
public const string CLAIM_EMAIL = "unique_name";
public const string CLAIM_ROLE = "role";
#endregion ApiConfig #endregion ApiConfig
#region DirectoriesConfig #region DirectoriesConfig
@@ -1,8 +1,7 @@
using System.Windows.Media; using System.Windows.Media;
using Azaion.Common.DTO;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Azaion.Annotator.DTO; namespace Azaion.Common.DTO;
public class AnnotationResult public class AnnotationResult
{ {
+4 -9
View File
@@ -1,12 +1,7 @@
using CommandLine; namespace Azaion.Common.DTO;
namespace Azaion.Common.DTO; public class ApiCredentials(string email, string password) : EventArgs
public class ApiCredentials
{ {
[Option('e', "email", Required = true, HelpText = "The email for authorization.")] public string Email { get; set; } = email;
public string Email { get; set; } = null!; public string Password { get; set; } = password;
[Option('p', "password", Required = true, HelpText = "The password for authorization.")]
public string Password { get; set; } = null!;
} }
@@ -2,7 +2,7 @@
using System.IO; using System.IO;
using System.Windows; using System.Windows;
namespace Azaion.Annotator.DTO; namespace Azaion.Common.DTO;
public class FormState public class FormState
{ {
@@ -18,6 +18,7 @@ public class FormState
public TimeSpan? BackgroundTime { get; set; } public TimeSpan? BackgroundTime { get; set; }
public int CurrentVolume { get; set; } = 100; public int CurrentVolume { get; set; } = 100;
public ObservableCollection<AnnotationResult> AnnotationResults { get; set; } = []; public ObservableCollection<AnnotationResult> AnnotationResults { get; set; } = [];
public WindowEnum ActiveWindow { get; set; }
public string GetTimeName(TimeSpan? ts) => $"{VideoName}_{ts:hmmssf}"; public string GetTimeName(TimeSpan? ts) => $"{VideoName}_{ts:hmmssf}";
} }
@@ -1,4 +1,4 @@
namespace Azaion.Annotator.DTO; namespace Azaion.Common.DTO;
public class MediaFileInfo public class MediaFileInfo
{ {
@@ -1,4 +1,4 @@
namespace Azaion.Annotator.DTO; namespace Azaion.Common.DTO;
public enum MediaTypes public enum MediaTypes
{ {
+12
View File
@@ -0,0 +1,12 @@
namespace Azaion.Common.DTO;
public enum RoleEnum
{
None = 0,
Operator = 10, //only annotator is available. Could send annotations to queue.
Validator = 20, //annotator + dataset explorer. This role allows to receive annotations from the queue.
CompanionPC = 30,
Admin = 40, //
ResourceUploader = 50, //Uploading dll and ai models
ApiAdmin = 1000 //everything
}
+21
View File
@@ -0,0 +1,21 @@
using System.Security.Claims;
namespace Azaion.Common.DTO;
public class User
{
public Guid Id { get; set; }
public string Email { get; set; }
public RoleEnum Role { get; set; }
public User(IEnumerable<Claim> claims)
{
var claimDict = claims.ToDictionary(x => x.Type, x => x.Value);
Id = Guid.Parse(claimDict[Constants.CLAIM_NAME_ID]);
Email = claimDict[Constants.CLAIM_EMAIL];
if (!Enum.TryParse(claimDict[Constants.CLAIM_ROLE], out RoleEnum role))
role = RoleEnum.None;
Role = role;
}
}
+11 -4
View File
@@ -6,6 +6,7 @@ using System.Security;
using System.Text; using System.Text;
using Azaion.Common.DTO; using Azaion.Common.DTO;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
namespace Azaion.Common.Services; namespace Azaion.Common.Services;
@@ -15,7 +16,9 @@ public class AzaionApiClient(HttpClient httpClient) : IDisposable
private string Email { get; set; } = null!; private string Email { get; set; } = null!;
private SecureString Password { get; set; } = new(); private SecureString Password { get; set; } = new();
private string JwtToken { get; set; } = null!; private string JwtToken { get; set; } = null!;
public User User { get; set; } = null!;
public void EnterCredentials(ApiCredentials credentials) public void EnterCredentials(ApiCredentials credentials)
{ {
@@ -35,7 +38,7 @@ public class AzaionApiClient(HttpClient httpClient) : IDisposable
return await response.Content.ReadAsStreamAsync(); return await response.Content.ReadAsStreamAsync();
} }
private async Task<string> Authorize() private async Task Authorize()
{ {
if (string.IsNullOrEmpty(Email) || Password.Length == 0) if (string.IsNullOrEmpty(Email) || Password.Length == 0)
throw new Exception("Email or password is empty! Please do EnterCredentials first!"); throw new Exception("Email or password is empty! Please do EnterCredentials first!");
@@ -59,19 +62,23 @@ public class AzaionApiClient(HttpClient httpClient) : IDisposable
if (string.IsNullOrEmpty(result?.Token)) if (string.IsNullOrEmpty(result?.Token))
throw new Exception("JWT Token not found in response"); throw new Exception("JWT Token not found in response");
return result.Token; var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(result.Token);
User = new User(token.Claims);
JwtToken = result.Token;
} }
private async Task<HttpResponseMessage> Send(HttpClient client, HttpRequestMessage request) private async Task<HttpResponseMessage> Send(HttpClient client, HttpRequestMessage request)
{ {
if (string.IsNullOrEmpty(JwtToken)) if (string.IsNullOrEmpty(JwtToken))
JwtToken = await Authorize(); await Authorize();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JwtToken); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JwtToken);
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
if (response.StatusCode == HttpStatusCode.Unauthorized) if (response.StatusCode == HttpStatusCode.Unauthorized)
{ {
JwtToken = await Authorize(); await Authorize();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JwtToken); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JwtToken);
response = await client.SendAsync(request); response = await client.SendAsync(request);
} }
+6 -6
View File
@@ -8,7 +8,7 @@ namespace Azaion.Common.Services;
public interface IHardwareService public interface IHardwareService
{ {
Task<HardwareInfo> GetHardware(); HardwareInfo GetHardware();
} }
public class HardwareService : IHardwareService public class HardwareService : IHardwareService
@@ -23,11 +23,11 @@ public class HardwareService : IHardwareService
"lscpu | grep 'Model name:' | cut -d':' -f2 && " + "lscpu | grep 'Model name:' | cut -d':' -f2 && " +
"lspci | grep VGA | cut -d':' -f3\""; "lspci | grep VGA | cut -d':' -f3\"";
public async Task<HardwareInfo> GetHardware() public HardwareInfo GetHardware()
{ {
try try
{ {
var output = await RunCommand(Environment.OSVersion.Platform == PlatformID.Win32NT var output = RunCommand(Environment.OSVersion.Platform == PlatformID.Win32NT
? WIN32_GET_HARDWARE_COMMAND ? WIN32_GET_HARDWARE_COMMAND
: UNIX_GET_HARDWARE_COMMAND); : UNIX_GET_HARDWARE_COMMAND);
@@ -77,7 +77,7 @@ public class HardwareService : IHardwareService
return macAddress ?? string.Empty; return macAddress ?? string.Empty;
} }
private async Task<string> RunCommand(string command) private string RunCommand(string command)
{ {
try try
{ {
@@ -91,8 +91,8 @@ public class HardwareService : IHardwareService
process.StartInfo.CreateNoWindow = true; process.StartInfo.CreateNoWindow = true;
process.Start(); process.Start();
var result = await process.StandardOutput.ReadToEndAsync(); var result = process.StandardOutput.ReadToEnd();
await process.WaitForExitAsync(); process.WaitForExit();
return result.Trim(); return result.Trim();
} }
+3 -2
View File
@@ -46,8 +46,9 @@ public class ResourceLoader(AzaionApiClient api, ApiCredentials credentials) : I
public async Task<MemoryStream> Load(string fileName, CancellationToken cancellationToken = default) public async Task<MemoryStream> Load(string fileName, CancellationToken cancellationToken = default)
{ {
var hardwareService = new HardwareService(); var hardwareService = new HardwareService();
var hardwareInfo = await hardwareService.GetHardware(); var hardwareInfo = hardwareService.GetHardware();
var encryptedStream = await api.GetResource(fileName, credentials.Password, hardwareInfo);
var encryptedStream = Task.Run(() => api.GetResource(fileName, credentials.Password, hardwareInfo), cancellationToken).Result;
var key = Security.MakeEncryptionKey(credentials.Email, credentials.Password, hardwareInfo.Hash); var key = Security.MakeEncryptionKey(credentials.Email, credentials.Password, hardwareInfo.Hash);
var stream = new MemoryStream(); var stream = new MemoryStream();
+36 -31
View File
@@ -24,6 +24,7 @@ public partial class DatasetExplorer
private int _tempSelectedClassIdx = 0; private int _tempSelectedClassIdx = 0;
private readonly IGalleryManager _galleryManager; private readonly IGalleryManager _galleryManager;
private readonly FormState _formState;
public bool ThumbnailLoading { get; set; } public bool ThumbnailLoading { get; set; }
@@ -33,15 +34,46 @@ public partial class DatasetExplorer
IOptions<DirectoriesConfig> directoriesConfig, IOptions<DirectoriesConfig> directoriesConfig,
IOptions<AnnotationConfig> annotationConfig, IOptions<AnnotationConfig> annotationConfig,
ILogger<DatasetExplorer> logger, ILogger<DatasetExplorer> logger,
IGalleryManager galleryManager) IGalleryManager galleryManager,
FormState formState)
{ {
_directoriesConfig = directoriesConfig.Value; _directoriesConfig = directoriesConfig.Value;
_annotationConfig = annotationConfig.Value; _annotationConfig = annotationConfig.Value;
_logger = logger; _logger = logger;
_galleryManager = galleryManager; _galleryManager = galleryManager;
_formState = formState;
InitializeComponent(); InitializeComponent();
Loaded += async (_, _) => Loaded += OnLoaded;
ThumbnailsView.KeyDown += async (sender, args) =>
{
switch (args.Key)
{
case Key.Delete:
DeleteAnnotations();
break;
case Key.Enter:
await EditAnnotation();
break;
}
};
ThumbnailsView.MouseDoubleClick += async (_, _) => await EditAnnotation();
ThumbnailsView.SelectionChanged += (_, _) =>
{
StatusText.Text = $"Обрано: {ThumbnailsView.SelectedItems.Count} | {ThumbnailsView.SelectedIndex} / {ThumbnailsDtos.Count}";
};
ExplorerEditor.GetTimeFunc = () => Constants.GetTime(CurrentThumbnail!.ImagePath);
galleryManager.ThumbnailsUpdate += thumbnailsPercentage =>
{
Dispatcher.Invoke(() => RefreshThumbBar.Value = thumbnailsPercentage);
};
}
private async void OnLoaded(object sender, RoutedEventArgs e)
{ {
_ = Task.Run(async () => await _galleryManager.RefreshThumbnails()); _ = Task.Run(async () => await _galleryManager.RefreshThumbnails());
@@ -77,42 +109,15 @@ public partial class DatasetExplorer
foreach (var ann in ExplorerEditor.CurrentAnns.Where(x => x.IsSelected)) foreach (var ann in ExplorerEditor.CurrentAnns.Where(x => x.IsSelected))
ann.AnnotationClass = selectedClass; ann.AnnotationClass = selectedClass;
}; };
Activated += (_, _) => _formState.ActiveWindow = WindowEnum.Annotator;
LvClasses.SelectedIndex = _annotationConfig.LastSelectedExplorerClass ?? 0; LvClasses.SelectedIndex = _annotationConfig.LastSelectedExplorerClass ?? 0;
ExplorerEditor.CurrentAnnClass = (AnnotationClass)LvClasses.SelectedItem; ExplorerEditor.CurrentAnnClass = (AnnotationClass)LvClasses.SelectedItem;
await ReloadThumbnails(); await ReloadThumbnails();
LoadClassDistribution(); LoadClassDistribution();
RefreshThumbBar.Value = galleryManager.ThumbnailsPercentage; RefreshThumbBar.Value = _galleryManager.ThumbnailsPercentage;
DataContext = this; DataContext = this;
};
ThumbnailsView.KeyDown += async (sender, args) =>
{
switch (args.Key)
{
case Key.Delete:
DeleteAnnotations();
break;
case Key.Enter:
await EditAnnotation();
break;
}
};
ThumbnailsView.MouseDoubleClick += async (_, _) => await EditAnnotation();
ThumbnailsView.SelectionChanged += (_, _) =>
{
StatusText.Text = $"Обрано: {ThumbnailsView.SelectedItems.Count} | {ThumbnailsView.SelectedIndex} / {ThumbnailsDtos.Count}";
};
ExplorerEditor.GetTimeFunc = () => Constants.GetTime(CurrentThumbnail!.ImagePath);
galleryManager.ThumbnailsUpdate += thumbnailsPercentage =>
{
Dispatcher.Invoke(() => RefreshThumbBar.Value = thumbnailsPercentage);
};
} }
private void LoadClassDistribution() private void LoadClassDistribution()
-8
View File
@@ -1,8 +0,0 @@
<Application x:Class="Azaion.Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Loader.xaml">
<Application.Resources>
</Application.Resources>
</Application>
-3
View File
@@ -1,3 +0,0 @@
namespace Azaion.Launcher;
public partial class App;
-10
View File
@@ -1,10 +0,0 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
-19
View File
@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Page Update="Loader.xaml">
<Generator>MSBuild:Compile</Generator>
<XamlRuntime>Wpf</XamlRuntime>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
</Project>
-6
View File
@@ -10,8 +10,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Common", "Azaion.Com
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Dataset", "Azaion.Dataset\Azaion.Dataset.csproj", "{01A5CA37-A62E-4EF3-8678-D72CD9525677}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Dataset", "Azaion.Dataset\Azaion.Dataset.csproj", "{01A5CA37-A62E-4EF3-8678-D72CD9525677}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Launcher", "Azaion.Launcher\Azaion.Launcher.csproj", "{00CC9AFE-2952-4943-BCBA-976AE03DE841}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dummy", "Dummy", "{C307BE2E-FFCC-4BD7-AD89-C82D40B65D03}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dummy", "Dummy", "{C307BE2E-FFCC-4BD7-AD89-C82D40B65D03}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
Dummy\Azaion.Annotator.dll = Dummy\Azaion.Annotator.dll Dummy\Azaion.Annotator.dll = Dummy\Azaion.Annotator.dll
@@ -48,10 +46,6 @@ Global
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Debug|Any CPU.Build.0 = Debug|Any CPU {01A5CA37-A62E-4EF3-8678-D72CD9525677}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.ActiveCfg = Release|Any CPU {01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.ActiveCfg = Release|Any CPU
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.Build.0 = Release|Any CPU {01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.Build.0 = Release|Any CPU
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Release|Any CPU.Build.0 = Release|Any CPU
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Debug|Any CPU.Build.0 = Debug|Any CPU {32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Release|Any CPU.ActiveCfg = Release|Any CPU {32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+48 -61
View File
@@ -1,10 +1,8 @@
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Windows; using System.Windows;
using System.Windows.Input;
using System.Windows.Threading; using System.Windows.Threading;
using Azaion.Annotator; using Azaion.Annotator;
using Azaion.Annotator.DTO;
using Azaion.Annotator.Extensions; using Azaion.Annotator.Extensions;
using Azaion.Common; using Azaion.Common;
using Azaion.Common.DTO; using Azaion.Common.DTO;
@@ -12,7 +10,6 @@ using Azaion.Common.DTO.Config;
using Azaion.Common.Extensions; using Azaion.Common.Extensions;
using Azaion.Common.Services; using Azaion.Common.Services;
using Azaion.Dataset; using Azaion.Dataset;
using CommandLine;
using LibVLCSharp.Shared; using LibVLCSharp.Shared;
using MediatR; using MediatR;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@@ -22,31 +19,19 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using Serilog; using Serilog;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
namespace Azaion.Suite; namespace Azaion.Suite;
public partial class App public partial class App
{ {
private readonly IHost _host; private IHost _host = null!;
private readonly ILogger<App> _logger; private ILogger<App> _logger = null!;
private readonly IMediator _mediator; private IMediator _mediator = null!;
private FormState _formState = null!;
//Authorize to api and private AzaionApiClient _apiClient = null!;
private static readonly IResourceLoader ResourceLoader; private IResourceLoader _resourceLoader = null!;
static App()
{
new ConfigUpdater().CheckConfig();
var result = Parser.Default.ParseArguments<ApiCredentials>(Environment.GetCommandLineArgs());
var apiCreds = !result.Errors.Any()
? result.Value
: new ApiCredentials();
ResourceLoader = new ResourceLoader(CreateApiClient(apiCreds), apiCreds);
AppDomain.CurrentDomain.AssemblyResolve += (_, args) => ResourceLoader.LoadAssembly(args.Name);
}
private static AzaionApiClient CreateApiClient(ApiCredentials credentials) private static AzaionApiClient CreateApiClient(ApiCredentials credentials)
{ {
@@ -68,6 +53,7 @@ public partial class App
TimeoutSeconds = 40 TimeoutSeconds = 40
}; };
} }
var api = new AzaionApiClient(new HttpClient var api = new AzaionApiClient(new HttpClient
{ {
BaseAddress = new Uri(apiConfig.Url), BaseAddress = new Uri(apiConfig.Url),
@@ -78,7 +64,40 @@ public partial class App
return api; return api;
} }
public App()
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
_logger.LogError(e.Exception, e.Exception.Message);
e.Handled = true;
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
StartLogin();
}
private void StartLogin()
{
new ConfigUpdater().CheckConfig();
var login = new Login();
login.CredentialsEntered += async (s, args) =>
{
_apiClient = CreateApiClient(args);
_resourceLoader = new ResourceLoader(_apiClient, args);
AppDomain.CurrentDomain.AssemblyResolve += (_, a) => _resourceLoader.LoadAssembly(a.Name);
StartMain();
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.KeyDownEvent, new RoutedEventHandler(GlobalClick));
await _host.StartAsync();
_host.Services.GetRequiredService<MainSuite>().Show();
};
login.ShowDialog();
}
private void StartMain()
{ {
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext() .Enrich.FromLogContext()
@@ -97,7 +116,9 @@ public partial class App
{ {
services.AddSingleton<MainSuite>(); services.AddSingleton<MainSuite>();
services.AddSingleton<IHardwareService, HardwareService>(); services.AddSingleton<IHardwareService, HardwareService>();
services.AddSingleton(ResourceLoader);
services.AddSingleton(_apiClient);
services.AddSingleton(_resourceLoader);
services.Configure<AppConfig>(context.Configuration); services.Configure<AppConfig>(context.Configuration);
services.ConfigureSection<ApiConfig>(context.Configuration); services.ConfigureSection<ApiConfig>(context.Configuration);
@@ -141,31 +162,15 @@ public partial class App
.Build(); .Build();
_mediator = _host.Services.GetRequiredService<IMediator>(); _mediator = _host.Services.GetRequiredService<IMediator>();
_logger = _host.Services.GetRequiredService<ILogger<App>>(); _logger = _host.Services.GetRequiredService<ILogger<App>>();
_formState = _host.Services.GetRequiredService<FormState>();
DispatcherUnhandledException += OnDispatcherUnhandledException; DispatcherUnhandledException += OnDispatcherUnhandledException;
} }
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
_logger.LogError(e.Exception, e.Exception.Message);
e.Handled = true;
}
protected override async void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.KeyDownEvent, new RoutedEventHandler(GlobalClick));
await _host.StartAsync();
_host.Services.GetRequiredService<MainSuite>().Show();
base.OnStartup(e);
}
private void GlobalClick(object sender, RoutedEventArgs e) private void GlobalClick(object sender, RoutedEventArgs e)
{ {
var args = (KeyEventArgs)e; var args = (KeyEventArgs)e;
var windowEnum = GetParentWindow(sender as FrameworkElement);
if (windowEnum == WindowEnum.None) var keyEvent = new KeyEvent(sender, args, _formState.ActiveWindow);
return;
var keyEvent = new KeyEvent(sender, args, windowEnum);
_ = ThrottleExt.Throttle(() => _mediator.Publish(keyEvent), TimeSpan.FromMilliseconds(50)); _ = ThrottleExt.Throttle(() => _mediator.Publish(keyEvent), TimeSpan.FromMilliseconds(50));
} }
@@ -176,27 +181,9 @@ public partial class App
{ "Azaion.Dataset.DatasetExplorer", WindowEnum.DatasetExplorer } { "Azaion.Dataset.DatasetExplorer", WindowEnum.DatasetExplorer }
}; };
private WindowEnum GetParentWindow(FrameworkElement? element)
{
while (element != null)
{
var windowEnum = _uiElementToWindowEnum!.GetValueOrDefault(element.GetType().FullName);
if (windowEnum != WindowEnum.None)
return windowEnum;
element = (element.Parent ?? element.TemplatedParent) as FrameworkElement;
}
return WindowEnum.None;
}
protected override async void OnExit(ExitEventArgs e) protected override async void OnExit(ExitEventArgs e)
{ {
base.OnExit(e); base.OnExit(e);
await _host.StopAsync(); await _host.StopAsync();
//_host.Dispose();
} }
} }
+8 -1
View File
@@ -10,7 +10,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="LibVLCSharp" Version="3.9.1" /> <PackageReference Include="LibVLCSharp" Version="3.9.1" />
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" /> <PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
<PackageReference Include="MediatR" Version="12.4.1" /> <PackageReference Include="MediatR" Version="12.4.1" />
@@ -40,6 +39,14 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Page Update="Login.xaml">
<Generator>MSBuild:Compile</Generator>
<XamlRuntime>Wpf</XamlRuntime>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="Build"> <Target Name="PostBuild" AfterTargets="Build">
<MakeDir Directories="$(TargetDir)secure" /> <MakeDir Directories="$(TargetDir)secure" />
<Move SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)secure" /> <Move SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)secure" />
@@ -1,4 +1,4 @@
<Window x:Class="Azaion.Launcher.Loader" <Window x:Class="Azaion.Suite.Login"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -97,7 +97,7 @@
Height="35" Height="35"
Width="280" Width="280"
Cursor="Hand" Cursor="Hand"
Click="RunClick"> Click="LoginClick">
<Button.Style> <Button.Style>
<Style TargetType="Button"> <Style TargetType="Button">
<Setter Property="Template"> <Setter Property="Template">
@@ -1,21 +1,22 @@
using System.Diagnostics; using System.Windows;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Azaion.Common.DTO;
namespace Azaion.Launcher; namespace Azaion.Suite;
public partial class Loader : Window public partial class Login
{ {
public Loader() public Login()
{ {
InitializeComponent(); InitializeComponent();
} }
private async void RunClick(object sender, RoutedEventArgs e) public event EventHandler<ApiCredentials>? CredentialsEntered;
private void LoginClick(object sender, RoutedEventArgs e)
{ {
Process.Start("Azaion.Suite.exe", $"-e {TbEmail.Text} -p {TbPassword.Password}"); CredentialsEntered?.Invoke(this, new ApiCredentials(TbEmail.Text, TbPassword.Password));
await Task.Delay(2000);
Close(); Close();
} }
+2 -2
View File
@@ -6,10 +6,10 @@ namespace Azaion.Annotator.Test;
public class HardwareServiceTest public class HardwareServiceTest
{ {
[Fact] [Fact]
public async Task GetHardware_Test() public void GetHardware_Test()
{ {
var hardwareService = new HardwareService(); var hardwareService = new HardwareService();
var hw = await hardwareService.GetHardware(); var hw = hardwareService.GetHardware();
Console.WriteLine(hw); Console.WriteLine(hw);
} }
} }