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
+33
View File
@@ -66,6 +66,7 @@ public class LiteDbContext : IDisposable
public ILiteCollection<SchoolHoliday> SchoolHolidays => _db.GetCollection<SchoolHoliday>("school_holidays");
public ILiteCollection<SupervisionDuty> SupervisionDuties => _db.GetCollection<SupervisionDuty>("supervision_duties");
public ILiteCollection<SubstitutionEntry> SubstitutionEntries => _db.GetCollection<SubstitutionEntry>("substitution_entries");
public ILiteCollection<TrashedItem> TrashedItems => _db.GetCollection<TrashedItem>("trash");
public void Checkpoint() => _db.Checkpoint();
@@ -182,6 +183,38 @@ public class LiteDbContext : IDisposable
Documentation.Delete(id);
}
// ── Papierkorb (14.3) ────────────────────────────────────────────────────
//
// Absichtlich hier statt in einer eigenen TrashRepository-Konstruktorabhängigkeit: jede
// Fach-Repository hat db (LiteDbContext) bereits im Konstruktor, ein zusätzlicher Papierkorb-
// Parameter wäre nur Boilerplate. Snapshot/Restore sind generisch über den Modelltyp, die
// eigentliche Wiederherstellung ruft aber bewusst die jeweilige Repository.Save-Methode auf
// (nicht direkt die LiteDB-Collection) — nur die kennt Validierung und OnChange-Ereignis für
// ihr Modell.
/// <summary>Legt einen Papierkorb-Eintrag an, BEVOR die aufrufende Repository die Entität aus
/// ihrer eigentlichen Collection löscht.</summary>
internal void MoveToTrash<T>(string entityType, Guid entityId, T entity, string summary) =>
TrashedItems.Insert(new TrashedItem
{
EntityType = entityType,
EntityId = entityId,
Snapshot = System.Text.Json.JsonSerializer.Serialize(entity),
Summary = summary,
});
/// <summary>Liefert die gelöschte Entität aus dem Papierkorb-Eintrag zurück und entfernt den
/// Eintrag - unabhängig davon, ob die aufrufende Repository den Schnappschuss danach
/// erfolgreich speichert (ein fehlgeschlagenes Restore soll nicht endlos wiederholbar sein,
/// derselbe Datensatz landet notfalls einfach nicht wieder im Papierkorb).</summary>
internal T? RestoreFromTrash<T>(Guid trashId)
{
var item = TrashedItems.FindById(trashId);
if (item is null) return default;
TrashedItems.Delete(trashId);
return System.Text.Json.JsonSerializer.Deserialize<T>(item.Snapshot);
}
internal void ExecuteInTransaction(Action action)
{
_db.BeginTrans();