Browse Source

Add compile conditionals to fix release builds

pull/109/head
Ionite 1 year ago
parent
commit
1cba65eefb
No known key found for this signature in database
  1. 341
      StabilityMatrix.Avalonia/App.axaml.cs
  2. 76
      StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs

341
StabilityMatrix.Avalonia/App.axaml.cs

@ -1,3 +1,7 @@
#if DEBUG
using StabilityMatrix.Avalonia.Diagnostics.LogViewer;
using StabilityMatrix.Avalonia.Diagnostics.LogViewer.Extensions;
#endif
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
@ -33,8 +37,6 @@ using Refit;
using Sentry; using Sentry;
using StabilityMatrix.Avalonia.Controls; using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.DesignData; using StabilityMatrix.Avalonia.DesignData;
using StabilityMatrix.Avalonia.Diagnostics.LogViewer;
using StabilityMatrix.Avalonia.Diagnostics.LogViewer.Extensions;
using StabilityMatrix.Avalonia.Helpers; using StabilityMatrix.Avalonia.Helpers;
using StabilityMatrix.Avalonia.Languages; using StabilityMatrix.Avalonia.Languages;
using StabilityMatrix.Avalonia.Models; using StabilityMatrix.Avalonia.Models;
@ -68,12 +70,19 @@ namespace StabilityMatrix.Avalonia;
public sealed class App : Application public sealed class App : Application
{ {
[NotNull] public static IServiceProvider? Services { get; private set; } [NotNull]
[NotNull] public static Visual? VisualRoot { get; private set; } public static IServiceProvider? Services { get; private set; }
[NotNull] public static IStorageProvider? StorageProvider { get; private set; }
[NotNull]
public static Visual? VisualRoot { get; private set; }
[NotNull]
public static IStorageProvider? StorageProvider { get; private set; }
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
[NotNull] public static IConfiguration? Config { get; private set; } [NotNull]
public static IConfiguration? Config { get; private set; }
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
public IClassicDesktopStyleApplicationLifetime? DesktopLifetime => public IClassicDesktopStyleApplicationLifetime? DesktopLifetime =>
ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
@ -88,11 +97,11 @@ public sealed class App : Application
RequestedThemeVariant = ThemeVariant.Dark; RequestedThemeVariant = ThemeVariant.Dark;
} }
} }
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
if (Design.IsDesignMode) if (Design.IsDesignMode)
{ {
DesignData.DesignData.Initialize(); DesignData.DesignData.Initialize();
@ -117,9 +126,10 @@ public sealed class App : Application
setupWindow.ShowAsDialog = true; setupWindow.ShowAsDialog = true;
setupWindow.ShowActivated = true; setupWindow.ShowActivated = true;
setupWindow.ShowAsyncCts = new CancellationTokenSource(); setupWindow.ShowAsyncCts = new CancellationTokenSource();
setupWindow.ExtendClientAreaChromeHints = Program.Args.NoWindowChromeEffects ? setupWindow.ExtendClientAreaChromeHints = Program.Args.NoWindowChromeEffects
ExtendClientAreaChromeHints.NoChrome : ExtendClientAreaChromeHints.PreferSystemChrome; ? ExtendClientAreaChromeHints.NoChrome
: ExtendClientAreaChromeHints.PreferSystemChrome;
DesktopLifetime.MainWindow = setupWindow; DesktopLifetime.MainWindow = setupWindow;
@ -146,47 +156,55 @@ public sealed class App : Application
private void ShowMainWindow() private void ShowMainWindow()
{ {
if (DesktopLifetime is null) return; if (DesktopLifetime is null)
return;
var mainViewModel = Services.GetRequiredService<MainWindowViewModel>(); var mainViewModel = Services.GetRequiredService<MainWindowViewModel>();
var mainWindow = Services.GetRequiredService<MainWindow>(); var mainWindow = Services.GetRequiredService<MainWindow>();
mainWindow.DataContext = mainViewModel; mainWindow.DataContext = mainViewModel;
mainWindow.ExtendClientAreaChromeHints = Program.Args.NoWindowChromeEffects ? mainWindow.ExtendClientAreaChromeHints = Program.Args.NoWindowChromeEffects
ExtendClientAreaChromeHints.NoChrome : ExtendClientAreaChromeHints.PreferSystemChrome; ? ExtendClientAreaChromeHints.NoChrome
: ExtendClientAreaChromeHints.PreferSystemChrome;
var settingsManager = Services.GetRequiredService<ISettingsManager>(); var settingsManager = Services.GetRequiredService<ISettingsManager>();
var windowSettings = settingsManager.Settings.WindowSettings; var windowSettings = settingsManager.Settings.WindowSettings;
if (windowSettings != null && !Program.Args.ResetWindowPosition) if (windowSettings != null && !Program.Args.ResetWindowPosition)
{ {
mainWindow.Position = new PixelPoint(windowSettings.X, windowSettings.Y); mainWindow.Position = new PixelPoint(windowSettings.X, windowSettings.Y);
mainWindow.Width = windowSettings.Width; mainWindow.Width = windowSettings.Width;
mainWindow.Height = windowSettings.Height; mainWindow.Height = windowSettings.Height;
} }
else else
{ {
mainWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen; mainWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
} }
mainWindow.Closing += (_, _) => mainWindow.Closing += (_, _) =>
{ {
var validWindowPosition = var validWindowPosition = mainWindow.Screens.All.Any(
mainWindow.Screens.All.Any(screen => screen.Bounds.Contains(mainWindow.Position)); screen => screen.Bounds.Contains(mainWindow.Position)
);
settingsManager.Transaction(s => settingsManager.Transaction(
{ s =>
s.WindowSettings = new WindowSettings( {
mainWindow.Width, mainWindow.Height, s.WindowSettings = new WindowSettings(
validWindowPosition ? mainWindow.Position.X : 0, mainWindow.Width,
validWindowPosition ? mainWindow.Position.Y : 0); mainWindow.Height,
}, ignoreMissingLibraryDir: true); validWindowPosition ? mainWindow.Position.X : 0,
validWindowPosition ? mainWindow.Position.Y : 0
);
},
ignoreMissingLibraryDir: true
);
}; };
mainWindow.Closed += (_, _) => Shutdown(); mainWindow.Closed += (_, _) => Shutdown();
VisualRoot = mainWindow; VisualRoot = mainWindow;
StorageProvider = mainWindow.StorageProvider; StorageProvider = mainWindow.StorageProvider;
DesktopLifetime.MainWindow = mainWindow; DesktopLifetime.MainWindow = mainWindow;
DesktopLifetime.Exit += OnExit; DesktopLifetime.Exit += OnExit;
} }
@ -195,49 +213,50 @@ public sealed class App : Application
{ {
var services = ConfigureServices(); var services = ConfigureServices();
Services = services.BuildServiceProvider(); Services = services.BuildServiceProvider();
var settingsManager = Services.GetRequiredService<ISettingsManager>(); var settingsManager = Services.GetRequiredService<ISettingsManager>();
if (settingsManager.TryFindLibrary()) if (settingsManager.TryFindLibrary())
{ {
Cultures.TrySetSupportedCulture(settingsManager.Settings.Language); Cultures.TrySetSupportedCulture(settingsManager.Settings.Language);
} }
Services.GetRequiredService<ProgressManagerViewModel>().StartEventListener(); Services.GetRequiredService<ProgressManagerViewModel>().StartEventListener();
} }
internal static void ConfigurePageViewModels(IServiceCollection services) internal static void ConfigurePageViewModels(IServiceCollection services)
{ {
services.AddSingleton<PackageManagerViewModel>() services
.AddSingleton<PackageManagerViewModel>()
.AddSingleton<SettingsViewModel>() .AddSingleton<SettingsViewModel>()
.AddSingleton<CheckpointBrowserViewModel>() .AddSingleton<CheckpointBrowserViewModel>()
.AddSingleton<CheckpointsPageViewModel>() .AddSingleton<CheckpointsPageViewModel>()
.AddSingleton<NewCheckpointsPageViewModel>() .AddSingleton<NewCheckpointsPageViewModel>()
.AddSingleton<LaunchPageViewModel>() .AddSingleton<LaunchPageViewModel>()
.AddSingleton<ProgressManagerViewModel>(); .AddSingleton<ProgressManagerViewModel>();
services.AddSingleton<MainWindowViewModel>(provider => services.AddSingleton<MainWindowViewModel>(
new MainWindowViewModel(provider.GetRequiredService<ISettingsManager>(), provider =>
provider.GetRequiredService<IDiscordRichPresenceService>(), new MainWindowViewModel(
provider.GetRequiredService<ServiceManager<ViewModelBase>>(), provider.GetRequiredService<ISettingsManager>(),
provider.GetRequiredService<ITrackedDownloadService>()) provider.GetRequiredService<IDiscordRichPresenceService>(),
{ provider.GetRequiredService<ServiceManager<ViewModelBase>>(),
Pages = provider.GetRequiredService<ITrackedDownloadService>()
{ )
provider.GetRequiredService<LaunchPageViewModel>(),
provider.GetRequiredService<PackageManagerViewModel>(),
provider.GetRequiredService<CheckpointsPageViewModel>(),
provider.GetRequiredService<CheckpointBrowserViewModel>(),
},
FooterPages =
{ {
provider.GetRequiredService<SettingsViewModel>() Pages =
{
provider.GetRequiredService<LaunchPageViewModel>(),
provider.GetRequiredService<PackageManagerViewModel>(),
provider.GetRequiredService<CheckpointsPageViewModel>(),
provider.GetRequiredService<CheckpointBrowserViewModel>(),
},
FooterPages = { provider.GetRequiredService<SettingsViewModel>() }
} }
}); );
// Register disposable view models for shutdown cleanup // Register disposable view models for shutdown cleanup
services.AddSingleton<IDisposable>(p services.AddSingleton<IDisposable>(p => p.GetRequiredService<LaunchPageViewModel>());
=> p.GetRequiredService<LaunchPageViewModel>());
} }
internal static void ConfigureDialogViewModels(IServiceCollection services) internal static void ConfigureDialogViewModels(IServiceCollection services)
@ -251,43 +270,44 @@ public sealed class App : Application
services.AddTransient<ExceptionViewModel>(); services.AddTransient<ExceptionViewModel>();
services.AddTransient<EnvVarsViewModel>(); services.AddTransient<EnvVarsViewModel>();
services.AddTransient<PackageImportViewModel>(); services.AddTransient<PackageImportViewModel>();
// Dialog view models (singleton) // Dialog view models (singleton)
services.AddSingleton<FirstLaunchSetupViewModel>(); services.AddSingleton<FirstLaunchSetupViewModel>();
services.AddSingleton<UpdateViewModel>(); services.AddSingleton<UpdateViewModel>();
// Other transients (usually sub view models) // Other transients (usually sub view models)
services.AddTransient<CheckpointFolder>(); services.AddTransient<CheckpointFolder>();
services.AddTransient<CheckpointFile>(); services.AddTransient<CheckpointFile>();
services.AddTransient<CheckpointBrowserCardViewModel>(); services.AddTransient<CheckpointBrowserCardViewModel>();
services.AddTransient<PackageCardViewModel>(); services.AddTransient<PackageCardViewModel>();
// Global progress // Global progress
services.AddSingleton<ProgressManagerViewModel>(); services.AddSingleton<ProgressManagerViewModel>();
// Controls // Controls
services.AddTransient<RefreshBadgeViewModel>(); services.AddTransient<RefreshBadgeViewModel>();
// Dialog factory // Dialog factory
services.AddSingleton<ServiceManager<ViewModelBase>>(provider => services.AddSingleton<ServiceManager<ViewModelBase>>(
new ServiceManager<ViewModelBase>() provider =>
.Register(provider.GetRequiredService<InstallerViewModel>) new ServiceManager<ViewModelBase>()
.Register(provider.GetRequiredService<OneClickInstallViewModel>) .Register(provider.GetRequiredService<InstallerViewModel>)
.Register(provider.GetRequiredService<SelectModelVersionViewModel>) .Register(provider.GetRequiredService<OneClickInstallViewModel>)
.Register(provider.GetRequiredService<SelectDataDirectoryViewModel>) .Register(provider.GetRequiredService<SelectModelVersionViewModel>)
.Register(provider.GetRequiredService<LaunchOptionsViewModel>) .Register(provider.GetRequiredService<SelectDataDirectoryViewModel>)
.Register(provider.GetRequiredService<UpdateViewModel>) .Register(provider.GetRequiredService<LaunchOptionsViewModel>)
.Register(provider.GetRequiredService<CheckpointBrowserCardViewModel>) .Register(provider.GetRequiredService<UpdateViewModel>)
.Register(provider.GetRequiredService<CheckpointFolder>) .Register(provider.GetRequiredService<CheckpointBrowserCardViewModel>)
.Register(provider.GetRequiredService<CheckpointFile>) .Register(provider.GetRequiredService<CheckpointFolder>)
.Register(provider.GetRequiredService<PackageCardViewModel>) .Register(provider.GetRequiredService<CheckpointFile>)
.Register(provider.GetRequiredService<RefreshBadgeViewModel>) .Register(provider.GetRequiredService<PackageCardViewModel>)
.Register(provider.GetRequiredService<ExceptionViewModel>) .Register(provider.GetRequiredService<RefreshBadgeViewModel>)
.Register(provider.GetRequiredService<EnvVarsViewModel>) .Register(provider.GetRequiredService<ExceptionViewModel>)
.Register(provider.GetRequiredService<ProgressManagerViewModel>) .Register(provider.GetRequiredService<EnvVarsViewModel>)
.Register(provider.GetRequiredService<FirstLaunchSetupViewModel>) .Register(provider.GetRequiredService<ProgressManagerViewModel>)
.Register(provider.GetRequiredService<PackageImportViewModel>) .Register(provider.GetRequiredService<FirstLaunchSetupViewModel>)
); .Register(provider.GetRequiredService<PackageImportViewModel>)
);
} }
internal static void ConfigureViews(IServiceCollection services) internal static void ConfigureViews(IServiceCollection services)
@ -300,7 +320,7 @@ public sealed class App : Application
services.AddSingleton<CheckpointBrowserPage>(); services.AddSingleton<CheckpointBrowserPage>();
services.AddSingleton<ProgressManagerPage>(); services.AddSingleton<ProgressManagerPage>();
services.AddSingleton<NewCheckpointsPage>(); services.AddSingleton<NewCheckpointsPage>();
// Dialogs // Dialogs
services.AddTransient<SelectDataDirectoryDialog>(); services.AddTransient<SelectDataDirectoryDialog>();
services.AddTransient<LaunchOptionsDialog>(); services.AddTransient<LaunchOptionsDialog>();
@ -308,15 +328,15 @@ public sealed class App : Application
services.AddTransient<ExceptionDialog>(); services.AddTransient<ExceptionDialog>();
services.AddTransient<EnvVarsDialog>(); services.AddTransient<EnvVarsDialog>();
services.AddTransient<PackageImportDialog>(); services.AddTransient<PackageImportDialog>();
// Controls // Controls
services.AddTransient<RefreshBadge>(); services.AddTransient<RefreshBadge>();
// Windows // Windows
services.AddSingleton<MainWindow>(); services.AddSingleton<MainWindow>();
services.AddSingleton<FirstLaunchSetupWindow>(); services.AddSingleton<FirstLaunchSetupWindow>();
} }
internal static void ConfigurePackages(IServiceCollection services) internal static void ConfigurePackages(IServiceCollection services)
{ {
services.AddSingleton<BasePackage, A3WebUI>(); services.AddSingleton<BasePackage, A3WebUI>();
@ -336,7 +356,7 @@ public sealed class App : Application
ConfigurePageViewModels(services); ConfigurePageViewModels(services);
ConfigureDialogViewModels(services); ConfigureDialogViewModels(services);
ConfigurePackages(services); ConfigurePackages(services);
// Other services // Other services
services.AddSingleton<ISettingsManager, SettingsManager>(); services.AddSingleton<ISettingsManager, SettingsManager>();
services.AddSingleton<ISharedFolders, SharedFolders>(); services.AddSingleton<ISharedFolders, SharedFolders>();
@ -350,23 +370,25 @@ public sealed class App : Application
services.AddSingleton<IUpdateHelper, UpdateHelper>(); services.AddSingleton<IUpdateHelper, UpdateHelper>();
services.AddSingleton<INavigationService, NavigationService>(); services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<IModelIndexService, ModelIndexService>(); services.AddSingleton<IModelIndexService, ModelIndexService>();
services.AddSingleton<ITrackedDownloadService, TrackedDownloadService>(); services.AddSingleton<ITrackedDownloadService, TrackedDownloadService>();
services.AddSingleton<IDisposable>(provider => services.AddSingleton<IDisposable>(
(IDisposable) provider.GetRequiredService<ITrackedDownloadService>()); provider => (IDisposable)provider.GetRequiredService<ITrackedDownloadService>()
);
// Rich presence // Rich presence
services.AddSingleton<IDiscordRichPresenceService, DiscordRichPresenceService>(); services.AddSingleton<IDiscordRichPresenceService, DiscordRichPresenceService>();
services.AddSingleton<IDisposable>(provider => services.AddSingleton<IDisposable>(
provider.GetRequiredService<IDiscordRichPresenceService>()); provider => provider.GetRequiredService<IDiscordRichPresenceService>()
);
Config = new ConfigurationBuilder() Config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()) .SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build(); .Build();
services.Configure<DebugOptions>(Config.GetSection(nameof(DebugOptions))); services.Configure<DebugOptions>(Config.GetSection(nameof(DebugOptions)));
if (Compat.IsWindows) if (Compat.IsWindows)
{ {
services.AddSingleton<IPrerequisiteHelper, WindowsPrerequisiteHelper>(); services.AddSingleton<IPrerequisiteHelper, WindowsPrerequisiteHelper>();
@ -408,13 +430,13 @@ public sealed class App : Application
jsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter()); jsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter<CivitFileType>()); jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter<CivitFileType>());
jsonSerializerOptions.Converters.Add( jsonSerializerOptions.Converters.Add(
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
);
jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
var defaultRefitSettings = new RefitSettings var defaultRefitSettings = new RefitSettings
{ {
ContentSerializer = ContentSerializer = new SystemTextJsonContentSerializer(jsonSerializerOptions)
new SystemTextJsonContentSerializer(jsonSerializerOptions)
}; };
// HTTP Policies // HTTP Policies
@ -426,9 +448,10 @@ public sealed class App : Application
HttpStatusCode.ServiceUnavailable, // 503 HttpStatusCode.ServiceUnavailable, // 503
HttpStatusCode.GatewayTimeout // 504 HttpStatusCode.GatewayTimeout // 504
}; };
var delay = Backoff var delay = Backoff.DecorrelatedJitterBackoffV2(
.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromMilliseconds(80), medianFirstRetryDelay: TimeSpan.FromMilliseconds(80),
retryCount: 5); retryCount: 5
);
var retryPolicy = HttpPolicyExtensions var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.Or<TimeoutRejectedException>() .Or<TimeoutRejectedException>()
@ -437,25 +460,29 @@ public sealed class App : Application
// Shorter timeout for local requests // Shorter timeout for local requests
var localTimeout = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(3)); var localTimeout = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(3));
var localDelay = Backoff var localDelay = Backoff.DecorrelatedJitterBackoffV2(
.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromMilliseconds(50), medianFirstRetryDelay: TimeSpan.FromMilliseconds(50),
retryCount: 3); retryCount: 3
);
var localRetryPolicy = HttpPolicyExtensions var localRetryPolicy = HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
.Or<TimeoutRejectedException>() .Or<TimeoutRejectedException>()
.OrResult(r => retryStatusCodes.Contains(r.StatusCode)) .OrResult(r => retryStatusCodes.Contains(r.StatusCode))
.WaitAndRetryAsync(localDelay, onRetryAsync: (_, _) => .WaitAndRetryAsync(
{ localDelay,
Debug.WriteLine("Retrying local request..."); onRetryAsync: (_, _) =>
return Task.CompletedTask; {
}); Debug.WriteLine("Retrying local request...");
return Task.CompletedTask;
}
);
// named client for update // named client for update
services.AddHttpClient("UpdateClient") services.AddHttpClient("UpdateClient").AddPolicyHandler(retryPolicy);
.AddPolicyHandler(retryPolicy);
// Add Refit clients // Add Refit clients
services.AddRefitClient<ICivitApi>(defaultRefitSettings) services
.AddRefitClient<ICivitApi>(defaultRefitSettings)
.ConfigureHttpClient(c => .ConfigureHttpClient(c =>
{ {
c.BaseAddress = new Uri("https://civitai.com"); c.BaseAddress = new Uri("https://civitai.com");
@ -464,27 +491,31 @@ public sealed class App : Application
.AddPolicyHandler(retryPolicy); .AddPolicyHandler(retryPolicy);
// Add Refit client managers // Add Refit client managers
services.AddHttpClient("A3Client") services
.AddHttpClient("A3Client")
.AddPolicyHandler(localTimeout.WrapAsync(localRetryPolicy)); .AddPolicyHandler(localTimeout.WrapAsync(localRetryPolicy));
ConditionalAddLogViewer(services); ConditionalAddLogViewer(services);
// Add logging // Add logging
services.AddLogging(builder => services.AddLogging(builder =>
{ {
builder.ClearProviders(); builder.ClearProviders();
builder.AddFilter("Microsoft.Extensions.Http", LogLevel.Warning) builder
.AddFilter("Microsoft.Extensions.Http", LogLevel.Warning)
.AddFilter("Microsoft.Extensions.Http.DefaultHttpClientFactory", LogLevel.Warning) .AddFilter("Microsoft.Extensions.Http.DefaultHttpClientFactory", LogLevel.Warning)
.AddFilter("Microsoft", LogLevel.Warning) .AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning); .AddFilter("System", LogLevel.Warning);
builder.SetMinimumLevel(LogLevel.Debug); builder.SetMinimumLevel(LogLevel.Debug);
#if DEBUG #if DEBUG
builder.AddNLog(ConfigureLogging(), builder.AddNLog(
ConfigureLogging(),
new NLogProviderOptions new NLogProviderOptions
{ {
IgnoreEmptyEventId = false, IgnoreEmptyEventId = false,
CaptureEventId = EventIdCaptureType.Legacy CaptureEventId = EventIdCaptureType.Legacy
}); }
);
#else #else
builder.AddNLog(ConfigureLogging()); builder.AddNLog(ConfigureLogging());
#endif #endif
@ -501,8 +532,8 @@ public sealed class App : Application
/// <exception cref="NullReferenceException">If Application.Current is null</exception> /// <exception cref="NullReferenceException">If Application.Current is null</exception>
public static void Shutdown(int exitCode = 0) public static void Shutdown(int exitCode = 0)
{ {
if (Current is null) throw new NullReferenceException( if (Current is null)
"Current Application was null when Shutdown called"); throw new NullReferenceException("Current Application was null when Shutdown called");
if (Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime) if (Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
{ {
lifetime.Shutdown(exitCode); lifetime.Shutdown(exitCode);
@ -516,11 +547,9 @@ public sealed class App : Application
var settingsManager = Services.GetRequiredService<ISettingsManager>(); var settingsManager = Services.GetRequiredService<ISettingsManager>();
// If RemoveFolderLinksOnShutdown is set, delete all package junctions // If RemoveFolderLinksOnShutdown is set, delete all package junctions
if (settingsManager is if (
{ settingsManager is { IsLibraryDirSet: true, Settings.RemoveFolderLinksOnShutdown: true }
IsLibraryDirSet: true, )
Settings.RemoveFolderLinksOnShutdown: true
})
{ {
var sharedFolders = Services.GetRequiredService<ISharedFolders>(); var sharedFolders = Services.GetRequiredService<ISharedFolders>();
sharedFolders.RemoveLinksForAllPackages(); sharedFolders.RemoveLinksForAllPackages();
@ -542,40 +571,48 @@ public sealed class App : Application
var setupBuilder = LogManager.Setup(); var setupBuilder = LogManager.Setup();
ConditionalAddLogViewerNLog(setupBuilder); ConditionalAddLogViewerNLog(setupBuilder);
setupBuilder.LoadConfiguration(builder => { setupBuilder.LoadConfiguration(builder =>
var debugTarget = builder.ForTarget("console").WriteTo(new DebuggerTarget {
{ var debugTarget = builder
Layout = "${message}" .ForTarget("console")
}).WithAsync(); .WriteTo(new DebuggerTarget { Layout = "${message}" })
.WithAsync();
var fileTarget = builder.ForTarget("logfile").WriteTo(new FileTarget
{ var fileTarget = builder
Layout = "${longdate}|${level:uppercase=true}|${logger}|${message:withexception=true}", .ForTarget("logfile")
ArchiveOldFileOnStartup = true, .WriteTo(
FileName = "${specialfolder:folder=ApplicationData}/StabilityMatrix/app.log", new FileTarget
ArchiveFileName = "${specialfolder:folder=ApplicationData}/StabilityMatrix/app.{#}.log", {
ArchiveNumbering = ArchiveNumberingMode.Rolling, Layout =
MaxArchiveFiles = 2 "${longdate}|${level:uppercase=true}|${logger}|${message:withexception=true}",
}).WithAsync(); ArchiveOldFileOnStartup = true,
FileName =
"${specialfolder:folder=ApplicationData}/StabilityMatrix/app.log",
ArchiveFileName =
"${specialfolder:folder=ApplicationData}/StabilityMatrix/app.{#}.log",
ArchiveNumbering = ArchiveNumberingMode.Rolling,
MaxArchiveFiles = 2
}
)
.WithAsync();
// Filter some sources to be warn levels or above only // Filter some sources to be warn levels or above only
builder.ForLogger("System.*").WriteToNil(NLog.LogLevel.Warn); builder.ForLogger("System.*").WriteToNil(NLog.LogLevel.Warn);
builder.ForLogger("Microsoft.*").WriteToNil(NLog.LogLevel.Warn); builder.ForLogger("Microsoft.*").WriteToNil(NLog.LogLevel.Warn);
builder.ForLogger("Microsoft.Extensions.Http.*").WriteToNil(NLog.LogLevel.Warn); builder.ForLogger("Microsoft.Extensions.Http.*").WriteToNil(NLog.LogLevel.Warn);
builder.ForLogger().FilterMinLevel(NLog.LogLevel.Trace).WriteTo(debugTarget); builder.ForLogger().FilterMinLevel(NLog.LogLevel.Trace).WriteTo(debugTarget);
builder.ForLogger().FilterMinLevel(NLog.LogLevel.Debug).WriteTo(fileTarget); builder.ForLogger().FilterMinLevel(NLog.LogLevel.Debug).WriteTo(fileTarget);
#if DEBUG #if DEBUG
var logViewerTarget = builder.ForTarget("DataStoreLogger").WriteTo(new DataStoreLoggerTarget() var logViewerTarget = builder
{ .ForTarget("DataStoreLogger")
Layout = "${message}" .WriteTo(new DataStoreLoggerTarget() { Layout = "${message}" });
});
builder.ForLogger().FilterMinLevel(NLog.LogLevel.Trace).WriteTo(logViewerTarget); builder.ForLogger().FilterMinLevel(NLog.LogLevel.Trace).WriteTo(logViewerTarget);
#endif #endif
}); });
// Sentry // Sentry
if (SentrySdk.IsEnabled) if (SentrySdk.IsEnabled)
{ {
@ -594,20 +631,26 @@ public sealed class App : Application
} }
LogManager.ReconfigExistingLoggers(); LogManager.ReconfigExistingLoggers();
return LogManager.Configuration; return LogManager.Configuration;
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void ConditionalAddLogViewer(IServiceCollection services) private static void ConditionalAddLogViewer(IServiceCollection services)
{ {
#if DEBUG
services.AddLogViewer(); services.AddLogViewer();
#endif
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void ConditionalAddLogViewerNLog(ISetupBuilder setupBuilder) private static void ConditionalAddLogViewerNLog(ISetupBuilder setupBuilder)
{ {
setupBuilder.SetupExtensions(extensionBuilder => #if DEBUG
extensionBuilder.RegisterTarget<DataStoreLoggerTarget>("DataStoreLogger")); setupBuilder.SetupExtensions(
extensionBuilder =>
extensionBuilder.RegisterTarget<DataStoreLoggerTarget>("DataStoreLogger")
);
#endif
} }
} }

76
StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs

@ -22,11 +22,13 @@ using FluentAvalonia.UI.Windowing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using StabilityMatrix.Avalonia.Animations; using StabilityMatrix.Avalonia.Animations;
using StabilityMatrix.Avalonia.Controls; using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Diagnostics.Views;
using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels; using StabilityMatrix.Avalonia.ViewModels;
using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Processes; using StabilityMatrix.Core.Processes;
#if DEBUG
using StabilityMatrix.Avalonia.Diagnostics.Views;
#endif
namespace StabilityMatrix.Avalonia.Views; namespace StabilityMatrix.Avalonia.Views;
@ -43,19 +45,21 @@ public partial class MainWindow : AppWindowBase
notificationService = null!; notificationService = null!;
navigationService = null!; navigationService = null!;
} }
public MainWindow(INotificationService notificationService, INavigationService navigationService) public MainWindow(
INotificationService notificationService,
INavigationService navigationService
)
{ {
this.notificationService = notificationService; this.notificationService = notificationService;
this.navigationService = navigationService; this.navigationService = navigationService;
InitializeComponent(); InitializeComponent();
#if DEBUG #if DEBUG
this.AttachDevTools(); this.AttachDevTools();
LogWindow.Attach(this, App.Services); LogWindow.Attach(this, App.Services);
#endif #endif
TitleBar.ExtendsContentIntoTitleBar = true; TitleBar.ExtendsContentIntoTitleBar = true;
TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex; TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex;
} }
@ -64,15 +68,17 @@ public partial class MainWindow : AppWindowBase
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
navigationService.SetFrame(FrameView ?? throw new NullReferenceException("Frame not found")); navigationService.SetFrame(
FrameView ?? throw new NullReferenceException("Frame not found")
);
// Navigate to first page // Navigate to first page
if (DataContext is not MainWindowViewModel vm) if (DataContext is not MainWindowViewModel vm)
{ {
throw new NullReferenceException("DataContext is not MainWindowViewModel"); throw new NullReferenceException("DataContext is not MainWindowViewModel");
} }
navigationService.NavigateTo(vm.Pages[0], new DrillInNavigationTransitionInfo()); navigationService.NavigateTo(vm.Pages[0], new DrillInNavigationTransitionInfo());
} }
@ -81,7 +87,7 @@ public partial class MainWindow : AppWindowBase
base.OnOpened(e); base.OnOpened(e);
Application.Current!.ActualThemeVariantChanged += OnActualThemeVariantChanged; Application.Current!.ActualThemeVariantChanged += OnActualThemeVariantChanged;
var theme = ActualThemeVariant; var theme = ActualThemeVariant;
// Enable mica for Windows 11 // Enable mica for Windows 11
if (IsWindows11 && theme != FluentAvaloniaTheme.HighContrastTheme) if (IsWindows11 && theme != FluentAvaloniaTheme.HighContrastTheme)
@ -93,11 +99,10 @@ public partial class MainWindow : AppWindowBase
protected override void OnClosing(WindowClosingEventArgs e) protected override void OnClosing(WindowClosingEventArgs e)
{ {
// Show confirmation if package running // Show confirmation if package running
var launchPageViewModel = App.Services var launchPageViewModel = App.Services.GetRequiredService<LaunchPageViewModel>();
.GetRequiredService<LaunchPageViewModel>();
launchPageViewModel.OnMainWindowClosing(e); launchPageViewModel.OnMainWindowClosing(e);
base.OnClosing(e); base.OnClosing(e);
} }
@ -106,7 +111,7 @@ public partial class MainWindow : AppWindowBase
base.OnLoaded(e); base.OnLoaded(e);
// Initialize notification service using this window as the visual root // Initialize notification service using this window as the visual root
notificationService.Initialize(this); notificationService.Initialize(this);
// Attach error notification handler for image loader // Attach error notification handler for image loader
if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader) if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader)
{ {
@ -117,7 +122,7 @@ public partial class MainWindow : AppWindowBase
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
{ {
base.OnUnloaded(e); base.OnUnloaded(e);
// Detach error notification handler for image loader // Detach error notification handler for image loader
if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader) if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader)
{ {
@ -134,20 +139,22 @@ public partial class MainWindow : AppWindowBase
{ {
return; return;
} }
if (nvi.Tag is null) if (nvi.Tag is null)
{ {
throw new InvalidOperationException("NavigationViewItem Tag is null"); throw new InvalidOperationException("NavigationViewItem Tag is null");
} }
if (nvi.Tag is not ViewModelBase vm) if (nvi.Tag is not ViewModelBase vm)
{ {
throw new InvalidOperationException($"NavigationViewItem Tag must be of type ViewModelBase, not {nvi.Tag?.GetType()}"); throw new InvalidOperationException(
$"NavigationViewItem Tag must be of type ViewModelBase, not {nvi.Tag?.GetType()}"
);
} }
navigationService.NavigateTo(vm, new BetterEntranceNavigationTransition()); navigationService.NavigateTo(vm, new BetterEntranceNavigationTransition());
} }
} }
private void OnActualThemeVariantChanged(object? sender, EventArgs e) private void OnActualThemeVariantChanged(object? sender, EventArgs e)
{ {
if (IsWindows11) if (IsWindows11)
@ -163,7 +170,7 @@ public partial class MainWindow : AppWindowBase
} }
} }
} }
private void OnImageLoadFailed(object? sender, ImageLoadFailedEventArgs e) private void OnImageLoadFailed(object? sender, ImageLoadFailedEventArgs e)
{ {
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
@ -173,24 +180,30 @@ public partial class MainWindow : AppWindowBase
notificationService.ShowPersistent( notificationService.ShowPersistent(
"Failed to load image", "Failed to load image",
$"Could not load '{displayName}'\n({e.Exception.Message})", $"Could not load '{displayName}'\n({e.Exception.Message})",
NotificationType.Warning); NotificationType.Warning
);
}); });
} }
private void TryEnableMicaEffect() private void TryEnableMicaEffect()
{ {
TransparencyBackgroundFallback = Brushes.Transparent; TransparencyBackgroundFallback = Brushes.Transparent;
TransparencyLevelHint = new[] TransparencyLevelHint = new[]
{ {
WindowTransparencyLevel.Mica, WindowTransparencyLevel.Mica,
WindowTransparencyLevel.AcrylicBlur, WindowTransparencyLevel.AcrylicBlur,
WindowTransparencyLevel.Blur WindowTransparencyLevel.Blur
}; };
if (ActualThemeVariant == ThemeVariant.Dark) if (ActualThemeVariant == ThemeVariant.Dark)
{ {
var color = this.TryFindResource("SolidBackgroundFillColorBase", var color = this.TryFindResource(
ThemeVariant.Dark, out var value) ? (Color2)(Color)value! : new Color2(32, 32, 32); "SolidBackgroundFillColorBase",
ThemeVariant.Dark,
out var value
)
? (Color2)(Color)value!
: new Color2(32, 32, 32);
color = color.LightenPercent(-0.8f); color = color.LightenPercent(-0.8f);
@ -199,8 +212,13 @@ public partial class MainWindow : AppWindowBase
else if (ActualThemeVariant == ThemeVariant.Light) else if (ActualThemeVariant == ThemeVariant.Light)
{ {
// Similar effect here // Similar effect here
var color = this.TryFindResource("SolidBackgroundFillColorBase", var color = this.TryFindResource(
ThemeVariant.Light, out var value) ? (Color2)(Color)value! : new Color2(243, 243, 243); "SolidBackgroundFillColorBase",
ThemeVariant.Light,
out var value
)
? (Color2)(Color)value!
: new Color2(243, 243, 243);
color = color.LightenPercent(0.5f); color = color.LightenPercent(0.5f);

Loading…
Cancel
Save