feat: integrate invite API and improve notification handling
- Add invite code display and binding functionality via API - Fix notification unread count sync on auth state change - Improve notification mark read with server state validation - Add auth state listener to trigger notification refresh - Add YaoCoinConverter for coin-to-yao type conversion - Remove YaoLegend from divination screens (UI cleanup) - Abbreviate relation labels in yao detail view - Add re-register notice to account delete screen - Update 'coins' terminology to 'points' in localization - Fix backend points consumption to only run in CHAT mode - Add HttpxAuthNoiseFilter to suppress auth endpoint logging - Fix notification static_schema import path - Add test coverage for notification bloc error handling - Update AGENTS.md page header rules and image handling - Delete deprecated run-dev.sh script
This commit is contained in:
+36
-4
@@ -1,6 +1,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../shared/theme/design_tokens.dart';
|
||||
import '../../../../shared/widgets/notification/notification_detail_bottom_sheet.dart';
|
||||
import '../../data/models/notification_item.dart';
|
||||
import '../../data/models/notification_payload.dart';
|
||||
import '../../data/repositories/notification_repository.dart';
|
||||
@@ -13,12 +16,14 @@ class NotificationCenterScreen extends StatefulWidget {
|
||||
required this.repository,
|
||||
this.onNavigateToRoute,
|
||||
this.onOpenUrl,
|
||||
this.onUnreadCountChanged,
|
||||
});
|
||||
|
||||
final NotificationRepository repository;
|
||||
final void Function(String route, {String? entityId, String? tab})?
|
||||
onNavigateToRoute;
|
||||
final void Function(String url)? onOpenUrl;
|
||||
final Future<void> Function()? onUnreadCountChanged;
|
||||
|
||||
@override
|
||||
State<NotificationCenterScreen> createState() =>
|
||||
@@ -55,6 +60,7 @@ class _NotificationCenterScreenState extends State<NotificationCenterScreen> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('通知'),
|
||||
centerTitle: true,
|
||||
actions: [
|
||||
if (state.items.any((item) => !item.isRead))
|
||||
TextButton(
|
||||
@@ -136,15 +142,32 @@ class _NotificationCenterScreenState extends State<NotificationCenterScreen> {
|
||||
final item = state.items[index];
|
||||
return NotificationListItem(
|
||||
item: item,
|
||||
onTap: () => _handleNotificationTap(item),
|
||||
onTap: () => _handleNotificationTap(context, item),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _handleNotificationTap(NotificationItem item) {
|
||||
Future<void> _handleNotificationTap(
|
||||
BuildContext context,
|
||||
NotificationItem item,
|
||||
) async {
|
||||
final wasUnread = !item.isRead;
|
||||
if (!item.isRead) {
|
||||
_bloc.handleEvent(MarkNotificationRead(notificationId: item.id));
|
||||
await _bloc.handleEvent(MarkNotificationRead(notificationId: item.id));
|
||||
final updatedIndex = _bloc.state.items.indexWhere((n) => n.id == item.id);
|
||||
if (wasUnread &&
|
||||
updatedIndex >= 0 &&
|
||||
_bloc.state.items[updatedIndex].isRead) {
|
||||
await widget.onUnreadCountChanged?.call();
|
||||
}
|
||||
}
|
||||
if (context.mounted) {
|
||||
await showNotificationDetailBottomSheet(
|
||||
context: context,
|
||||
item: item,
|
||||
onMarkRead: () async {},
|
||||
);
|
||||
}
|
||||
_executePayload(item.payload);
|
||||
}
|
||||
@@ -161,6 +184,15 @@ class _NotificationCenterScreenState extends State<NotificationCenterScreen> {
|
||||
}
|
||||
|
||||
void _onMarkAllRead() {
|
||||
_bloc.handleEvent(MarkAllNotificationsRead());
|
||||
unawaited(_markAllRead());
|
||||
}
|
||||
|
||||
Future<void> _markAllRead() async {
|
||||
final unreadBefore = _bloc.state.items.any((item) => !item.isRead);
|
||||
await _bloc.handleEvent(MarkAllNotificationsRead());
|
||||
final unreadAfter = _bloc.state.items.any((item) => !item.isRead);
|
||||
if (unreadBefore && !unreadAfter) {
|
||||
await widget.onUnreadCountChanged?.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user