refactor(apps): 主题系统迁移至 ColorScheme + 扩展架构并支持 Dark Mode
This commit is contained in:
@@ -3,15 +3,15 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../../app/di/injection.dart';
|
||||
import '../../../../data/repositories/calendar_event_repository.dart';
|
||||
import '../../../../data/repositories/models/inbox_message.dart';
|
||||
import '../../../../data/repositories/inbox_repository.dart';
|
||||
import '../../../../data/repositories/user_repository.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 '../../../contacts/data/users/users_api.dart';
|
||||
import '../../data/inbox_api.dart';
|
||||
|
||||
class MessageInviteDetailScreen extends StatefulWidget {
|
||||
final String inviteId;
|
||||
@@ -24,25 +24,27 @@ class MessageInviteDetailScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
late final InboxApi _inboxApi;
|
||||
late final CalendarApi _calendarApi;
|
||||
late final UsersApi _usersApi;
|
||||
late final InboxRepository _inboxRepository;
|
||||
late final CalendarEventRepository _calendarRepository;
|
||||
late final UserRepository _userRepository;
|
||||
|
||||
InboxMessageResponse? _message;
|
||||
InboxMessage? _message;
|
||||
String? _calendarTitle;
|
||||
String? _senderName;
|
||||
bool _loading = true;
|
||||
bool _submitting = false;
|
||||
String? _error;
|
||||
|
||||
ColorScheme get _colorScheme => Theme.of(context).colorScheme;
|
||||
|
||||
bool get _isPending => _message?.status == InboxMessageStatus.pending;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_inboxApi = sl<InboxApi>();
|
||||
_calendarApi = sl<CalendarApi>();
|
||||
_usersApi = sl<UsersApi>();
|
||||
_inboxRepository = sl<InboxRepository>();
|
||||
_calendarRepository = sl<CalendarEventRepository>();
|
||||
_userRepository = sl<UserRepository>();
|
||||
_loadDetail();
|
||||
}
|
||||
|
||||
@@ -54,11 +56,11 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
|
||||
try {
|
||||
final results = await Future.wait([
|
||||
_inboxApi.getMessages(isRead: false),
|
||||
_inboxApi.getMessages(isRead: true),
|
||||
_inboxRepository.getMessages(isRead: false),
|
||||
_inboxRepository.getMessages(isRead: true),
|
||||
]);
|
||||
final messages = [...results[0], ...results[1]];
|
||||
InboxMessageResponse? message;
|
||||
InboxMessage? message;
|
||||
for (final item in messages) {
|
||||
if (item.id == widget.inviteId) {
|
||||
message = item;
|
||||
@@ -72,7 +74,9 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
String? calendarTitle;
|
||||
if (message.scheduleItemId != null) {
|
||||
try {
|
||||
final event = await _calendarApi.getById(message.scheduleItemId!);
|
||||
final event = await _calendarRepository.getById(
|
||||
message.scheduleItemId!,
|
||||
);
|
||||
calendarTitle = event.title;
|
||||
} catch (_) {
|
||||
calendarTitle = null;
|
||||
@@ -82,7 +86,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
String? senderName;
|
||||
if (message.senderId != null) {
|
||||
try {
|
||||
final sender = await _usersApi.getById(message.senderId!);
|
||||
final sender = await _userRepository.getById(message.senderId!);
|
||||
senderName = sender.username;
|
||||
} catch (_) {
|
||||
senderName = null;
|
||||
@@ -118,8 +122,8 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
|
||||
setState(() => _submitting = true);
|
||||
try {
|
||||
await _calendarApi.acceptSubscription(itemId);
|
||||
await _inboxApi.markAsRead(message.id);
|
||||
await _calendarRepository.acceptSubscription(itemId);
|
||||
await _inboxRepository.markAsRead(message.id);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
@@ -154,8 +158,8 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
|
||||
setState(() => _submitting = true);
|
||||
try {
|
||||
await _calendarApi.rejectSubscription(itemId);
|
||||
await _inboxApi.markAsRead(message.id);
|
||||
await _calendarRepository.rejectSubscription(itemId);
|
||||
await _inboxRepository.markAsRead(message.id);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
@@ -190,7 +194,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.messageBg,
|
||||
backgroundColor: _colorScheme.surface,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -211,9 +215,9 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
const SizedBox(height: 14),
|
||||
Text(
|
||||
_error!,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.feedbackErrorText,
|
||||
color: _colorScheme.error,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -250,9 +254,9 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.messageCardBg,
|
||||
color: _colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: AppColors.messageCardBorder),
|
||||
border: Border.all(color: _colorScheme.outlineVariant),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -262,7 +266,7 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.slate900,
|
||||
color: _colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@@ -270,10 +274,10 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
context.l10n.messagesInviteEvent(
|
||||
_calendarTitle ?? context.l10n.messagesInviteUnnamedEvent,
|
||||
),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.slate700,
|
||||
color: _colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@@ -281,37 +285,37 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
context.l10n.messagesInviteSender(
|
||||
_senderName ?? context.l10n.messagesInviteUnknownUser,
|
||||
),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.slate500,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
context.l10n.messagesInviteTime(createdAtText),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.slate500,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
context.l10n.messagesInviteStatus(statusText),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.slate500,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
context.l10n.messagesInviteId(widget.inviteId),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.slate500,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -324,21 +328,25 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.messageTipBg,
|
||||
color: _colorScheme.surfaceContainerLow,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageTipBorder),
|
||||
border: Border.all(color: _colorScheme.outlineVariant),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.info_outline, size: 14, color: AppColors.slate500),
|
||||
Icon(
|
||||
Icons.info_outline,
|
||||
size: 14,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
context.l10n.messagesInviteTip,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.slate500,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -353,16 +361,16 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.messageCardBg,
|
||||
color: _colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageCardBorder),
|
||||
border: Border.all(color: _colorScheme.outlineVariant),
|
||||
),
|
||||
child: Text(
|
||||
context.l10n.messagesInviteAlreadyHandled,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.slate600,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@@ -378,28 +386,21 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
onTap: _submitting ? null : _rejectInvite,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.messageCardBg,
|
||||
color: _colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageRejectBorder),
|
||||
border: Border.all(color: _colorScheme.error),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
'×',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppColors.red400,
|
||||
),
|
||||
),
|
||||
Icon(Icons.close, size: 15, color: _colorScheme.error),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
context.l10n.messagesReject,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.red400,
|
||||
color: _colorScheme.error,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -413,28 +414,21 @@ class _MessageInviteDetailScreenState extends State<MessageInviteDetailScreen> {
|
||||
onTap: _submitting ? null : _acceptInvite,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.messageTagBg,
|
||||
color: _colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.messageAcceptBorder),
|
||||
border: Border.all(color: _colorScheme.primary),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
'√',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppColors.blue600,
|
||||
),
|
||||
),
|
||||
Icon(Icons.check, size: 15, color: _colorScheme.primary),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
context.l10n.messagesAccept,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.blue600,
|
||||
color: _colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -3,20 +3,21 @@ import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../../app/di/injection.dart';
|
||||
import '../../../../app/router/app_routes.dart';
|
||||
import '../../../../data/repositories/friend_repository.dart';
|
||||
import '../../../../data/repositories/inbox_repository.dart';
|
||||
import '../../../../data/repositories/models/friend_request.dart';
|
||||
import '../../../../data/repositories/models/inbox_message.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 '../../../contacts/data/friends_api.dart';
|
||||
import '../../data/inbox_api.dart';
|
||||
import '../../presentation/widgets/message_action_sheet.dart';
|
||||
|
||||
class MessageWithFriend {
|
||||
final InboxMessageResponse message;
|
||||
final FriendRequestResponse? friendRequest;
|
||||
final InboxMessage message;
|
||||
final FriendRequest? friendRequest;
|
||||
|
||||
const MessageWithFriend({required this.message, this.friendRequest});
|
||||
}
|
||||
@@ -30,8 +31,8 @@ class MessageInviteListScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
late final InboxApi _inboxApi;
|
||||
late final FriendsApi _friendsApi;
|
||||
late final InboxRepository _inboxRepository;
|
||||
late final FriendRepository _friendRepository;
|
||||
|
||||
List<MessageWithFriend> _unreadMessages = [];
|
||||
List<MessageWithFriend> _readMessages = [];
|
||||
@@ -39,11 +40,13 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
bool _isPullRefreshing = false;
|
||||
int _activeTabIndex = 0;
|
||||
|
||||
ColorScheme get _colorScheme => Theme.of(context).colorScheme;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_inboxApi = sl<InboxApi>();
|
||||
_friendsApi = sl<FriendsApi>();
|
||||
_inboxRepository = sl<InboxRepository>();
|
||||
_friendRepository = sl<FriendRepository>();
|
||||
_loadMessages();
|
||||
}
|
||||
|
||||
@@ -59,8 +62,8 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
}
|
||||
try {
|
||||
final results = await Future.wait([
|
||||
_inboxApi.getMessages(isRead: false),
|
||||
_inboxApi.getMessages(isRead: true),
|
||||
_inboxRepository.getMessages(isRead: false),
|
||||
_inboxRepository.getMessages(isRead: true),
|
||||
]);
|
||||
final unreadRaw = results[0];
|
||||
final readRaw = results[1];
|
||||
@@ -76,22 +79,9 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
.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 requestMap = await _friendRepository.getRequestsByIds(
|
||||
friendshipIds,
|
||||
);
|
||||
|
||||
final unread = _mapMessagesWithFriend(unreadRaw, requestMap);
|
||||
final read = _mapMessagesWithFriend(readRaw, requestMap);
|
||||
@@ -122,8 +112,8 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
}
|
||||
|
||||
List<MessageWithFriend> _mapMessagesWithFriend(
|
||||
List<InboxMessageResponse> messages,
|
||||
Map<String, FriendRequestResponse?> requestMap,
|
||||
List<InboxMessage> messages,
|
||||
Map<String, FriendRequest> requestMap,
|
||||
) {
|
||||
return messages.map((message) {
|
||||
final friendRequest = message.friendshipId == null
|
||||
@@ -185,16 +175,16 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
);
|
||||
final description = message.content?['message'] as String?;
|
||||
final statusText = isReadOnly
|
||||
? (friendRequest.status == 'accepted'
|
||||
? (friendRequest.status == FriendRequestStatus.accepted
|
||||
? context.l10n.messagesInviteStatusAccepted
|
||||
: friendRequest.status == 'rejected'
|
||||
: friendRequest.status == FriendRequestStatus.rejected
|
||||
? context.l10n.messagesInviteStatusRejected
|
||||
: context.l10n.messagesInviteStatusHandled)
|
||||
: null;
|
||||
|
||||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
backgroundColor: _colorScheme.surface.withValues(alpha: 0),
|
||||
isScrollControlled: true,
|
||||
builder: (ctx) => MessageActionSheet(
|
||||
title: title,
|
||||
@@ -202,7 +192,7 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
statusText: statusText,
|
||||
isReadOnly: isReadOnly,
|
||||
icon: Icons.person_add_outlined,
|
||||
iconColor: AppColors.emerald500,
|
||||
iconColor: _colorScheme.tertiary,
|
||||
onAccept: isReadOnly
|
||||
? null
|
||||
: () async {
|
||||
@@ -234,7 +224,7 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
|
||||
try {
|
||||
if (accept) {
|
||||
await _friendsApi.acceptRequest(friendshipId);
|
||||
await _friendRepository.acceptRequest(friendshipId);
|
||||
if (mounted) {
|
||||
Toast.show(
|
||||
context,
|
||||
@@ -243,7 +233,7 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await _friendsApi.declineRequest(friendshipId);
|
||||
await _friendRepository.declineRequest(friendshipId);
|
||||
if (mounted) {
|
||||
Toast.show(
|
||||
context,
|
||||
@@ -252,7 +242,7 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
);
|
||||
}
|
||||
}
|
||||
await _inboxApi.markAsRead(message.id);
|
||||
await _inboxRepository.markAsRead(message.id);
|
||||
await _loadMessages();
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
@@ -268,7 +258,7 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.background,
|
||||
backgroundColor: _colorScheme.surface,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -278,8 +268,6 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
? const Center(
|
||||
child: AppLoadingIndicator(
|
||||
size: 22,
|
||||
color: AppColors.blue500,
|
||||
trackColor: AppColors.blue100,
|
||||
withContainer: false,
|
||||
),
|
||||
)
|
||||
@@ -311,7 +299,7 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.slate100,
|
||||
color: _colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
@@ -347,7 +335,9 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? AppColors.white : Colors.transparent,
|
||||
color: isSelected
|
||||
? _colorScheme.surface
|
||||
: _colorScheme.surface.withValues(alpha: 0),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
@@ -356,7 +346,9 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
Icon(
|
||||
icon,
|
||||
size: 16,
|
||||
color: isSelected ? AppColors.slate900 : AppColors.slate500,
|
||||
color: isSelected
|
||||
? _colorScheme.onSurface
|
||||
: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
@@ -364,7 +356,9 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
|
||||
color: isSelected ? AppColors.slate900 : AppColors.slate500,
|
||||
color: isSelected
|
||||
? _colorScheme.onSurface
|
||||
: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
if (index == 0 && _unreadMessages.isNotEmpty) ...[
|
||||
@@ -372,17 +366,17 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.red500,
|
||||
color: _colorScheme.error,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
_unreadMessages.length > 99
|
||||
? '99+'
|
||||
: _unreadMessages.length.toString(),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.white,
|
||||
color: _colorScheme.onError,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -440,13 +434,13 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
width: 80,
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.slate100,
|
||||
color: _colorScheme.surfaceContainerHigh,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
isUnread ? Icons.notifications_none : Icons.inbox_outlined,
|
||||
size: 36,
|
||||
color: AppColors.slate400,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@@ -454,10 +448,10 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
isUnread
|
||||
? context.l10n.messagesEmptyUnreadTitle
|
||||
: context.l10n.messagesEmptyReadTitle,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.slate500,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
@@ -465,7 +459,10 @@ class _MessageInviteListScreenState extends State<MessageInviteListScreen> {
|
||||
isUnread
|
||||
? context.l10n.messagesEmptyUnreadDesc
|
||||
: context.l10n.messagesEmptyReadDesc,
|
||||
style: const TextStyle(fontSize: 13, color: AppColors.slate400),
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -479,22 +476,24 @@ class _MessageCard extends StatelessWidget {
|
||||
|
||||
const _MessageCard({required this.item, required this.onTap});
|
||||
|
||||
InboxMessageResponse get message => item.message;
|
||||
FriendRequestResponse? get friendRequest => item.friendRequest;
|
||||
InboxMessage get message => item.message;
|
||||
FriendRequest? get friendRequest => item.friendRequest;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
color: colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: message.isRead
|
||||
? AppColors.borderSecondary
|
||||
: AppColors.blue100,
|
||||
? colorScheme.outlineVariant
|
||||
: colorScheme.primary,
|
||||
width: message.isRead ? 1 : 1.5,
|
||||
),
|
||||
),
|
||||
@@ -505,13 +504,13 @@ class _MessageCard extends StatelessWidget {
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.emerald500.withValues(alpha: 0.1),
|
||||
color: colorScheme.tertiaryContainer,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.person_add_outlined,
|
||||
size: 22,
|
||||
color: AppColors.emerald500,
|
||||
color: colorScheme.tertiary,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
@@ -521,18 +520,18 @@ class _MessageCard extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
_title(),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.slate900,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
_content(),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: AppColors.slate500,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -572,12 +571,12 @@ class _MessageCard extends StatelessWidget {
|
||||
|
||||
final type = data['type'] as String?;
|
||||
if (type == 'invite') {
|
||||
final status = message.status.value;
|
||||
if (status == 'pending') {
|
||||
final status = message.status;
|
||||
if (status == InboxMessageStatus.pending) {
|
||||
return L10n.current.messagesInviteJoinCalendar;
|
||||
} else if (status == 'accepted') {
|
||||
} else if (status == InboxMessageStatus.accepted) {
|
||||
return L10n.current.messagesInviteAccepted;
|
||||
} else if (status == 'rejected') {
|
||||
} else if (status == InboxMessageStatus.rejected) {
|
||||
return L10n.current.messagesInviteRejected;
|
||||
}
|
||||
} else if (type == 'update') {
|
||||
|
||||
@@ -25,6 +25,7 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
@@ -33,9 +34,9 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
),
|
||||
padding: const EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
color: colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: Border.all(color: AppColors.border),
|
||||
border: Border.all(color: colorScheme.outlineVariant),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -45,12 +46,12 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.blue100,
|
||||
color: colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.calendar_today,
|
||||
color: AppColors.blue600,
|
||||
color: colorScheme.primary,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
@@ -71,7 +72,7 @@ class CalendarInviteCard extends StatelessWidget {
|
||||
eventTitle != null
|
||||
? l10n.messagesCalendarCardInviteWithTitle(eventTitle!)
|
||||
: l10n.messagesCalendarCardInviteWithoutTitle,
|
||||
style: const TextStyle(fontSize: 14, color: AppColors.slate700),
|
||||
style: TextStyle(fontSize: 14, color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
Row(
|
||||
@@ -112,6 +113,7 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
@@ -122,21 +124,21 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
),
|
||||
padding: const EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
color: colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: Border.all(color: AppColors.border),
|
||||
border: Border.all(color: colorScheme.outlineVariant),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.blue100,
|
||||
color: colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.calendar_today,
|
||||
color: AppColors.blue600,
|
||||
color: colorScheme.primary,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
@@ -157,15 +159,15 @@ class CalendarUpdateCard extends StatelessWidget {
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
_formatTime(context, message.createdAt),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.slate500,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Icon(Icons.chevron_right, color: AppColors.slate400),
|
||||
Icon(Icons.chevron_right, color: colorScheme.outline),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -201,6 +203,7 @@ class CalendarDeleteCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
@@ -209,21 +212,21 @@ class CalendarDeleteCard extends StatelessWidget {
|
||||
),
|
||||
padding: const EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.slate50,
|
||||
color: colorScheme.surfaceContainerLowest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: Border.all(color: AppColors.slate200),
|
||||
border: Border.all(color: colorScheme.outlineVariant),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.slate200,
|
||||
color: colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.calendar_today,
|
||||
color: AppColors.slate500,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
@@ -233,7 +236,10 @@ class CalendarDeleteCard extends StatelessWidget {
|
||||
eventTitle != null
|
||||
? l10n.messagesCalendarCardDeletedWithTitle(eventTitle!)
|
||||
: l10n.messagesCalendarCardDeletedWithoutTitle,
|
||||
style: const TextStyle(fontSize: 14, color: AppColors.slate500),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -27,12 +27,15 @@ class MessageActionSheet extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final resolvedIconColor = iconColor ?? colorScheme.primary;
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.fromLTRB(24, 20, 24, 0),
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface,
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -41,7 +44,7 @@ class MessageActionSheet extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.slate300,
|
||||
color: colorScheme.outlineVariant,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
@@ -51,23 +54,19 @@ class MessageActionSheet extends StatelessWidget {
|
||||
width: 72,
|
||||
height: 72,
|
||||
decoration: BoxDecoration(
|
||||
color: (iconColor ?? AppColors.blue500).withValues(alpha: 0.1),
|
||||
color: resolvedIconColor.withValues(alpha: 0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
size: 32,
|
||||
color: iconColor ?? AppColors.blue500,
|
||||
),
|
||||
child: Icon(icon, size: 32, color: resolvedIconColor),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.slate900,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@@ -75,7 +74,10 @@ class MessageActionSheet extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
description!,
|
||||
style: const TextStyle(fontSize: 14, color: AppColors.slate500),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
@@ -84,12 +86,15 @@ class MessageActionSheet extends StatelessWidget {
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.slate100,
|
||||
color: colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Text(
|
||||
statusText!,
|
||||
style: const TextStyle(fontSize: 14, color: AppColors.slate600),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user