it0/it0_app/lib/features/chat/presentation/widgets/message_bubble.dart

84 lines
2.7 KiB
Dart

import 'package:flutter/material.dart';
import '../../../../core/theme/app_colors.dart';
import '../../domain/entities/chat_message.dart';
/// Renders a single chat message bubble with appropriate styling
/// for user and assistant messages.
class MessageBubble extends StatelessWidget {
final ChatMessage message;
const MessageBubble({super.key, required this.message});
bool get _isUser => message.role == MessageRole.user;
@override
Widget build(BuildContext context) {
return Align(
alignment: _isUser ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
margin: const EdgeInsets.symmetric(vertical: 4),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.78,
),
decoration: BoxDecoration(
color: _isUser ? AppColors.primary : AppColors.surface,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(16),
topRight: const Radius.circular(16),
bottomLeft: Radius.circular(_isUser ? 16 : 4),
bottomRight: Radius.circular(_isUser ? 4 : 16),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Role label for assistant messages
if (!_isUser && message.type == MessageType.thinking)
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Text(
'思考中...',
style: TextStyle(
color: AppColors.textMuted,
fontSize: 11,
fontStyle: FontStyle.italic,
),
),
),
// Message content
SelectableText(
message.content,
style: TextStyle(
color: _isUser ? Colors.white : AppColors.textPrimary,
fontSize: 15,
),
),
// Timestamp
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
_formatTime(message.timestamp),
style: TextStyle(
color: _isUser
? Colors.white.withOpacity(0.6)
: AppColors.textMuted,
fontSize: 10,
),
),
),
],
),
),
);
}
String _formatTime(DateTime time) {
final hour = time.hour.toString().padLeft(2, '0');
final minute = time.minute.toString().padLeft(2, '0');
return '$hour:$minute';
}
}