import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; import '../controls/app_bottom_nav_bar.dart'; import '../controls/async_value_widget.dart'; import '../controls/error_message_widget.dart'; import '../controls/notifications_control.dart'; import '../controls/padding.dart'; import '../controls/responsive_max_width.dart'; import '../controls/standard_app_drawer.dart'; import '../controls/standard_appbar.dart'; import '../controls/status_and_refresh_button.dart'; import '../globals.dart'; import '../models/auth/profile.dart'; import '../riverpod_controllers/account_services.dart'; import '../riverpod_controllers/networking/network_status_services.dart'; import '../riverpod_controllers/notification_services.dart'; import '../utils/snackbar_builder.dart'; class NotificationsScreen extends ConsumerWidget { static final _logger = Logger('$NotificationsScreen'); const NotificationsScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { _logger.finer('Building'); final profile = ref.watch(activeProfileProvider); const title = 'Notifications'; late final Widget body; final notificationsValue = ref.watch(notificationsManagerProvider(profile)); final loading = ref.watch(notificationsLoadingProvider(profile)) || switch (notificationsValue) { AsyncData() => false, _ => true, }; final actions = [ if (platformIsDesktop) StatusAndRefreshButton( executing: loading, refreshFunction: () async => ref .read(notificationsManagerProvider(profile).notifier) .refreshNotifications(), ), IconButton( onPressed: () async => _clearAllNotifications(context, ref, profile), icon: const Icon(Icons.cleaning_services), ), ]; body = AsyncValueWidget(notificationsValue, valueBuilder: (context, ref, result) { if (result.isFailure) { return ErrorMessageWidget( message: 'Error getting notifications: ${result.error.message}'); } final notifications = result.value; if (notifications.isEmpty) { return RefreshIndicator( onRefresh: () async => ref .read(notificationsManagerProvider(profile).notifier) .refreshNotifications(), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: loading ? [ const Center(child: Text('Loading Notifications')), ] : [ const Center(child: Text('No notifications')), const VerticalPadding(), ElevatedButton( onPressed: () => ref .read(notificationsManagerProvider(profile).notifier) .refreshNotifications(), child: const Text('Load Notifications'), ) ], )), ); } else { return RefreshIndicator( onRefresh: () async => ref .read(notificationsManagerProvider(profile).notifier) .refreshNotifications(), child: ResponsiveMaxWidth( child: ListView.separated( physics: const AlwaysScrollableScrollPhysics(), itemBuilder: (context, index) { if (index == 0) { return TextButton( onPressed: () async { final result = await ref .read(notificationsManagerProvider(profile) .notifier) .loadNewerNotifications(); final noMore = result.fold( onSuccess: (value) => !value, onError: (_) => true); if (context.mounted && noMore) { buildSnackbar( context, 'No newer notifications to load'); } }, child: const Text('Load newer notifications')); } if (index == notifications.length + 1) { return TextButton( onPressed: () async { final result = await ref .read(notificationsManagerProvider(profile) .notifier) .loadOlderNotifications(); final noMore = result.fold( onSuccess: (value) => !value, onError: (_) => true); if (context.mounted && noMore) { buildSnackbar( context, 'No older notifications to load'); } }, child: const Text('Load older notifications')); } return NotificationControl( notification: notifications[index - 1]); }, separatorBuilder: (context, index) { return const Divider( color: Colors.black54, height: 0.0, ); }, itemCount: notifications.length + 2), ), ); } }); return Scaffold( appBar: StandardAppBar.build( context, title, withHome: false, withDrawer: true, actions: actions, ), drawer: const StandardAppDrawer(), body: Center( child: Column( children: [ if (loading) const LinearProgressIndicator(), Expanded( child: ResponsiveMaxWidth(child: body), ), ], ), ), bottomNavigationBar: const AppBottomNavBar( currentButton: NavBarButtons.notifications, ), ); } Future _clearAllNotifications( BuildContext context, WidgetRef ref, Profile profile) async { final confirmed = await showYesNoDialog(context, 'Clear all notifications?'); if (confirmed == true) { final message = (await ref .read(notificationsManagerProvider(profile).notifier) .markAllAsRead()) .fold( onSuccess: (_) => 'Marked all notifications as read', onError: (error) => 'Error marking notifications: $error'); if (context.mounted) { buildSnackbar(context, message); } } } }