diff --git a/frontend/lib/devices/device_list.dart b/frontend/lib/devices/device_list.dart index 76d528a..d3845d5 100644 --- a/frontend/lib/devices/device_list.dart +++ b/frontend/lib/devices/device_list.dart @@ -286,11 +286,13 @@ class _DeviceListState extends State with RouteAware { final device = _devices[index]; return isWide ? DeviceRowWide( + key: ValueKey(device.macAddress), device: device, formatter: formatter, onRefresh: () => _fetchPage(_currentPage), ) : DeviceRowCompact( + key: ValueKey(device.macAddress), device: device, formatter: formatter, onRefresh: () => _fetchPage(_currentPage), diff --git a/frontend/lib/home/notification_card.dart b/frontend/lib/home/notification_card.dart index 3e179e6..13608a1 100644 --- a/frontend/lib/home/notification_card.dart +++ b/frontend/lib/home/notification_card.dart @@ -7,7 +7,7 @@ import '../utils/friendly_date_formatter.dart'; class NotificationCard extends StatelessWidget { final oott_model.Notification item; final FriendlyDateFormatter formatter; - final Future Function(BuildContext, bool read) onSetRead; + final Future Function(bool read) onSetRead; const NotificationCard({ required this.item, @@ -22,10 +22,9 @@ class NotificationCard extends StatelessWidget { return Card( color: item.isNew ? theme.colorScheme.secondaryContainer : null, child: Dismissible( - key: UniqueKey(), - confirmDismiss: (direction) => direction == DismissDirection.startToEnd - ? onSetRead(context, false) - : onSetRead(context, true), + key: ValueKey(item.id), + confirmDismiss: (direction) => + onSetRead(direction != DismissDirection.startToEnd), background: Container( color: theme.colorScheme.tertiaryContainer, alignment: Alignment.centerLeft, @@ -54,14 +53,14 @@ class NotificationCard extends StatelessWidget { icon: const Icon(Icons.more_vert), onSelected: (value) async { if (value == 'view_device') { - if (item.isNew) await onSetRead(context, true); + if (item.isNew) await onSetRead(true); if (context.mounted) { context.push('/devices/${item.macAddress}'); } } else if (value == 'mark_read') { - await onSetRead(context, true); + await onSetRead(true); } else if (value == 'mark_new') { - await onSetRead(context, false); + await onSetRead(false); } }, itemBuilder: (context) => [ @@ -84,7 +83,7 @@ class NotificationCard extends StatelessWidget { ), onTap: item.macAddress != null ? () async { - if (item.isNew) await onSetRead(context, true); + if (item.isNew) await onSetRead(true); if (context.mounted) { context.push('/devices/${item.macAddress}'); } diff --git a/frontend/lib/home/notifications_list.dart b/frontend/lib/home/notifications_list.dart index 19dd5cd..77ea608 100644 --- a/frontend/lib/home/notifications_list.dart +++ b/frontend/lib/home/notifications_list.dart @@ -112,32 +112,41 @@ class _NotificationsListState extends State with RouteAware { } } - Future _markAllAsRead(BuildContext context) async { - await BackendAPI.instance.markAllNotificationsAsRead(); - _fetchPage(_currentPage); - if (context.mounted) { - UISnackbars.showSuccess(context, 'All notifications marked as read'); + Future _markAllAsRead() async { + try { + await BackendAPI.instance.markAllNotificationsAsRead(); + } catch (e) { + if (!mounted) return; + UISnackbars.showError(context, dioErrorToUserMessage(e)); + return; } + if (!mounted) return; + _fetchPage(_currentPage); + UISnackbars.showSuccess(context, 'All notifications marked as read'); } - Future _setRead( - BuildContext context, - oott_model.Notification item, - bool read, - ) async { + Future _setRead(oott_model.Notification item, bool read) async { if (item.isNew == !read) { - UISnackbars.showWarning( - context, - 'Notification was already marked as ${read ? 'read' : 'unread'}', - ); + if (mounted) { + UISnackbars.showWarning( + context, + 'Notification was already marked as ${read ? 'read' : 'unread'}', + ); + } return false; } - if (read) { - await BackendAPI.instance.markNotificationAsRead(item.id); - } else { - await BackendAPI.instance.markNotificationAsNew(item.id); + try { + if (read) { + await BackendAPI.instance.markNotificationAsRead(item.id); + } else { + await BackendAPI.instance.markNotificationAsNew(item.id); + } + } catch (e) { + if (!mounted) return false; + UISnackbars.showError(context, dioErrorToUserMessage(e)); + return false; } - if (!context.mounted) return false; + if (!mounted) return false; UISnackbars.showSuccess( context, 'Event marked as ${read ? 'read' : 'unread'}', @@ -185,7 +194,7 @@ class _NotificationsListState extends State with RouteAware { const Spacer(), if (_filter == _NotificationFilter.newOnly && _items.isNotEmpty) IconButton( - onPressed: () => _markAllAsRead(context), + onPressed: _markAllAsRead, icon: const Icon(Icons.done_all), tooltip: 'Mark all as read', ), @@ -266,7 +275,7 @@ class _NotificationsListState extends State with RouteAware { return NotificationCard( item: item, formatter: formatter, - onSetRead: (ctx, read) => _setRead(ctx, item, read), + onSetRead: (read) => _setRead(item, read), ); }, );