feat: sichtbare Seite nach eingehendem Sync automatisch neu laden
EventApplier schreibt eingehende Sync-Ereignisse absichtlich direkt auf die rohe LiteDB-Collection (Ping-Pong-Vermeidung), benachrichtigt dabei aber kein ViewModel - eine per Sync empfangene neue Stunde erschien bisher erst nach manuellem Neuladen (z.B. Tab-Wechsel). Neues SyncEngine.DataChanged-Ereignis, gefeuert nach jedem Pull mit Ereignissen sowie bei einer RemoteWon-Konfliktauflösung; SyncStatusViewModel reicht es durch. MainWindowViewModel abonniert es und lädt ausschließlich die gerade sichtbare Seite über ihren eigenen, längst vorhandenen Lade-Einstieg neu - keine Navigation weg von offenen Detailansichten, keine neue Lade-Logik, und eine laufende Inline-Bearbeitung (Schülerdetail) wird nicht überschrieben. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1669,6 +1669,42 @@ die Docker-Verifikation unter 10.2.4 (kein Docker im Entwicklungsstand verfügba
|
||||
setzt `EventQueue.SetLastServerSeq(0)` und stößt danach `SyncEngine.SyncNowAsync()` an —
|
||||
sicher wiederholbar, da `EventApplier` jedes Ereignis idempotent per Upsert/Delete-by-Id
|
||||
anwendet.
|
||||
- [x] **10.1.11** Offene ViewModels aktualisierten sich nicht automatisch, wenn per Sync
|
||||
eingehende Ereignisse angewendet werden (Nutzer-Bug-Report: eine per Sync empfangene neue
|
||||
Stunde erschien im Stundenplan/Unterrichtsplanung erst nach Schließen und erneutem Öffnen
|
||||
des Tabs — kein Datenverlust, nur ein reines Anzeigeproblem).
|
||||
|
||||
**Ursache:** `EventApplier.ApplyAsync` schreibt bewusst immer direkt auf die rohe LiteDB-
|
||||
Collection (`db.Students.Upsert(...)` etc.), nie über eine Repository-Save/Delete-Methode —
|
||||
sonst würde der `OnChange`-Hook erneut feuern und die gerade angewendete Änderung als neues
|
||||
*ausgehendes* Ereignis re-enqueuen (Sync-Ping-Pong, siehe Kommentar am Klassenkopf). Genau
|
||||
dieser direkte Collection-Zugriff bedeutet aber auch, dass kein ViewModel benachrichtigt
|
||||
wird — viele ViewModels haben zwar bereits ein `Refresh()`/`Load...()`, das man manuell
|
||||
auslösen kann (z.B. `PlanningViewModels.LoadLessons`, `GroupViewModels.LoadGroups`), aber
|
||||
nichts ruft das automatisch auf, wenn `SyncEngine.PullAsync` im Hintergrund neue Daten
|
||||
anwendet.
|
||||
|
||||
**Umsetzung** (zunächst für v1 zurückgestellt, dann doch umgesetzt, da leicht möglich): neues
|
||||
`SyncEngine.DataChanged`-Ereignis, gefeuert nach jedem Pull mit mindestens einem Ereignis
|
||||
sowie nach einer RemoteWon-Konfliktauflösung (dort wird ebenso lokal Daten angewendet).
|
||||
`SyncStatusViewModel` reicht es unverändert durch (bereits als DI-Singleton überall
|
||||
verfügbar, kein neuer Dienst nötig). `MainWindowViewModel` abonniert es und lädt darauf
|
||||
**ausschließlich die gerade sichtbare Seite** (`CurrentPage`) über ihren eigenen, längst
|
||||
vorhandenen Lade-Einstieg neu (Type-Switch: `DashboardViewModel`/`GroupListViewModel`/
|
||||
`StudentListViewModel`/`TimetableViewModel`/`WorkloadViewModel` per `RefreshCommand`/
|
||||
`Load()`, `GroupDetailViewModel` per `LoadGroup(Group.Id)`, `StudentDetailViewModel` per
|
||||
`LoadStudent(Student.Id)` — letzteres nur wenn `!IsEditing`, um eine laufende
|
||||
Inline-Bearbeitung von Name/Geschlecht nicht zu überschreiben; `GroupDetailViewModel` hat
|
||||
kein Äquivalent, da dort ausschließlich über Dialoge bearbeitet wird). Bewusst **keine**
|
||||
Navigation weg von einer offenen Detailansicht und keine neue Lade-Logik — nur die fehlende
|
||||
Verdrahtung zwischen Sync-Empfang und den längst vorhandenen Refresh-Methoden. `SyncEngine.
|
||||
DataChanged` feuert aus dem Sync-Timer-Hintergrundthread; `MainWindowViewModel` springt
|
||||
deshalb wie `NotificationService.Show` per `Dispatcher.UIThread` zurück auf den UI-Thread.
|
||||
Neue Tests: `SyncEngineTests` (`DataChanged` bei Pull mit/ohne Ereignisse, bei RemoteWon),
|
||||
`SyncStatusViewModelTests` (Durchreichen). `MainWindowViewModel` selbst ist mangels
|
||||
Testinfrastruktur für seine vielen ViewModel-Abhängigkeiten nicht direkt getestet — die
|
||||
Refresh-Aufrufe delegieren aber ausschließlich an bereits anderswo getestete
|
||||
Lade-Methoden der einzelnen ViewModels.
|
||||
|
||||
### 10.2 Server
|
||||
- [x] **10.2.1** Benutzerverwaltung/Registrierung prüfen und absichern
|
||||
|
||||
Reference in New Issue
Block a user