import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../api/errors/error_mapper.dart'; import '../../../../api/marianumconnect/queries/push_device_test/push_device_test.dart'; import '../../../../push/push_registration.dart'; import '../../../../push/push_registration_store.dart'; import '../../../../routing/app_routes.dart'; import '../../../../state/app/modules/settings/bloc/settings_cubit.dart'; import '../../../../utils/haptics.dart'; import '../../../../widget/centered_leading.dart'; class TalkSection extends StatelessWidget { const TalkSection({super.key}); @override Widget build(BuildContext context) { final settings = context.watch(); final talkSettings = settings.val().talkSettings; final notificationSettings = settings.val().notificationSettings; return Column( children: [ ListTile( leading: const Icon(Icons.star_border), title: const Text('Favoriten im Talk nach oben sortieren'), trailing: Checkbox( value: talkSettings.sortFavoritesToTop, onChanged: (e) { Haptics.selection(); settings.val(write: true).talkSettings.sortFavoritesToTop = e!; }, ), ), ListTile( leading: const Icon(Icons.mark_email_unread_outlined), title: const Text('Ungelesene Chats nach oben sortieren'), trailing: Checkbox( value: talkSettings.sortUnreadToTop, onChanged: (e) { Haptics.selection(); settings.val(write: true).talkSettings.sortUnreadToTop = e!; }, ), ), ListTile( leading: const Icon(Icons.wallpaper_outlined), title: const Text('Chat-Hintergrund'), subtitle: const Text('Bild, Farbe und Darstellung anpassen'), trailing: const Icon(Icons.arrow_right), onTap: () => AppRoutes.openChatBackgroundSettings(context), ), ListTile( leading: const CenteredLeading( Icon(Icons.notifications_active_outlined), ), title: const Text('Push-Benachrichtigungen'), subtitle: const Text('Neue Talk-Nachrichten direkt aufs Gerät'), trailing: Checkbox( value: notificationSettings.enabled, onChanged: (e) { Haptics.selection(); final enabled = e ?? false; settings.val(write: true).notificationSettings.enabled = enabled; if (enabled) { final messenger = ScaffoldMessenger.of(context); unawaited(() async { // Only register when the OS permission isn't explicitly // denied — otherwise NC + proxy would push into the void. if (await PushRegistration.requestOsPermission()) { await PushRegistration().register(); } else { messenger.showSnackBar( const SnackBar( content: Text( 'Benachrichtigungen sind in den Systemeinstellungen ' 'deaktiviert — bitte dort erlauben.', ), ), ); } }()); } else { unawaited(PushRegistration().unregister()); } }, ), ), if (notificationSettings.enabled) const _TestNotificationTile(), ], ); } } /// "Send a test notification" action, shown only while push is enabled. The /// button stays disabled until a registration is confirmed present, then calls /// the backend and reports the result via a SnackBar. class _TestNotificationTile extends StatefulWidget { const _TestNotificationTile(); @override State<_TestNotificationTile> createState() => _TestNotificationTileState(); } class _TestNotificationTileState extends State<_TestNotificationTile> { static const _permissionDeniedHint = 'Benachrichtigungen sind in den Systemeinstellungen deaktiviert'; bool _registered = false; bool _permissionDenied = false; bool _sending = false; @override void initState() { super.initState(); _loadState(); } Future _loadState() async { final registered = await const PushRegistrationStore().isRegistered(); final denied = await PushRegistration.isOsPermissionDenied(); if (!mounted) return; setState(() { _registered = registered; _permissionDenied = denied; }); } Future _sendTest() async { if (_sending) return; Haptics.selection(); final messenger = ScaffoldMessenger.of(context); // Re-check right before sending: the user may have flipped the OS // permission in the system settings since this tile was built. final denied = await PushRegistration.isOsPermissionDenied(); if (!mounted) return; if (denied) { setState(() => _permissionDenied = true); messenger.showSnackBar( const SnackBar( content: Text('$_permissionDeniedHint — bitte dort erlauben.'), ), ); return; } setState(() { _permissionDenied = false; _sending = true; }); String message; try { final devices = await PushDeviceTest().run(); message = devices >= 1 ? 'Testbenachrichtigung an $devices Gerät(e) gesendet' : 'Kein Gerät registriert — Push-Registrierung prüfen'; } on Object catch (e) { message = errorToUserMessage(e); } if (!mounted) return; setState(() => _sending = false); messenger.showSnackBar(SnackBar(content: Text(message))); } @override Widget build(BuildContext context) { if (!_registered) return const SizedBox.shrink(); return ListTile( leading: const CenteredLeading(Icon(Icons.send_outlined)), title: const Text('Testbenachrichtigung senden'), subtitle: _permissionDenied ? Text( _permissionDeniedHint, style: TextStyle(color: Theme.of(context).colorScheme.error), ) : const Text('Prüft, ob Push auf diesem Gerät ankommt'), trailing: _sending ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.arrow_right), enabled: !_sending, onTap: _sending ? null : _sendTest, ); } }