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.
 
 
 
 
 

319 lines
10 KiB

import 'dart:convert';
import 'dart:typed_data';
import 'package:agora_rtm/agora_rtm.dart';
import 'package:dating_touchme_app/controller/discover/room_controller.dart';
import 'package:dating_touchme_app/controller/global.dart';
import 'package:dating_touchme_app/controller/message/call_controller.dart';
import 'package:dating_touchme_app/controller/overlay_controller.dart';
import 'package:dating_touchme_app/model/live/live_chat_message.dart';
import 'package:dating_touchme_app/pages/discover/live_end_page.dart';
import 'package:dating_touchme_app/rtc/rtc_manager.dart';
import 'package:dating_touchme_app/rtc/rtm_manager.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
/// 直播间聊天消息服务
/// 负责消息的发送、接收、解析和管理
class LiveChatMessageService {
// 单例模式
static final LiveChatMessageService _instance = LiveChatMessageService._internal();
factory LiveChatMessageService() => _instance;
static LiveChatMessageService get instance => _instance;
final GetStorage _storage = GetStorage();
bool _isListenerRegistered = false;
// 消息监听回调
Function(LiveChatMessage message)? onMessageReceived;
Function(String error)? onMessageError;
LiveChatMessageService._internal();
/// 注册消息监听器
void registerMessageListener({
Function(LiveChatMessage message)? onMessageReceived,
Function(String error)? onMessageError,
}) {
if (_isListenerRegistered) {
print('⚠️ 消息监听器已注册,跳过重复注册');
return;
}
this.onMessageReceived = onMessageReceived;
this.onMessageError = onMessageError;
RTMManager.instance.onMessageEvent = (MessageEvent event) {
_handleIncomingMessage(event);
};
_isListenerRegistered = true;
print('✅ 消息监听器注册完成');
}
/// 移除消息监听器
void unregisterMessageListener() {
RTMManager.instance.onMessageEvent = null;
_isListenerRegistered = false;
onMessageReceived = null;
onMessageError = null;
print('✅ 消息监听器已移除');
}
/// 处理接收到的消息
void _handleIncomingMessage(MessageEvent event) async{
try {
// 解析消息内容
final messageText = _parseMessageContent(event.message);
final messageData = json.decode(messageText) as Map<String, dynamic>;
print('📥 收到消息: $messageData');
// 处理结束直播消息
if (messageData['type'] == 'end_live') {
RoomController controller = Get.find<RoomController>();
await controller.leaveChannel();
_handleEndLiveMessage();
return;
}
// 处理通话消息
if (messageData['type'] == 'call_message') {
final event = messageData['event'] as String?;
if (event == 'accept') {
// 接收方收到 accept 消息,设置远端用户 UID
final uid = messageData['uid'];
if (uid != null && Get.isRegistered<CallController>()) {
final callController = Get.find<CallController>();
callController.remoteUid.value = uid is int ? uid : int.tryParse(uid.toString());
print('📞 [LiveChatMessageService] 收到 accept 消息,设置 remoteUid: ${callController.remoteUid.value}');
}
} else if (event == 'hangup') {
// 接收方收到 hangup 消息,关闭视频通话邀请弹框
SmartDialog.dismiss();
print('📞 [LiveChatMessageService] 收到 hangup 消息,已关闭视频通话邀请弹框');
// 停止播放来电铃声
if (Get.isRegistered<CallController>()) {
final callController = Get.find<CallController>();
callController.stopCallAudio();
print('📞 [LiveChatMessageService] 已停止播放来电铃声');
}
}
return;
}
// 只处理聊天消息类型
if (messageData['type'] == 'chat_message') {
final chatMessage = LiveChatMessage.fromJson(messageData);
onMessageReceived?.call(chatMessage);
}else{
RoomController controller = Get.find<RoomController>();
await controller.receiveRTCMessage(messageData);
}
} catch (e, stackTrace) {
final error = '解析RTM消息失败: $e';
print('$error');
print('❌ 堆栈信息: $stackTrace');
onMessageError?.call(error);
}
}
/// 处理结束直播消息
void _handleEndLiveMessage() {
try {
// 检查 overlay 是否显示,如果显示则关闭
if (Get.isRegistered<OverlayController>()) {
final overlayController = Get.find<OverlayController>();
if (overlayController.showOverlay.value) {
overlayController.hide();
print('✅ 已关闭 overlay 小窗');
return;
}
}
// 检查当前是否在 LiveRoomPage,如果是则跳转到 live_end_page
final currentRoute = Get.currentRoute;
if (currentRoute == '/LiveRoomPage' || currentRoute.contains('LiveRoomPage')) {
Get.off(() => const LiveEndPage());
print('✅ 已跳转到直播结束页面');
}
} catch (e) {
print('❌ 处理结束直播消息失败: $e');
}
}
/// 解析消息内容(支持 String 和 Uint8List)
String _parseMessageContent(dynamic message) {
if (message is String) {
return message;
} else if (message is Uint8List) {
return utf8.decode(message);
} else {
return message.toString();
}
}
/// 构建消息数据
Map<String, dynamic> _buildMessageData(String content) {
final userId = _storage.read('userId') ?? GlobalData().userId ?? '';
final userData = GlobalData().userData;
final userName = userData?.nickName ?? '用户';
final avatar = userData?.profilePhoto;
RoomController controller = Get.find<RoomController>();
final uid = controller.rtcChannel.value?.uid;
return {
'type': 'chat_message',
'userId': userId,
'userName': userName,
'uid': uid,
'avatar': avatar,
'content': content.trim(),
'timestamp': DateTime.now().millisecondsSinceEpoch,
};
}
/// 验证消息内容
String? _validateMessage(String content) {
final trimmed = content.trim();
if (trimmed.isEmpty) {
return '消息内容不能为空';
}
if (trimmed.length > 500) {
return '消息内容不能超过500个字符';
}
return null;
}
/// 检查发送前置条件
String? _checkSendPreconditions(String channelName) {
if (!RTMManager.instance.isInitialized) {
return 'RTM 未初始化,无法发送消息';
}
if (!RTMManager.instance.isLoggedIn) {
return 'RTM 未登录,无法发送消息';
}
if (channelName.isEmpty) {
return '未加入频道,无法发送消息';
}
return null;
}
/// 发送聊天消息
///
/// [content] 消息内容
/// [channelName] 频道名称,如果为空则从 RTCManager 获取
/// [showToast] 是否显示 Toast 提示,默认为 true
///
/// 返回发送结果,true 表示成功,false 表示失败
Future<MessageSendResult> sendMessage({
required String content,
String? channelName,
bool showToast = true,
}) async {
// 验证消息内容
final validationError = _validateMessage(content);
if (validationError != null) {
if (showToast) {
SmartDialog.showToast(validationError);
}
return MessageSendResult.failure(validationError);
}
// 获取频道名称
final targetChannelName = channelName ??
RTCManager.instance.currentChannelId ?? '';
// 检查前置条件
final preconditionError = _checkSendPreconditions(targetChannelName);
if (preconditionError != null) {
print('$preconditionError');
if (showToast) {
SmartDialog.showToast(preconditionError);
}
return MessageSendResult.failure(preconditionError);
}
try {
// 构建消息数据
final messageData = _buildMessageData(content);
final messageJson = json.encode(messageData);
print('📤 发送消息到频道: $targetChannelName');
print('📤 消息内容: $messageJson');
// 通过 RTM 发送消息
final success = await RTMManager.instance.publishChannelMessage(
channelName: targetChannelName,
message: messageJson,
);
if (success) {
print('✅ 消息发送成功');
// 创建消息对象(用于立即显示)
final chatMessage = LiveChatMessage(
userId: messageData['userId'] as String,
userName: messageData['userName'] as String,
avatar: messageData['avatar'] as String?,
content: messageData['content'] as String,
timestamp: messageData['timestamp'] as int,
);
return MessageSendResult.success(chatMessage);
} else {
final error = '消息发送失败,请重试';
print('$error');
if (showToast) {
SmartDialog.showToast(error);
}
return MessageSendResult.failure(error);
}
} catch (e, stackTrace) {
final error = '发送消息异常: $e';
print('$error');
print('❌ 堆栈信息: $stackTrace');
if (showToast) {
SmartDialog.showToast(error);
}
return MessageSendResult.failure(error);
}
}
/// 创建消息对象(用于本地显示)
LiveChatMessage createLocalMessage(String content) {
final messageData = _buildMessageData(content);
return LiveChatMessage(
userId: messageData['userId'] as String,
userName: messageData['userName'] as String,
avatar: messageData['avatar'] as String?,
content: messageData['content'] as String,
timestamp: messageData['timestamp'] as int,
);
}
}
/// 消息发送结果
class MessageSendResult {
final bool success;
final LiveChatMessage? message;
final String? error;
MessageSendResult._({
required this.success,
this.message,
this.error,
});
factory MessageSendResult.success(LiveChatMessage message) {
return MessageSendResult._(
success: true,
message: message,
);
}
factory MessageSendResult.failure(String error) {
return MessageSendResult._(
success: false,
error: error,
);
}
}