feat: Dunkelmodus, Fenstergröße merken, Papierkorb für Löschvorgänge (12.4, 14.3, 14.6)

Dunkelmodus über neuen Einstellungen-Tab "Darstellung" (Systemvorgabe/Hell/Dunkel),
Fenstergröße/Maximiert-Status wird über Sitzungen hinweg gemerkt (bewusst ohne
Fensterposition), und ein generischer Snapshot-basierter Papierkorb (30 Tage) für
Sitzpläne, Noten, Notenschlüssel-Vorlagen, Aufgaben und Zeiteinträge. Details und
bewusste Scope-Entscheidungen (Spaltenbreiten zurückgestellt, Farb-Audit für
Dunkelmodus offen, welche Entitäten der Papierkorb abdeckt) in TODO.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 16:26:10 +02:00
co-authored by Claude Sonnet 5
parent d9d007cd4b
commit 331033db5c
20 changed files with 1023 additions and 12 deletions
+25
View File
@@ -1,6 +1,8 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Styling;
using LehrerApp.Core.Interfaces;
using LehrerApp.Core.Services;
using LehrerApp.Data;
using LehrerApp.Desktop.Services;
@@ -24,6 +26,13 @@ public class App : Application
public override void OnFrameworkInitializationCompleted()
{
// Vor jedem Fenster (auch dem DB-Passwort-Prompt) anwenden, damit kein kurzes Aufblitzen
// der Systemvorgabe zu sehen ist, falls Hell/Dunkel manuell erzwungen wurde. Eigenständige
// Instanz statt über den DI-Container (der erst in BuildServices() entsteht, die den
// Passwort-Prompt bereits verzögert) - dieselbe appData-Datei wie später der
// DI-Singleton, rein lesend also unproblematisch doppelt konstruiert.
ApplyTheme(new AppearanceSettingsService(AppBootstrapper.ResolveAppDataPath()).Load());
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Verschlüsselte Datenbank (13.3.4): Passwort abfragen, bevor die Datenbank
@@ -57,6 +66,10 @@ public class App : Application
Services = _serviceProvider;
Services.GetRequiredService<AppLogger>().Info("Anwendung gestartet.");
GlobalExceptionHandler.AttachNotifications(Services.GetRequiredService<NotificationService>());
// Papierkorb (14.3): Einträge älter als 30 Tage endgültig entfernen. Beim Start statt per
// Timer - reicht für ein Werkzeug, das ohnehin nur "Fehlklick eben rückgängig machen" sein
// soll, kein dauerhaftes Archiv.
Services.GetRequiredService<ITrashRepository>().PurgeOlderThan(DateTime.UtcNow.AddDays(-30));
if (!_exitHandlerAttached)
{
@@ -67,12 +80,24 @@ public class App : Application
var mainVm = Services.GetRequiredService<MainWindowViewModel>();
WireCallbacks(mainVm);
var main = new MainWindow { DataContext = mainVm };
main.EnableWindowSizePersistence(Services.GetRequiredService<WindowSettingsService>());
if (Services.GetService<SyncEngine>() is { } syncEngine)
main.EnableFinalSync(syncEngine);
desktop.MainWindow = main;
if (showImmediately) main.Show();
}
/// <summary>Wechselt die Darstellung sofort, ohne Neustart (12.4) — Avalonia stylt den
/// gesamten sichtbaren Baum automatisch neu, sobald sich <see cref="ThemeVariant"/>
/// ändert.</summary>
public static void ApplyTheme(AppTheme theme) =>
Current!.RequestedThemeVariant = theme switch
{
AppTheme.Light => ThemeVariant.Light,
AppTheme.Dark => ThemeVariant.Dark,
_ => ThemeVariant.Default,
};
private static void DisposeServices()
{
if (_serviceProvider is null) return;