feat: 优化前端 UI 组件与交互体验

- 优化日历、待办、消息等页面交互
- 更新 ChatBloc 与 UI Schema 渲染
- 优化联系人、首页、设置页面体验
This commit is contained in:
qzl
2026-03-16 16:11:28 +08:00
parent a75c868bca
commit 4b92772535
18 changed files with 1591 additions and 1780 deletions
@@ -3,11 +3,14 @@ import 'package:go_router/go_router.dart';
import '../../../../core/di/injection.dart';
import '../../../../core/theme/design_tokens.dart';
import '../../../../shared/widgets/app_loading_indicator.dart';
import '../../../../shared/widgets/page_header.dart';
import '../../../../shared/widgets/toast/toast.dart';
import '../../../../shared/widgets/toast/toast_type.dart';
import '../../../calendar/data/calendar_api.dart';
import '../../../calendar/data/models/schedule_item_model.dart';
import '../../../friends/data/friends_api.dart';
import '../../../users/data/models/user_response.dart';
import '../../../users/data/users_api.dart';
import '../../data/inbox_api.dart';
import '../../ui/widgets/message_action_sheet.dart';
@@ -49,15 +52,50 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
}
Future<void> _loadMessages() async {
if (_isLoading) {
return;
}
if (mounted) {
setState(() => _isLoading = true);
}
try {
final unreadRaw = await _inboxApi.getMessages(isRead: false);
final readRaw = await _inboxApi.getMessages(isRead: true);
final results = await Future.wait([
_inboxApi.getMessages(isRead: false),
_inboxApi.getMessages(isRead: true),
]);
final unreadRaw = results[0];
final readRaw = results[1];
final unread = await _enrichWithFriendDetails(unreadRaw);
final read = await _enrichWithFriendDetails(readRaw);
final allMessages = [...unreadRaw, ...readRaw];
final friendshipIds = allMessages
.where(
(m) =>
m.messageType == InboxMessageType.friendRequest &&
m.friendshipId != null,
)
.map((m) => m.friendshipId!)
.toSet()
.toList();
final requestMap = <String, FriendRequestResponse?>{};
if (friendshipIds.isNotEmpty) {
final fetched = await Future.wait(
friendshipIds.map((id) async {
try {
final req = await _friendsApi.getRequestById(id);
return (id, req as FriendRequestResponse?);
} catch (_) {
return (id, null as FriendRequestResponse?);
}
}),
);
for (final pair in fetched) {
requestMap[pair.$1] = pair.$2;
}
}
final unread = _mapMessagesWithFriend(unreadRaw, requestMap);
final read = _mapMessagesWithFriend(readRaw, requestMap);
if (!mounted) return;
setState(() {
@@ -72,36 +110,16 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
}
}
Future<List<MessageWithFriend>> _enrichWithFriendDetails(
List<MessageWithFriend> _mapMessagesWithFriend(
List<InboxMessageResponse> messages,
) async {
final futures = messages.map(_fetchFriendRequest);
final results = await Future.wait(futures);
final enriched = <MessageWithFriend>[];
for (int i = 0; i < messages.length; i++) {
final message = messages[i];
final friendRequest = results[i];
enriched.add(
MessageWithFriend(message: message, friendRequest: friendRequest),
);
}
return enriched;
}
Future<FriendRequestResponse?> _fetchFriendRequest(
InboxMessageResponse message,
) async {
if (message.messageType != InboxMessageType.friendRequest ||
message.friendshipId == null) {
return null;
}
try {
return await _friendsApi.getRequestById(message.friendshipId!);
} catch (_) {
return null;
}
Map<String, FriendRequestResponse?> requestMap,
) {
return messages.map((message) {
final friendRequest = message.friendshipId == null
? null
: requestMap[message.friendshipId!];
return MessageWithFriend(message: message, friendRequest: friendRequest);
}).toList();
}
Future<void> _handleMessageTap(MessageWithFriend item) async {
@@ -148,8 +166,12 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
return null;
}
try {
final calendar = await _calendarApi.getById(message.scheduleItemId!);
final sender = await _usersApi.getById(message.senderId!);
final result = await Future.wait([
_calendarApi.getById(message.scheduleItemId!),
_usersApi.getById(message.senderId!),
]);
final calendar = result[0] as ScheduleItemModel;
final sender = result[1] as UserResponse;
return (calendar.title, sender.username);
} catch (e) {
return null;
@@ -320,8 +342,11 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
Expanded(
child: _isLoading
? const Center(
child: CircularProgressIndicator(
child: AppLoadingIndicator(
size: 22,
color: AppColors.blue500,
trackColor: AppColors.blue100,
withContainer: false,
),
)
: _activeTabIndex == 0