You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
5.2 KiB
160 lines
5.2 KiB
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
|
|
import 'package:get/get.dart';
|
|
|
|
import 'text_item.dart';
|
|
import 'image_item.dart';
|
|
import 'voice_item.dart';
|
|
import 'video_item.dart';
|
|
import '../../controller/message/chat_controller.dart';
|
|
|
|
class MessageItem extends StatelessWidget {
|
|
final EMMessage message;
|
|
final bool isSentByMe;
|
|
final EMMessage? previousMessage;
|
|
|
|
const MessageItem({
|
|
required this.message,
|
|
required this.isSentByMe,
|
|
this.previousMessage,
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
print('📨 [MessageItem] 渲染消息,类型: ${message.body.type}');
|
|
|
|
// 处理文本消息
|
|
if (message.body.type == MessageType.TXT) {
|
|
final textBody = message.body as EMTextMessageBody;
|
|
return TextItem(
|
|
textBody: textBody,
|
|
isSentByMe: isSentByMe,
|
|
showTime: shouldShowTime(),
|
|
formattedTime: formatMessageTime(message.serverTime),
|
|
message: message,
|
|
onResend: () {
|
|
// 通过Get找到ChatController并调用重发方法
|
|
try {
|
|
final controller = Get.find<ChatController>();
|
|
controller.resendMessage(message);
|
|
} catch (e) {
|
|
print('重发消息失败: $e');
|
|
}
|
|
},
|
|
);
|
|
}
|
|
// 处理图片消息
|
|
else if (message.body.type == MessageType.IMAGE) {
|
|
final imageBody = message.body as EMImageMessageBody;
|
|
return ImageItem(
|
|
imageBody: imageBody,
|
|
isSentByMe: isSentByMe,
|
|
showTime: shouldShowTime(),
|
|
formattedTime: formatMessageTime(message.serverTime),
|
|
message: message,
|
|
onResend: () {
|
|
// 通过Get找到ChatController并调用重发方法
|
|
try {
|
|
final controller = Get.find<ChatController>();
|
|
controller.resendMessage(message);
|
|
} catch (e) {
|
|
print('重发消息失败: $e');
|
|
}
|
|
},
|
|
);
|
|
}
|
|
// 处理语音消息
|
|
else if (message.body.type == MessageType.VOICE) {
|
|
final voiceBody = message.body as EMVoiceMessageBody;
|
|
return VoiceItem(
|
|
voiceBody: voiceBody,
|
|
messageId: message.msgId, // 传递消息ID作为音频唯一标识
|
|
isSentByMe: isSentByMe,
|
|
showTime: shouldShowTime(),
|
|
formattedTime: formatMessageTime(message.serverTime),
|
|
);
|
|
}
|
|
// 处理视频消息
|
|
else if (message.body.type == MessageType.VIDEO) {
|
|
print('🎬 [MessageItem] 检测到视频消息,准备渲染 VideoItem');
|
|
final videoBody = message.body as EMVideoMessageBody;
|
|
return VideoItem(
|
|
videoBody: videoBody,
|
|
isSentByMe: isSentByMe,
|
|
showTime: shouldShowTime(),
|
|
formattedTime: formatMessageTime(message.serverTime),
|
|
message: message,
|
|
onResend: () {
|
|
// 通过Get找到ChatController并调用重发方法
|
|
try {
|
|
final controller = Get.find<ChatController>();
|
|
controller.resendMessage(message);
|
|
} catch (e) {
|
|
print('重发消息失败: $e');
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
// 非文本消息显示占位符
|
|
print('⚠️ [MessageItem] 不支持的消息类型: ${message.body.type}');
|
|
return Column(
|
|
children: [
|
|
if (shouldShowTime()) _buildTimeLabel(),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
|
|
child: Text('不支持的消息类型: ${message.body.type}'),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 判断是否需要显示时间
|
|
bool shouldShowTime() {
|
|
if (previousMessage == null) {
|
|
return true; // 第一条消息显示时间
|
|
}
|
|
|
|
// 判断距离上一条消息是否超过20分钟(1200000毫秒)
|
|
return (message.serverTime - previousMessage!.serverTime) > 1200000;
|
|
}
|
|
|
|
// 构建时间标签
|
|
Widget _buildTimeLabel() {
|
|
final formattedTime = formatMessageTime(message.serverTime);
|
|
|
|
return Container(
|
|
alignment: Alignment.center,
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 12.w),
|
|
child: Text(
|
|
formattedTime,
|
|
style: TextStyle(fontSize: 12.sp, color: Colors.grey),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 格式化消息时间
|
|
String formatMessageTime(int timestamp) {
|
|
final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
|
final now = DateTime.now();
|
|
final today = DateTime(now.year, now.month, now.day);
|
|
final yesterday = DateTime(now.year, now.month, now.day - 1);
|
|
final messageDate = DateTime(date.year, date.month, date.day);
|
|
|
|
if (messageDate.isAtSameMomentAs(today)) {
|
|
// 今天的消息显示时间
|
|
return '今天 ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
|
|
} else if (messageDate.isAtSameMomentAs(yesterday)) {
|
|
// 昨天的消息
|
|
return '昨天 ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
|
|
} else {
|
|
// 其他日期显示完整日期和时间
|
|
return '${date.month}月${date.day}日 ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
|
|
}
|
|
}
|
|
}
|