v2.53 — Tombstone-Sync + Konflikt-Report (Sprint E): deleted_at, lokal nachgezogene Löschungen, Willkommen-zurück-Dialog

This commit is contained in:
Dustin
2026-08-05 11:14:21 +02:00
parent 22ce611537
commit 2d735464c0
3 changed files with 244 additions and 9 deletions
+104
View File
@@ -118,6 +118,7 @@ class _CloudScreenState extends State<CloudScreen>
_berechneNaechstenSync();
};
_sync.onSyncEnde = _syncEnde;
_sync.onBericht = _zeigeKonfliktReport;
// Verbindung stellt der CloudService beim App-Start her (MeloHome.initState).
// Hier nur Settings laden + Serverdaten, sobald der Service verbunden ist.
_ladeSettings();
@@ -262,6 +263,109 @@ class _CloudScreenState extends State<CloudScreen>
}
}
/// Konflikt-Report (Sprint E): Zusammenfassung nach langem Offline-Sync.
/// „Willkommen zurück! Seit letztem Sync: +8 neue · 3 gelöscht · ⭐5“
void _zeigeKonfliktReport(SyncBericht bericht) {
if (!mounted) return;
final titel = 'Willkommen zurück!';
final zeilen = <String>[
'Seit deinem letzten Sync:',
if (bericht.neueSongs > 0) ' ${bericht.neueSongs} neue Songs',
if (bericht.geloeschteSongs > 0) '🗑️ ${bericht.geloeschteSongs} gelöscht',
if (bericht.favoritenGeaendert > 0)
'${bericht.favoritenGeaendert} Favoriten geändert',
];
showDialog<void>(
context: context,
barrierDismissible: true,
builder: (ctx) => AlertDialog(
backgroundColor: MeloTheme.dunkel1,
title: Text(titel,
style: const TextStyle(color: Colors.white, fontSize: 18)),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: zeilen
.map((z) => Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Text(z,
style: const TextStyle(
color: MeloTheme.textSekundaer,
fontSize: 14)),
))
.toList(),
),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(ctx);
if (bericht.details.isNotEmpty) {
_zeigeReportDetails(bericht);
}
},
child: const Text('Details',
style: TextStyle(color: MeloTheme.rot)),
),
TextButton(
onPressed: () => Navigator.pop(ctx),
child: const Text('OK',
style: TextStyle(color: Colors.white)),
),
],
),
);
}
void _zeigeReportDetails(SyncBericht bericht) {
if (!mounted) return;
showModalBottomSheet<void>(
context: context,
backgroundColor: MeloTheme.dunkel1,
builder: (ctx) => SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Änderungen',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
Flexible(
child: ListView(
shrinkWrap: true,
children: bericht.details
.map((d) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Text(d,
style: const TextStyle(
color: MeloTheme.textSekundaer,
fontSize: 13)),
))
.toList(),
),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: TextButton(
onPressed: () => Navigator.pop(ctx),
child: const Text('Schließen',
style: TextStyle(color: MeloTheme.rot)),
),
),
],
),
),
),
);
}
// ─── 📜 Sync-Historie (fürs Dashboard) ───
static const _historieKey = 'cloud_sync_history';