feat(apps): 重构 UI 架构为 presentation 层并新增 l10n 国际化支持
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import 'package:social_app/core/api/i_api_client.dart';
|
||||
import 'package:social_app/core/network/i_api_client.dart';
|
||||
|
||||
class InboxApi {
|
||||
final IApiClient _client;
|
||||
|
||||
+63
-38
@@ -1,14 +1,16 @@
|
||||
import 'package:flutter/material.dart' hide BackButton;
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../../core/di/injection.dart';
|
||||
import '../../../../app/di/injection.dart';
|
||||
import '../../../../core/l10n/l10n.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 '../../../users/data/users_api.dart';
|
||||
import '../../../contacts/data/users/users_api.dart';
|
||||
import '../../data/inbox_api.dart';
|
||||
|
||||
class MessageInviteDetailScreen extends StatefulWidget {
|
||||
@@ -64,7 +66,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
}
|
||||
}
|
||||
if (message == null) {
|
||||
throw StateError('邀请不存在或已失效');
|
||||
throw StateError(L10n.current.messagesInviteDetailNotFound);
|
||||
}
|
||||
|
||||
String? calendarTitle;
|
||||
@@ -121,13 +123,21 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
Toast.show(context, '已接受邀请', type: ToastType.success);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesInviteAcceptedToast,
|
||||
type: ToastType.success,
|
||||
);
|
||||
await _loadDetail();
|
||||
} catch (_) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
Toast.show(context, '操作失败,请稍后重试', type: ToastType.error);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesInviteOperationFailed,
|
||||
type: ToastType.error,
|
||||
);
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _submitting = false);
|
||||
@@ -149,13 +159,21 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
Toast.show(context, '已拒绝邀请', type: ToastType.success);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesInviteRejectedToast,
|
||||
type: ToastType.success,
|
||||
);
|
||||
await _loadDetail();
|
||||
} catch (_) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
Toast.show(context, '操作失败,请稍后重试', type: ToastType.error);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesInviteOperationFailed,
|
||||
type: ToastType.error,
|
||||
);
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _submitting = false);
|
||||
@@ -212,18 +230,21 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
Widget _buildSummaryCard() {
|
||||
final message = _message;
|
||||
final statusText = message == null
|
||||
? '未知'
|
||||
? context.l10n.commonUnknown
|
||||
: switch (message.status) {
|
||||
InboxMessageStatus.pending => '待处理',
|
||||
InboxMessageStatus.accepted => '已接受',
|
||||
InboxMessageStatus.rejected => '已拒绝',
|
||||
InboxMessageStatus.dismissed => '已处理',
|
||||
InboxMessageStatus.pending => context.l10n.messagesStatusPending,
|
||||
InboxMessageStatus.accepted =>
|
||||
context.l10n.messagesInviteStatusAccepted,
|
||||
InboxMessageStatus.rejected =>
|
||||
context.l10n.messagesInviteStatusRejected,
|
||||
InboxMessageStatus.dismissed =>
|
||||
context.l10n.messagesInviteStatusHandled,
|
||||
};
|
||||
|
||||
final createdAt = message?.createdAt;
|
||||
final createdAtText = createdAt == null
|
||||
? '未知'
|
||||
: '${createdAt.year}-${createdAt.month.toString().padLeft(2, '0')}-${createdAt.day.toString().padLeft(2, '0')} ${createdAt.hour.toString().padLeft(2, '0')}:${createdAt.minute.toString().padLeft(2, '0')}';
|
||||
? context.l10n.commonUnknown
|
||||
: DateFormat.yMd(context.l10n.localeName).add_Hm().format(createdAt);
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
@@ -236,8 +257,8 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'日历邀请详情',
|
||||
Text(
|
||||
context.l10n.messagesInviteDetailTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -246,7 +267,9 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'事件:${_calendarTitle ?? '未命名日程'}',
|
||||
context.l10n.messagesInviteEvent(
|
||||
_calendarTitle ?? context.l10n.messagesInviteUnnamedEvent,
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -255,7 +278,9 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'邀请人:${_senderName ?? '未知用户'}',
|
||||
context.l10n.messagesInviteSender(
|
||||
_senderName ?? context.l10n.messagesInviteUnknownUser,
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
@@ -264,7 +289,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'消息时间:$createdAtText',
|
||||
context.l10n.messagesInviteTime(createdAtText),
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
@@ -273,7 +298,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'状态:$statusText',
|
||||
context.l10n.messagesInviteStatus(statusText),
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
@@ -282,7 +307,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'邀请ID:${widget.inviteId}',
|
||||
context.l10n.messagesInviteId(widget.inviteId),
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
@@ -303,14 +328,14 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageTipBorder),
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.info_outline, size: 14, color: AppColors.slate500),
|
||||
SizedBox(width: 8),
|
||||
const Icon(Icons.info_outline, size: 14, color: AppColors.slate500),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'同意后将加入该日历事件,拒绝后该邀请会被标记为已处理',
|
||||
style: TextStyle(
|
||||
context.l10n.messagesInviteTip,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.slate500,
|
||||
@@ -332,8 +357,8 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageCardBorder),
|
||||
),
|
||||
child: const Text(
|
||||
'该邀请已处理,无需重复操作',
|
||||
child: Text(
|
||||
context.l10n.messagesInviteAlreadyHandled,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -357,10 +382,10 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageRejectBorder),
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'×',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
@@ -368,10 +393,10 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
color: AppColors.red400,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 6),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'拒绝',
|
||||
style: TextStyle(
|
||||
context.l10n.messagesReject,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.red400,
|
||||
@@ -392,10 +417,10 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageAcceptBorder),
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'√',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
@@ -403,10 +428,10 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
color: AppColors.blue600,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 6),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'同意',
|
||||
style: TextStyle(
|
||||
context.l10n.messagesAccept,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.blue600,
|
||||
+75
-29
@@ -1,17 +1,18 @@
|
||||
import 'package:flutter/material.dart' hide BackButton;
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../../core/di/injection.dart';
|
||||
import '../../../../core/router/app_routes.dart';
|
||||
import '../../../../app/di/injection.dart';
|
||||
import '../../../../app/router/app_routes.dart';
|
||||
import '../../../../core/l10n/l10n.dart';
|
||||
import '../../../../core/theme/design_tokens.dart';
|
||||
import '../../../../shared/widgets/app_loading_indicator.dart';
|
||||
import '../../../../shared/widgets/app_pull_refresh_feedback.dart';
|
||||
import '../../../../shared/widgets/page_header.dart';
|
||||
import '../../../../shared/widgets/toast/toast.dart';
|
||||
import '../../../../shared/widgets/toast/toast_type.dart';
|
||||
import '../../../friends/data/friends_api.dart';
|
||||
import '../../../contacts/data/friends_api.dart';
|
||||
import '../../data/inbox_api.dart';
|
||||
import '../../ui/widgets/message_action_sheet.dart';
|
||||
import '../../presentation/widgets/message_action_sheet.dart';
|
||||
|
||||
class MessageWithFriend {
|
||||
final InboxMessageResponse message;
|
||||
@@ -108,7 +109,11 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
_isLoading = false;
|
||||
_isPullRefreshing = false;
|
||||
});
|
||||
Toast.show(context, '消息加载失败,请稍后重试', type: ToastType.error);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesLoadFailed,
|
||||
type: ToastType.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +153,11 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
return;
|
||||
case InboxMessageType.friendRequest:
|
||||
if (item.friendRequest == null) {
|
||||
Toast.show(context, '发送者信息加载失败,请下拉重试', type: ToastType.error);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesSenderLoadFailed,
|
||||
type: ToastType.error,
|
||||
);
|
||||
return;
|
||||
}
|
||||
_showFriendRequestSheet(item, isReadOnly: message.isRead);
|
||||
@@ -171,14 +180,16 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
final friendRequest = item.friendRequest;
|
||||
if (friendRequest == null) return;
|
||||
|
||||
final title = '${friendRequest.sender.username} 请求添加您为好友';
|
||||
final title = context.l10n.messagesFriendRequestTitle(
|
||||
friendRequest.sender.username,
|
||||
);
|
||||
final description = message.content?['message'] as String?;
|
||||
final statusText = isReadOnly
|
||||
? (friendRequest.status == 'accepted'
|
||||
? '已接受'
|
||||
? context.l10n.messagesInviteStatusAccepted
|
||||
: friendRequest.status == 'rejected'
|
||||
? '已拒绝'
|
||||
: '已处理')
|
||||
? context.l10n.messagesInviteStatusRejected
|
||||
: context.l10n.messagesInviteStatusHandled)
|
||||
: null;
|
||||
|
||||
showModalBottomSheet<void>(
|
||||
@@ -213,7 +224,11 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
final message = item.message;
|
||||
final friendshipId = message.friendshipId;
|
||||
if (friendshipId == null) {
|
||||
Toast.show(context, '好友请求数据缺失', type: ToastType.error);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesFriendRequestMissing,
|
||||
type: ToastType.error,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,19 +236,31 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
if (accept) {
|
||||
await _friendsApi.acceptRequest(friendshipId);
|
||||
if (mounted) {
|
||||
Toast.show(context, '已接受好友请求', type: ToastType.success);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesAcceptedFriendRequest,
|
||||
type: ToastType.success,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await _friendsApi.declineRequest(friendshipId);
|
||||
if (mounted) {
|
||||
Toast.show(context, '已拒绝好友请求', type: ToastType.success);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesRejectedFriendRequest,
|
||||
type: ToastType.success,
|
||||
);
|
||||
}
|
||||
}
|
||||
await _inboxApi.markAsRead(message.id);
|
||||
await _loadMessages();
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
Toast.show(context, '处理失败,请稍后重试', type: ToastType.error);
|
||||
Toast.show(
|
||||
context,
|
||||
context.l10n.messagesActionFailed,
|
||||
type: ToastType.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,9 +316,21 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: _buildTab(0, '未读', Icons.mark_email_unread_outlined)),
|
||||
Expanded(
|
||||
child: _buildTab(
|
||||
0,
|
||||
context.l10n.messagesTabUnread,
|
||||
Icons.mark_email_unread_outlined,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(child: _buildTab(1, '已读', Icons.mark_email_read_outlined)),
|
||||
Expanded(
|
||||
child: _buildTab(
|
||||
1,
|
||||
context.l10n.messagesTabRead,
|
||||
Icons.mark_email_read_outlined,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -412,7 +451,9 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
isUnread ? '暂无未读消息' : '暂无已读消息',
|
||||
isUnread
|
||||
? context.l10n.messagesEmptyUnreadTitle
|
||||
: context.l10n.messagesEmptyReadTitle,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -421,7 +462,9 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
isUnread ? '有新消息时会在这里显示' : '处理过的消息会显示在这里',
|
||||
isUnread
|
||||
? context.l10n.messagesEmptyUnreadDesc
|
||||
: context.l10n.messagesEmptyReadDesc,
|
||||
style: const TextStyle(fontSize: 13, color: AppColors.slate400),
|
||||
),
|
||||
],
|
||||
@@ -506,15 +549,17 @@ class _MessageCard extends StatelessWidget {
|
||||
String _title() {
|
||||
if (message.messageType == InboxMessageType.friendRequest) {
|
||||
if (friendRequest == null) {
|
||||
return '好友请求信息加载失败';
|
||||
return L10n.current.messagesFriendRequestLoadFailed;
|
||||
}
|
||||
return '${friendRequest!.sender.username} 请求添加您为好友';
|
||||
return L10n.current.messagesFriendRequestTitle(
|
||||
friendRequest!.sender.username,
|
||||
);
|
||||
}
|
||||
if (message.messageType == InboxMessageType.calendar) {
|
||||
final data = message.content;
|
||||
return data?['title'] as String? ?? '日历邀请';
|
||||
return data?['title'] as String? ?? L10n.current.messagesCalendarInvite;
|
||||
}
|
||||
return '系统消息';
|
||||
return L10n.current.messagesSystemMessage;
|
||||
}
|
||||
|
||||
String _content() {
|
||||
@@ -523,23 +568,24 @@ class _MessageCard extends StatelessWidget {
|
||||
if (message.content != null) {
|
||||
data = message.content;
|
||||
}
|
||||
if (data == null) return '点击查看详情';
|
||||
if (data == null) return L10n.current.messagesTapToView;
|
||||
|
||||
final type = data['type'] as String?;
|
||||
if (type == 'invite') {
|
||||
final status = message.status.value;
|
||||
if (status == 'pending') {
|
||||
return '邀请您加入日历';
|
||||
return L10n.current.messagesInviteJoinCalendar;
|
||||
} else if (status == 'accepted') {
|
||||
return '已接受日历邀请';
|
||||
return L10n.current.messagesInviteAccepted;
|
||||
} else if (status == 'rejected') {
|
||||
return '已拒绝日历邀请';
|
||||
return L10n.current.messagesInviteRejected;
|
||||
}
|
||||
} else if (type == 'update') {
|
||||
return '更新了日历事件';
|
||||
return L10n.current.messagesCalendarUpdated;
|
||||
}
|
||||
return '点击查看详情';
|
||||
return L10n.current.messagesTapToView;
|
||||
}
|
||||
return message.content?['message'] as String? ?? '点击查看详情';
|
||||
return message.content?['message'] as String? ??
|
||||
L10n.current.messagesTapToView;
|
||||
}
|
||||
}
|
||||
+34
-14
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:social_app/core/l10n/l10n.dart';
|
||||
|
||||
import '../../../../core/theme/design_tokens.dart';
|
||||
import '../../../../shared/widgets/app_button.dart';
|
||||
@@ -23,6 +24,8 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.md,
|
||||
@@ -52,17 +55,22 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Text(
|
||||
'日历邀请',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14),
|
||||
l10n.messagesCalendarCardInviteTitle,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
eventTitle != null ? '邀请你访问 "$eventTitle"' : '邀请你访问日历',
|
||||
eventTitle != null
|
||||
? l10n.messagesCalendarCardInviteWithTitle(eventTitle!)
|
||||
: l10n.messagesCalendarCardInviteWithoutTitle,
|
||||
style: const TextStyle(fontSize: 14, color: AppColors.slate700),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
@@ -70,14 +78,17 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: AppButton(
|
||||
text: '拒绝',
|
||||
text: l10n.messagesReject,
|
||||
isOutlined: true,
|
||||
onPressed: onReject,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
Expanded(
|
||||
child: AppButton(text: '接受', onPressed: onAccept),
|
||||
child: AppButton(
|
||||
text: l10n.messagesAccept,
|
||||
onPressed: onAccept,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -100,6 +111,8 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
@@ -133,7 +146,9 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
eventTitle != null ? '$eventTitle 已更新' : '日历事件已更新',
|
||||
eventTitle != null
|
||||
? l10n.messagesCalendarCardUpdatedWithTitle(eventTitle!)
|
||||
: l10n.messagesCalendarCardUpdatedWithoutTitle,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -141,7 +156,7 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
_formatTime(message.createdAt),
|
||||
_formatTime(context, message.createdAt),
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.slate500,
|
||||
@@ -157,17 +172,18 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
String _formatTime(DateTime time) {
|
||||
String _formatTime(BuildContext context, DateTime time) {
|
||||
final l10n = context.l10n;
|
||||
final now = DateTime.now();
|
||||
final diff = now.difference(time);
|
||||
if (diff.inMinutes < 60) {
|
||||
return '${diff.inMinutes}分钟前';
|
||||
return l10n.messagesCalendarCardTimeMinutesAgo(diff.inMinutes);
|
||||
} else if (diff.inHours < 24) {
|
||||
return '${diff.inHours}小时前';
|
||||
return l10n.messagesCalendarCardTimeHoursAgo(diff.inHours);
|
||||
} else if (diff.inDays < 7) {
|
||||
return '${diff.inDays}天前';
|
||||
return l10n.messagesCalendarCardTimeDaysAgo(diff.inDays);
|
||||
} else {
|
||||
return '${time.month}月${time.day}日';
|
||||
return l10n.messagesCalendarCardTimeDate(time.month, time.day);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,6 +200,8 @@ class CalendarDeleteCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.md,
|
||||
@@ -212,7 +230,9 @@ class CalendarDeleteCard extends StatelessWidget {
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
Expanded(
|
||||
child: Text(
|
||||
eventTitle != null ? '$eventTitle 已删除' : '日历事件已删除',
|
||||
eventTitle != null
|
||||
? l10n.messagesCalendarCardDeletedWithTitle(eventTitle!)
|
||||
: l10n.messagesCalendarCardDeletedWithoutTitle,
|
||||
style: const TextStyle(fontSize: 14, color: AppColors.slate500),
|
||||
),
|
||||
),
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../../core/theme/design_tokens.dart';
|
||||
import '../../../../core/l10n/l10n.dart';
|
||||
import '../../../../shared/widgets/app_button.dart';
|
||||
|
||||
class MessageActionSheet extends StatelessWidget {
|
||||
@@ -98,7 +99,7 @@ class MessageActionSheet extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: AppButton(
|
||||
text: '拒绝',
|
||||
text: context.l10n.messagesReject,
|
||||
isOutlined: true,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
@@ -109,7 +110,7 @@ class MessageActionSheet extends StatelessWidget {
|
||||
const SizedBox(width: AppSpacing.md),
|
||||
Expanded(
|
||||
child: AppButton(
|
||||
text: '接受',
|
||||
text: context.l10n.messagesAccept,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
onAccept?.call();
|
||||
Reference in New Issue
Block a user