From 2dd2606943a4b9a54c04e09b9f8a6a3d129fe902 Mon Sep 17 00:00:00 2001 From: Dynesshely Date: Tue, 27 Feb 2024 06:33:42 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=92=BE=20=F0=9F=A7=A9=20Feat,=20Refac?= =?UTF-8?q?tor:=20Imported=20self-hosted=20asp.net=20core=20and=20refactor?= =?UTF-8?q?ed=20devices=20server.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KitX Dashboard/App.axaml.cs | 8 +- KitX Dashboard/AppFramework.cs | 13 +- KitX Dashboard/Configuration/AppConfig.cs | 2 + KitX Dashboard/Configuration/ConfigFetcher.cs | 6 +- KitX Dashboard/Configuration/PluginsConfig.cs | 2 +- KitX Dashboard/ConstantTable.cs | 8 +- .../Converters/ActivityStatusConverters.cs | 3 +- .../Converters/DeviceInfoConverters.cs | 42 +++ .../Converters/OperatingSystem2Enum.cs | 33 -- .../Converters/OperatingSystemUtils.cs | 66 ++++ .../Converters/PluginInfoConverters.cs | 3 +- .../Generators/GreetingTextGenerator.cs | 15 +- KitX Dashboard/Instances.cs | 20 +- KitX Dashboard/KitX.Dashboard.csproj | 2 + KitX Dashboard/Managers/ActivityManager.cs | 4 +- KitX Dashboard/Managers/AnouncementManager.cs | 6 +- KitX Dashboard/Managers/CacheManager.cs | 101 ----- KitX Dashboard/Managers/ConfigManager.cs | 4 + KitX Dashboard/Managers/DevicesManager.cs | 355 ------------------ KitX Dashboard/Managers/PluginsManager.cs | 6 +- KitX Dashboard/Managers/WebManager.cs | 63 +++- KitX Dashboard/Models/DeviceCase.cs | 15 + .../Models/Network/WebManagerOperationInfo.cs | 43 --- .../{Plugin.cs => PluginInstallation.cs} | 8 +- KitX Dashboard/Names/PluginTagsNames.cs | 11 +- KitX Dashboard/Network/DevicesClient.cs | 249 ------------ .../DevicesNetwork/DevicesDiscoveryServer.cs | 319 +++++++++------- .../DevicesNetwork/DevicesOrganizer.cs | 263 +++++++++++++ .../Network/DevicesNetwork/DevicesServer.cs | 127 +++++++ .../DeviceController.cs | 16 + KitX Dashboard/Network/DevicesServer.cs | 273 -------------- KitX Dashboard/Network/NetworkHelper.cs | 10 +- .../Network/PluginsNetwork/PluginConnector.cs | 12 +- .../Network/PluginsNetwork/PluginsServer.cs | 4 +- KitX Dashboard/Services/EventService.cs | 8 +- .../ViewModels/AnouncementsWindowViewModel.cs | 23 +- KitX Dashboard/ViewModels/AppViewModel.cs | 12 +- .../Pages/Controls/Home_CountViewModel.cs | 4 +- .../Pages/Controls/Home_RecentUseViewModel.cs | 2 +- .../Pages/Controls/PluginBarViewModel.cs | 55 ++- .../Pages/Controls/Settings_AboutViewModel.cs | 16 +- .../Controls/Settings_GeneralViewModel.cs | 18 +- .../Controls/Settings_PerformenceViewModel.cs | 86 ++--- .../Controls/Settings_PersonaliseViewModel.cs | 36 +- .../Controls/Settings_UpdateViewModel.cs | 81 ++-- .../ViewModels/Pages/DevicePageViewModel.cs | 55 +-- .../ViewModels/Pages/HomePageViewModel.cs | 8 +- .../ViewModels/Pages/RepoPageViewModel.cs | 12 +- .../ViewModels/Pages/SettingsPageViewModel.cs | 24 +- .../ViewModels/PluginDetailWindowViewModel.cs | 26 +- .../PluginsLaunchWindowViewModel.cs | 6 +- KitX Dashboard/ViewModels/ViewModelBase.cs | 65 ++-- .../Views/AnouncementsWindow.axaml.cs | 3 +- KitX Dashboard/Views/MainWindow.axaml.cs | 3 +- .../Views/Pages/Controls/DeviceCard.axaml | 69 ---- .../Views/Pages/Controls/PluginBar.axaml.cs | 4 +- KitX Dashboard/Views/Pages/DevicePage.axaml | 83 +++- KitX Dashboard/Views/Pages/HomePage.axaml.cs | 6 +- .../Views/Pages/SettingsPage.axaml.cs | 4 +- KitX Dashboard/Views/PluginDetailWindow.axaml | 20 - KitX Dashboard/Views/ViewInstances.cs | 6 +- 61 files changed, 1156 insertions(+), 1691 deletions(-) create mode 100644 KitX Dashboard/Converters/DeviceInfoConverters.cs delete mode 100644 KitX Dashboard/Converters/OperatingSystem2Enum.cs create mode 100644 KitX Dashboard/Converters/OperatingSystemUtils.cs delete mode 100644 KitX Dashboard/Managers/CacheManager.cs delete mode 100644 KitX Dashboard/Managers/DevicesManager.cs create mode 100644 KitX Dashboard/Models/DeviceCase.cs delete mode 100644 KitX Dashboard/Models/Network/WebManagerOperationInfo.cs rename KitX Dashboard/Models/{Plugin.cs => PluginInstallation.cs} (59%) delete mode 100644 KitX Dashboard/Network/DevicesClient.cs create mode 100644 KitX Dashboard/Network/DevicesNetwork/DevicesOrganizer.cs create mode 100644 KitX Dashboard/Network/DevicesNetwork/DevicesServer.cs create mode 100644 KitX Dashboard/Network/DevicesNetwork/DevicesServerControllers/DeviceController.cs delete mode 100644 KitX Dashboard/Network/DevicesServer.cs diff --git a/KitX Dashboard/App.axaml.cs b/KitX Dashboard/App.axaml.cs index d6868ef8..8577e931 100644 --- a/KitX Dashboard/App.axaml.cs +++ b/KitX Dashboard/App.axaml.cs @@ -23,7 +23,7 @@ namespace KitX.Dashboard; public partial class App : Application { public static readonly Bitmap DefaultIcon = new( - $"{ConstantTable.AssetsPath}{Instances.ConfigManager.AppConfig.App.CoverIconFileName}".GetFullPath() + $"{ConstantTable.AssetsPath}{ConfigManager.Instance.AppConfig.App.CoverIconFileName}".GetFullPath() ); private AppViewModel? viewModel; @@ -46,7 +46,7 @@ public override void Initialize() private void LoadLanguage() { - var config = Instances.ConfigManager.AppConfig; + var config = ConfigManager.Instance.AppConfig; var lang = config.App.AppLanguage; var backup_lang = config.App.SurpportLanguages.Keys.First(); var path = $"{ConstantTable.LanguageFilePath}/{lang}.axaml".GetFullPath(); @@ -100,7 +100,7 @@ private void LoadLanguage() private static void CalculateThemeColor() { - Color c = Color.Parse(Instances.ConfigManager.AppConfig.App.ThemeColor); + Color c = Color.Parse(ConfigManager.Instance.AppConfig.App.ThemeColor); if (Current is not null) { @@ -155,7 +155,7 @@ public override void OnFrameworkInitializationCompleted() }; } - if (Instances.ConfigManager.AppConfig.App.ShowAnnouncementWhenStart) + if (ConfigManager.Instance.AppConfig.App.ShowAnnouncementWhenStart) new Thread(async () => { try diff --git a/KitX Dashboard/AppFramework.cs b/KitX Dashboard/AppFramework.cs index c92fb6d4..b049a8ac 100644 --- a/KitX Dashboard/AppFramework.cs +++ b/KitX Dashboard/AppFramework.cs @@ -47,11 +47,9 @@ public static void RunFramework() if (File.Exists("./dump.log".GetFullPath())) File.Delete("./dump.log".GetFullPath()); - Instances.Initialize(); - - Instances.ConfigManager.AppConfig.App.RanTime++; + ConfigManager.Instance.AppConfig.App.RanTime++; - var config = Instances.ConfigManager.AppConfig; + var config = ConfigManager.Instance.AppConfig; ProcessStartupArguments(); @@ -94,6 +92,8 @@ public static void RunFramework() #endregion + Instances.Initialize(); + #region Initialize global exception catching AppDomain.CurrentDomain.UnhandledException += (sender, e) => @@ -237,20 +237,19 @@ public static void EnsureExit() Instances.FileWatcherManager?.Clear(); - Instances.ConfigManager.SaveAll(); + ConfigManager.Instance.SaveAll(); Log.CloseAndFlush(); if (Instances.WebManager is not null) await Instances.WebManager.CloseAsync(new()); - Instances.WebManager?.Dispose(); Instances.ActivitiesDataBase?.Commit(); Instances.ActivitiesDataBase?.Dispose(); ConstantTable.Running = false; - Thread.Sleep(Instances.ConfigManager.AppConfig.App.LastBreakAfterExit); + Thread.Sleep(ConfigManager.Instance.AppConfig.App.LastBreakAfterExit); Environment.Exit(0); } diff --git a/KitX Dashboard/Configuration/AppConfig.cs b/KitX Dashboard/Configuration/AppConfig.cs index 2a51c05a..53c266ec 100644 --- a/KitX Dashboard/Configuration/AppConfig.cs +++ b/KitX Dashboard/Configuration/AppConfig.cs @@ -180,6 +180,8 @@ public class Config_Web public List? AcceptedNetworkInterfaces { get; set; } = null; + public int? UserSpecifiedDevicesServerPort { get; set; } = null; + public int? UserSpecifiedPluginsServerPort { get; set; } = null; public int UdpPortSend { get; set; } = 23404; diff --git a/KitX Dashboard/Configuration/ConfigFetcher.cs b/KitX Dashboard/Configuration/ConfigFetcher.cs index 13046a99..19155aae 100644 --- a/KitX Dashboard/Configuration/ConfigFetcher.cs +++ b/KitX Dashboard/Configuration/ConfigFetcher.cs @@ -1,6 +1,8 @@ -namespace KitX.Dashboard.Configuration; +using KitX.Dashboard.Managers; + +namespace KitX.Dashboard.Configuration; public class ConfigFetcher { - public static AppConfig AppConfig => Instances.ConfigManager.AppConfig; + public static AppConfig AppConfig => ConfigManager.Instance.AppConfig; } diff --git a/KitX Dashboard/Configuration/PluginsConfig.cs b/KitX Dashboard/Configuration/PluginsConfig.cs index 05bae6a5..453ec1f2 100644 --- a/KitX Dashboard/Configuration/PluginsConfig.cs +++ b/KitX Dashboard/Configuration/PluginsConfig.cs @@ -5,5 +5,5 @@ namespace KitX.Dashboard.Configuration; public class PluginsConfig : ConfigBase { - public List Plugins { get; set; } = []; + public List Plugins { get; set; } = []; } diff --git a/KitX Dashboard/ConstantTable.cs b/KitX Dashboard/ConstantTable.cs index 878427b1..99886ea0 100644 --- a/KitX Dashboard/ConstantTable.cs +++ b/KitX Dashboard/ConstantTable.cs @@ -29,6 +29,8 @@ internal static class ConstantTable internal static string ThirdPartLicenseFilePath => thirdPartLicenseFilePath.GetFullPath(); + internal static int DevicesServerPort = -1; + internal static int PluginsServerPort = -1; internal static bool Running = true; @@ -37,9 +39,11 @@ internal static class ConstantTable internal static bool IsMainMachine = false; - internal static bool SkipNetworkSystemOnStartup = false; + internal static string? MainMachineAddress; - internal static int DevicesServerPort = -1; + internal static int MainMachinePort = -1; + + internal static bool SkipNetworkSystemOnStartup = false; internal static DateTime ServerBuildTime = new(); diff --git a/KitX Dashboard/Converters/ActivityStatusConverters.cs b/KitX Dashboard/Converters/ActivityStatusConverters.cs index 7666c71c..24732997 100644 --- a/KitX Dashboard/Converters/ActivityStatusConverters.cs +++ b/KitX Dashboard/Converters/ActivityStatusConverters.cs @@ -1,9 +1,8 @@ using Avalonia.Data.Converters; using Common.Activity; +using Material.Icons; using System; using System.Globalization; -using Material.Icons; -using Avalonia.Media; namespace KitX.Dashboard.Converters; diff --git a/KitX Dashboard/Converters/DeviceInfoConverters.cs b/KitX Dashboard/Converters/DeviceInfoConverters.cs new file mode 100644 index 00000000..996cdeba --- /dev/null +++ b/KitX Dashboard/Converters/DeviceInfoConverters.cs @@ -0,0 +1,42 @@ +using Avalonia.Data.Converters; +using KitX.Shared.Device; +using System; +using System.Globalization; + +namespace KitX.Dashboard.Converters; + +public class PluginsServerAddressConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is not DeviceInfo info) return null; + + return $"{info.Device.IPv4}:{info.PluginsServerPort}"; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); +} + +public class DevicesServerAddressConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is not DeviceInfo info) return null; + + return $"{info.Device.IPv4}:{info.DevicesServerPort}"; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); +} + +public class DeviceLastOnLineTimeConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is not DateTime time) return null; + + return time.ToLocalTime().ToString("yyyy.MM.dd HH:mm:ss"); + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); +} diff --git a/KitX Dashboard/Converters/OperatingSystem2Enum.cs b/KitX Dashboard/Converters/OperatingSystem2Enum.cs deleted file mode 100644 index 504d860f..00000000 --- a/KitX Dashboard/Converters/OperatingSystem2Enum.cs +++ /dev/null @@ -1,33 +0,0 @@ -using KitX.Shared.Device; -using System; - -namespace KitX.Dashboard.Converters; - -internal class OperatingSystem2Enum -{ - internal static OperatingSystems GetOSType() - { - if (OperatingSystem.IsAndroid()) - return OperatingSystems.Android; - if (OperatingSystem.IsBrowser()) - return OperatingSystems.Browser; - if (OperatingSystem.IsFreeBSD()) - return OperatingSystems.FreeBSD; - if (OperatingSystem.IsIOS()) - return OperatingSystems.IOS; - if (OperatingSystem.IsLinux()) - return OperatingSystems.Linux; - if (OperatingSystem.IsMacCatalyst()) - return OperatingSystems.MacCatalyst; - if (OperatingSystem.IsMacOS()) - return OperatingSystems.MacOS; - if (OperatingSystem.IsTvOS()) - return OperatingSystems.TvOS; - if (OperatingSystem.IsWatchOS()) - return OperatingSystems.WatchOS; - if (OperatingSystem.IsWindows()) - return OperatingSystems.Windows; - - return OperatingSystems.Unknown; - } -} diff --git a/KitX Dashboard/Converters/OperatingSystemUtils.cs b/KitX Dashboard/Converters/OperatingSystemUtils.cs new file mode 100644 index 00000000..9844d745 --- /dev/null +++ b/KitX Dashboard/Converters/OperatingSystemUtils.cs @@ -0,0 +1,66 @@ +using Avalonia.Data.Converters; +using KitX.Shared.Device; +using Material.Icons; +using System; +using System.Globalization; + +namespace KitX.Dashboard.Converters; + +public static class OperatingSystemUtils +{ + public static OperatingSystems GetOSType() + { + if (OperatingSystem.IsAndroid()) + return OperatingSystems.Android; + if (OperatingSystem.IsBrowser()) + return OperatingSystems.Browser; + if (OperatingSystem.IsFreeBSD()) + return OperatingSystems.FreeBSD; + if (OperatingSystem.IsIOS()) + return OperatingSystems.IOS; + if (OperatingSystem.IsLinux()) + return OperatingSystems.Linux; + if (OperatingSystem.IsMacCatalyst()) + return OperatingSystems.MacCatalyst; + if (OperatingSystem.IsMacOS()) + return OperatingSystems.MacOS; + if (OperatingSystem.IsTvOS()) + return OperatingSystems.TvOS; + if (OperatingSystem.IsWatchOS()) + return OperatingSystems.WatchOS; + if (OperatingSystem.IsWindows()) + return OperatingSystems.Windows; + + return OperatingSystems.Unknown; + } +} + +public class OperatingSystemToIconConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is null) return null; + + var os = (OperatingSystems)value; + + return os switch + { + OperatingSystems.Unknown => MaterialIconKind.QuestionMarkCircle, + OperatingSystems.Android => MaterialIconKind.Android, + OperatingSystems.Browser => MaterialIconKind.MicrosoftEdge, + OperatingSystems.FreeBSD => MaterialIconKind.Freebsd, + OperatingSystems.IOS => MaterialIconKind.AppleIos, + OperatingSystems.Linux => MaterialIconKind.Linux, + OperatingSystems.MacCatalyst => MaterialIconKind.Apple, + OperatingSystems.MacOS => MaterialIconKind.AppleKeyboardCommand, + OperatingSystems.TvOS => MaterialIconKind.Apple, + OperatingSystems.WatchOS => MaterialIconKind.Apple, + OperatingSystems.Windows => MaterialIconKind.MicrosoftWindows, + OperatingSystems.IoT => MaterialIconKind.Chip, + OperatingSystems.AppleVisionOS => MaterialIconKind.Apple, + _ => MaterialIconKind.QuestionMarkCircle, + }; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); +} diff --git a/KitX Dashboard/Converters/PluginInfoConverters.cs b/KitX Dashboard/Converters/PluginInfoConverters.cs index 2f7d26d4..56ed7df2 100644 --- a/KitX Dashboard/Converters/PluginInfoConverters.cs +++ b/KitX Dashboard/Converters/PluginInfoConverters.cs @@ -1,4 +1,5 @@ using Avalonia.Data.Converters; +using KitX.Dashboard.Managers; using System; using System.Collections.Generic; using System.Globalization; @@ -15,7 +16,7 @@ public class PluginMultiLanguagePropertyConverter : IValueConverter if (value is Dictionary dict) { var result = dict.TryGetValue( - Instances.ConfigManager.AppConfig.App.AppLanguage, + ConfigManager.Instance.AppConfig.App.AppLanguage, out var lang ) ? lang : dict.Values.First(); diff --git a/KitX Dashboard/Generators/GreetingTextGenerator.cs b/KitX Dashboard/Generators/GreetingTextGenerator.cs index 82399fa0..7efd2025 100644 --- a/KitX Dashboard/Generators/GreetingTextGenerator.cs +++ b/KitX Dashboard/Generators/GreetingTextGenerator.cs @@ -1,8 +1,9 @@ -using System; +using KitX.Dashboard.Configuration; +using System; namespace KitX.Dashboard.Generators; -internal class GreetingTextGenerator +internal class GreetingTextGenerator : ConfigFetcher { private static int PreviousIndex = 0; @@ -59,31 +60,31 @@ internal static int GenerateRandomIndex(Step step) case Step.Morning: result = random.Next( 1, - Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingTextCount_Morning + 1 + AppConfig.Windows.MainWindow.GreetingTextCount_Morning + 1 ); break; case Step.Noon: result = random.Next( 1, - Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingTextCount_Noon + 1 + AppConfig.Windows.MainWindow.GreetingTextCount_Noon + 1 ); break; case Step.AfterNoon: result = random.Next( 1, - Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingTextCount_AfterNoon + 1 + AppConfig.Windows.MainWindow.GreetingTextCount_AfterNoon + 1 ); break; case Step.Evening: result = random.Next( 1, - Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingTextCount_Evening + 1 + AppConfig.Windows.MainWindow.GreetingTextCount_Evening + 1 ); break; case Step.Night: result = random.Next( 1, - Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingTextCount_Night + 1 + AppConfig.Windows.MainWindow.GreetingTextCount_Night + 1 ); break; } diff --git a/KitX Dashboard/Instances.cs b/KitX Dashboard/Instances.cs index 2c21e583..f0131515 100644 --- a/KitX Dashboard/Instances.cs +++ b/KitX Dashboard/Instances.cs @@ -16,12 +16,8 @@ public static class Instances public static LiteDatabase? ActivitiesDataBase { get; set; } - public static CacheManager? CacheManager { get; set; } - public static KeyHookManager? KeyHookManager { get; set; } - public static ConfigManager ConfigManager { get; set; } = new ConfigManager().SetLocation("./Config/").Load(); - internal static void Initialize() { var location = $"{nameof(Instances)}.{nameof(Initialize)}"; @@ -34,17 +30,11 @@ internal static void Initialize() catchException: true ); - TasksManager.RunTask( - () => CacheManager = new(), - location.Append("." + nameof(CacheManager)), - catchException: true - ); - - TasksManager.RunTask( - () => KeyHookManager = new KeyHookManager().Hook(), - location.Append("." + nameof(KeyHookManager)), - catchException: true - ); + //TasksManager.RunTask( + // () => KeyHookManager = new KeyHookManager().Hook(), + // location.Append("." + nameof(KeyHookManager)), + // catchException: true + //); TasksManager.RunTask(() => { diff --git a/KitX Dashboard/KitX.Dashboard.csproj b/KitX Dashboard/KitX.Dashboard.csproj index 09ac20ab..60d42dc5 100644 --- a/KitX Dashboard/KitX.Dashboard.csproj +++ b/KitX Dashboard/KitX.Dashboard.csproj @@ -92,8 +92,10 @@ + + diff --git a/KitX Dashboard/Managers/ActivityManager.cs b/KitX Dashboard/Managers/ActivityManager.cs index b1c990d6..5826dd3d 100644 --- a/KitX Dashboard/Managers/ActivityManager.cs +++ b/KitX Dashboard/Managers/ActivityManager.cs @@ -44,7 +44,7 @@ public static void Record(Activity activity, Expression> key col?.EnsureIndex(keySelector); - Instances.ConfigManager.AppConfig.Activity.TotalRecorded += col is null ? 0 : 1; + ConfigManager.Instance.AppConfig.Activity.TotalRecorded += col is null ? 0 : 1; db.Commit(); } @@ -76,7 +76,7 @@ public static void RecordAppStart() { var activity = new Activity() { - Id = Instances.ConfigManager.AppConfig.Activity.TotalRecorded, + Id = ConfigManager.Instance.AppConfig.Activity.TotalRecorded, Name = nameof(ActivityNames.AppLifetime), Author = ConstantTable.AppFullName, Title = ActivityTitles.AppStart, diff --git a/KitX Dashboard/Managers/AnouncementManager.cs b/KitX Dashboard/Managers/AnouncementManager.cs index 6709948b..25b2f626 100644 --- a/KitX Dashboard/Managers/AnouncementManager.cs +++ b/KitX Dashboard/Managers/AnouncementManager.cs @@ -17,7 +17,7 @@ public static async Task CheckNewAnnouncements() client.DefaultRequestHeaders.Accept.Clear(); - var appConfig = Instances.ConfigManager.AppConfig; + var appConfig = ConfigManager.Instance.AppConfig; var linkBase = new StringBuilder() .Append("https://") @@ -36,7 +36,7 @@ public static async Task CheckNewAnnouncements() var list = JsonSerializer.Deserialize>(msg); - var accepted = Instances.ConfigManager.AnnouncementConfig.Accepted; + var accepted = ConfigManager.Instance.AnnouncementConfig.Accepted; var unreads = new List(); @@ -53,7 +53,7 @@ public static async Task CheckNewAnnouncements() var apiLink = new StringBuilder() .Append($"{linkBase}{ConstantTable.Api_Get_Announcement}") .Append('?') - .Append($"lang={Instances.ConfigManager.AppConfig.App.AppLanguage}") + .Append($"lang={ConfigManager.Instance.AppConfig.App.AppLanguage}") .Append('&') .Append($"date={item:yyyy-MM-dd HH-mm}") .ToString() diff --git a/KitX Dashboard/Managers/CacheManager.cs b/KitX Dashboard/Managers/CacheManager.cs deleted file mode 100644 index 08f0a363..00000000 --- a/KitX Dashboard/Managers/CacheManager.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace KitX.Dashboard.Managers; - -public class CacheManager -{ - internal CacheManager() - { - FilesCache = []; - ReceivingFilesCache = []; - } - - private static async Task GetMD5(byte[] bytes, bool trans = false) - { - byte[]? result = null; - - await Task.Run(() => - { - result = MD5.HashData(bytes); - }); - - if (result is null) - return null; - - var sb = new StringBuilder(); - - if (trans) foreach (var bt in result) sb.Append(bt.ToString("x2")); - else sb.Append(Encoding.UTF8.GetString(result)); - - return sb.ToString(); - } - - public async Task LoadFileToCache(string fileLocation, CancellationToken token = default) - { - var fullPath = Path.GetFullPath(fileLocation); - var bin = await File.ReadAllBytesAsync(fullPath, token); - - if (bin is null) return null; - - var id = await GetMD5(bin, true); - - if (token.IsCancellationRequested || FilesCache is null || id is null) - return null; - - if (!FilesCache.ContainsKey(id)) - FilesCache?.Add(id, bin); - - GC.Collect(); - - return id; - } - - public async Task ReceiveFileToCache(byte[] bin, CancellationToken token = default) - { - var id = await GetMD5(bin, true); - - if (token.IsCancellationRequested) return null; - - if (ReceivingFilesCache is null || id is null) return null; - - _ = ReceivingFilesCache.TryAdd(id, bin); - - GC.Collect(); - - return id; - } - - public byte[]? GetReceivedFileFromCache(string id) - { - if (ReceivingFilesCache is null) return null; - - if (ReceivingFilesCache.TryGetValue(id, out byte[]? bin)) - return bin; - else return null; - } - - public bool? DisposeFileCache(string id) - { - if (FilesCache is null) return null; - - if (FilesCache.Remove(id)) - { - GC.Collect(); - - return true; - } - - return false; - } - - private readonly Dictionary? FilesCache; - - private readonly Dictionary? ReceivingFilesCache; - -} diff --git a/KitX Dashboard/Managers/ConfigManager.cs b/KitX Dashboard/Managers/ConfigManager.cs index c48ccc5d..9bf9d41e 100644 --- a/KitX Dashboard/Managers/ConfigManager.cs +++ b/KitX Dashboard/Managers/ConfigManager.cs @@ -11,6 +11,10 @@ namespace KitX.Dashboard.Managers; public class ConfigManager { + private static ConfigManager? _instance; + + public static ConfigManager Instance => _instance ??= new ConfigManager().SetLocation("./Config/").Load(); + internal class ConfigManagerInfo { private string? _location; diff --git a/KitX Dashboard/Managers/DevicesManager.cs b/KitX Dashboard/Managers/DevicesManager.cs deleted file mode 100644 index eec24b0c..00000000 --- a/KitX Dashboard/Managers/DevicesManager.cs +++ /dev/null @@ -1,355 +0,0 @@ -using Avalonia.Threading; -using KitX.Dashboard.Network; -using KitX.Dashboard.Network.DevicesNetwork; -using KitX.Dashboard.Services; -using KitX.Dashboard.Views; -using KitX.Dashboard.Views.Pages.Controls; -using KitX.Shared.Device; -using Serilog; -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using Timer = System.Timers.Timer; - -namespace KitX.Dashboard.Managers; - -internal class DevicesManager -{ - internal static DevicesServer? devicesServer = null; - - internal static DevicesClient? devicesClient = null; - - private static readonly object _receivedDeviceInfo4WatchLock = new(); - - internal static List? receivedDeviceInfo4Watch; - - internal static readonly Queue deviceInfoStructs = new(); - - private static readonly object AddDeviceCard2ViewLock = new(); - - private static bool KeepCheckAndRemoveTaskRunning = false; - - private static void InitEvents() - { - EventService.OnReceivingDeviceInfo += dis => - { - if (dis.IsMainDevice && dis.DevicesServerBuildTime < ConstantTable.ServerBuildTime) - { - Stop(); - - Watch4MainDevice(); - - Log.Information( - new StringBuilder() - .AppendLine("Watched earlier built server.") - .AppendLine($"DevicesServerAddress: {dis.Device.IPv4}:{dis.DevicesServerPort} ") - .AppendLine($"DevicesServerBuildTime: {dis.DevicesServerBuildTime}") - .ToString() - ); - } - }; - } - - private static bool CheckDeviceIsOffline(DeviceInfo info) - => DateTime.UtcNow - info.SendTime.ToUniversalTime() > new TimeSpan( - 0, - 0, - Instances.ConfigManager.AppConfig.Web.DeviceInfoTTLSeconds - ); - - private static bool CheckIsCurrentMachine(DeviceInfo info) - { - var self = DevicesDiscoveryServer.DefaultDeviceInfo; - - return info.Device.MacAddress.Equals(self.Device.MacAddress) - && info.Device.DeviceName.Equals(self.Device.DeviceName); - } - - private static void UpdateSourceAndAddCards() - { - var needToAddDevicesCount = 0; - - var thisTurnAdded = new List(); - - while (deviceInfoStructs.Count > 0) - { - var deviceInfoStruct = deviceInfoStructs.Dequeue(); - - var hashCode = deviceInfoStruct.GetHashCode(); - - var findThis = thisTurnAdded.Contains(hashCode); - - if (findThis) continue; - - foreach (var item in ViewInstances.DeviceCards) - { - if (item.viewModel.DeviceInfo.Device.DeviceName.Equals(deviceInfoStruct.Device.DeviceName)) - { - item.viewModel.DeviceInfo = deviceInfoStruct; - findThis = true; - break; - } - } - - if (!findThis) - { - thisTurnAdded.Add(hashCode); - - lock (AddDeviceCard2ViewLock) - { - ++needToAddDevicesCount; - } - - Dispatcher.UIThread.Post(() => - { - lock (AddDeviceCard2ViewLock) - { - ViewInstances.DeviceCards.Add(new(deviceInfoStruct)); - - --needToAddDevicesCount; - } - }); - } - } - - while (needToAddDevicesCount != 0) ; - } - - private static void RemoveOfflineCards() - { - var devicesNeedToBeRemoved = new List(); - - foreach (var item in ViewInstances.DeviceCards) - { - var info = item.viewModel.DeviceInfo; - - if (CheckDeviceIsOffline(info)) devicesNeedToBeRemoved.Add(item); - } - - var removeDeviceTaskRunning = true; - - Dispatcher.UIThread.Post(() => - { - lock (AddDeviceCard2ViewLock) - { - foreach (var item in devicesNeedToBeRemoved) - ViewInstances.DeviceCards.Remove(item); - } - removeDeviceTaskRunning = false; - }); - - while (removeDeviceTaskRunning) ; - } - - private static void MoveSelfCard2First() - { - var index = 0; - var moveSelfCardTaskRunning = true; - - foreach (var item in ViewInstances.DeviceCards) - { - var info = item.viewModel.DeviceInfo; - - if (CheckIsCurrentMachine(info)) - { - if (index != 0) - { - Dispatcher.UIThread.Post(() => - { - try - { - ViewInstances.DeviceCards.Move(index, 0); - } - catch (Exception e) - { - Log.Warning(e, $"Can't move self 2 first. {e.Message}"); - } - - moveSelfCardTaskRunning = false; - }); - - while (moveSelfCardTaskRunning) ; - } - break; - } - ++index; - } - } - - private static void KeepCheckAndRemove() - { - var location = $"{nameof(DevicesManager)}.{nameof(KeepCheckAndRemove)}"; - - var timer = new Timer() - { - Interval = Instances.ConfigManager.AppConfig.Web.DevicesViewRefreshDelay, - AutoReset = true - }; - - timer.Elapsed += (_, _) => - { - try - { - if (KeepCheckAndRemoveTaskRunning) - Log.Information($"In {location}: Timer elapsed and skip task."); - else - { - KeepCheckAndRemoveTaskRunning = true; - - UpdateSourceAndAddCards(); - - if (!Instances.ConfigManager.AppConfig.Web.DisableRemovingOfflineDeviceCard) - RemoveOfflineCards(); - - MoveSelfCard2First(); - - KeepCheckAndRemoveTaskRunning = false; - } - } - catch (Exception ex) - { - Log.Error(ex, $"In {location}: {ex.Message}"); - } - }; - - timer.Start(); - - EventService.AppConfigChanged += () => - { - timer.Interval = Instances.ConfigManager.AppConfig.Web.DevicesViewRefreshDelay; - }; - } - - internal static void Update(DeviceInfo deviceInfo) - { - deviceInfoStructs.Enqueue(deviceInfo); - - if (receivedDeviceInfo4Watch is not null) - { - lock (_receivedDeviceInfo4WatchLock) - { - receivedDeviceInfo4Watch.Add(deviceInfo); - } - } - - EventService.Invoke(nameof(EventService.OnReceivingDeviceInfo), [deviceInfo]); - } - - internal static void Watch4MainDevice() - { - var location = $"{nameof(DevicesManager)}.{nameof(Watch4MainDevice)}"; - - new Thread(() => - { - receivedDeviceInfo4Watch = []; - - var checkedTime = 0; - var hadMainDevice = false; - var earliestBuiltServerTime = DateTime.UtcNow; - var serverPort = 0; - var serverAddress = string.Empty; - - while (checkedTime < 7) - { - try - { - if (receivedDeviceInfo4Watch is null) continue; - - lock (_receivedDeviceInfo4WatchLock) - { - foreach (var item in receivedDeviceInfo4Watch) - { - if (item.IsMainDevice) - { - if (item.DevicesServerBuildTime.ToUniversalTime() < earliestBuiltServerTime) - { - serverPort = item.DevicesServerPort; - serverAddress = item.Device.IPv4; - } - hadMainDevice = true; - } - } - } - - ++checkedTime; - - Log.Information($"In {location}: Watched for {checkedTime} times."); - - if (checkedTime == 7) - { - receivedDeviceInfo4Watch?.Clear(); - receivedDeviceInfo4Watch = null; - - WatchingOver(hadMainDevice, serverAddress, serverPort); - } - - Thread.Sleep(1 * 1000); // Sleep 1 second. - } - catch (Exception e) - { - receivedDeviceInfo4Watch?.Clear(); - receivedDeviceInfo4Watch = null; - - Log.Error(e, $"In {location}: {e.Message} Rewatch."); - - Watch4MainDevice(); - - break; - } - } - }).Start(); - } - - internal static async void WatchingOver(bool foundMainDevice, string serverAddress, int serverPort) - { - var location = $"{nameof(DevicesManager)}.{nameof(WatchingOver)}"; - - Log.Information($"In {location}: " + - $"{nameof(foundMainDevice)} -> {foundMainDevice}, " + - $"{nameof(serverAddress)} -> {serverAddress}, " + - $"{nameof(serverPort)} -> {serverPort}"); - - if (foundMainDevice) - { - devicesClient ??= new(); - - await devicesClient - .SetServerAddress(serverAddress) - .SetServerPort(serverPort) - .Start() - ; - } - else - { - devicesServer?.Start(); - } - } - - public static void Start() - { - devicesServer = new(); - - devicesClient = new(); - - InitEvents(); - - KeepCheckAndRemove(); - - Watch4MainDevice(); - } - - public static void Stop() - { - devicesServer?.Stop(); - - devicesClient?.Stop(); - } - - public static void Restart() - { - Stop(); - - Start(); - } -} diff --git a/KitX Dashboard/Managers/PluginsManager.cs b/KitX Dashboard/Managers/PluginsManager.cs index 6a68882d..1003d71e 100644 --- a/KitX Dashboard/Managers/PluginsManager.cs +++ b/KitX Dashboard/Managers/PluginsManager.cs @@ -14,7 +14,7 @@ namespace KitX.Dashboard.Managers; internal class PluginsManager { - internal static List Plugins => Instances.ConfigManager.PluginsConfig.Plugins; + internal static List Plugins => ConfigManager.Instance.PluginsConfig.Plugins; internal static void ImportPlugin(string[] kxpfiles, bool inGraphic = false) { @@ -36,7 +36,9 @@ internal static void ImportPlugin(string[] kxpfiles, bool inGraphic = false) var pluginInfo = JsonSerializer.Deserialize(rst.Item2); - var config = Instances.ConfigManager.AppConfig; + if (pluginInfo is null) continue; + + var config = ConfigManager.Instance.AppConfig; var pluginsavedir = config?.App?.LocalPluginsFileFolder.GetFullPath(); diff --git a/KitX Dashboard/Managers/WebManager.cs b/KitX Dashboard/Managers/WebManager.cs index cd3c405b..ab681bdf 100644 --- a/KitX Dashboard/Managers/WebManager.cs +++ b/KitX Dashboard/Managers/WebManager.cs @@ -1,5 +1,4 @@ -using KitX.Dashboard.Models.Network; -using KitX.Dashboard.Network.DevicesNetwork; +using KitX.Dashboard.Network.DevicesNetwork; using KitX.Dashboard.Network.PluginsNetwork; using Serilog; using System; @@ -9,14 +8,13 @@ namespace KitX.Dashboard.Managers; -public class WebManager : IDisposable +public class WebManager { - internal ObservableCollection? NetworkInterfaceRegistered; + private static WebManager? _instance; - public WebManager() - { - NetworkInterfaceRegistered = []; - } + public static WebManager Instance => _instance ??= new(); + + internal readonly ObservableCollection NetworkInterfaceRegistered = []; public async Task RunAsync(WebManagerOperationInfo info) { @@ -33,7 +31,7 @@ await TasksManager.RunTaskAsync(async () => await DevicesDiscoveryServer.Instance.RunAsync(); if (info.RunAll || info.RunDevicesServer) - DevicesManager.Start(); + await DevicesServer.Instance.RunAsync(); } catch (Exception ex) { @@ -51,20 +49,20 @@ public async Task CloseAsync(WebManagerOperationInfo info) try { if (info.CloseAll || info.CloseDevicesServer) - DevicesManager.Stop(); + await DevicesServer.Instance.CloseAsync(); if (info.CloseAll || info.CloseDevicesDiscoveryServer) { await DevicesDiscoveryServer.Instance.CloseAsync().ContinueWith( async server => { - await Task.Delay(Instances.ConfigManager.AppConfig.Web.UdpSendFrequency + 500); + await Task.Delay(ConfigManager.Instance.AppConfig.Web.UdpSendFrequency + 500); server.Dispose(); } ); - while (DevicesDiscoveryServer.CloseDevicesDiscoveryServerRequest) { } + while (DevicesDiscoveryServer.Instance.CloseDevicesDiscoveryServerRequest) { } } if (info.CloseAll || info.ClosePluginsServer) @@ -88,9 +86,46 @@ public async Task RestartAsync(WebManagerOperationInfo info, Action? return this; } +} + +public struct WebManagerOperationInfo +{ + public bool RunPluginsServer = true; + + public bool RunDevicesServer = true; + + public bool RunDevicesDiscoveryServer = true; + + public bool RunAll + { + readonly get => RunPluginsServer && RunDevicesServer && RunDevicesDiscoveryServer; + set + { + RunPluginsServer = value; + RunDevicesServer = value; + RunDevicesDiscoveryServer = value; + } + } + + public bool ClosePluginsServer = true; - public void Dispose() + public bool CloseDevicesServer = true; + + public bool CloseDevicesDiscoveryServer = true; + + public bool CloseAll { - GC.SuppressFinalize(this); + readonly get => ClosePluginsServer && CloseDevicesServer && CloseDevicesDiscoveryServer; + set + { + ClosePluginsServer = value; + CloseDevicesServer = value; + CloseDevicesDiscoveryServer = value; + } + } + + public WebManagerOperationInfo() + { + } } diff --git a/KitX Dashboard/Models/DeviceCase.cs b/KitX Dashboard/Models/DeviceCase.cs new file mode 100644 index 00000000..0c3ecf3b --- /dev/null +++ b/KitX Dashboard/Models/DeviceCase.cs @@ -0,0 +1,15 @@ +using KitX.Shared.Device; +using ReactiveUI; + +namespace KitX.Dashboard.Models; + +public class DeviceCase(DeviceInfo deviceInfo) : ReactiveObject +{ + private DeviceInfo deviceInfo = deviceInfo; + + public DeviceInfo DeviceInfo + { + get => deviceInfo; + set => this.RaiseAndSetIfChanged(ref deviceInfo, value); + } +} diff --git a/KitX Dashboard/Models/Network/WebManagerOperationInfo.cs b/KitX Dashboard/Models/Network/WebManagerOperationInfo.cs deleted file mode 100644 index f1f9b4cd..00000000 --- a/KitX Dashboard/Models/Network/WebManagerOperationInfo.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace KitX.Dashboard.Models.Network; - -public struct WebManagerOperationInfo -{ - public bool RunPluginsServer = true; - - public bool RunDevicesServer = true; - - public bool RunDevicesDiscoveryServer = true; - - public bool RunAll - { - readonly get => RunPluginsServer && RunDevicesServer && RunDevicesDiscoveryServer; - set - { - RunPluginsServer = value; - RunDevicesServer = value; - RunDevicesDiscoveryServer = value; - } - } - - public bool ClosePluginsServer = true; - - public bool CloseDevicesServer = true; - - public bool CloseDevicesDiscoveryServer = true; - - public bool CloseAll - { - readonly get => ClosePluginsServer && CloseDevicesServer && CloseDevicesDiscoveryServer; - set - { - ClosePluginsServer = value; - CloseDevicesServer = value; - CloseDevicesDiscoveryServer = value; - } - } - - public WebManagerOperationInfo() - { - - } -} diff --git a/KitX Dashboard/Models/Plugin.cs b/KitX Dashboard/Models/PluginInstallation.cs similarity index 59% rename from KitX Dashboard/Models/Plugin.cs rename to KitX Dashboard/Models/PluginInstallation.cs index 57c98786..f4a8c8a9 100644 --- a/KitX Dashboard/Models/Plugin.cs +++ b/KitX Dashboard/Models/PluginInstallation.cs @@ -6,17 +6,17 @@ namespace KitX.Dashboard.Models; -public class Plugin +public class PluginInstallation { [JsonInclude] public string? InstallPath { get; set; } [JsonIgnore] - public PluginInfo PluginDetails { get; set; } + public PluginInfo PluginInfo { get; set; } = new(); [JsonIgnore] - public LoaderInfo RequiredLoaderInfo { get; set; } + public LoaderInfo LoaderInfo { get; set; } = new(); [JsonIgnore] - public List? InstalledDevices { get; set; } + public List InstalledDevices { get; set; } = []; } diff --git a/KitX Dashboard/Names/PluginTagsNames.cs b/KitX Dashboard/Names/PluginTagsNames.cs index 4253d72a..24f3250b 100644 --- a/KitX Dashboard/Names/PluginTagsNames.cs +++ b/KitX Dashboard/Names/PluginTagsNames.cs @@ -1,13 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace KitX.Dashboard.Names; +namespace KitX.Dashboard.Names; internal static class PluginTagsNames { internal static object? JoinTime => null; -} + internal static object? ConnectionId => null; +} diff --git a/KitX Dashboard/Network/DevicesClient.cs b/KitX Dashboard/Network/DevicesClient.cs deleted file mode 100644 index 2ed06887..00000000 --- a/KitX Dashboard/Network/DevicesClient.cs +++ /dev/null @@ -1,249 +0,0 @@ -using Common.BasicHelper.Utils.Extensions; -using KitX.Dashboard.Managers; -using Serilog; -using System; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace KitX.Dashboard.Network; - -internal class DevicesClient -{ - private static TcpClient? client = null; - - private static bool keepReceiving = false; - - public static string ServerAddress { get; set; } = string.Empty; - - public static int ServerPort { get; set; } = 0; - - private static ClientStatus status = ClientStatus.Pending; - - public static ClientStatus Status - { - get => status; - set - { - status = value; - - if (status == ClientStatus.Errored) - DevicesManager.Restart(); - } - } - - public static Action? onReceive = null; - - public DevicesClient SetServerAddress(string address) - { - ServerAddress = address; - - return this; - } - - public DevicesClient SetServerPort(int port) - { - if (port <= 0 || port >= 65536) - throw new ArgumentOutOfRangeException(nameof(port), "0 < port < 65536"); - - ServerPort = port; - - return this; - } - - public async void Receive() - { - var location = $"{nameof(DevicesClient)}.{nameof(Receive)}"; - - if (client is null) return; - - var stream = client?.GetStream(); - - if (stream is null) return; - - var buffer = new byte[Instances.ConfigManager.AppConfig.Web.SocketBufferSize]; // Default 10 MB buffer - - try - { - while (keepReceiving) - { - if (buffer is null) break; - - var length = await stream.ReadAsync(buffer); - - if (length > 0) - { - var msg = buffer.ToUTF8(0, length); - - Log.Information($"Receive from Host: {msg}"); - } - else - { - keepReceiving = false; - break; - } - } - } - catch (Exception e) - { - Log.Error(e, $"In {location}: {e.Message}"); - - Status = ClientStatus.Errored; - } - - stream.CloseAndDispose(); - - client?.CloseAndDispose(); - } - - public async Task Connect() - { - var location = $"{nameof(DevicesClient)}.{nameof(Connect)}"; - - if (client is null) return this; - - Status = ClientStatus.Connecting; - - await TasksManager.RunTaskAsync(async () => - { - try - { - await client.ConnectAsync(ServerAddress, ServerPort); - - new Thread(Receive).Start(); - } - catch (Exception ex) - { - Log.Error(ex, $"In {location}: {ex.Message}"); - - await Stop(); - - Status = ClientStatus.Errored; - } - - }, location); - - Status = ClientStatus.Running; - - return this; - } - - public async Task Disconnect() - { - var location = $"{nameof(DevicesClient)}.{nameof(Disconnect)}"; - - Status = ClientStatus.Disconnecting; - - await TasksManager.RunTaskAsync(() => - { - keepReceiving = false; - - client?.Close(); - - }, location); - - Status = ClientStatus.Pending; - - return this; - } - - public DevicesClient OnReceive(Action action) - { - onReceive = action; - - return this; - } - - public async Task Send(byte[] content) - { - var location = $"{nameof(DevicesClient)}.{nameof(Send)}"; - - await TasksManager.RunTaskAsync(async () => - { - try - { - var stream = client?.GetStream(); - - if (stream is null) return; - - stream.Write(content, 0, content.Length); - stream.Flush(); - - Log.Information($"Sent Message to Host, msg: {content.ToUTF8()}"); - } - catch (Exception e) - { - Log.Error(e, $"In {location}: {e.Message}"); - - await Stop(); - - Status = ClientStatus.Errored; - } - }, location); - - return this; - } - - private static void Init() - { - keepReceiving = true; - - client = new(); - } - - public async Task Start() - { - var location = $"{nameof(DevicesClient)}.{nameof(Start)}"; - - if (Status != ClientStatus.Pending) return this; - - await TasksManager.RunTaskAsync(async () => - { - Status = ClientStatus.Pending; - - Init(); - - await Connect(); - - }, location); - - return this; - } - - public async Task Stop() - { - var location = $"{nameof(DevicesClient)}.{nameof(Stop)}"; - - if (Status != ClientStatus.Running) return this; - - await TasksManager.RunTaskAsync(async () => - { - keepReceiving = false; - - await Disconnect(); - - }, location); - - return this; - } - - public async Task Restart() - { - var location = $"{nameof(DevicesClient)}.{nameof(Restart)}"; - - await TasksManager.RunTaskAsync(async () => - { - await Stop(); - - await Start(); - - }, location); - - return this; - } - - public void Dispose() - { - client?.Dispose(); - } -} diff --git a/KitX Dashboard/Network/DevicesNetwork/DevicesDiscoveryServer.cs b/KitX Dashboard/Network/DevicesNetwork/DevicesDiscoveryServer.cs index ee084950..9bd0c320 100644 --- a/KitX Dashboard/Network/DevicesNetwork/DevicesDiscoveryServer.cs +++ b/KitX Dashboard/Network/DevicesNetwork/DevicesDiscoveryServer.cs @@ -1,6 +1,7 @@ using Common.BasicHelper.Utils.Extensions; using KitX.Dashboard.Managers; using KitX.Dashboard.Names; +using KitX.Dashboard.Services; using KitX.Dashboard.Views; using KitX.Shared.Device; using Serilog; @@ -20,33 +21,31 @@ public class DevicesDiscoveryServer { private static DevicesDiscoveryServer? _instance; - public static DevicesDiscoveryServer Instance => _instance ??= new DevicesDiscoveryServer(); + public static DevicesDiscoveryServer Instance => _instance ??= new(); - private static UdpClient? UdpSender = null; + private UdpClient? UdpSender = null; - private static UdpClient? UdpReceiver = null; + private UdpClient? UdpReceiver = null; - private static System.Timers.Timer? UdpSendTimer = null; + private System.Timers.Timer? UdpSendTimer = null; - private static int DeviceInfoUpdatedTimes = 0; + private int DeviceInfoUpdatedTimes = 0; - private static int LastTimeToOSVersionUpdated = 0; + private int LastTimeToOSVersionUpdated = 0; - private static readonly List SupportedNetworkInterfacesIndexes = []; + private readonly List SupportedNetworkInterfacesIndexes = []; - private static bool disposed = false; + private bool disposed = false; - private static Action? onReceive = null; + internal bool CloseDevicesDiscoveryServerRequest = false; - internal static bool CloseDevicesDiscoveryServerRequest = false; + internal readonly Queue Messages2BroadCast = new(); - internal static readonly Queue Messages2BroadCast = new(); + internal DeviceInfo DefaultDeviceInfo = NetworkHelper.GetDeviceInfo(); - internal static DeviceInfo DefaultDeviceInfo = NetworkHelper.GetDeviceInfo(); + private ServerStatus status = ServerStatus.Pending; - private static ServerStatus status = ServerStatus.Pending; - - internal static ServerStatus Status + internal ServerStatus Status { get => status; set @@ -55,7 +54,112 @@ internal static ServerStatus Status } } - private static void FindSupportNetworkInterfaces(List clients, IPAddress multicastAddress) + public DevicesDiscoveryServer() + { + Initialize(); + + DevicesOrganizer.Start(); + } + + private void Initialize() + { + disposed = false; + + DeviceInfoUpdatedTimes = 0; + + LastTimeToOSVersionUpdated = 0; + + CloseDevicesDiscoveryServerRequest = false; + + SupportedNetworkInterfacesIndexes.Clear(); + + Messages2BroadCast.Clear(); + + DefaultDeviceInfo = NetworkHelper.GetDeviceInfo(); + } + + public async Task RunAsync() + { + if (Status != ServerStatus.Pending) return this; + + Status = ServerStatus.Starting; + + Initialize(); + + UdpSender = new( + ConfigManager.Instance.AppConfig.Web.UdpPortSend, + AddressFamily.InterNetwork + ) + { + EnableBroadcast = true, + MulticastLoopback = true + }; + + UdpReceiver = new( + new IPEndPoint( + IPAddress.Any, + ConfigManager.Instance.AppConfig.Web.UdpPortReceive + ) + ); + + await TasksManager.RunTaskAsync(() => + { + try + { + FindSupportNetworkInterfaces( + [UdpSender, UdpReceiver], + IPAddress.Parse(ConfigManager.Instance.AppConfig.Web.UdpBroadcastAddress) + ); // 寻找所有支持的网络适配器 + } + catch (Exception ex) + { + var location = $"{nameof(DevicesServer)}.{nameof(RunAsync)}"; + Log.Warning(ex, $"In {location}: {ex.Message}"); + } + }, nameof(FindSupportNetworkInterfaces)); + + await TasksManager.RunTaskAsync( + MultiDevicesBroadCastSend, + nameof(MultiDevicesBroadCastSend) + ); + + await TasksManager.RunTaskAsync( + MultiDevicesBroadCastReceive, + nameof(MultiDevicesBroadCastReceive) + ); + + Status = ServerStatus.Running; + + return this; + } + + public async Task CloseAsync() + { + if (Status != ServerStatus.Running) return this; + + await Task.Run(() => + { + Status = ServerStatus.Stopping; + + CloseDevicesDiscoveryServerRequest = true; + }); + + return this; + } + + public async Task Restart() + { + await Task.Run(async () => + { + await CloseAsync(); + + await RunAsync(); + }); + + return this; + } + + private void FindSupportNetworkInterfaces(List clients, IPAddress multicastAddress) { var multicastGroupJoinedInterfacesCount = 0; @@ -106,7 +210,7 @@ private static void FindSupportNetworkInterfaces(List clients, IPAddr Log.Information($"Joined {multicastGroupJoinedInterfacesCount} multicast groups."); } - private static void UpdateDefaultDeviceInfo() + private void UpdateDefaultDeviceInfo() { DefaultDeviceInfo.IsMainDevice = ConstantTable.IsMainMachine; DefaultDeviceInfo.SendTime = DateTime.UtcNow; @@ -120,7 +224,7 @@ private static void UpdateDefaultDeviceInfo() DefaultDeviceInfo.DevicesServerPort = ConstantTable.DevicesServerPort; DefaultDeviceInfo.DevicesServerBuildTime = ConstantTable.ServerBuildTime; - if (LastTimeToOSVersionUpdated > Instances.ConfigManager.AppConfig.IO.OperatingSystemVersionUpdateInterval) + if (LastTimeToOSVersionUpdated > ConfigManager.Instance.AppConfig.IO.OperatingSystemVersionUpdateInterval) { LastTimeToOSVersionUpdated = 0; DefaultDeviceInfo.DeviceOSVersion = NetworkHelper.TryGetOSVersionString() ?? ""; @@ -136,10 +240,11 @@ private void MultiDevicesBroadCastSend() { var location = $"{nameof(DevicesDiscoveryServer)}.{nameof(MultiDevicesBroadCastSend)}"; - IPEndPoint multicast = new( - IPAddress.Parse(Instances.ConfigManager.AppConfig.Web.UdpBroadcastAddress), - Instances.ConfigManager.AppConfig.Web.UdpPortReceive + var multicast = new IPEndPoint( + IPAddress.Parse(ConfigManager.Instance.AppConfig.Web.UdpBroadcastAddress), + ConfigManager.Instance.AppConfig.Web.UdpPortReceive ); + UdpSender?.Client.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, @@ -151,7 +256,7 @@ private void MultiDevicesBroadCastSend() UdpSendTimer = new() { - Interval = Instances.ConfigManager.AppConfig.Web.UdpSendFrequency, + Interval = ConfigManager.Instance.AppConfig.Web.UdpSendFrequency, AutoReset = true }; @@ -223,6 +328,7 @@ private void MultiDevicesBroadCastSend() CloseDevicesDiscoveryServerRequest = false; } }; + UdpSendTimer.Start(); } @@ -231,6 +337,7 @@ private void MultiDevicesBroadCastReceive() var location = $"{nameof(DevicesDiscoveryServer)}.{nameof(MultiDevicesBroadCastReceive)}"; var multicast = new IPEndPoint(IPAddress.Any, 0); + UdpReceiver?.Client.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, @@ -248,23 +355,27 @@ private void MultiDevicesBroadCastReceive() if (bytes is null) continue; // null byte[] cause exception in next line. - onReceive?.Invoke(bytes, null, client); - var result = bytes.ToUTF8(); Log.Information($"UDP From: {client,-21}, Receive: {result}"); try { - DevicesManager.Update( - JsonSerializer.Deserialize(result) - ); + var info = JsonSerializer.Deserialize(result); + + if (info is not null) + EventService.Invoke( + nameof(EventService.OnReceivingDeviceInfo), + [info] + ); } catch (Exception ex) { Log.Warning(ex, $"When trying to deserialize `{result}`"); } } + + Status = ServerStatus.Pending; } catch (Exception e) { @@ -278,145 +389,63 @@ private void MultiDevicesBroadCastReceive() }).Start(); } - private static void Init() + public void Dispose() { - disposed = false; - - DeviceInfoUpdatedTimes = 0; + if (disposed) return; - LastTimeToOSVersionUpdated = 0; + disposed = true; CloseDevicesDiscoveryServerRequest = false; - SupportedNetworkInterfacesIndexes.Clear(); - - Messages2BroadCast.Clear(); + UdpSender?.Dispose(); + UdpReceiver?.Dispose(); - DefaultDeviceInfo = NetworkHelper.GetDeviceInfo(); + GC.Collect(); } +} - public async Task RunAsync() - { - if (Status != ServerStatus.Pending) return this; - - Status = ServerStatus.Starting; - - Init(); - - UdpSender = new( - Instances.ConfigManager.AppConfig.Web.UdpPortSend, - AddressFamily.InterNetwork - ) - { - EnableBroadcast = true, - MulticastLoopback = true - }; - - UdpReceiver = new( - new IPEndPoint( - IPAddress.Any, - Instances.ConfigManager.AppConfig.Web.UdpPortReceive - ) +public static class DevicesDiscoveryServerExtensions +{ + public static bool IsOffline(this DeviceInfo info) + => DateTime.UtcNow - info.SendTime.ToUniversalTime() > new TimeSpan( + 0, 0, ConfigManager.Instance.AppConfig.Web.DeviceInfoTTLSeconds ); - await TasksManager.RunTaskAsync(() => - { - try - { - FindSupportNetworkInterfaces( - [UdpSender, UdpReceiver], - IPAddress.Parse(Instances.ConfigManager.AppConfig.Web.UdpBroadcastAddress) - ); // 寻找所有支持的网络适配器 - } - catch (Exception ex) - { - var location = $"{nameof(DevicesServer)}.{nameof(RunAsync)}"; - Log.Warning(ex, $"In {location}: {ex.Message}"); - } - }, nameof(FindSupportNetworkInterfaces)); - - await TasksManager.RunTaskAsync( - MultiDevicesBroadCastSend, - nameof(MultiDevicesBroadCastSend) - ); // 开始发送组播报文 - - await TasksManager.RunTaskAsync( - MultiDevicesBroadCastReceive, - nameof(MultiDevicesBroadCastReceive) - ); // 开始接收组播报文 - - Status = ServerStatus.Running; + public static bool IsCurrentDevice(this DeviceInfo info) + => info.IsSameDevice(DevicesDiscoveryServer.Instance.DefaultDeviceInfo); - return this; - } + public static bool IsSameDevice(this DeviceInfo info, DeviceInfo target) + => info.Device.DeviceName.Equals(target.Device.DeviceName) + && info.Device.MacAddress.Equals(target.Device.MacAddress); - public async Task CloseAsync() + public static void UpdateTo(this DeviceInfo info, DeviceInfo target) { - if (Status != ServerStatus.Running) return this; - - await Task.Run(() => - { - Status = ServerStatus.Stopping; - - CloseDevicesDiscoveryServerRequest = true; + var type = typeof(DeviceInfo); - Status = ServerStatus.Pending; - }); - - return this; - } + var fields = type.GetFields(); - public async Task Restart() - { - await Task.Run(async () => + foreach (var field in fields) { - await CloseAsync(); - - await RunAsync(); - }); - - return this; - } - - public async Task Send(byte[] content, string target) - { - await Task.Run(() => { }); - - return this; - } - - public async Task Broadcast(byte[] content) - { - await Task.Run(() => { }); - - return this; - } + var firstValue = field.GetValue(info); + var secondValue = field.GetValue(target); - public async Task BroadCast(byte[] content, Func? pattern) - { - await Task.Run(() => { }); - - return this; - } + if (firstValue?.Equals(secondValue) ?? false) + continue; - public DevicesDiscoveryServer OnReceive(Action action) - { - onReceive = action; - - return this; - } - - public void Dispose() - { - if (disposed) return; + field.SetValue(info, secondValue); + } - disposed = true; + var properties = type.GetProperties(); - CloseDevicesDiscoveryServerRequest = false; + foreach (var property in properties) + { + object? firstValue = property.GetValue(info); + object? secondValue = property.GetValue(target); - UdpSender?.Dispose(); - UdpReceiver?.Dispose(); + if (firstValue?.Equals(secondValue) ?? false) + continue; - GC.Collect(); + property.SetValue(info, secondValue); + } } } diff --git a/KitX Dashboard/Network/DevicesNetwork/DevicesOrganizer.cs b/KitX Dashboard/Network/DevicesNetwork/DevicesOrganizer.cs new file mode 100644 index 00000000..bc337953 --- /dev/null +++ b/KitX Dashboard/Network/DevicesNetwork/DevicesOrganizer.cs @@ -0,0 +1,263 @@ +using KitX.Dashboard.Configuration; +using KitX.Dashboard.Models; +using KitX.Dashboard.Services; +using KitX.Dashboard.Views; +using KitX.Shared.Device; +using Serilog; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using Timer = System.Timers.Timer; + +namespace KitX.Dashboard.Network.DevicesNetwork; + +internal class DevicesOrganizer : ConfigFetcher +{ + private static readonly object _receivedDeviceInfo4WatchLock = new(); + + internal static List? receivedDeviceInfo4Watch; + + internal static readonly Queue deviceInfoStructs = new(); + + private static readonly object AddDeviceCard2ViewLock = new(); + + private static bool KeepCheckAndRemoveTaskRunning = false; + + public static void Start() + { + InitEvents(); + + KeepCheckAndRemove(); + + Watch4MainDevice(); + } + + private static void InitEvents() + { + EventService.OnReceivingDeviceInfo += deviceInfo => + { + deviceInfoStructs.Enqueue(deviceInfo); + + lock (_receivedDeviceInfo4WatchLock) + { + receivedDeviceInfo4Watch?.Add(deviceInfo); + } + + if (deviceInfo.IsMainDevice && deviceInfo.DevicesServerBuildTime < ConstantTable.ServerBuildTime) + { + ConstantTable.IsMainMachine = false; + + Watch4MainDevice(); + + Log.Information( + new StringBuilder() + .AppendLine("Watched earlier built server.") + .AppendLine($"DevicesServerAddress: {deviceInfo.Device.IPv4}:{deviceInfo.DevicesServerPort} ") + .AppendLine($"DevicesServerBuildTime: {deviceInfo.DevicesServerBuildTime}") + .ToString() + ); + } + }; + } + + private static void UpdateSourceAndAddCards() + { + var thisTurnAdded = new List(); + + while (deviceInfoStructs.Count > 0) + { + var deviceInfoStruct = deviceInfoStructs.Dequeue(); + + var hashCode = deviceInfoStruct.GetHashCode(); + + var findThis = thisTurnAdded.Contains(hashCode); + + if (findThis) continue; + + foreach (var item in ViewInstances.DeviceCases) + { + if (item.DeviceInfo.IsSameDevice(deviceInfoStruct)) + { + item.DeviceInfo = deviceInfoStruct; + findThis = true; + break; + } + } + + if (!findThis) + { + thisTurnAdded.Add(hashCode); + + ViewInstances.DeviceCases.Add(new(deviceInfoStruct)); + } + } + } + + private static void RemoveOfflineCards() + { + var devicesNeedToBeRemoved = new List(); + + foreach (var item in ViewInstances.DeviceCases) + if (item.DeviceInfo.IsOffline()) + devicesNeedToBeRemoved.Add(item); + + foreach (var item in devicesNeedToBeRemoved) + ViewInstances.DeviceCases.Remove(item); + } + + private static void MoveSelfCardToFirst() + { + var index = 0; + + foreach (var item in ViewInstances.DeviceCases) + { + if (item.DeviceInfo.IsCurrentDevice()) + { + if (index != 0) + ViewInstances.DeviceCases.Move(index, 0); + + break; + } + + ++index; + } + } + + private static void KeepCheckAndRemove() + { + var location = $"{nameof(DevicesOrganizer)}.{nameof(KeepCheckAndRemove)}"; + + var timer = new Timer() + { + Interval = AppConfig.Web.DevicesViewRefreshDelay, + AutoReset = true + }; + + timer.Elapsed += (_, _) => + { + try + { + if (KeepCheckAndRemoveTaskRunning) + Log.Information($"In {location}: Timer elapsed and skip task."); + else + { + KeepCheckAndRemoveTaskRunning = true; + + UpdateSourceAndAddCards(); + + if (AppConfig.Web.DisableRemovingOfflineDeviceCard == false) + RemoveOfflineCards(); + + MoveSelfCardToFirst(); + + KeepCheckAndRemoveTaskRunning = false; + } + } + catch (Exception ex) + { + Log.Error(ex, $"In {location}: {ex.Message}"); + } + }; + + timer.Start(); + + EventService.AppConfigChanged += () => + { + timer.Interval = AppConfig.Web.DevicesViewRefreshDelay; + }; + } + + internal static void Watch4MainDevice(CancellationToken token = default) + { + var location = $"{nameof(DevicesOrganizer)}.{nameof(Watch4MainDevice)}"; + + new Thread(() => + { + receivedDeviceInfo4Watch = []; + + var checkedTime = 0; + var hadMainDevice = false; + var earliestBuiltServerTime = DateTime.UtcNow; + var serverPort = 0; + var serverAddress = string.Empty; + + while (checkedTime < 7 && token.IsCancellationRequested == false) + { + try + { + if (receivedDeviceInfo4Watch is null) continue; + + lock (_receivedDeviceInfo4WatchLock) + { + foreach (var item in receivedDeviceInfo4Watch) + { + if (item.IsMainDevice) + { + if (item.DevicesServerBuildTime.ToUniversalTime() < earliestBuiltServerTime) + { + serverPort = item.DevicesServerPort; + serverAddress = item.Device.IPv4; + } + hadMainDevice = true; + } + } + } + + ++checkedTime; + + Log.Information($"In {location}: Watched for {checkedTime} times."); + + if (checkedTime == 7) + { + receivedDeviceInfo4Watch?.Clear(); + receivedDeviceInfo4Watch = null; + + if (token.IsCancellationRequested == false) + WatchingOver(hadMainDevice, serverAddress, serverPort); + } + + Thread.Sleep(1 * 1000); // Sleep 1 second. + } + catch (Exception e) + { + receivedDeviceInfo4Watch?.Clear(); + receivedDeviceInfo4Watch = null; + + Log.Error(e, $"In {location}: {e.Message} Rewatch."); + + if (token.IsCancellationRequested == false) + Watch4MainDevice(); + + break; + } + } + }).Start(); + } + + private static void WatchingOver(bool foundMainDevice, string serverAddress, int serverPort) + { + var location = $"{nameof(DevicesOrganizer)}.{nameof(WatchingOver)}"; + + Log.Information( + new StringBuilder() + .Append($"In {location}: ") + .Append($"{nameof(foundMainDevice)} -> {foundMainDevice}") + .Append(", ") + .Append($"{nameof(serverAddress)} -> {serverAddress}") + .Append(", ") + .Append($"{nameof(serverPort)} -> {serverPort}") + .ToString() + ); + + if (foundMainDevice) + { + ConstantTable.MainMachineAddress = serverAddress; + ConstantTable.MainMachinePort = serverPort; + } + else + { + ConstantTable.IsMainMachine = true; + } + } +} diff --git a/KitX Dashboard/Network/DevicesNetwork/DevicesServer.cs b/KitX Dashboard/Network/DevicesNetwork/DevicesServer.cs new file mode 100644 index 00000000..cc6c1b94 --- /dev/null +++ b/KitX Dashboard/Network/DevicesNetwork/DevicesServer.cs @@ -0,0 +1,127 @@ +using KitX.Dashboard.Configuration; +using KitX.Dashboard.Services; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; +using Serilog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace KitX.Dashboard.Network.DevicesNetwork; + +public class DevicesServer : ConfigFetcher +{ + private static DevicesServer? _devicesServer; + + public static DevicesServer Instance => _devicesServer ??= new(); + + private readonly int port = AppConfig.Web.UserSpecifiedDevicesServerPort ?? 0; + + private IHost? _host; + + public async Task RunAsync() + { + var host = CreateHostBuilder([]).Build(); + + _host = host; + + new Thread(host.Run).Start(); + + var addresses = host.Services.GetService()?.Features.Get()?.Addresses; + + while (addresses is null || addresses.Count == 0) + { + await Task.Delay(500); + + addresses = host.Services.GetService()?.Features.Get()?.Addresses; + } + + if (addresses is not null && addresses.Count != 0) + EventService.Invoke( + nameof(EventService.DevicesServerPortChanged), + [new Uri(addresses.First()).Port] + ); + + return this; + } + + public async Task CloseAsync() + { + if (_host is not null) + await _host.StopAsync(); + + return this; + } + + private IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseSerilog() + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + webBuilder.UseUrls($"http://0.0.0.0:{port}"); + }) + ; +} + +public class Startup +{ + private readonly List apiVersions = [.. typeof(DevicesServerApiVersions).GetEnumNames()]; + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + + services.AddEndpointsApiExplorer(); + + services.AddSwaggerGen(options => + { + apiVersions.ForEach(version => + { + options.SwaggerDoc(version, new OpenApiInfo + { + Title = "KitX Dashboard DevicesServer API", + Version = version, + Description = $"Version: {version}" + }); + }); + }); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseSwagger(); + + app.UseSwaggerUI(options => + { + apiVersions.ForEach(version => + { + options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version); + }); + }); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } +} + +public enum DevicesServerApiVersions +{ + V1 = 1, +} diff --git a/KitX Dashboard/Network/DevicesNetwork/DevicesServerControllers/DeviceController.cs b/KitX Dashboard/Network/DevicesNetwork/DevicesServerControllers/DeviceController.cs new file mode 100644 index 00000000..08083c02 --- /dev/null +++ b/KitX Dashboard/Network/DevicesNetwork/DevicesServerControllers/DeviceController.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Mvc; + +namespace KitX.Dashboard.Network.DevicesNetwork.DevicesServerControllers; + +[ApiController] +[Route("Api/[controller]")] +[ApiExplorerSettings(GroupName = "V1")] +public class DeviceController : ControllerBase +{ + [ApiExplorerSettings(GroupName = "V1")] + [HttpGet("{name}", Name = nameof(GreetingTest))] + public string GreetingTest(string name) + { + return $"Hello, {name} !"; + } +} diff --git a/KitX Dashboard/Network/DevicesServer.cs b/KitX Dashboard/Network/DevicesServer.cs deleted file mode 100644 index 557e7de8..00000000 --- a/KitX Dashboard/Network/DevicesServer.cs +++ /dev/null @@ -1,273 +0,0 @@ -using Common.BasicHelper.Utils.Extensions; -using KitX.Dashboard.Managers; -using KitX.Dashboard.Services; -using Serilog; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace KitX.Dashboard.Network; - -internal class DevicesServer -{ - private static TcpListener? listener = null; - - private static bool keepListen = true; - - private static bool disposed = false; - - private static readonly Dictionary clients = []; - - private static Action? onReceive = null; - - private static ServerStatus status = ServerStatus.Pending; - - public static ServerStatus Status - { - get => status; - set - { - status = value; - - if (status == ServerStatus.Errored) - DevicesManager.Restart(); - } - } - - private static void Init() - { - disposed = false; - - clients.Clear(); - - listener = new(IPAddress.Any, 0); - - keepListen = true; - } - - private static void AcceptClient() - { - var location = $"{nameof(DevicesServer)}.{nameof(AcceptClient)}"; - - try - { - while (keepListen && listener is not null) - { - var client = listener.AcceptTcpClient(); - - if (client.Client.RemoteEndPoint is not IPEndPoint endpoint) continue; - - clients.Add(endpoint.ToString(), client); - - Log.Information($"New device connection: {endpoint}"); - - ReceiveMessage(client); - } - } - catch (Exception ex) - { - Log.Error(ex, $"In {nameof(location)}: {ex.Message}"); - - Status = ServerStatus.Errored; - } - } - - private static void ReceiveMessage(TcpClient client) - { - var location = $"{nameof(DevicesServer)}.{nameof(ReceiveMessage)}"; - - IPEndPoint? endpoint = null; - NetworkStream? stream = null; - - new Thread(async () => - { - try - { - endpoint = client?.Client.RemoteEndPoint as IPEndPoint; - - stream = client?.GetStream(); - - if (endpoint is null || stream is null) return; - - while (keepListen) - { - var buffer = new byte[Instances.ConfigManager.AppConfig.Web.SocketBufferSize]; - - var length = await stream.ReadAsync(buffer); - - if (length > 0) - { - onReceive?.Invoke(buffer, length, endpoint.ToString()); - - var msg = buffer.ToUTF8(0, length); - - Log.Information($"From: {endpoint}\tReceive: {msg}"); - } - else break; // 客户端断开连接 跳出循环 - } - } - catch (Exception ex) - { - Log.Error($"In {location}: {ex.Message}"); - Log.Information($"Connection broke from: {endpoint}"); - } - finally - { - if (endpoint is not null) - { - clients.Remove(endpoint.ToString()); - } - - stream?.CloseAndDispose(); - - client?.CloseAndDispose(); - } - }).Start(); - } - - public async Task Broadcast(byte[] content) - { - var location = $"{nameof(DevicesServer)}.{nameof(Broadcast)}"; - - await TasksManager.RunTaskAsync(() => - { - foreach (var client in clients) - client.Value.Client.Send(content); - }, location, catchException: true); - - return this; - } - - public async Task BroadCast(byte[] content, Func? pattern) - { - var location = $"{nameof(DevicesServer)}.{nameof(BroadCast)}"; - - await TasksManager.RunTaskAsync(() => - { - foreach (var client in clients) - { - if (pattern is not null && pattern.Invoke(client.Value)) - client.Value.Client.Send(content); - else client.Value.Client.Send(content); - } - }, location, catchException: true); - - return this; - } - - public async Task Send(byte[] content, string target) - { - var location = $"{nameof(DevicesServer)}.{nameof(Send)}"; - - await TasksManager.RunTaskAsync(() => - { - if (clients.TryGetValue(target, out var client)) - client.Client.Send(content); - }, location, catchException: true); - - return this; - } - - public DevicesServer OnReceive(Action action) - { - onReceive = action; - - return this; - } - - public async Task Start() - { - var location = $"{nameof(DevicesServer)}.{nameof(Start)}"; - - if (Status != ServerStatus.Pending) return this; - - await TasksManager.RunTaskAsync(() => - { - Status = ServerStatus.Starting; - - Init(); - - if (listener is null) return; - - listener.Start(); - - var port = ((IPEndPoint)listener.LocalEndpoint).Port; // 取服务端口号 - - ConstantTable.DevicesServerPort = port; // 全局端口号标明 - ConstantTable.ServerBuildTime = DateTime.UtcNow; - ConstantTable.IsMainMachine = true; - - Log.Information($"DevicesServer Port: {port}"); - - EventService.Invoke(nameof(EventService.DevicesServerPortChanged)); - - new Thread(AcceptClient).Start(); - - Status = ServerStatus.Running; - - }, location, catchException: true); - - return this; - } - - public async Task Stop() - { - var location = $"{nameof(DevicesServer)}.{nameof(Stop)}"; - - if (Status != ServerStatus.Running) return this; - - await TasksManager.RunTaskAsync(() => - { - Status = ServerStatus.Stopping; - - listener?.Stop(); - - keepListen = false; - - foreach (KeyValuePair item in clients) - { - item.Value.Close(); - item.Value.Dispose(); - } - - clients.Clear(); - - ConstantTable.IsMainMachine = false; - ConstantTable.DevicesServerPort = -1; - - EventService.Invoke(nameof(EventService.DevicesServerPortChanged)); - - Status = ServerStatus.Pending; - - }, location, catchException: true); - - return this; - } - - public async Task Restart() - { - var location = $"{nameof(DevicesServer)}.{nameof(Restart)}"; - - await TasksManager.RunTaskAsync(async () => - { - await Stop(); - - await Start(); - - }, location); - - return this; - } - - public void Dispose() - { - if (disposed) return; - - disposed = true; - - GC.SuppressFinalize(this); - } -} diff --git a/KitX Dashboard/Network/NetworkHelper.cs b/KitX Dashboard/Network/NetworkHelper.cs index b72f131c..425fe2ca 100644 --- a/KitX Dashboard/Network/NetworkHelper.cs +++ b/KitX Dashboard/Network/NetworkHelper.cs @@ -1,6 +1,8 @@ using Common.BasicHelper.Core.Shell; using Common.BasicHelper.Utils.Extensions; +using KitX.Dashboard.Configuration; using KitX.Dashboard.Converters; +using KitX.Dashboard.Managers; using KitX.Dashboard.Views; using KitX.Shared.Device; using Serilog; @@ -21,7 +23,7 @@ internal static bool CheckNetworkInterface IPInterfaceProperties adapterProperties ) { - var userPointed = Instances.ConfigManager.AppConfig.Web.AcceptedNetworkInterfaces; + var userPointed = ConfigManager.Instance.AppConfig.Web.AcceptedNetworkInterfaces; if (userPointed is not null) if (userPointed.Contains(adapter.Name)) @@ -68,7 +70,7 @@ from ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList where ip.AddressFamily == AddressFamily.InterNetwork && IsInterNetworkAddressV4(ip) && !ip.ToString().Equals("127.0.0.1") - && ip.ToString().StartsWith(Instances.ConfigManager.AppConfig.Web.IPFilter) + && ip.ToString().StartsWith(ConfigManager.Instance.AppConfig.Web.IPFilter) select ip; Log.Information($"IPv4 addresses: {search.Print(print: false)}"); @@ -145,7 +147,7 @@ from nic in NetworkInterface.GetAllNetworkInterfaces() try { - switch (OperatingSystem2Enum.GetOSType()) + switch (OperatingSystemUtils.GetOSType()) { case OperatingSystems.Linux: @@ -216,7 +218,7 @@ from nic in NetworkInterface.GetAllNetworkInterfaces() }, IsMainDevice = ConstantTable.IsMainMachine, SendTime = DateTime.UtcNow, - DeviceOSType = OperatingSystem2Enum.GetOSType(), + DeviceOSType = OperatingSystemUtils.GetOSType(), DeviceOSVersion = TryGetOSVersionString() ?? "", PluginsServerPort = ConstantTable.PluginsServerPort, DevicesServerPort = ConstantTable.DevicesServerPort, diff --git a/KitX Dashboard/Network/PluginsNetwork/PluginConnector.cs b/KitX Dashboard/Network/PluginsNetwork/PluginConnector.cs index 23f849c3..3c543af8 100644 --- a/KitX Dashboard/Network/PluginsNetwork/PluginConnector.cs +++ b/KitX Dashboard/Network/PluginsNetwork/PluginConnector.cs @@ -111,7 +111,7 @@ public PluginConnector Run() try { if (PluginInfo is not null) - ViewInstances.PluginInfos.Remove(PluginInfo.Value); + ViewInstances.PluginInfos.Remove(PluginInfo); } catch (Exception e) { @@ -137,15 +137,15 @@ public PluginConnector Run() ArgumentNullException.ThrowIfNull(PluginInfo, nameof(PluginInfo)); - ArgumentNullException.ThrowIfNull(PluginInfo.Value.Tags, nameof(PluginInfo.Value.Tags)); + ArgumentNullException.ThrowIfNull(PluginInfo.Tags, nameof(PluginInfo.Tags)); - PluginInfo.Value.Tags.Add(nameof(ConnectionId), ConnectionId ?? string.Empty); - PluginInfo.Value.Tags.Add( + PluginInfo.Tags.Add(nameof(ConnectionId), ConnectionId ?? string.Empty); + PluginInfo.Tags.Add( nameof(PluginTagsNames.JoinTime), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss(FF)") ); - ViewInstances.PluginInfos.Add(PluginInfo.Value); + ViewInstances.PluginInfos.Add(PluginInfo); Log.Information($"In {location}: New plugin registered with {body.Replace("\r", "").Replace("\n", "")}"); @@ -167,7 +167,7 @@ public PluginConnector Run() try { if (PluginInfo is not null) - ViewInstances.PluginInfos.Remove(PluginInfo.Value); + ViewInstances.PluginInfos.Remove(PluginInfo); } catch (Exception e) { diff --git a/KitX Dashboard/Network/PluginsNetwork/PluginsServer.cs b/KitX Dashboard/Network/PluginsNetwork/PluginsServer.cs index c1f3c5a5..a7506b11 100644 --- a/KitX Dashboard/Network/PluginsNetwork/PluginsServer.cs +++ b/KitX Dashboard/Network/PluginsNetwork/PluginsServer.cs @@ -13,7 +13,7 @@ public class PluginsServer : ConfigFetcher { private static PluginsServer? _pluginsServer; - public static PluginsServer Instance => _pluginsServer ??= new PluginsServer(); + public static PluginsServer Instance => _pluginsServer ??= new(); private WebSocketServer? _server; @@ -54,7 +54,7 @@ public PluginsServer Run() public PluginConnector? FindConnector(PluginInfo info) { var query = PluginConnectors.Where( - x => x.PluginInfo.HasValue && x.PluginInfo.Value.Equals(info) + x => x.PluginInfo is not null && x.PluginInfo.Equals(info) ); if (query.Any()) diff --git a/KitX Dashboard/Services/EventService.cs b/KitX Dashboard/Services/EventService.cs index 5fc2be6d..b9381195 100644 --- a/KitX Dashboard/Services/EventService.cs +++ b/KitX Dashboard/Services/EventService.cs @@ -67,14 +67,14 @@ public static void Invoke(string eventName, object[]? objects = null) public static event UseStatisticsChangedHandler UseStatisticsChanged = new(() => { }); - public delegate void PluginsServerPortChangedHandler(int port); + public delegate void DevicesServerPortChangedHandler(int port); - public static event PluginsServerPortChangedHandler PluginsServerPortChanged = new(port => ConstantTable.PluginsServerPort = port); + public static event DevicesServerPortChangedHandler DevicesServerPortChanged = new(port => ConstantTable.DevicesServerPort = port); - public delegate void DevicesServerPortChangedHandler(); + public delegate void PluginsServerPortChangedHandler(int port); - public static event DevicesServerPortChangedHandler DevicesServerPortChanged = new(() => { }); + public static event PluginsServerPortChangedHandler PluginsServerPortChanged = new(port => ConstantTable.PluginsServerPort = port); public delegate void OnActivitiesUpdatedHandler(); diff --git a/KitX Dashboard/ViewModels/AnouncementsWindowViewModel.cs b/KitX Dashboard/ViewModels/AnouncementsWindowViewModel.cs index 94e3b690..ce0930a2 100644 --- a/KitX Dashboard/ViewModels/AnouncementsWindowViewModel.cs +++ b/KitX Dashboard/ViewModels/AnouncementsWindowViewModel.cs @@ -1,5 +1,4 @@ -using Avalonia; -using FluentAvalonia.UI.Controls; +using FluentAvalonia.UI.Controls; using KitX.Dashboard.Configuration; using KitX.Dashboard.Views; using ReactiveUI; @@ -12,8 +11,6 @@ namespace KitX.Dashboard.ViewModels; internal class AnouncementsWindowViewModel : ViewModelBase, INotifyPropertyChanged { - public new event PropertyChangedEventHandler? PropertyChanged; - public AnouncementsWindowViewModel() { InitCommands(); @@ -23,7 +20,7 @@ public override void InitCommands() { ConfirmReceivedCommand = ReactiveCommand.Create(() => { - var config = Instances.ConfigManager.AnnouncementConfig; + var config = AnnouncementConfig; var accepted = config.Accepted; @@ -60,7 +57,7 @@ public override void InitCommands() ConfirmReceivedAllCommand = ReactiveCommand.Create(() => { - var config = Instances.ConfigManager.AnnouncementConfig; + var config = AnnouncementConfig; var accepted = config.Accepted; @@ -119,10 +116,7 @@ internal NavigationViewItem? SelectedMenuItem Markdown = Sources[key]; - PropertyChanged?.Invoke( - this, - new(nameof(SelectedMenuItem)) - ); + this.RaiseAndSetIfChanged(ref selectedMenuItem, value); } } @@ -131,14 +125,7 @@ internal NavigationViewItem? SelectedMenuItem internal string Markdown { get => markdown; - set - { - markdown = value; - PropertyChanged?.Invoke( - this, - new(nameof(Markdown)) - ); - } + set => this.RaiseAndSetIfChanged(ref markdown, value); } private Dictionary sources = []; diff --git a/KitX Dashboard/ViewModels/AppViewModel.cs b/KitX Dashboard/ViewModels/AppViewModel.cs index b659e315..6db3d74b 100644 --- a/KitX Dashboard/ViewModels/AppViewModel.cs +++ b/KitX Dashboard/ViewModels/AppViewModel.cs @@ -34,7 +34,7 @@ public override void InitCommands() win?.Activate(); - Instances.ConfigManager.AppConfig.Windows.MainWindow.IsHidden = false; + ConfigManager.Instance.AppConfig.Windows.MainWindow.IsHidden = false; SaveAppConfigChanges(); }); @@ -64,7 +64,7 @@ public override void InitCommands() ExitCommand = ReactiveCommand.Create(() => { - ViewInstances.DeviceCards.Clear(); + ViewInstances.DeviceCases.Clear(); ViewInstances.PluginInfos.Clear(); @@ -80,13 +80,13 @@ public override void InitCommands() public override void InitEvents() { - ViewInstances.DeviceCards.CollectionChanged += (_, _) => UpdateTrayIconText(); + ViewInstances.DeviceCases.CollectionChanged += (_, _) => UpdateTrayIconText(); ViewInstances.PluginInfos.CollectionChanged += (_, _) => UpdateTrayIconText(); - EventService.DevicesServerPortChanged += UpdateTrayIconText; + EventService.DevicesServerPortChanged += _ => UpdateTrayIconText(); - EventService.DevicesServerPortChanged += UpdateTrayIconText; + EventService.PluginsServerPortChanged += _ => UpdateTrayIconText(); } private void UpdateTrayIconText() @@ -100,7 +100,7 @@ private void UpdateTrayIconText() .Append(Translate("Text_Settings_Performence_Web_PluginsServerPort")) .AppendLine(": " + ConstantTable.PluginsServerPort) .AppendLine() - .Append(ViewInstances.DeviceCards.Count + " ") + .Append(ViewInstances.DeviceCases.Count + " ") .AppendLine(Translate("Text_Device_Tip_Detected")) .Append(ViewInstances.PluginInfos.Count + " ") .AppendLine(Translate("Text_Lib_Tip_Connected")) diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Home_CountViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Home_CountViewModel.cs index e4409651..76f655a8 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Home_CountViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Home_CountViewModel.cs @@ -93,10 +93,10 @@ internal double NoCount_TipHeight internal bool UseAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Home.UseAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Home.UseAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Home.UseAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Home.UseAreaExpanded = value; PropertyChanged?.Invoke( this, diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Home_RecentUseViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Home_RecentUseViewModel.cs index b8a8f483..ead595ec 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Home_RecentUseViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Home_RecentUseViewModel.cs @@ -13,7 +13,7 @@ public Home_RecentUseViewModel() public double NoRecent_TipHeight { get; set; } = 200; - public ObservableCollection RecentPlugins { get; } = []; + public ObservableCollection RecentPlugins { get; } = []; public override void InitCommands() => throw new System.NotImplementedException(); diff --git a/KitX Dashboard/ViewModels/Pages/Controls/PluginBarViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/PluginBarViewModel.cs index 50bae5c4..019775fc 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/PluginBarViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/PluginBarViewModel.cs @@ -2,7 +2,6 @@ using Avalonia.Media.Imaging; using Common.BasicHelper.Utils.Extensions; using KitX.Dashboard.Models; -using KitX.Dashboard.Network; using KitX.Dashboard.Network.DevicesNetwork; using KitX.Dashboard.Services; using KitX.Dashboard.Views; @@ -11,7 +10,6 @@ using Serilog; using System; using System.Collections.ObjectModel; -using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reactive; @@ -19,10 +17,8 @@ namespace KitX.Dashboard.ViewModels.Pages.Controls; -internal class PluginBarViewModel : ViewModelBase, INotifyPropertyChanged +internal class PluginBarViewModel : ViewModelBase { - public new event PropertyChangedEventHandler? PropertyChanged; - public PluginBarViewModel() { InitCommands(); @@ -33,18 +29,18 @@ public override void InitCommands() { ViewDetailsCommand = ReactiveCommand.Create(() => { - if (PluginDetail is not null && ViewInstances.MainWindow is not null) + if (Plugin is not null && ViewInstances.MainWindow is not null) new PluginDetailWindow() { WindowStartupLocation = WindowStartupLocation.CenterOwner } - .SetPluginInfo(PluginDetail.PluginDetails) + .SetPluginInfo(Plugin.PluginInfo) .Show(ViewInstances.MainWindow); }); RemoveCommand = ReactiveCommand.Create(() => { - if (PluginDetail is not null && PluginBar is not null) + if (Plugin is not null && PluginBar is not null) { PluginBars?.Remove(PluginBar); @@ -54,7 +50,7 @@ public override void InitCommands() DeleteCommand = ReactiveCommand.Create(() => { - if (PluginDetail is not null && PluginBar is not null) + if (Plugin is not null && PluginBar is not null) { PluginBars?.Remove(PluginBar); //PluginsNetwork.RequireDeletePlugin(PluginDetail); @@ -65,28 +61,30 @@ public override void InitCommands() { var location = $"{nameof(PluginBarViewModel)}.{nameof(LaunchCommand)}"; + if (Plugin?.LoaderInfo is null) return; + new Thread(() => { try { - var loaderName = PluginDetail?.RequiredLoaderInfo.LoaderName; - var loaderVersion = PluginDetail?.RequiredLoaderInfo.LoaderVersion; - var pd = PluginDetail?.PluginDetails; + var loaderName = Plugin?.LoaderInfo.LoaderName; + var loaderVersion = Plugin?.LoaderInfo.LoaderVersion; + var pd = Plugin?.PluginInfo; - var pluginPath = $"{PluginDetail?.InstallPath}/{pd?.RootStartupFileName}"; + var pluginPath = $"{Plugin?.InstallPath}/{pd?.RootStartupFileName}"; var pluginFile = pluginPath.GetFullPath(); var connectStr = "ws://" + - $"{DevicesDiscoveryServer.DefaultDeviceInfo.Device.IPv4}" + + $"{DevicesDiscoveryServer.Instance.DefaultDeviceInfo.Device.IPv4}" + $":" + $"{ConstantTable.PluginsServerPort}/"; - if (PluginDetail is null) return; + if (Plugin is null) return; - if (PluginDetail.RequiredLoaderInfo.SelfLoad) + if (Plugin.LoaderInfo.SelfLoad) Process.Start(pluginFile, $"--connect {connectStr}"); else { - var loaderFile = $"{Instances.ConfigManager.AppConfig.Loaders.InstallPath}/" + + var loaderFile = $"{AppConfig.Loaders.InstallPath}/" + $"{loaderName}/{loaderVersion}/{loaderName}"; if (OperatingSystem.IsWindows()) @@ -116,31 +114,28 @@ public override void InitCommands() public override void InitEvents() { - EventService.LanguageChanged += () => - { - PropertyChanged?.Invoke(this, new(nameof(DisplayName))); - }; + EventService.LanguageChanged += () => this.RaisePropertyChanged(nameof(DisplayName)); } internal PluginBar? PluginBar { get; set; } - internal Plugin? PluginDetail { get; set; } + internal PluginInstallation? Plugin { get; set; } internal string? DisplayName { get { - if (PluginDetail is null) return null; + if (Plugin is null) return null; - return PluginDetail.PluginDetails.DisplayName.TryGetValue( - Instances.ConfigManager.AppConfig.App.AppLanguage, out var lang - ) ? lang : PluginDetail.PluginDetails.DisplayName.Values.GetEnumerator().Current; + return Plugin.PluginInfo.DisplayName.TryGetValue( + AppConfig.App.AppLanguage, out var lang + ) ? lang : Plugin.PluginInfo.DisplayName.Values.GetEnumerator().Current; } } - internal string? AuthorName => PluginDetail?.PluginDetails.AuthorName; + internal string? AuthorName => Plugin?.PluginInfo.AuthorName; - internal string? Version => PluginDetail?.PluginDetails.Version; + internal string? Version => Plugin?.PluginInfo.Version; internal ObservableCollection? PluginBars { get; set; } @@ -152,9 +147,9 @@ internal Bitmap IconDisplay try { - if (PluginDetail is null) return App.DefaultIcon; + if (Plugin is null) return App.DefaultIcon; - var src = Convert.FromBase64String(PluginDetail.PluginDetails.IconInBase64); + var src = Convert.FromBase64String(Plugin.PluginInfo.IconInBase64); using var ms = new MemoryStream(src); diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Settings_AboutViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Settings_AboutViewModel.cs index 4dc1d19c..3b0c97c4 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Settings_AboutViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Settings_AboutViewModel.cs @@ -66,40 +66,40 @@ internal string ThirdPartyLicenseString public static bool AboutAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.AboutAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.AboutAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.AboutAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.AboutAreaExpanded = value; SaveAppConfigChanges(); } } public static bool AuthorsAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.AuthorsAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.AuthorsAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.AuthorsAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.AuthorsAreaExpanded = value; SaveAppConfigChanges(); } } public static bool LinksAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.LinksAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.LinksAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.LinksAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.LinksAreaExpanded = value; SaveAppConfigChanges(); } } public static bool ThirdPartyLicensesAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.ThirdPartyLicensesAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.ThirdPartyLicensesAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.ThirdPartyLicensesAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.ThirdPartyLicensesAreaExpanded = value; SaveAppConfigChanges(); } } diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Settings_GeneralViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Settings_GeneralViewModel.cs index 7b05d2d5..8ccb91c1 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Settings_GeneralViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Settings_GeneralViewModel.cs @@ -56,45 +56,45 @@ public override void InitEvents() internal static string LocalPluginsFileDirectory { - get => Instances.ConfigManager.AppConfig.App.LocalPluginsFileFolder; + get => ConfigManager.Instance.AppConfig.App.LocalPluginsFileFolder; set { - Instances.ConfigManager.AppConfig.App.LocalPluginsFileFolder = value; + ConfigManager.Instance.AppConfig.App.LocalPluginsFileFolder = value; SaveAppConfigChanges(); } } internal static string LocalPluginsDataDirectory { - get => Instances.ConfigManager.AppConfig.App.LocalPluginsDataFolder; + get => ConfigManager.Instance.AppConfig.App.LocalPluginsDataFolder; set { - Instances.ConfigManager.AppConfig.App.LocalPluginsDataFolder = value; + ConfigManager.Instance.AppConfig.App.LocalPluginsDataFolder = value; SaveAppConfigChanges(); } } internal static int ShowAnnouncementsStatus { - get => Instances.ConfigManager.AppConfig.App.ShowAnnouncementWhenStart ? 0 : 1; + get => ConfigManager.Instance.AppConfig.App.ShowAnnouncementWhenStart ? 0 : 1; set { - Instances.ConfigManager.AppConfig.App.ShowAnnouncementWhenStart = value == 0; + ConfigManager.Instance.AppConfig.App.ShowAnnouncementWhenStart = value == 0; SaveAppConfigChanges(); } } internal static bool DeveloperSettingEnabled { - get => Instances.ConfigManager.AppConfig.App.DeveloperSetting; + get => ConfigManager.Instance.AppConfig.App.DeveloperSetting; } internal static int DeveloperSettingStatus { - get => Instances.ConfigManager.AppConfig.App.DeveloperSetting ? 0 : 1; + get => ConfigManager.Instance.AppConfig.App.DeveloperSetting ? 0 : 1; set { - Instances.ConfigManager.AppConfig.App.DeveloperSetting = value == 0; + ConfigManager.Instance.AppConfig.App.DeveloperSetting = value == 0; EventService.Invoke(nameof(EventService.DevelopSettingsChanged)); SaveAppConfigChanges(); } diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Settings_PerformenceViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Settings_PerformenceViewModel.cs index af480f9e..52d186fd 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Settings_PerformenceViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Settings_PerformenceViewModel.cs @@ -38,7 +38,7 @@ public override void InitCommands() Task.Run(() => { var dir = new DirectoryInfo( - Instances.ConfigManager.AppConfig.Log.LogFilePath.GetFullPath() + ConfigManager.Instance.AppConfig.Log.LogFilePath.GetFullPath() ); foreach (var file in dir.GetFiles()) @@ -71,24 +71,24 @@ public override void InitEvents() { EventService.LogConfigUpdated += () => { - var logdir = Instances.ConfigManager.AppConfig.Log.LogFilePath.GetFullPath(); + var logdir = ConfigManager.Instance.AppConfig.Log.LogFilePath.GetFullPath(); Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File( $"{logdir}Log_.log", - outputTemplate: Instances.ConfigManager.AppConfig.Log.LogTemplate, + outputTemplate: ConfigManager.Instance.AppConfig.Log.LogTemplate, rollingInterval: RollingInterval.Hour, - fileSizeLimitBytes: Instances.ConfigManager.AppConfig.Log.LogFileSingleMaxSize, + fileSizeLimitBytes: ConfigManager.Instance.AppConfig.Log.LogFileSingleMaxSize, buffered: true, flushToDiskInterval: new( 0, 0, - Instances.ConfigManager.AppConfig.Log.LogFileFlushInterval + ConfigManager.Instance.AppConfig.Log.LogFileFlushInterval ), - restrictedToMinimumLevel: Instances.ConfigManager.AppConfig.Log.LogLevel, + restrictedToMinimumLevel: ConfigManager.Instance.AppConfig.Log.LogLevel, rollOnFileSizeLimit: true, - retainedFileCountLimit: Instances.ConfigManager.AppConfig.Log.LogFileMaxCount + retainedFileCountLimit: ConfigManager.Instance.AppConfig.Log.LogFileMaxCount ) .CreateLogger(); }; @@ -104,12 +104,12 @@ public override void InitEvents() ); }; - EventService.DevicesServerPortChanged += () => PropertyChanged?.Invoke( + EventService.DevicesServerPortChanged += _ => PropertyChanged?.Invoke( this, new(nameof(DevicesServerPort)) ); - EventService.PluginsServerPortChanged += port => PropertyChanged?.Invoke( + EventService.PluginsServerPortChanged += _ => PropertyChanged?.Invoke( this, new(nameof(PluginsServerPort)) ); @@ -170,10 +170,10 @@ public override void InitEvents() internal static double DelayedWebStartSeconds { - get => Instances.ConfigManager.AppConfig.Web.DelayStartSeconds; + get => ConfigManager.Instance.AppConfig.Web.DelayStartSeconds; set { - Instances.ConfigManager.AppConfig.Web.DelayStartSeconds = value; + ConfigManager.Instance.AppConfig.Web.DelayStartSeconds = value; SaveAppConfigChanges(); } } @@ -182,13 +182,13 @@ internal static double DelayedWebStartSeconds internal int PluginsServerPortType { - get => Instances.ConfigManager.AppConfig.Web.UserSpecifiedPluginsServerPort is null ? 0 : 1; + get => ConfigManager.Instance.AppConfig.Web.UserSpecifiedPluginsServerPort is null ? 0 : 1; set { if (value == 0) - Instances.ConfigManager.AppConfig.Web.UserSpecifiedPluginsServerPort = null; + ConfigManager.Instance.AppConfig.Web.UserSpecifiedPluginsServerPort = null; else - Instances.ConfigManager.AppConfig.Web.UserSpecifiedPluginsServerPort = PluginsServerPort; + ConfigManager.Instance.AppConfig.Web.UserSpecifiedPluginsServerPort = PluginsServerPort; PropertyChanged?.Invoke( this, @@ -205,7 +205,7 @@ internal static int PluginsServerPort set { if (value >= 0 && value <= 65535) - Instances.ConfigManager.AppConfig.Web.UserSpecifiedPluginsServerPort = value; + ConfigManager.Instance.AppConfig.Web.UserSpecifiedPluginsServerPort = value; } } @@ -213,10 +213,10 @@ internal static int PluginsServerPort internal static string LocalIPFilter { - get => Instances.ConfigManager.AppConfig.Web.IPFilter; + get => ConfigManager.Instance.AppConfig.Web.IPFilter; set { - Instances.ConfigManager.AppConfig.Web.IPFilter = value; + ConfigManager.Instance.AppConfig.Web.IPFilter = value; SaveAppConfigChanges(); } } @@ -225,7 +225,7 @@ internal static string AcceptedNetworkInterfacesNames { get { - var userPointed = Instances.ConfigManager.AppConfig.Web.AcceptedNetworkInterfaces; + var userPointed = ConfigManager.Instance.AppConfig.Web.AcceptedNetworkInterfaces; if (userPointed is null) return "Auto"; @@ -235,12 +235,12 @@ internal static string AcceptedNetworkInterfacesNames set { if (value.ToLower().Equals("auto")) - Instances.ConfigManager.AppConfig.Web.AcceptedNetworkInterfaces = null; + ConfigManager.Instance.AppConfig.Web.AcceptedNetworkInterfaces = null; else { var userInput = value.Split(';'); - Instances.ConfigManager.AppConfig.Web.AcceptedNetworkInterfaces = [.. userInput]; + ConfigManager.Instance.AppConfig.Web.AcceptedNetworkInterfaces = [.. userInput]; } } } @@ -251,20 +251,20 @@ internal static string AcceptedNetworkInterfacesNames internal static int DevicesListRefreshDelay { - get => Instances.ConfigManager.AppConfig.Web.DevicesViewRefreshDelay; + get => ConfigManager.Instance.AppConfig.Web.DevicesViewRefreshDelay; set { - Instances.ConfigManager.AppConfig.Web.DevicesViewRefreshDelay = value; + ConfigManager.Instance.AppConfig.Web.DevicesViewRefreshDelay = value; SaveAppConfigChanges(); } } internal static int GreetingTextUpdateInterval { - get => Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingUpdateInterval; + get => ConfigManager.Instance.AppConfig.Windows.MainWindow.GreetingUpdateInterval; set { - Instances.ConfigManager.AppConfig.Windows.MainWindow.GreetingUpdateInterval = value; + ConfigManager.Instance.AppConfig.Windows.MainWindow.GreetingUpdateInterval = value; EventService.Invoke(nameof(EventService.GreetingTextIntervalUpdated)); SaveAppConfigChanges(); } @@ -272,53 +272,53 @@ internal static int GreetingTextUpdateInterval internal static bool WebRelatedAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.WebRelatedAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.WebRelatedAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.WebRelatedAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.WebRelatedAreaExpanded = value; SaveAppConfigChanges(); } } internal static bool WebRelatedAreaOfNetworkInterfacesExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.WebRelatedAreaOfNetworkInterfacesExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.WebRelatedAreaOfNetworkInterfacesExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.WebRelatedAreaOfNetworkInterfacesExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.WebRelatedAreaOfNetworkInterfacesExpanded = value; SaveAppConfigChanges(); } } internal static bool LogRelatedAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.LogRelatedAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.LogRelatedAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.LogRelatedAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.LogRelatedAreaExpanded = value; SaveAppConfigChanges(); } } internal static bool UpdateRelatedAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.UpdateRelatedAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.UpdateRelatedAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.UpdateRelatedAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.UpdateRelatedAreaExpanded = value; SaveAppConfigChanges(); } } internal static int LogFileSizeUsage - => (int)(Instances.ConfigManager.AppConfig.Log.LogFilePath.GetTotalSize() / 1000 / 1024); + => (int)(ConfigManager.Instance.AppConfig.Log.LogFilePath.GetTotalSize() / 1000 / 1024); internal static int LogFileSizeLimit { - get => (int)(Instances.ConfigManager.AppConfig.Log.LogFileSingleMaxSize / 1024 / 1024); + get => (int)(ConfigManager.Instance.AppConfig.Log.LogFileSingleMaxSize / 1024 / 1024); set { - Instances.ConfigManager.AppConfig.Log.LogFileSingleMaxSize = value * 1024 * 1024; + ConfigManager.Instance.AppConfig.Log.LogFileSingleMaxSize = value * 1024 * 1024; EventService.Invoke(nameof(EventService.LogConfigUpdated)); SaveAppConfigChanges(); } @@ -326,10 +326,10 @@ internal static int LogFileSizeLimit internal static int LogFileMaxCount { - get => Instances.ConfigManager.AppConfig.Log.LogFileMaxCount; + get => ConfigManager.Instance.AppConfig.Log.LogFileMaxCount; set { - Instances.ConfigManager.AppConfig.Log.LogFileMaxCount = value; + ConfigManager.Instance.AppConfig.Log.LogFileMaxCount = value; EventService.Invoke(nameof(EventService.LogConfigUpdated)); SaveAppConfigChanges(); } @@ -337,10 +337,10 @@ internal static int LogFileMaxCount internal static int LogFileFlushInterval { - get => Instances.ConfigManager.AppConfig.Log.LogFileFlushInterval; + get => ConfigManager.Instance.AppConfig.Log.LogFileFlushInterval; set { - Instances.ConfigManager.AppConfig.Log.LogFileFlushInterval = value; + ConfigManager.Instance.AppConfig.Log.LogFileFlushInterval = value; EventService.Invoke(nameof(EventService.LogConfigUpdated)); SaveAppConfigChanges(); } @@ -348,10 +348,10 @@ internal static int LogFileFlushInterval internal static int CheckerPerThreadFilesCountLimit { - get => Instances.ConfigManager.AppConfig.IO.UpdatingCheckPerThreadFilesCount; + get => ConfigManager.Instance.AppConfig.IO.UpdatingCheckPerThreadFilesCount; set { - Instances.ConfigManager.AppConfig.IO.UpdatingCheckPerThreadFilesCount = value; + ConfigManager.Instance.AppConfig.IO.UpdatingCheckPerThreadFilesCount = value; SaveAppConfigChanges(); } } @@ -399,7 +399,7 @@ internal static int CheckerPerThreadFilesCountLimit ]; private SupportedLogLevel? _currentLogLevel = SupportedLogLevels.Find( - x => x.LogEventLevel == Instances.ConfigManager.AppConfig.Log.LogLevel + x => x.LogEventLevel == ConfigManager.Instance.AppConfig.Log.LogLevel ); internal SupportedLogLevel? CurrentLogLevel @@ -411,7 +411,7 @@ internal SupportedLogLevel? CurrentLogLevel if (value is not null) { - Instances.ConfigManager.AppConfig.Log.LogLevel = value.LogEventLevel; + ConfigManager.Instance.AppConfig.Log.LogLevel = value.LogEventLevel; EventService.Invoke(nameof(EventService.LogConfigUpdated)); diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Settings_PersonaliseViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Settings_PersonaliseViewModel.cs index f8268171..514f7892 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Settings_PersonaliseViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Settings_PersonaliseViewModel.cs @@ -61,7 +61,7 @@ await Dispatcher.UIThread.InvokeAsync(() => ); }); - Instances.ConfigManager.AppConfig.App.ThemeColor = themeColor.ToHexString(); + ConfigManager.Instance.AppConfig.App.ThemeColor = themeColor.ToHexString(); SaveAppConfigChanges(); }); @@ -75,7 +75,7 @@ public override void InitEvents() { EventService.DevelopSettingsChanged += () => { - MicaOpacityConfirmButtonVisibility = Instances.ConfigManager.AppConfig.App.DeveloperSetting; + MicaOpacityConfirmButtonVisibility = ConfigManager.Instance.AppConfig.App.DeveloperSetting; }; EventService.LanguageChanged += () => @@ -84,7 +84,7 @@ public override void InitEvents() item.ThemeDisplayName = GetThemeDisplayText(item.ThemeName); _currentAppTheme = SupportedThemes.Find( - x => x.ThemeName.Equals(Instances.ConfigManager.AppConfig.App.Theme) + x => x.ThemeName.Equals(ConfigManager.Instance.AppConfig.App.Theme) ); PropertyChanged?.Invoke( @@ -98,7 +98,7 @@ private void InitData() { SupportedLanguages.Clear(); - foreach (var item in Instances.ConfigManager.AppConfig.App.SurpportLanguages) + foreach (var item in ConfigManager.Instance.AppConfig.App.SurpportLanguages) SupportedLanguages.Add(new SupportedLanguage() { LanguageCode = item.Key, @@ -106,7 +106,7 @@ private void InitData() }); LanguageSelected = SupportedLanguages.FindIndex( - x => x.LanguageCode.Equals(Instances.ConfigManager.AppConfig.App.AppLanguage) + x => x.LanguageCode.Equals(ConfigManager.Instance.AppConfig.App.AppLanguage) ); } @@ -147,7 +147,7 @@ internal Color2 ThemeColor ]; private SupportedTheme? _currentAppTheme = SupportedThemes.Find( - x => x.ThemeName.Equals(Instances.ConfigManager.AppConfig.App.Theme) + x => x.ThemeName.Equals(ConfigManager.Instance.AppConfig.App.Theme) ); internal SupportedTheme? CurrentAppTheme @@ -159,7 +159,7 @@ internal SupportedTheme? CurrentAppTheme if (value is null) return; - Instances.ConfigManager.AppConfig.App.Theme = value.ThemeName; + ConfigManager.Instance.AppConfig.App.Theme = value.ThemeName; if (Application.Current is null) return; @@ -182,7 +182,7 @@ internal static void LoadLanguage() { var location = $"{nameof(Settings_PersonaliseViewModel)}.{nameof(LoadLanguage)}"; - var lang = Instances.ConfigManager.AppConfig.App.AppLanguage; + var lang = ConfigManager.Instance.AppConfig.App.AppLanguage; if (Application.Current is null) return; @@ -219,7 +219,7 @@ internal int LanguageSelected { try { - Instances.ConfigManager.AppConfig.App.AppLanguage = SupportedLanguages[value].LanguageCode; + ConfigManager.Instance.AppConfig.App.AppLanguage = SupportedLanguages[value].LanguageCode; if (languageSelected != -1) LoadLanguage(); @@ -236,37 +236,37 @@ internal int LanguageSelected internal static bool MicaAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.MicaAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.MicaAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.MicaAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.MicaAreaExpanded = value; SaveAppConfigChanges(); } } internal static int MicaStatus { - get => Instances.ConfigManager.AppConfig.Windows.MainWindow.EnabledMica ? 0 : 1; + get => ConfigManager.Instance.AppConfig.Windows.MainWindow.EnabledMica ? 0 : 1; set { - Instances.ConfigManager.AppConfig.Windows.MainWindow.EnabledMica = value != 1; + ConfigManager.Instance.AppConfig.Windows.MainWindow.EnabledMica = value != 1; SaveAppConfigChanges(); } } internal static bool MicaToolTipIsOpen { - get => Instances.ConfigManager.AppConfig.Pages.Settings.MicaToolTipIsOpen; + get => ConfigManager.Instance.AppConfig.Pages.Settings.MicaToolTipIsOpen; set { - Instances.ConfigManager.AppConfig.Pages.Settings.MicaToolTipIsOpen = value; + ConfigManager.Instance.AppConfig.Pages.Settings.MicaToolTipIsOpen = value; SaveAppConfigChanges(); } } internal bool MicaOpacityConfirmButtonVisibility { - get => Instances.ConfigManager.AppConfig.App.DeveloperSetting; + get => ConfigManager.Instance.AppConfig.App.DeveloperSetting; set => PropertyChanged?.Invoke( this, new(nameof(MicaOpacityConfirmButtonVisibility)) @@ -275,10 +275,10 @@ internal bool MicaOpacityConfirmButtonVisibility internal static bool PaletteAreaExpanded { - get => Instances.ConfigManager.AppConfig.Pages.Settings.PaletteAreaExpanded; + get => ConfigManager.Instance.AppConfig.Pages.Settings.PaletteAreaExpanded; set { - Instances.ConfigManager.AppConfig.Pages.Settings.PaletteAreaExpanded = value; + ConfigManager.Instance.AppConfig.Pages.Settings.PaletteAreaExpanded = value; SaveAppConfigChanges(); } } diff --git a/KitX Dashboard/ViewModels/Pages/Controls/Settings_UpdateViewModel.cs b/KitX Dashboard/ViewModels/Pages/Controls/Settings_UpdateViewModel.cs index 03906caa..55c3881a 100644 --- a/KitX Dashboard/ViewModels/Pages/Controls/Settings_UpdateViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/Controls/Settings_UpdateViewModel.cs @@ -1,11 +1,10 @@ -using Avalonia; -using Avalonia.Metadata; +using Avalonia.Metadata; using Avalonia.Threading; using Common.BasicHelper.Utils.Extensions; using Common.Update.Checker; using KitX.Dashboard.Converters; +using KitX.Dashboard.Models; using KitX.Dashboard.Network.DevicesNetwork; -using KitX.Dashboard.Services; using KitX.Shared.Device; using MsBox.Avalonia; using MsBox.Avalonia.Enums; @@ -14,7 +13,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.ComponentModel; using System.IO; using System.Linq; using System.Net.Http; @@ -22,15 +20,12 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Component = KitX.Dashboard.Models.Component; using Timer = System.Timers.Timer; namespace KitX.Dashboard.ViewModels.Pages.Controls; -internal class Settings_UpdateViewModel : ViewModelBase, INotifyPropertyChanged +internal class Settings_UpdateViewModel : ViewModelBase { - public new event PropertyChangedEventHandler? PropertyChanged; - private bool _canUpdateDataGridView = true; internal Settings_UpdateViewModel() @@ -54,7 +49,8 @@ public override void InitEvents() if (_canUpdateDataGridView) { CanUpdateCount = Components.Count(x => x.CanUpdate); - PropertyChanged?.Invoke(this, new(nameof(ComponentsCount))); + + this.RaisePropertyChanged(nameof(ComponentsCount)); } }; } @@ -64,15 +60,7 @@ public override void InitEvents() internal int CanUpdateCount { get => canUpdateCount; - set - { - canUpdateCount = value; - - PropertyChanged?.Invoke( - this, - new(nameof(CanUpdateCount)) - ); - } + set => this.RaiseAndSetIfChanged(ref canUpdateCount, value); } internal static int ComponentsCount { get => Components.Count; } @@ -84,11 +72,7 @@ internal int CanUpdateCount internal string? Tip { get => tip; - set - { - tip = value; - PropertyChanged?.Invoke(this, new(nameof(Tip))); - } + set => this.RaiseAndSetIfChanged(ref tip, value); } private string diskUseStatus = string.Empty; @@ -96,16 +80,12 @@ internal string? Tip internal string DiskUseStatus { get => diskUseStatus; - set - { - diskUseStatus = value; - PropertyChanged?.Invoke(this, new(nameof(DiskUseStatus))); - } + set => this.RaiseAndSetIfChanged(ref diskUseStatus, value); } public static int UpdateChannel { - get => Instances.ConfigManager.AppConfig.Web.UpdateChannel switch + get => AppConfig.Web.UpdateChannel switch { "stable" => 0, "beta" => 1, @@ -114,7 +94,7 @@ public static int UpdateChannel }; set { - Instances.ConfigManager.AppConfig.Web.UpdateChannel = value switch + AppConfig.Web.UpdateChannel = value switch { 0 => "stable", 1 => "beta", @@ -159,7 +139,7 @@ private Checker ScanComponents(string workbase) var checker = new Checker() .SetRootDirectory(wd) - .SetPerThreadFilesCount(Instances.ConfigManager.AppConfig.IO.UpdatingCheckPerThreadFilesCount) + .SetPerThreadFilesCount(AppConfig.IO.UpdatingCheckPerThreadFilesCount) .SetTransHash2String(true) .AppendIgnoreFolder("Config") .AppendIgnoreFolder("Core") @@ -169,10 +149,10 @@ private Checker ScanComponents(string workbase) .AppendIgnoreFolder("Update") .AppendIgnoreFolder("Loaders") .AppendIgnoreFolder("Plugins") - .AppendIgnoreFolder(Instances.ConfigManager.AppConfig.App.LocalPluginsFileFolder) - .AppendIgnoreFolder(Instances.ConfigManager.AppConfig.App.LocalPluginsDataFolder); + .AppendIgnoreFolder(AppConfig.App.LocalPluginsFileFolder) + .AppendIgnoreFolder(AppConfig.App.LocalPluginsDataFolder); - foreach (var item in Instances.ConfigManager.AppConfig.App.SurpportLanguages) + foreach (var item in AppConfig.App.SurpportLanguages) _ = checker.AppendIncludeFile($"{ld}/{item.Key}.axaml"); Tip = GetUpdateTip("Scan"); @@ -233,10 +213,10 @@ HttpClient client client.DefaultRequestHeaders.Accept.Clear(); // 清除请求头部 var link = "https://" + - Instances.ConfigManager.AppConfig.Web.UpdateServer + - Instances.ConfigManager.AppConfig.Web.UpdatePath.Replace( + AppConfig.Web.UpdateServer + + AppConfig.Web.UpdatePath.Replace( "%platform%", - DevicesDiscoveryServer.DefaultDeviceInfo.DeviceOSType switch + DevicesDiscoveryServer.Instance.DefaultDeviceInfo.DeviceOSType switch { OperatingSystems.Windows => "win", OperatingSystems.Linux => "linux", @@ -244,8 +224,8 @@ HttpClient client _ => "" } ) + - $"{Instances.ConfigManager.AppConfig.Web.UpdateChannel}/" + - Instances.ConfigManager.AppConfig.Web.UpdateSource; + $"{AppConfig.Web.UpdateChannel}/" + + AppConfig.Web.UpdateSource; var json = await client.GetStringAsync(link); @@ -404,10 +384,7 @@ private void UpdateFrontendViewAfterCompare { CanUpdateCount = Components.Count(x => x.CanUpdate); - PropertyChanged?.Invoke( - this, - new PropertyChangedEventArgs(nameof(Components)) - ); + this.RaisePropertyChanged(nameof(Components)); } while (Components.Count != result.Count + new2addComponents.Count) { } @@ -431,17 +408,17 @@ ref HttpClient client //TODO: 下载有变更的文件 var downloadLinkBase = "https://" + - Instances.ConfigManager.AppConfig.Web.UpdateServer + - Instances.ConfigManager.AppConfig.Web.UpdateDownloadPath.Replace( + AppConfig.Web.UpdateServer + + AppConfig.Web.UpdateDownloadPath.Replace( "%platform%", - DevicesDiscoveryServer.DefaultDeviceInfo.DeviceOSType switch + DevicesDiscoveryServer.Instance.DefaultDeviceInfo.DeviceOSType switch { OperatingSystems.Windows => "win", OperatingSystems.Linux => "linux", OperatingSystems.MacOS => "mac", _ => "" }) + - $"{Instances.ConfigManager.AppConfig.Web.UpdateChannel}/"; + $"{AppConfig.Web.UpdateChannel}/"; if (!Directory.Exists(ConstantTable.UpdateSavePath.GetFullPath())) Directory.CreateDirectory(ConstantTable.UpdateSavePath.GetFullPath()); @@ -459,15 +436,7 @@ ref HttpClient client internal bool IsCheckingOrUpdating { get => isCheckingOrUpdating; - set - { - isCheckingOrUpdating = value; - - PropertyChanged?.Invoke( - this, - new PropertyChangedEventArgs(nameof(IsCheckingOrUpdating)) - ); - } + set => this.RaiseAndSetIfChanged(ref isCheckingOrUpdating, value); } public void CheckUpdate() diff --git a/KitX Dashboard/ViewModels/Pages/DevicePageViewModel.cs b/KitX Dashboard/ViewModels/Pages/DevicePageViewModel.cs index 60b88c4c..8a8b059c 100644 --- a/KitX Dashboard/ViewModels/Pages/DevicePageViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/DevicePageViewModel.cs @@ -1,17 +1,16 @@ -using KitX.Dashboard.Views; -using KitX.Dashboard.Views.Pages.Controls; +using KitX.Dashboard.Models; +using KitX.Dashboard.Services; +using KitX.Dashboard.Views; +using KitX.Shared.Device; using ReactiveUI; using System.Collections.ObjectModel; -using System.ComponentModel; using System.Reactive; using System.Threading.Tasks; namespace KitX.Dashboard.ViewModels.Pages; -internal class DevicePageViewModel : ViewModelBase, INotifyPropertyChanged +internal class DevicePageViewModel : ViewModelBase { - public new event PropertyChangedEventHandler? PropertyChanged; - public DevicePageViewModel() { InitCommands(); @@ -30,9 +29,11 @@ await Instances.WebManager.RestartAsync( new() { ClosePluginsServer = false, - RunPluginsServer = false + RunPluginsServer = false, + CloseDevicesServer = false, + RunDevicesServer = false, }, - actionBeforeStarting: () => DeviceCards.Clear() + actionBeforeStarting: () => DeviceCases.Clear() ); }); @@ -45,60 +46,44 @@ await Instances.WebManager.CloseAsync( new() { ClosePluginsServer = false, - RunPluginsServer = false + CloseDevicesServer = false, } ); - await Task.Delay(Instances.ConfigManager.AppConfig.Web.UdpSendFrequency + 200); + await Task.Delay(AppConfig.Web.UdpSendFrequency + 200); - DeviceCards.Clear(); + DeviceCases.Clear(); }); } public override void InitEvents() { - DeviceCards.CollectionChanged += (_, _) => + DeviceCases.CollectionChanged += (_, _) => { - NoDevice_TipHeight = DeviceCards.Count == 0 ? 300 : 0; - DevicesCount = DeviceCards.Count.ToString(); + NoDevice_TipHeight = DeviceCases.Count == 0 ? 300 : 0; + DevicesCount = DeviceCases.Count.ToString(); }; } internal string? SearchingText { get; set; } - internal string devicesCount = DeviceCards.Count.ToString(); + internal string devicesCount = DeviceCases.Count.ToString(); internal string DevicesCount { get => devicesCount; - set - { - devicesCount = value; - - PropertyChanged?.Invoke( - this, - new(nameof(DevicesCount)) - ); - } + set => this.RaiseAndSetIfChanged(ref devicesCount, value); } - internal double noDevice_TipHeight = DeviceCards.Count == 0 ? 300 : 0; + internal double noDevice_TipHeight = DeviceCases.Count == 0 ? 300 : 0; internal double NoDevice_TipHeight { get => noDevice_TipHeight; - set - { - noDevice_TipHeight = value; - - PropertyChanged?.Invoke( - this, - new(nameof(NoDevice_TipHeight)) - ); - } + set => this.RaiseAndSetIfChanged(ref noDevice_TipHeight, value); } - internal static ObservableCollection DeviceCards => ViewInstances.DeviceCards; + internal static ObservableCollection DeviceCases => ViewInstances.DeviceCases; internal ReactiveCommand? RestartDevicesServerCommand { get; set; } diff --git a/KitX Dashboard/ViewModels/Pages/HomePageViewModel.cs b/KitX Dashboard/ViewModels/Pages/HomePageViewModel.cs index 3c631de5..8d8cd981 100644 --- a/KitX Dashboard/ViewModels/Pages/HomePageViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/HomePageViewModel.cs @@ -39,10 +39,10 @@ public override void InitCommands() internal static bool IsPaneOpen { - get => Instances.ConfigManager.AppConfig.Pages.Home.IsNavigationViewPaneOpened; + get => ConfigManager.Instance.AppConfig.Pages.Home.IsNavigationViewPaneOpened; set { - Instances.ConfigManager.AppConfig.Pages.Home.IsNavigationViewPaneOpened = value; + ConfigManager.Instance.AppConfig.Pages.Home.IsNavigationViewPaneOpened = value; SaveAppConfigChanges(); } @@ -60,10 +60,10 @@ internal static bool IsPaneOpen internal NavigationViewPaneDisplayMode NavigationViewPaneDisplayMode { - get => Instances.ConfigManager.AppConfig.Pages.Home.NavigationViewPaneDisplayMode; + get => ConfigManager.Instance.AppConfig.Pages.Home.NavigationViewPaneDisplayMode; set { - Instances.ConfigManager.AppConfig.Pages.Home.NavigationViewPaneDisplayMode = value; + ConfigManager.Instance.AppConfig.Pages.Home.NavigationViewPaneDisplayMode = value; PropertyChanged?.Invoke( this, diff --git a/KitX Dashboard/ViewModels/Pages/RepoPageViewModel.cs b/KitX Dashboard/ViewModels/Pages/RepoPageViewModel.cs index fc7c45e9..7c2596c5 100644 --- a/KitX Dashboard/ViewModels/Pages/RepoPageViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/RepoPageViewModel.cs @@ -85,15 +85,15 @@ public override void InitCommands() { try { - var plugin = new Plugin() + var plugin = new PluginInstallation() { InstallPath = item.InstallPath, - PluginDetails = JsonSerializer.Deserialize( + PluginInfo = JsonSerializer.Deserialize( File.ReadAllText( Path.GetFullPath($"{item.InstallPath}/PluginInfo.json") ) ), - RequiredLoaderInfo = JsonSerializer.Deserialize( + LoaderInfo = JsonSerializer.Deserialize( File.ReadAllText( Path.GetFullPath($"{item.InstallPath}/LoaderInfo.json") ) @@ -121,7 +121,7 @@ public override void InitEvents() { EventService.AppConfigChanged += () => { - ImportButtonVisibility = Instances.ConfigManager.AppConfig.App.DeveloperSetting; + ImportButtonVisibility = ConfigManager.Instance.AppConfig.App.DeveloperSetting; }; PluginBars.CollectionChanged += (_, _) => @@ -167,10 +167,10 @@ internal double NoPlugins_TipHeight internal bool ImportButtonVisibility { - get => Instances.ConfigManager.AppConfig.App.DeveloperSetting; + get => ConfigManager.Instance.AppConfig.App.DeveloperSetting; set { - Instances.ConfigManager.AppConfig.App.DeveloperSetting = value; + ConfigManager.Instance.AppConfig.App.DeveloperSetting = value; PropertyChanged?.Invoke( this, diff --git a/KitX Dashboard/ViewModels/Pages/SettingsPageViewModel.cs b/KitX Dashboard/ViewModels/Pages/SettingsPageViewModel.cs index 5b866f91..c7179cd8 100644 --- a/KitX Dashboard/ViewModels/Pages/SettingsPageViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/SettingsPageViewModel.cs @@ -1,16 +1,12 @@ using Avalonia; using FluentAvalonia.UI.Controls; -using KitX.Dashboard.Services; using ReactiveUI; -using System.ComponentModel; using System.Reactive; namespace KitX.Dashboard.ViewModels.Pages; -internal class SettingsPageViewModel : ViewModelBase, INotifyPropertyChanged +internal class SettingsPageViewModel : ViewModelBase { - public new event PropertyChangedEventHandler? PropertyChanged; - internal SettingsPageViewModel() { InitCommands(); @@ -38,10 +34,10 @@ public override void InitCommands() internal static bool IsPaneOpen { - get => Instances.ConfigManager.AppConfig.Pages.Settings.IsNavigationViewPaneOpened; + get => AppConfig.Pages.Settings.IsNavigationViewPaneOpened; set { - Instances.ConfigManager.AppConfig.Pages.Settings.IsNavigationViewPaneOpened = value; + AppConfig.Pages.Settings.IsNavigationViewPaneOpened = value; SaveAppConfigChanges(); } @@ -59,20 +55,14 @@ internal static bool IsPaneOpen internal NavigationViewPaneDisplayMode NavigationViewPaneDisplayMode { - get => Instances.ConfigManager.AppConfig.Pages.Settings.NavigationViewPaneDisplayMode; + get => AppConfig.Pages.Settings.NavigationViewPaneDisplayMode; set { - Instances.ConfigManager.AppConfig.Pages.Settings.NavigationViewPaneDisplayMode = value; + AppConfig.Pages.Settings.NavigationViewPaneDisplayMode = value; - PropertyChanged?.Invoke( - this, - new(nameof(NavigationViewPaneDisplayMode)) - ); + this.RaisePropertyChanged(nameof(NavigationViewPaneDisplayMode)); - PropertyChanged?.Invoke( - this, - new(nameof(FirstItemMargin)) - ); + this.RaisePropertyChanged(nameof(FirstItemMargin)); SaveAppConfigChanges(); } diff --git a/KitX Dashboard/ViewModels/PluginDetailWindowViewModel.cs b/KitX Dashboard/ViewModels/PluginDetailWindowViewModel.cs index fed825e6..049fd15f 100644 --- a/KitX Dashboard/ViewModels/PluginDetailWindowViewModel.cs +++ b/KitX Dashboard/ViewModels/PluginDetailWindowViewModel.cs @@ -13,8 +13,6 @@ namespace KitX.Dashboard.ViewModels; internal class PluginDetailWindowViewModel : ViewModelBase { - private PluginInfo? pluginDetail; - public PluginDetailWindowViewModel() { InitCommands(); @@ -34,24 +32,26 @@ public override void InitEvents() EventService.ThemeConfigChanged += () => this.RaisePropertyChanged(nameof(TintColor)); } - internal PluginInfo? PluginDetail { get => pluginDetail; set => pluginDetail = value; } + private PluginInfo? pluginDetail; + + internal PluginInfo? PluginDetail + { + get => pluginDetail; + set => this.RaiseAndSetIfChanged(ref pluginDetail, value); + } internal string? PublishDate => PluginDetail?.PublishDate.ToLocalTime().ToString("yyyy.MM.dd"); internal string? LastUpdateDate => PluginDetail?.LastUpdateDate.ToLocalTime().ToString("yyyy.MM.dd"); - internal static Color TintColor => Instances.ConfigManager.AppConfig.App.Theme switch + internal static Color TintColor => AppConfig.App.Theme switch { "Light" => Colors.WhiteSmoke, "Dark" => Colors.Black, "Follow" => Application.Current?.ActualThemeVariant == ThemeVariant.Light ? Colors.WhiteSmoke : Colors.Black, - _ => Color.Parse(Instances.ConfigManager.AppConfig.App.ThemeColor), + _ => Color.Parse(AppConfig.App.ThemeColor), }; - private readonly ObservableCollection functions = []; - - private readonly ObservableCollection tags = []; - internal void InitFunctionsAndTags() { if (PluginDetail is null) return; @@ -60,7 +60,7 @@ internal void InitFunctionsAndTags() if (PluginDetail?.Tags is null) return; - foreach (var func in PluginDetail.Value.Functions) + foreach (var func in PluginDetail.Functions) { var sb = new StringBuilder() .Append(func.ReturnValueType) @@ -89,13 +89,13 @@ internal void InitFunctionsAndTags() Functions.Add(sb.ToString()); } - foreach (var tag in PluginDetail.Value.Tags) + foreach (var tag in PluginDetail.Tags) Tags.Add($"{{ {tag.Key}: {tag.Value} }}"); } - internal ObservableCollection Functions => functions; + internal ObservableCollection Functions { get; set; } = []; - internal ObservableCollection Tags => tags; + internal ObservableCollection Tags { get; set; } = []; internal ReactiveCommand? FinishCommand { get; set; } } diff --git a/KitX Dashboard/ViewModels/PluginsLaunchWindowViewModel.cs b/KitX Dashboard/ViewModels/PluginsLaunchWindowViewModel.cs index 6d6773ce..41b112ff 100644 --- a/KitX Dashboard/ViewModels/PluginsLaunchWindowViewModel.cs +++ b/KitX Dashboard/ViewModels/PluginsLaunchWindowViewModel.cs @@ -75,7 +75,7 @@ public PluginInfo? SelectedPluginInfo { if (value is null) return; - var index = PluginInfos.IndexOf(value.Value); + var index = PluginInfos.IndexOf(value); this.RaiseAndSetIfChanged(ref selectedPluginIndex, index); } @@ -334,7 +334,7 @@ internal void SubmitSearchingText() else if (IsSelectingFunction) { if (SelectedPluginInfo is not null) - foreach (var func in SelectedPluginInfo.Value.Functions) + foreach (var func in SelectedPluginInfo.Functions) if (func.Name.Equals(text)) { SelectedFunction = func; @@ -344,7 +344,7 @@ internal void SubmitSearchingText() if (SelectedPluginInfo is not null && SelectedFunction is not null && (HavingParameters == false)) { - var plugConnector = PluginsServer.Instance.FindConnector(SelectedPluginInfo.Value); + var plugConnector = PluginsServer.Instance.FindConnector(SelectedPluginInfo); if (plugConnector is not null) { diff --git a/KitX Dashboard/ViewModels/ViewModelBase.cs b/KitX Dashboard/ViewModels/ViewModelBase.cs index 95a7582d..ea03f97e 100644 --- a/KitX Dashboard/ViewModels/ViewModelBase.cs +++ b/KitX Dashboard/ViewModels/ViewModelBase.cs @@ -1,43 +1,46 @@ -using Avalonia; +using Avalonia; using Avalonia.Controls; -using KitX.Dashboard.Configuration; -using KitX.Dashboard.Services; -using ReactiveUI; - -namespace KitX.Dashboard.ViewModels; - -public abstract class ViewModelBase : ReactiveObject -{ +using KitX.Dashboard.Configuration; +using KitX.Dashboard.Managers; +using KitX.Dashboard.Services; +using ReactiveUI; + +namespace KitX.Dashboard.ViewModels; + +public abstract class ViewModelBase : ReactiveObject +{ protected static string? Translate - ( - string key = "", - string prefix = "", - string suffix = "", - string seperator = "", + ( + string key = "", + string prefix = "", + string suffix = "", + string seperator = "", Application? app = null - ) - { + ) + { app ??= Application.Current; - if (app is null) return null; - - var res_key = $"{prefix}{seperator}{key}{seperator}{suffix}"; - - if (app.TryFindResource(res_key, out var found)) - { - if (found is string text) return text; - else return null; - } - else return null; - } - - protected static void SaveAppConfigChanges() => EventService.Invoke( - nameof(EventService.AppConfigChanged) + if (app is null) return null; + + var res_key = $"{prefix}{seperator}{key}{seperator}{suffix}"; + + if (app.TryFindResource(res_key, out var found)) + { + if (found is string text) return text; + else return null; + } + else return null; + } + + protected static void SaveAppConfigChanges() => EventService.Invoke( + nameof(EventService.AppConfigChanged) ); public abstract void InitCommands(); public abstract void InitEvents(); - internal static AppConfig AppConfig => Instances.ConfigManager.AppConfig; + internal static AppConfig AppConfig => ConfigManager.Instance.AppConfig; + + internal static AnnouncementConfig AnnouncementConfig => ConfigManager.Instance.AnnouncementConfig; } diff --git a/KitX Dashboard/Views/AnouncementsWindow.axaml.cs b/KitX Dashboard/Views/AnouncementsWindow.axaml.cs index 367b1327..53890153 100644 --- a/KitX Dashboard/Views/AnouncementsWindow.axaml.cs +++ b/KitX Dashboard/Views/AnouncementsWindow.axaml.cs @@ -2,6 +2,7 @@ using Common.BasicHelper.Graphics.Screen; using KitX.Dashboard.Configuration; using KitX.Dashboard.Converters; +using KitX.Dashboard.Managers; using KitX.Dashboard.Utils; using KitX.Dashboard.ViewModels; using System; @@ -13,7 +14,7 @@ public partial class AnouncementsWindow : Window, IView { private readonly AnouncementsWindowViewModel viewModel = new(); - private readonly AppConfig appConfig = Instances.ConfigManager.AppConfig; + private readonly AppConfig appConfig = ConfigManager.Instance.AppConfig; public AnouncementsWindow() { diff --git a/KitX Dashboard/Views/MainWindow.axaml.cs b/KitX Dashboard/Views/MainWindow.axaml.cs index 7530f721..c20d3f3c 100644 --- a/KitX Dashboard/Views/MainWindow.axaml.cs +++ b/KitX Dashboard/Views/MainWindow.axaml.cs @@ -7,6 +7,7 @@ using KitX.Dashboard.Configuration; using KitX.Dashboard.Converters; using KitX.Dashboard.Generators; +using KitX.Dashboard.Managers; using KitX.Dashboard.Names; using KitX.Dashboard.Services; using KitX.Dashboard.Utils; @@ -21,7 +22,7 @@ public partial class MainWindow : Window, IView { private readonly MainWindowViewModel viewModel = new(); - private static AppConfig AppConfig => Instances.ConfigManager.AppConfig; + private static AppConfig AppConfig => ConfigManager.Instance.AppConfig; public MainWindow() { diff --git a/KitX Dashboard/Views/Pages/Controls/DeviceCard.axaml b/KitX Dashboard/Views/Pages/Controls/DeviceCard.axaml index 944b6329..53ce8aa3 100644 --- a/KitX Dashboard/Views/Pages/Controls/DeviceCard.axaml +++ b/KitX Dashboard/Views/Pages/Controls/DeviceCard.axaml @@ -9,73 +9,4 @@ d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> - - - - - - diff --git a/KitX Dashboard/Views/Pages/Controls/PluginBar.axaml.cs b/KitX Dashboard/Views/Pages/Controls/PluginBar.axaml.cs index 379b6cce..91eb09cd 100644 --- a/KitX Dashboard/Views/Pages/Controls/PluginBar.axaml.cs +++ b/KitX Dashboard/Views/Pages/Controls/PluginBar.axaml.cs @@ -16,11 +16,11 @@ public PluginBar() DataContext = viewModel; } - public PluginBar(Plugin plugin, ref ObservableCollection pluginBars) + public PluginBar(PluginInstallation plugin, ref ObservableCollection pluginBars) { InitializeComponent(); - viewModel.PluginDetail = plugin; + viewModel.Plugin = plugin; viewModel.PluginBars = pluginBars; viewModel.PluginBar = this; diff --git a/KitX Dashboard/Views/Pages/DevicePage.axaml b/KitX Dashboard/Views/Pages/DevicePage.axaml index 8b5bc20c..31fcb9d3 100644 --- a/KitX Dashboard/Views/Pages/DevicePage.axaml +++ b/KitX Dashboard/Views/Pages/DevicePage.axaml @@ -2,6 +2,7 @@ xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:KitX.Dashboard.Views.Pages.Controls" + xmlns:converters="using:KitX.Dashboard.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:icon="using:Material.Icons.Avalonia" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -10,6 +11,13 @@ d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> + + + + + + + - + + + + + + diff --git a/KitX Dashboard/Views/Pages/HomePage.axaml.cs b/KitX Dashboard/Views/Pages/HomePage.axaml.cs index b1520faf..5e710f35 100644 --- a/KitX Dashboard/Views/Pages/HomePage.axaml.cs +++ b/KitX Dashboard/Views/Pages/HomePage.axaml.cs @@ -1,6 +1,6 @@ using Avalonia.Controls; using FluentAvalonia.UI.Controls; -using KitX.Dashboard.Services; +using KitX.Dashboard.Managers; using KitX.Dashboard.ViewModels.Pages; using KitX.Dashboard.Views.Pages.Controls; using Serilog; @@ -31,10 +31,10 @@ private void InitHomePage() private static string SelectedViewName { - get => Instances.ConfigManager.AppConfig.Pages.Home.SelectedViewName; + get => ConfigManager.Instance.AppConfig.Pages.Home.SelectedViewName; set { - Instances.ConfigManager.AppConfig.Pages.Home.SelectedViewName = value; + ConfigManager.Instance.AppConfig.Pages.Home.SelectedViewName = value; IView.SaveAppConfigChanges(); } diff --git a/KitX Dashboard/Views/Pages/SettingsPage.axaml.cs b/KitX Dashboard/Views/Pages/SettingsPage.axaml.cs index 4e973197..d7f074ec 100644 --- a/KitX Dashboard/Views/Pages/SettingsPage.axaml.cs +++ b/KitX Dashboard/Views/Pages/SettingsPage.axaml.cs @@ -52,10 +52,10 @@ private void SettingsNavigationView_SelectionChanged( private static string SelectedViewName { - get => Instances.ConfigManager.AppConfig.Pages.Settings.SelectedViewName; + get => ConfigManager.Instance.AppConfig.Pages.Settings.SelectedViewName; set { - Instances.ConfigManager.AppConfig.Pages.Settings.SelectedViewName = value; + ConfigManager.Instance.AppConfig.Pages.Settings.SelectedViewName = value; IView.SaveAppConfigChanges(); } diff --git a/KitX Dashboard/Views/PluginDetailWindow.axaml b/KitX Dashboard/Views/PluginDetailWindow.axaml index 9c66d08a..61f830ff 100644 --- a/KitX Dashboard/Views/PluginDetailWindow.axaml +++ b/KitX Dashboard/Views/PluginDetailWindow.axaml @@ -34,42 +34,31 @@ - - - - - - - - - - - @@ -79,7 +68,6 @@ TintOpacity="1"/> - - @@ -170,22 +157,15 @@ - - - - -