v2.53.1 — MED-1: Tombstone-Race behoben (Snapshot vor listSongs + Server-Zeit)

## MED-1 (Review-Fix)
- sync_service.dart: letzterSync-Snapshot wird VOR listSongs gelesen und am
  Sync-Ende persistiert (Sync-BEGINN statt now-am-Ende) — Löschungen, die
  zwischen listSongs und Sync-Ende auf dem Server ankommen, werden im
  nächsten Sync korrekt angewendet statt als „bereits gesehen“ übersprungen
- cloud_screen.dart: _download schreibt cloud_last_sync_ts nicht mehr
  nachträglich mit now-am-Ende (redundant + Race-Wieder-Einführung);
  UI-Anzeige liest den von SyncService persistierten Snapshot
- melo_cloud.py: handle_delete stempelt deleted_at IMMER mit Server-Zeit
  (datetime('now')) — Client-Timestamps werden ignoriert (Uhr-Drift würde
  Löschungen dauerhaft überspringen lassen; konsistente Uhr für alle Geräte)
This commit is contained in:
Dustin
2026-08-05 11:22:36 +02:00
parent 2d735464c0
commit 3fe20e1c7b
2 changed files with 32 additions and 15 deletions
+14 -7
View File
@@ -790,15 +790,22 @@ class _CloudScreenState extends State<CloudScreen>
return;
}
final erfolgreich = await _syncAlles();
if (!erfolgreich) return; // cloud_last_sync nur bei Erfolg schreiben
if (!erfolgreich) return; // SyncService persistiert cloud_last_sync nur bei Erfolg
// UI: letzten Sync anzeigen. KEINE zweite cloud_last_sync_ts-Schreibung
// mit now-am-Ende hier — SyncService persistiert bereits den
// Sync-BEGINN-Snapshot (MED-1: Tombstone-Race). Eine spätere Schreibung
// würde die Löschungen zwischen listSongs und Sync-Ende wieder als
// „bereits gesehen“ markieren.
final p = await SharedPreferences.getInstance();
final now = DateTime.now();
final zeit = _formatZeit(now);
await p.setString('cloud_last_sync', zeit);
await p.setString('cloud_last_sync_ts', now.toIso8601String());
final letzterTs = p.getString('cloud_last_sync_ts');
if (mounted) {
setState(() => _letzterSync = zeit);
_berechneNaechstenSync();
setState(() {
_letzterSyncTs = letzterTs;
_letzterSync = letzterTs != null
? _formatZeit(DateTime.tryParse(letzterTs) ?? DateTime.now())
: _formatZeit(DateTime.now());
_berechneNaechstenSync();
});
}
}