Was-ist-neu-Bericht als In-App-Dialog nach dem Abgleich

This commit is contained in:
Hermes (Server)
2026-08-27 12:40:21 +02:00
parent 9de61bbf94
commit 676f2c5f29
3 changed files with 87 additions and 2 deletions
+19 -2
View File
@@ -30,6 +30,7 @@ import 'services/sync_service.dart';
import 'services/yt_download_service.dart';
import 'services/yt_search_service.dart';
import 'settings/app_settings.dart';
import 'shared/sync_bericht_dialog.dart';
import 'shared/theme.dart';
late final MeloAudioHandler _handler;
@@ -177,7 +178,7 @@ class _HomeShellState extends State<HomeShell> with WidgetsBindingObserver {
WidgetsBinding.instance.addObserver(this);
// Beim Start einmal mit dem Server abgleichen — neue Titel von anderen
// Geräten sind dann sofort da.
context.read<SyncService>().automatisch();
unawaited(_gleicheAbUndZeigeBericht());
unawaited(context.read<LibraryService>().ensureStartupPermissions());
unawaited(_pruefeGeteilteAdresse());
}
@@ -205,13 +206,29 @@ class _HomeShellState extends State<HomeShell> with WidgetsBindingObserver {
// auf dem Gerät wie am Server.
if (state == AppLifecycleState.resumed) {
if (Platform.isAndroid) _autoScan.pruefe();
context.read<SyncService>().automatisch();
unawaited(_gleicheAbUndZeigeBericht());
// Ein zweites Teilen startet die App nicht neu (singleTop), sondern
// bringt sie nur nach vorn — deshalb auch hier nachsehen.
unawaited(_pruefeGeteilteAdresse());
}
}
/// Gleicht ab und zeigt danach höchstens einmal den „Was ist neu"-Bericht.
Future<void> _gleicheAbUndZeigeBericht() async {
final sync = context.read<SyncService>();
await sync.automatisch();
if (!mounted) return;
final bericht = sync.bericht;
if (bericht == null) return;
// Zuerst quittieren: ein zweites Zurückkehren in die App soll denselben
// Bericht nicht erneut zeigen.
sync.berichtGesehen();
await showDialog<void>(
context: context,
builder: (_) => SyncBerichtDialog(bericht: bericht),
);
}
@override
Widget build(BuildContext context) {
final tabs = <Widget>[
+35
View File
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import '../services/sync_service.dart';
/// „Willkommen zurück" — was sich seit dem letzten erfolgreichen Abgleich
/// getan hat. Rein in-App, ohne Benachrichtigungs-Kanal und ohne neue
/// Abhängigkeit.
class SyncBerichtDialog extends StatelessWidget {
const SyncBerichtDialog({super.key, required this.bericht});
final SyncBericht bericht;
static String textFuer(SyncBericht b) {
if (b.istLeer) return 'Nichts Neues seit dem letzten Abgleich.';
final teile = <String>[];
if (b.neueSongs > 0) teile.add('${b.neueSongs} neue Titel');
if (b.geloeschte > 0) teile.add('${b.geloeschte} entfernt');
if (b.favoriten > 0) teile.add('${b.favoriten} Favoriten geändert');
return '${teile.join(' · ')}.';
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Willkommen zurück!'),
content: Text(textFuer(bericht)),
actions: [
FilledButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Alles klar'),
),
],
);
}
}
+33
View File
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:melo/services/sync_service.dart';
import 'package:melo/shared/sync_bericht_dialog.dart';
void main() {
Future<void> zeige(WidgetTester tester, SyncBericht bericht) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(body: SyncBerichtDialog(bericht: bericht)),
));
await tester.pump();
}
testWidgets('nennt neue und entfernte Titel', (tester) async {
await zeige(
tester,
const SyncBericht(neueSongs: 3, geloeschte: 1, favoriten: 0),
);
expect(find.text('Willkommen zurück!'), findsOneWidget);
expect(find.textContaining('3 neue Titel'), findsOneWidget);
expect(find.textContaining('1 entfernt'), findsOneWidget);
});
testWidgets('ohne Änderungen sagt er das auch', (tester) async {
await zeige(
tester,
const SyncBericht(neueSongs: 0, geloeschte: 0, favoriten: 0),
);
expect(find.textContaining('Nichts Neues'), findsOneWidget);
});
}