using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; using Avalonia.Threading; using Predictalytics.Hosting; using Predictalytics.Shell.ViewModels; using Predictalytics.Shell.Views; using Serilog; namespace Predictalytics.Shell; /// /// Avalonia-Anwendungsobjekt. /// /// Die Basisklasse wird voll qualifiziert angegeben: innerhalb von /// Predictalytics.* loest der kurze Name Application auf den /// Namespace Predictalytics.Application auf, nicht auf den Avalonia-Typ. /// /// public partial class App : global::Avalonia.Application { private IDisposable? _licenseWatch; public override void Initialize() => AvaloniaXamlLoader.Load(this); public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { // Das Lizenzfenster darf beim Schliessen nicht die Anwendung beenden — // danach soll ja erst das Hauptfenster kommen. desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; desktop.Exit += (_, _) => _licenseWatch?.Dispose(); // Nicht awaiten: OnFrameworkInitializationCompleted muss zurueckkehren, // damit die Nachrichtenschleife anlaufen kann. Dispatcher.UIThread.Post(async () => await StartupAsync(desktop)); } base.OnFrameworkInitializationCompleted(); } private async Task StartupAsync(IClassicDesktopStyleApplicationLifetime desktop) { // ─── Lizenzschranke: ohne nutzbare Lizenz keine Anwendung ─── var client = LicenseGuard.CreateClient(); var result = await LicenseGuard.RevalidateAsync(client); if (!LicenseGuard.IsUsable(client, result)) { var licenseWindow = new LicenseWindow(client, result); desktop.MainWindow = licenseWindow; licenseWindow.Show(); if (!await licenseWindow.Completion) { desktop.Shutdown(); return; } } // ─── Hauptfenster ─── var viewModel = new MainWindowViewModel(); var window = new MainWindow(viewModel); // Serilog-Aufbau liegt in Predictalytics.Hosting; hier kommt nur der // Terminal-Sink dazu, der selbst auf den UI-Thread marshallt. LoggingSetup.Configure(viewModel.AppendLog); LoggingSetup.LogStartupBanner(); desktop.MainWindow = window; desktop.ShutdownMode = ShutdownMode.OnMainWindowClose; window.Show(); viewModel.Start(); // Waehrend des Betriebs alle 12 h nachpruefen (Widerruf, Ablauf, Offline-Frist). _licenseWatch = LicenseGuard.StartPeriodicRevalidation(client, unusable => Dispatcher.UIThread.Post(async () => { await Dialogs.ShowErrorAsync(window, "Lizenzfehler", $"Die Lizenz ist nicht mehr gültig ({unusable.State}):\n{unusable.Message}\n\nPredictalytics wird beendet."); desktop.Shutdown(); })); desktop.Exit += (_, _) => { Log.Information("Application shutting down."); Log.CloseAndFlush(); }; } }