From e21c9e8c2221d146fd4745f467017fbdcf2109ab Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Sat, 12 Sep 2026 09:52:01 -0400 Subject: [PATCH] make highlights work better for Notifications page --- lib/controllers/notification.dart | 2 +- lib/pages/notifications.dart | 45 ++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/controllers/notification.dart b/lib/controllers/notification.dart index d3db8b7..7996a47 100644 --- a/lib/controllers/notification.dart +++ b/lib/controllers/notification.dart @@ -34,7 +34,7 @@ class NotificationController Navigator.of(context).push( MaterialPageRoute( builder: (_) => NotificationsPage( - eventId: eventId, + highlightedEventId: eventId, defaultToAllNotifications: true, ), ), diff --git a/lib/pages/notifications.dart b/lib/pages/notifications.dart index 380e6af..3e70104 100644 --- a/lib/pages/notifications.dart +++ b/lib/pages/notifications.dart @@ -1,3 +1,5 @@ +import "dart:async"; + import "package:m3e_buttons/m3e_buttons.dart"; import "package:material_ui/material_ui.dart"; import "package:flutter_hooks/flutter_hooks.dart"; @@ -12,7 +14,7 @@ import "package:nexus/widgets/renderers/event.dart"; import "package:super_sliver_list/super_sliver_list.dart"; class const NotificationsPage({ - final String? eventId, + final String? highlightedEventId, final bool defaultToAllNotifications = false, super.key, }) extends HookConsumerWidget { @@ -30,6 +32,10 @@ class const NotificationsPage({ }; final unreadTypeIndex = useState(defaultToAllNotifications ? 1 : 0); + final highlightedId = useState(highlightedEventId); + final listController = useRef(ListController()); + final scrollController = useScrollController(); + final provider = NotificationsController.provider(( options.values.toList()[unreadTypeIndex.value], null, @@ -37,7 +43,38 @@ class const NotificationsPage({ final notifications = ref.watch(provider); final notifier = ref.watch(provider.notifier); - final scrollController = useScrollController(); + useEffect(() { + if (highlightedId.value == null) return null; + Timer? timer; + + void listener() => + WidgetsBinding.instance.addPostFrameCallback((_) async { + if (!listController.value.isAttached) return; + + final notifications = await ref.watch(provider.future); + + final index = notifications.indexWhere( + (element) => element.eventId == highlightedId.value!, + ); + + if (index == -1) return; + + listController.value.animateToItem( + index: index, + scrollController: scrollController, + alignment: 0.5, + duration: (_) => .new(milliseconds: 700), + curve: (_) => Curves.easeInOut, + ); + timer = Timer(.new(seconds: 1), () { + highlightedId.value = null; + }); + listController.value.removeListener(listener); + }); + + listController.value.addListener(listener); + return timer?.cancel; + }, []); useEffect(() { Future listener() async { @@ -72,6 +109,7 @@ class const NotificationsPage({ ), ) : SuperListView.builder( + listController: listController.value, controller: scrollController, itemCount: value.length, padding: const EdgeInsets.symmetric( @@ -81,7 +119,8 @@ class const NotificationsPage({ reverse: true, itemBuilder: (context, index) { final event = value[index]; - final isHighlighted = event.eventId == eventId; + final isHighlighted = + event.eventId == highlightedId.value; return Padding( padding: .only(top: 8),