Add mark all as read action to notifications list

Shows a done_all icon button in the AppBar when the New filter is active
and the list is non-empty, calling the notifications/mark_all_as_old endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-05-27 12:10:02 -04:00
co-authored by Claude Sonnet 4.6
parent bda7b87cc7
commit 6002597383
2 changed files with 71 additions and 43 deletions
@@ -32,6 +32,20 @@ class _NotificationListState extends State<NotificationList> {
},
);
Future<void> _markAllAsRead(BuildContext context) async {
await BackendAPI.instance.markAllNotificationsAsRead();
_pagingController.refresh();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('All notifications marked as read'),
behavior: SnackBarBehavior.floating,
showCloseIcon: true,
),
);
}
}
Future<bool> _markAsRead(
BuildContext context,
oott_model.Notification item,
@@ -102,50 +116,59 @@ class _NotificationListState extends State<NotificationList> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Notifications')),
body:
// Paginated list start
PagingListener(
controller: _pagingController,
builder: (context, state, fetchNextPage) => CustomScrollView(
slivers: [
// Filters go here
SliverToBoxAdapter(
child: Container(
height: 50,
alignment: Alignment.centerRight,
child: Wrap(
spacing: 8.0,
children: [
ChoiceChip(
label: Text('New'),
selected: _filterChoice == 1,
onSelected: (bool selected) {
_filterChoice = 1;
_pagingController.refresh();
},
),
ChoiceChip(
label: Text('Old'),
selected: _filterChoice == 2,
onSelected: (bool selected) {
_filterChoice = 2;
_pagingController.refresh();
},
),
ChoiceChip(
label: Text('All'),
selected: _filterChoice == 3,
onSelected: (bool selected) {
_filterChoice = 3;
_pagingController.refresh();
},
),
],
// Paginated list start
return PagingListener(
controller: _pagingController,
builder: (context, state, fetchNextPage) => Scaffold(
appBar: AppBar(
title: const Text('Notifications'),
actions: [
if (_filterChoice == 1 && (state.items?.isNotEmpty ?? false))
IconButton(
onPressed: () => _markAllAsRead(context),
icon: const Icon(Icons.done_all),
tooltip: 'Mark all as read',
),
],
),
body: CustomScrollView(
slivers: [
// Filters go here
SliverToBoxAdapter(
child: Container(
height: 50,
alignment: Alignment.centerRight,
child: Wrap(
spacing: 8.0,
children: [
ChoiceChip(
label: Text('New'),
selected: _filterChoice == 1,
onSelected: (bool selected) {
_filterChoice = 1;
_pagingController.refresh();
},
),
),
ChoiceChip(
label: Text('Old'),
selected: _filterChoice == 2,
onSelected: (bool selected) {
_filterChoice = 2;
_pagingController.refresh();
},
),
ChoiceChip(
label: Text('All'),
selected: _filterChoice == 3,
onSelected: (bool selected) {
_filterChoice = 3;
_pagingController.refresh();
},
),
],
),
),
),
PagedSliverList<int, oott_model.Notification>(
state: state,
fetchNextPage: fetchNextPage,
@@ -231,7 +254,7 @@ class _NotificationListState extends State<NotificationList> {
],
),
),
);
);
// Paginated list end
}
+5
View File
@@ -76,6 +76,11 @@ class BackendAPI {
await _dio.post('/notifications/$id/mark_as_new');
}
Future<void> markAllNotificationsAsRead() async {
print('About to call /notifications/mark_all_as_old');
await _dio.post('/notifications/mark_all_as_old');
}
Future<List<Notification>> listNotifications(bool? isNew, int offset) async {
print('About to call /notifications');