diff --git a/StabilityMatrix.Avalonia/App.axaml.cs b/StabilityMatrix.Avalonia/App.axaml.cs index ab962db2..64a347e8 100644 --- a/StabilityMatrix.Avalonia/App.axaml.cs +++ b/StabilityMatrix.Avalonia/App.axaml.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; @@ -15,6 +16,7 @@ using Avalonia.Markup.Xaml; using Avalonia.Platform.Storage; using Avalonia.Styling; using FluentAvalonia.UI.Controls; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog; @@ -43,6 +45,7 @@ using StabilityMatrix.Core.Helper; using StabilityMatrix.Core.Helper.Cache; using StabilityMatrix.Core.Helper.Factory; using StabilityMatrix.Core.Models.Api; +using StabilityMatrix.Core.Models.Configs; using StabilityMatrix.Core.Models.Packages; using StabilityMatrix.Core.Models.Settings; using StabilityMatrix.Core.Python; @@ -58,7 +61,8 @@ public sealed class App : Application [NotNull] public static IServiceProvider? Services { get; private set; } [NotNull] public static Visual? VisualRoot { get; private set; } [NotNull] public static IStorageProvider? StorageProvider { get; private set; } - + [NotNull] public static IConfiguration? Config { get; private set; } + // ReSharper disable once MemberCanBePrivate.Global public IClassicDesktopStyleApplicationLifetime? DesktopLifetime => ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; @@ -150,6 +154,15 @@ public sealed class App : Application mainWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen; } + mainWindow.Closing += (_, _) => + { + settingsManager.Transaction(s => + { + s.WindowSettings = new WindowSettings( + mainWindow.Width, mainWindow.Height, + mainWindow.Position.X, mainWindow.Position.Y); + }, ignoreMissingLibraryDir: true); + }; mainWindow.Closed += (_, _) => Shutdown(); VisualRoot = mainWindow; @@ -292,11 +305,18 @@ public sealed class App : Application services.AddSingleton(); services.AddSingleton(); + Config = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .Build(); + + services.Configure(Config.GetSection(nameof(DebugOptions))); + if (Compat.IsWindows) { services.AddSingleton(); } - else if (Compat.IsLinux) + else { services.AddSingleton(); } @@ -440,10 +460,6 @@ public sealed class App : Application sharedFolders.RemoveLinksForAllPackages(); } - var mainWindow = Services.GetRequiredService(); - settingsManager.Transaction(s => s.WindowSettings = new WindowSettings(mainWindow.Width, - mainWindow.Height, mainWindow.Position.X, mainWindow.Position.Y)); - Debug.WriteLine("Start OnExit: Disposing services"); // Dispose all services foreach (var disposable in Services.GetServices()) diff --git a/StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs b/StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs index 97b4f73e..7fa14d18 100644 --- a/StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs +++ b/StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs @@ -15,7 +15,7 @@ using StabilityMatrix.Core.Services; namespace StabilityMatrix.Avalonia.Helpers; -[SupportedOSPlatform("linux")] +[UnsupportedOSPlatform("windows")] public class UnixPrerequisiteHelper : IPrerequisiteHelper { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); diff --git a/StabilityMatrix.Avalonia/Program.cs b/StabilityMatrix.Avalonia/Program.cs index 2c984837..5d614db1 100644 --- a/StabilityMatrix.Avalonia/Program.cs +++ b/StabilityMatrix.Avalonia/Program.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -13,6 +14,7 @@ using NLog; using Polly.Contrib.WaitAndRetry; using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia.FontAwesome; +using Semver; using Sentry; using StabilityMatrix.Avalonia.ViewModels.Dialogs; using StabilityMatrix.Avalonia.Views.Dialogs; @@ -35,6 +37,10 @@ public class Program { HandleUpdateReplacement(); + var infoVersion = Assembly.GetExecutingAssembly() + .GetCustomAttribute()?.InformationalVersion; + Compat.AppVersion = SemVersion.Parse(infoVersion ?? "0.0.0", SemVersionStyles.Strict); + // Configure exception dialog for unhandled exceptions if (!Debugger.IsAttached || args.Contains("--debug-exception-dialog")) { diff --git a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj index e7c37276..95b22859 100644 --- a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj +++ b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj @@ -8,8 +8,11 @@ app.manifest true partial - true + true ./Assets/Icon.ico + 2.0.0 + dev.1 + $(Version) @@ -28,8 +31,12 @@ + + + + @@ -50,7 +57,6 @@ - diff --git a/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs index 2ce4573c..2aa32b67 100644 --- a/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.ObjectModel; +using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading.Tasks; @@ -34,19 +34,22 @@ public partial class SettingsViewModel : PageViewModelBase public override string Title => "Settings"; public override IconSource IconSource => new SymbolIconSource {Symbol = Symbol.Settings, IsFilled = true}; - public string AppVersion => GetAppVersion(); - // Theme panel + // ReSharper disable once MemberCanBeMadeStatic.Global + public string AppVersion => $"Version {Compat.AppVersion}"; + + // Theme section [ObservableProperty] private string? selectedTheme; - // Debug info + // Shared folder options + [ObservableProperty] private bool removeSymlinksOnShutdown; + + // Debug section [ObservableProperty] private string? debugPaths; [ObservableProperty] private string? debugCompatInfo; [ObservableProperty] private string? debugGpuInfo; - - [ObservableProperty] private bool removeSymlinksOnShutdown; - public ObservableCollection AvailableThemes { get; } = new() + public IReadOnlyList AvailableThemes { get; } = new[] { "Light", "Dark", @@ -81,7 +84,39 @@ public partial class SettingsViewModel : PageViewModelBase }; } + [RelayCommand] + private async Task CheckPythonVersion() + { + var isInstalled = prerequisiteHelper.IsPythonInstalled; + Logger.Debug($"Check python installed: {isInstalled}"); + // Ensure python installed + if (!prerequisiteHelper.IsPythonInstalled) + { + // Need 7z as well for site packages repack + Logger.Debug("Python not installed, unpacking resources..."); + await prerequisiteHelper.UnpackResourcesIfNecessary(); + Logger.Debug("Unpacked resources, installing python..."); + await prerequisiteHelper.InstallPythonIfNecessary(); + } + + // Get python version + await pyRunner.Initialize(); + var result = await pyRunner.GetVersionInfo(); + // Show dialog box + var dialog = new ContentDialog + { + Title = "Python version info", + Content = result, + PrimaryButtonText = "Ok", + IsPrimaryButtonEnabled = true + }; + dialog.Title = "Python version info"; + dialog.Content = result; + dialog.PrimaryButtonText = "Ok"; + await dialog.ShowAsync(); + } + #region Debug Section public void LoadDebugInfo() { var assembly = Assembly.GetExecutingAssembly(); @@ -156,45 +191,7 @@ public partial class SettingsViewModel : PageViewModelBase // Use try-catch to generate traceback information throw new OperationCanceledException("Example Message"); } + #endregion - [RelayCommand] - private async Task CheckPythonVersion() - { - var isInstalled = prerequisiteHelper.IsPythonInstalled; - Logger.Debug($"Check python installed: {isInstalled}"); - // Ensure python installed - if (!prerequisiteHelper.IsPythonInstalled) - { - // Need 7z as well for site packages repack - Logger.Debug("Python not installed, unpacking resources..."); - await prerequisiteHelper.UnpackResourcesIfNecessary(); - Logger.Debug("Unpacked resources, installing python..."); - await prerequisiteHelper.InstallPythonIfNecessary(); - } - // Get python version - await pyRunner.Initialize(); - var result = await pyRunner.GetVersionInfo(); - // Show dialog box - var dialog = new ContentDialog - { - Title = "Python version info", - Content = result, - PrimaryButtonText = "Ok", - IsPrimaryButtonEnabled = true - }; - dialog.Title = "Python version info"; - dialog.Content = result; - dialog.PrimaryButtonText = "Ok"; - await dialog.ShowAsync(); - } - - private static string GetAppVersion() - { - var assembly = Assembly.GetExecutingAssembly(); - var version = assembly.GetName().Version; - return version == null - ? "(Unknown)" - : $"Version {version.Major}.{version.Minor}.{version.Build}"; - } } diff --git a/StabilityMatrix.Avalonia/Views/SettingsPage.axaml b/StabilityMatrix.Avalonia/Views/SettingsPage.axaml index 92ee9df0..2f24458f 100644 --- a/StabilityMatrix.Avalonia/Views/SettingsPage.axaml +++ b/StabilityMatrix.Avalonia/Views/SettingsPage.axaml @@ -6,7 +6,6 @@ xmlns:ui="using:FluentAvalonia.UI.Controls" xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData" xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls" - xmlns:icons="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:DataType="vm:SettingsViewModel" x:CompileBindings="True" @@ -28,7 +27,6 @@ - @@ -163,7 +161,7 @@ Text="Stability Matrix" />