kopia lustrzana https://gitlab.com/mysocialportal/relatica
186 wiersze
6.7 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
}
|