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:
2026-08-19 00:18:56 +02:00
co-authored by Claude Sonnet 5
parent 979511ab6a
commit f868b3a259
6 changed files with 211 additions and 2 deletions
+9
View File
@@ -22,6 +22,13 @@ public class SyncEngine : IDisposable
public SyncStatus Status { get; private set; } = new();
public event Action<SyncStatus>? StatusChanged;
/// <summary>
/// Feuert, wenn ein Pull tatsächlich Ereignisse angewendet hat (siehe TODO 10.1.11) - der
/// Desktop-Client abonniert das, um die gerade sichtbare Seite neu zu laden, da
/// EventApplier absichtlich an jedem ViewModel vorbei direkt auf die LiteDB schreibt (siehe
/// EventApplier-Klassenkommentar).
/// </summary>
public event Action? DataChanged;
public SyncEngine(EventQueue queue, ConflictResolver resolver, EventApplier applier,
AttachmentSyncer attachments, HttpClient http, SyncConfig config, AppLogger? logger = null)
@@ -200,6 +207,7 @@ public class SyncEngine : IDisposable
{
await _applier.ApplyAsync(remote);
_queue.Acknowledge([local.EventId]);
DataChanged?.Invoke();
}
// LocalWon: Ereignis bleibt unbestätigt in der Queue - der nächste PushAsync-Lauf
// versucht es erneut, jetzt mit dem soeben aktualisierten BasedOnServerSeq.
@@ -231,6 +239,7 @@ public class SyncEngine : IDisposable
if (c.Resolution == "RemoteWon") await _applier.ApplyAsync(evt);
}
_queue.SetLastServerSeq(resp.ServerSequenceNr);
DataChanged?.Invoke();
return (resp.Events.Count, conflicts);
}