kopia lustrzana https://gitlab.com/mysocialportal/relatica
224 wiersze
7.2 KiB
Dart
224 wiersze
7.2 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/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 '../models/user_notification.dart';
|
|
import '../riverpod_controllers/account_services.dart';
|
|
import '../riverpod_controllers/networking/network_status_services.dart';
|
|
import '../riverpod_controllers/notification_services.dart';
|
|
import '../riverpod_controllers/settings_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';
|
|
final loading = ref.watch(notificationsLoadingProvider(profile));
|
|
late final Widget body;
|
|
|
|
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),
|
|
),
|
|
];
|
|
|
|
final hasNoNotifications = !ref.watch(hasAnyNotificationsProvider(profile));
|
|
if (hasNoNotifications) {
|
|
body = 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 {
|
|
final groupNotifications = ref.watch(notificationGroupingSettingProvider);
|
|
final notificationEntries = groupNotifications
|
|
? [
|
|
...orderedNotificationTypes.map((type) =>
|
|
_NotificationsByTypeListElement(
|
|
profile: profile, type: type, isRead: false)),
|
|
_NotificationsByReadStatusListElement(
|
|
profile: profile, isRead: true),
|
|
]
|
|
: [
|
|
_NotificationsByReadStatusListElement(
|
|
profile: profile, isRead: false),
|
|
_NotificationsByReadStatusListElement(
|
|
profile: profile, isRead: true),
|
|
];
|
|
|
|
final allEntries = [
|
|
TextButton(
|
|
onPressed: () async {
|
|
await ref
|
|
.read(notificationsManagerProvider(profile).notifier)
|
|
.loadNewerNotifications();
|
|
},
|
|
child: const Text('Load newer notifications')),
|
|
...notificationEntries,
|
|
TextButton(
|
|
onPressed: () async {
|
|
await ref
|
|
.read(notificationsManagerProvider(profile).notifier)
|
|
.loadOlderNotifications();
|
|
},
|
|
child: const Text('Load older notifications'))
|
|
];
|
|
|
|
body = RefreshIndicator(
|
|
onRefresh: () async => ref
|
|
.read(notificationsManagerProvider(profile).notifier)
|
|
.refreshNotifications(),
|
|
child: ResponsiveMaxWidth(
|
|
child: ListView.separated(
|
|
itemBuilder: (_, index) => allEntries[index],
|
|
separatorBuilder: (_, __) => _standardDivider,
|
|
itemCount: allEntries.length,
|
|
),
|
|
));
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class _NotificationsByTypeListElement extends ConsumerWidget {
|
|
final Profile profile;
|
|
final NotificationType type;
|
|
final bool isRead;
|
|
|
|
const _NotificationsByTypeListElement(
|
|
{required this.profile, required this.type, required this.isRead});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final notifications =
|
|
ref.watch(userNotificationsByTypeProvider(profile, type, isRead));
|
|
return ListView.separated(
|
|
primary: false,
|
|
shrinkWrap: true,
|
|
itemBuilder: (_, index) =>
|
|
NotificationControl(notification: notifications[index]),
|
|
separatorBuilder: (_, __) => _standardDivider,
|
|
itemCount: notifications.length,
|
|
);
|
|
}
|
|
}
|
|
|
|
class _NotificationsByReadStatusListElement extends ConsumerWidget {
|
|
final Profile profile;
|
|
final bool isRead;
|
|
|
|
const _NotificationsByReadStatusListElement(
|
|
{required this.profile, required this.isRead});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final notifications = ref.watch(allNotificationsProvider(profile, isRead));
|
|
return ListView.separated(
|
|
primary: false,
|
|
shrinkWrap: true,
|
|
itemBuilder: (_, index) =>
|
|
NotificationControl(notification: notifications[index]),
|
|
separatorBuilder: (_, __) => _standardDivider,
|
|
itemCount: notifications.length,
|
|
);
|
|
}
|
|
}
|
|
|
|
final orderedNotificationTypes = [
|
|
NotificationType.follow_request,
|
|
NotificationType.follow,
|
|
NotificationType.direct_message,
|
|
NotificationType.mention,
|
|
NotificationType.status,
|
|
NotificationType.reshare,
|
|
NotificationType.reblog,
|
|
NotificationType.favourite,
|
|
NotificationType.unknown,
|
|
];
|
|
|
|
const _standardDivider = Divider(
|
|
color: Colors.black54,
|
|
height: 0.0,
|
|
);
|