💄 Optimized notification list
This commit is contained in:
		| @@ -487,5 +487,6 @@ | ||||
|   "shareImageFooter": "Only on the Solar Network", | ||||
|   "fileSavedAt": "File saved at @path", | ||||
|   "showIp": "Show IP Address", | ||||
|   "shotOn": "Shot on @device" | ||||
|   "shotOn": "Shot on @device", | ||||
|   "unread": "Unread" | ||||
| } | ||||
|   | ||||
| @@ -483,5 +483,6 @@ | ||||
|   "shareImageFooter": "上 Solar Network 看更多有趣帖子", | ||||
|   "fileSavedAt": "文件保存于 @path", | ||||
|   "showIp": "显示 IP 地址", | ||||
|   "shotOn": "由 @device 拍摄" | ||||
|   "shotOn": "由 @device 拍摄", | ||||
|   "unread": "未读" | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,9 @@ part 'notification.g.dart'; | ||||
|  | ||||
| const Map<String, IconData> NotificationTopicIcons = { | ||||
|   'passport.security.alert': Icons.gpp_maybe, | ||||
|   'interactive.subscription': Icons.subscriptions, | ||||
|   'interactive.feedback': Icons.add_reaction, | ||||
|   'messaging.callStart': Icons.call_received, | ||||
| }; | ||||
|  | ||||
| @JsonSerializable() | ||||
|   | ||||
| @@ -55,7 +55,11 @@ class NotificationProvider extends GetxController { | ||||
|       await client.put('/notifications/read', {'messages': markList}); | ||||
|     } | ||||
|  | ||||
|     nty.notifications.clear(); | ||||
|     nty.notifications.value = nty.notifications.map((x) { | ||||
|       x.readAt = DateTime.now(); | ||||
|       return x; | ||||
|     }).toList(); | ||||
|     nty.notifications.refresh(); | ||||
|  | ||||
|     isBusy.value = false; | ||||
|   } | ||||
| @@ -79,7 +83,8 @@ class NotificationProvider extends GetxController { | ||||
|  | ||||
|     await client.put('/notifications/read/${element.id}', {}); | ||||
|  | ||||
|     nty.notifications.removeAt(index); | ||||
|     nty.notifications[0].readAt = DateTime.now(); | ||||
|     nty.notifications.refresh(); | ||||
|  | ||||
|     isBusy.value = false; | ||||
|   } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import 'package:solian/models/notification.dart'; | ||||
| import 'package:solian/providers/notifications.dart'; | ||||
| import 'package:solian/widgets/loading_indicator.dart'; | ||||
| import 'package:solian/widgets/markdown_text_content.dart'; | ||||
| import 'package:solian/widgets/relative_date.dart'; | ||||
| import 'package:uuid/uuid.dart'; | ||||
|  | ||||
| class NotificationScreen extends StatefulWidget { | ||||
| @@ -107,12 +108,26 @@ class _NotificationScreenState extends State<NotificationScreen> { | ||||
|                                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                                 children: [ | ||||
|                                   Icon(NotificationTopicIcons[element.topic]), | ||||
|                                   const Gap(12), | ||||
|                                   const Gap(16), | ||||
|                                   Expanded( | ||||
|                                     child: Column( | ||||
|                                       crossAxisAlignment: | ||||
|                                           CrossAxisAlignment.start, | ||||
|                                       children: [ | ||||
|                                         if (element.readAt == null) | ||||
|                                           Badge( | ||||
|                                             label: Row( | ||||
|                                               children: [ | ||||
|                                                 const Icon( | ||||
|                                                   Icons.new_releases_outlined, | ||||
|                                                   color: Colors.white, | ||||
|                                                   size: 12, | ||||
|                                                 ), | ||||
|                                                 const Gap(4), | ||||
|                                                 Text('unread'.tr), | ||||
|                                               ], | ||||
|                                             ), | ||||
|                                           ).paddingOnly(bottom: 4), | ||||
|                                         Text( | ||||
|                                           element.title, | ||||
|                                           style: Theme.of(context) | ||||
| @@ -126,7 +141,8 @@ class _NotificationScreenState extends State<NotificationScreen> { | ||||
|                                                 .textTheme | ||||
|                                                 .titleSmall, | ||||
|                                           ), | ||||
|                                         const Gap(4), | ||||
|                                         if (element.subtitle != null) | ||||
|                                           const Gap(4), | ||||
|                                         MarkdownTextContent( | ||||
|                                           content: element.body, | ||||
|                                           isAutoWarp: true, | ||||
| @@ -134,6 +150,29 @@ class _NotificationScreenState extends State<NotificationScreen> { | ||||
|                                           parentId: | ||||
|                                               'notification-${element.id}', | ||||
|                                         ), | ||||
|                                         const Gap(8), | ||||
|                                         Opacity( | ||||
|                                           opacity: 0.75, | ||||
|                                           child: Row( | ||||
|                                             children: [ | ||||
|                                               RelativeDate( | ||||
|                                                 element.createdAt, | ||||
|                                                 style: TextStyle(fontSize: 12), | ||||
|                                               ), | ||||
|                                               const Gap(4), | ||||
|                                               Text( | ||||
|                                                 '·', | ||||
|                                                 style: TextStyle(fontSize: 12), | ||||
|                                               ), | ||||
|                                               const Gap(4), | ||||
|                                               RelativeDate( | ||||
|                                                 element.createdAt, | ||||
|                                                 style: TextStyle(fontSize: 12), | ||||
|                                                 isFull: true, | ||||
|                                               ), | ||||
|                                             ], | ||||
|                                           ), | ||||
|                                         ), | ||||
|                                       ], | ||||
|                                     ), | ||||
|                                   ), | ||||
|   | ||||
| @@ -4,20 +4,25 @@ import 'package:timeago/timeago.dart'; | ||||
|  | ||||
| class RelativeDate extends StatelessWidget { | ||||
|   final DateTime date; | ||||
|   final TextStyle? style; | ||||
|   final bool isFull; | ||||
|  | ||||
|   const RelativeDate(this.date, {super.key, this.isFull = false}); | ||||
|   const RelativeDate(this.date, {super.key, this.style, this.isFull = false}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     if (isFull) { | ||||
|       return Text(DateFormat('y/M/d HH:mm').format(date)); | ||||
|       return Text( | ||||
|         DateFormat('y/M/d HH:mm').format(date), | ||||
|         style: style, | ||||
|       ); | ||||
|     } | ||||
|     return Text( | ||||
|       format( | ||||
|         date, | ||||
|         locale: 'en_short', | ||||
|       ), | ||||
|       style: style, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user