relatica/lib/screens/notifications_screen.dart

186 wiersze
6.7 KiB
Dart

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<void> _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);
}
}
}
}