From 6ca9b2a9487f3be7d013120f53884b66b9818406 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 11 Sep 2026 22:34:43 -0400 Subject: [PATCH] add notification page filter --- lib/controllers/notification.dart | 5 +- lib/pages/notifications.dart | 128 ++++++++++++++++++++---------- 2 files changed, 89 insertions(+), 44 deletions(-) diff --git a/lib/controllers/notification.dart b/lib/controllers/notification.dart index a8b9e6c..d3db8b7 100644 --- a/lib/controllers/notification.dart +++ b/lib/controllers/notification.dart @@ -33,7 +33,10 @@ class NotificationController if (navigatorKey.currentContext case final context?) { Navigator.of(context).push( MaterialPageRoute( - builder: (_) => NotificationsPage(eventId: eventId), + builder: (_) => NotificationsPage( + eventId: eventId, + defaultToAllNotifications: true, + ), ), ); } diff --git a/lib/pages/notifications.dart b/lib/pages/notifications.dart index 56afdad..0592acd 100644 --- a/lib/pages/notifications.dart +++ b/lib/pages/notifications.dart @@ -1,7 +1,9 @@ +import "package:m3e_buttons/m3e_buttons.dart"; import "package:material_ui/material_ui.dart"; import "package:flutter_hooks/flutter_hooks.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/notifications.dart"; +import "package:nexus/models/event.dart"; import "package:nexus/widgets/appbar.dart"; import "package:nexus/widgets/error_dialog.dart"; import "package:nexus/widgets/highlight_wrapper.dart"; @@ -9,11 +11,29 @@ import "package:nexus/widgets/loading.dart"; import "package:nexus/widgets/renderers/event.dart"; import "package:super_sliver_list/super_sliver_list.dart"; -class const NotificationsPage({final String? eventId, super.key}) - extends HookConsumerWidget { +class const NotificationsPage({ + final String? eventId, + final bool defaultToAllNotifications = false, + super.key, +}) extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final provider = NotificationsController.provider(null); + final options = { + M3EToggleButtonGroupAction( + label: Text("Mentions"), + icon: Icon(Icons.alternate_email), + ): .highlight, + M3EToggleButtonGroupAction( + label: Text("All Notifications"), + icon: Icon(Icons.notifications), + ): .notify, + }; + final unreadTypeIndex = useState(defaultToAllNotifications ? 1 : 0); + + final provider = NotificationsController.provider(( + options.values.toList()[unreadTypeIndex.value], + null, + )); final notifications = ref.watch(provider); final notifier = ref.watch(provider.notifier); @@ -35,49 +55,71 @@ class const NotificationsPage({final String? eventId, super.key}) return Scaffold( appBar: Appbar(title: Text("Notifications")), - body: Column( + body: Stack( children: [ - if (notifications is AsyncLoading && notifications.value != null) - const LinearProgressIndicator(minHeight: 2), - Expanded( - child: switch (notifications) { - AsyncData(:final value) || AsyncLoading(:final value?) => - value.isEmpty - ? Center( - child: Text( - "No notifications yet", - style: Theme.of(context).textTheme.headlineMedium, - ), - ) - : SuperListView.builder( - controller: scrollController, - itemCount: value.length, - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 12, - ), - reverse: true, - itemBuilder: (context, index) { - final event = value[index]; - final isHighlighted = event.eventId == eventId; - - return HighlightWrapper( - InkWell( - onTap: () { - //TODO - }, - child: EventRenderer(event), + Column( + children: [ + if (notifications is AsyncLoading && notifications.value != null) + const LinearProgressIndicator(minHeight: 2), + Expanded( + child: switch (notifications) { + AsyncData(:final value) || AsyncLoading(:final value?) => + value.isEmpty + ? Center( + child: Text( + "No notifications yet", + style: Theme.of(context).textTheme.headlineMedium, ), - isHighlighted: isHighlighted, - ); - }, - ), - AsyncLoading() => const Loading(), - AsyncError(:final error, :final stackTrace) => ErrorDialog( - error, - stackTrace, + ) + : SuperListView.builder( + controller: scrollController, + itemCount: value.length, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 12, + ), + reverse: true, + itemBuilder: (context, index) { + final event = value[index]; + final isHighlighted = event.eventId == eventId; + + return Padding( + padding: .only(top: 8), + child: HighlightWrapper( + InkWell( + onTap: () { + //TODO + }, + child: EventRenderer(event), + ), + isHighlighted: isHighlighted, + ), + ); + }, + ), + AsyncLoading() => const Loading(), + AsyncError(:final error, :final stackTrace) => ErrorDialog( + error, + stackTrace, + ), + }, ), - }, + ], + ), + Align( + alignment: .topRight, + child: Card( + color: Theme.of(context).colorScheme.surfaceContainer, + child: Padding( + padding: .all(12), + child: M3EToggleButtonGroup( + selectedIndex: unreadTypeIndex.value, + onSelectedIndexChanged: (index) => + unreadTypeIndex.value = index ?? unreadTypeIndex.value, + actions: options.keys.toList(), + ), + ), + ), ), ], ),