Browse Source

refactor(call): 重构通话控制器并集成RTM功能

- 移除所有try-catch异常处理块,简化代码逻辑
- 添加RTMManager导入并实现RTM频道订阅功能
- 在加入RTC频道后自动订阅对应的RTM频道
- 通过RTM消息传递通话接受事件和用户UID信息
- 优化通话音频播放逻辑,移除循环播放异常处理
- 简化通话创建、接听、拒绝、取消和结束流程
- 在视频通话页面移除用户信息加载的异常处理
- 改进通话状态管理和错误处理机制
master
Jolie 3 months ago
parent
commit
ecc8a5ee3c
3 changed files with 423 additions and 523 deletions
  1. 783
      lib/controller/message/call_controller.dart
  2. 147
      lib/pages/message/video_call_page.dart
  3. 16
      lib/service/live_chat_message_service.dart

783
lib/controller/message/call_controller.dart

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:dating_touchme_app/generated/assets.dart';
@ -6,6 +7,7 @@ import 'package:dating_touchme_app/im/im_manager.dart';
import 'package:dating_touchme_app/model/rtc/rtc_channel_data.dart';
import 'package:dating_touchme_app/network/network_service.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:im_flutter_sdk/im_flutter_sdk.dart';
@ -101,12 +103,7 @@ class CallController extends GetxController {
_callAudioPlayer.onPlayerComplete.listen((_) async {
if (_isPlayingCallAudio) {
//
try {
await _callAudioPlayer.play(AssetSource(Assets.audioCall.replaceFirst('assets/', '')));
} catch (e) {
print('❌ [CallController] 循环播放来电铃声失败: $e');
_isPlayingCallAudio = false;
}
await _callAudioPlayer.play(AssetSource(Assets.audioCall.replaceFirst('assets/', '')));
}
});
}
@ -127,30 +124,23 @@ class CallController extends GetxController {
isCreatingChannel.value = true;
try {
final response = await _networkService.rtcApi.createOneOnOneRtcChannel({
'type': type,
});
if (response.data.isSuccess && response.data.data != null) {
rtcChannel.value = response.data.data;
print('✅ 创建一对一RTC频道成功: ${response.data.data?.channelId}');
return response.data.data;
} else {
final message = response.data.message.isNotEmpty
? response.data.message
: '创建频道失败';
SmartDialog.showToast(message);
print('❌ 创建一对一RTC频道失败: $message');
return null;
}
} catch (e) {
final errorMessage = '创建频道异常:$e';
SmartDialog.showToast(errorMessage);
print('$errorMessage');
return null;
} finally {
final response = await _networkService.rtcApi.createOneOnOneRtcChannel({
'type': type,
});
if (response.data.isSuccess && response.data.data != null) {
rtcChannel.value = response.data.data;
print('✅ 创建一对一RTC频道成功: ${response.data.data?.channelId}');
isCreatingChannel.value = false;
return response.data.data;
} else {
final message = response.data.message.isNotEmpty
? response.data.message
: '创建频道失败';
SmartDialog.showToast(message);
print('❌ 创建一对一RTC频道失败: $message');
isCreatingChannel.value = false;
return null;
}
}
@ -173,91 +163,76 @@ class CallController extends GetxController {
required CallType callType,
ChatController? chatController,
}) async {
try {
if (currentCall.value != null) {
SmartDialog.showToast('已有通话正在进行中');
return false;
}
// UID
remoteUid.value = null;
print('📞 [CallController] 发起${callType == CallType.video ? "视频" : "语音"}通话,目标用户: $targetUserId');
if (currentCall.value != null) {
SmartDialog.showToast('已有通话正在进行中');
return false;
}
// UID
remoteUid.value = null;
// RTC
final type = callType == CallType.video ? 2 : 1; // 12
final channelData = await createOneOnOneRtcChannel(type: type);
if (channelData == null) {
print('❌ [CallController] 创建RTC频道失败,无法发起通话');
SmartDialog.showToast('创建通话频道失败');
return false;
}
print('✅ [CallController] RTC频道创建成功: ${channelData.channelId}');
print('📞 [CallController] 发起${callType == CallType.video ? "视频" : "语音"}通话,目标用户: $targetUserId');
//
final session = CallSession(
targetUserId: targetUserId,
callType: callType,
status: CallStatus.calling,
isInitiator: true,
startTime: DateTime.now(),
);
currentCall.value = session;
//
final callTypeStr = callType == CallType.video ? 'video' : 'voice';
await _sendCallMessage(
targetUserId: targetUserId,
callType: callTypeStr,
callStatus: 'waitCalling', //
channelId: channelData.channelId, // ID
chatController: chatController,
);
// RTC
final type = callType == CallType.video ? 2 : 1; // 12
final channelData = await createOneOnOneRtcChannel(type: type);
if (channelData == null) {
print('❌ [CallController] 创建RTC频道失败,无法发起通话');
SmartDialog.showToast('创建通话频道失败');
return false;
}
print('✅ [CallController] RTC频道创建成功: ${channelData.channelId}');
//
final session = CallSession(
targetUserId: targetUserId,
callType: callType,
status: CallStatus.calling,
isInitiator: true,
startTime: DateTime.now(),
);
currentCall.value = session;
//
final callTypeStr = callType == CallType.video ? 'video' : 'voice';
await _sendCallMessage(
targetUserId: targetUserId,
callType: callTypeStr,
callStatus: 'waitCalling', //
channelId: channelData.channelId, // ID
chatController: chatController,
);
startCallAudio();
//
try {
if (callType == CallType.voice) {
//
await RTCManager.instance.disableVideo();
print('📞 [CallController] 语音通话,已关闭摄像头');
} else {
//
await RTCManager.instance.enableVideo();
print('📞 [CallController] 视频通话,已打开摄像头');
}
} catch (e) {
print('⚠️ [CallController] 设置视频状态失败: $e');
//
}
startCallAudio();
// RTC
try {
await RTCManager.instance.joinChannel(
token: channelData.token,
channelId: channelData.channelId,
uid: channelData.uid,
role: ClientRoleType.clientRoleBroadcaster,
rtcType: RTCType.call,
);
print('✅ [CallController] 已加入 RTC 频道: ${channelData.channelId}');
} catch (e) {
print('❌ [CallController] 加入 RTC 频道失败: $e');
SmartDialog.showToast('加入通话频道失败');
currentCall.value = null;
return false;
}
return true;
} catch (e) {
print('❌ [CallController] 发起通话失败: $e');
SmartDialog.showToast('发起通话失败: $e');
currentCall.value = null;
return false;
//
if (callType == CallType.voice) {
//
await RTCManager.instance.disableVideo();
print('📞 [CallController] 语音通话,已关闭摄像头');
} else {
//
await RTCManager.instance.enableVideo();
print('📞 [CallController] 视频通话,已打开摄像头');
}
// RTC
await RTCManager.instance.joinChannel(
token: channelData.token,
channelId: channelData.channelId,
uid: channelData.uid,
role: ClientRoleType.clientRoleBroadcaster,
rtcType: RTCType.call,
);
print('✅ [CallController] 已加入 RTC 频道: ${channelData.channelId}');
// RTC RTM
await RTMManager.instance.subscribe(channelData.channelId);
print('✅ [CallController] 已订阅 RTM 频道: ${channelData.channelId}');
return true;
}
///
@ -267,85 +242,68 @@ class CallController extends GetxController {
required EMMessage message,
ChatController? chatController,
}) async {
try {
final callInfo = _parseCallInfo(message);
if (callInfo == null) {
return false;
}
final callInfo = _parseCallInfo(message);
if (callInfo == null) {
return false;
}
final targetUserId = message.from ?? '';
final callTypeStr = callInfo['callType'] as String?;
final callType = callTypeStr == 'video' ? CallType.video : CallType.voice;
final targetUserId = message.from ?? '';
final callTypeStr = callInfo['callType'] as String?;
final callType = callTypeStr == 'video' ? CallType.video : CallType.voice;
print('📞 [CallController] 接听${callType == CallType.video ? "视频" : "语音"}通话');
// UID
remoteUid.value = null;
print('📞 [CallController] 接听${callType == CallType.video ? "视频" : "语音"}通话');
// UID
remoteUid.value = null;
//
final session = CallSession(
targetUserId: targetUserId,
callType: callType,
status: CallStatus.calling,
isInitiator: false,
startTime: DateTime.now(),
);
currentCall.value = session;
//
final session = CallSession(
targetUserId: targetUserId,
callType: callType,
status: CallStatus.calling,
isInitiator: false,
startTime: DateTime.now(),
);
currentCall.value = session;
//
stopCallAudio();
//
stopCallAudio();
//
_startCallTimer();
//
_startCallTimer();
//
await _updateCallMessageStatus(
message: message,
callStatus: 'calling',
callDuration: 0,
chatController: chatController,
);
//
await _updateCallMessageStatus(
message: message,
callStatus: 'calling',
callDuration: 0,
chatController: chatController,
);
// channelId
final channelId = callInfo['channelId'] as String?;
if (channelId == null || channelId.isEmpty) {
print('❌ [CallController] channelId 为空,无法加入 RTC 频道');
SmartDialog.showToast('频道ID不存在');
return false;
}
// channelId
final channelId = callInfo['channelId'] as String?;
if (channelId == null || channelId.isEmpty) {
print('❌ [CallController] channelId 为空,无法加入 RTC 频道');
SmartDialog.showToast('频道ID不存在');
return false;
}
//
try {
if (callType == CallType.voice) {
//
await RTCManager.instance.disableVideo();
print('📞 [CallController] 语音通话,已关闭摄像头');
} else {
//
await RTCManager.instance.enableVideo();
print('📞 [CallController] 视频通话,已打开摄像头');
}
} catch (e) {
print('⚠️ [CallController] 设置视频状态失败: $e');
//
}
//
if (callType == CallType.voice) {
//
await RTCManager.instance.disableVideo();
print('📞 [CallController] 语音通话,已关闭摄像头');
} else {
//
await RTCManager.instance.enableVideo();
print('📞 [CallController] 视频通话,已打开摄像头');
}
// RTC
try {
await joinChannel(channelId);
print('✅ [CallController] 已加入 RTC 频道: $channelId');
} catch (e) {
print('❌ [CallController] 加入 RTC 频道失败: $e');
SmartDialog.showToast('加入通话频道失败');
return false;
}
// RTC
await joinChannel(channelId);
print('✅ [CallController] 已加入 RTC 频道: $channelId');
return true;
} catch (e) {
print('❌ [CallController] 接听通话失败: $e');
SmartDialog.showToast('接听通话失败: $e');
return false;
}
return true;
}
///
@ -355,31 +313,25 @@ class CallController extends GetxController {
required EMMessage message,
ChatController? chatController,
}) async {
try {
print('📞 [CallController] 拒绝通话');
print('📞 [CallController] 拒绝通话');
//
stopCallAudio();
//
stopCallAudio();
//
await _updateCallMessageStatus(
message: message,
callStatus: 'rejected',
chatController: chatController,
);
//
await _updateCallMessageStatus(
message: message,
callStatus: 'rejected',
chatController: chatController,
);
//
currentCall.value = null;
//
currentCall.value = null;
// TODO: SDK
// await RTCManager.instance.rejectCall(message.from ?? '');
// TODO: SDK
// await RTCManager.instance.rejectCall(message.from ?? '');
return true;
} catch (e) {
print('❌ [CallController] 拒绝通话失败: $e');
SmartDialog.showToast('拒绝通话失败: $e');
return false;
}
return true;
}
///
@ -389,36 +341,30 @@ class CallController extends GetxController {
EMMessage? message,
ChatController? chatController,
}) async {
try {
print('📞 [CallController] 取消通话');
//
if (message != null) {
await _updateCallMessageStatus(
message: message,
callStatus: 'cancelled',
chatController: chatController,
);
}
print('📞 [CallController] 取消通话');
//
stopCallAudio();
//
if (message != null) {
await _updateCallMessageStatus(
message: message,
callStatus: 'cancelled',
chatController: chatController,
);
}
//
_stopCallTimer();
//
stopCallAudio();
//
currentCall.value = null;
//
_stopCallTimer();
// TODO: SDK
// await RTCManager.instance.cancelCall();
//
currentCall.value = null;
return true;
} catch (e) {
print('❌ [CallController] 取消通话失败: $e');
SmartDialog.showToast('取消通话失败: $e');
return false;
}
// TODO: SDK
// await RTCManager.instance.cancelCall();
return true;
}
///
@ -429,38 +375,32 @@ class CallController extends GetxController {
EMMessage? message,
ChatController? chatController,
}) async {
try {
print('📞 [CallController] 结束通话,时长: ${callDuration}');
//
stopCallAudio();
//
_stopCallTimer();
//
if (message != null) {
await _updateCallMessageStatus(
message: message,
callStatus: 'calling',
callDuration: callDuration,
chatController: chatController,
);
}
print('📞 [CallController] 结束通话,时长: ${callDuration}');
// UID
currentCall.value = null;
remoteUid.value = null;
//
stopCallAudio();
// TODO: SDK
// await RTCManager.instance.endCall();
//
_stopCallTimer();
return true;
} catch (e) {
print('❌ [CallController] 结束通话失败: $e');
SmartDialog.showToast('结束通话失败: $e');
return false;
//
if (message != null) {
await _updateCallMessageStatus(
message: message,
callStatus: 'calling',
callDuration: callDuration,
chatController: chatController,
);
}
// UID
currentCall.value = null;
remoteUid.value = null;
// TODO: SDK
// await RTCManager.instance.endCall();
return true;
}
///
@ -491,39 +431,34 @@ class CallController extends GetxController {
String? channelId,
ChatController? chatController,
}) async {
try {
// chatController使
if (chatController != null) {
return await chatController.sendCallMessage(
callType: callType,
callStatus: callStatus,
callDuration: callDuration,
channelId: channelId,
);
}
// IMManager
final callParams = <String, String>{
'callType': callType,
'callStatus': callStatus,
};
if (callDuration != null) {
callParams['callDuration'] = callDuration.toString();
}
if (channelId != null && channelId.isNotEmpty) {
callParams['channelId'] = channelId;
}
final message = await IMManager.instance.sendCustomMessage(
targetUserId,
'call',
callParams,
// chatController使
if (chatController != null) {
return await chatController.sendCallMessage(
callType: callType,
callStatus: callStatus,
callDuration: callDuration,
channelId: channelId,
);
return message != null;
} catch (e) {
print('❌ [CallController] 发送通话消息失败: $e');
return false;
}
// IMManager
final callParams = <String, String>{
'callType': callType,
'callStatus': callStatus,
};
if (callDuration != null) {
callParams['callDuration'] = callDuration.toString();
}
if (channelId != null && channelId.isNotEmpty) {
callParams['channelId'] = channelId;
}
final message = await IMManager.instance.sendCustomMessage(
targetUserId,
'call',
callParams,
);
return message != null;
}
/// 使modifyMessage修改现有消息
@ -533,104 +468,91 @@ class CallController extends GetxController {
int? callDuration,
ChatController? chatController,
}) async {
try {
//
final callInfo = _parseCallInfo(message);
if (callInfo == null) {
return false;
}
//
final callInfo = _parseCallInfo(message);
if (callInfo == null) {
return false;
}
final callType = callInfo['callType'] as String? ?? 'voice';
final messageId = message.msgId;
final callType = callInfo['callType'] as String? ?? 'voice';
final messageId = message.msgId;
if (messageId.isEmpty) {
print('❌ [CallController] 消息ID为空,无法修改消息');
return false;
if (messageId.isEmpty) {
print('❌ [CallController] 消息ID为空,无法修改消息');
return false;
}
// 使modifyMessage修改
if (message.body.type == MessageType.CUSTOM) {
//
final callParams = <String, String>{
'callType': callType,
'callStatus': callStatus,
};
if (callDuration != null) {
callParams['callDuration'] = callDuration.toString();
}
// 使modifyMessage修改
if (message.body.type == MessageType.CUSTOM) {
//
final callParams = <String, String>{
'callType': callType,
'callStatus': callStatus,
};
if (callDuration != null) {
callParams['callDuration'] = callDuration.toString();
}
//
final customBody = EMCustomMessageBody(
event: 'call',
params: callParams,
);
// 使modifyMessage修改消息
final success = await IMManager.instance.modifyMessage(
messageId: messageId,
msgBody: customBody,
attributes: null, //
);
//
final customBody = EMCustomMessageBody(
event: 'call',
params: callParams,
);
// 使modifyMessage修改消息
final success = await IMManager.instance.modifyMessage(
messageId: messageId,
msgBody: customBody,
attributes: null, //
);
if (success) {
print('✅ [CallController] 消息修改成功: messageId=$messageId, callStatus=$callStatus');
// chatController
if (chatController != null) {
//
try {
final index = chatController.messages.indexWhere((msg) => msg.msgId == messageId);
if (index != -1) {
final updatedMessage = chatController.messages[index];
if (updatedMessage.body.type == MessageType.CUSTOM) {
final customBody = updatedMessage.body as EMCustomMessageBody;
// Map并更新
final updatedParams = Map<String, String>.from(customBody.params ?? {});
updatedParams['callType'] = callType;
updatedParams['callStatus'] = callStatus;
if (callDuration != null) {
updatedParams['callDuration'] = callDuration.toString();
}
// EMCustomMessageBody的params可能是只读的
// UI更新onMessageContentChanged回调时处理
chatController.update();
}
if (success) {
print('✅ [CallController] 消息修改成功: messageId=$messageId, callStatus=$callStatus');
// chatController
if (chatController != null) {
//
final index = chatController.messages.indexWhere((msg) => msg.msgId == messageId);
if (index != -1) {
final updatedMessage = chatController.messages[index];
if (updatedMessage.body.type == MessageType.CUSTOM) {
final customBody = updatedMessage.body as EMCustomMessageBody;
// Map并更新
final updatedParams = Map<String, String>.from(customBody.params ?? {});
updatedParams['callType'] = callType;
updatedParams['callStatus'] = callStatus;
if (callDuration != null) {
updatedParams['callDuration'] = callDuration.toString();
}
} catch (e) {
print('⚠️ [CallController] 更新本地消息列表失败: $e');
// EMCustomMessageBody的params可能是只读的
// UI更新onMessageContentChanged回调时处理
chatController.update();
}
}
}
return success;
}
//
return false;
} catch (e) {
print('❌ [CallController] 更新通话消息状态失败: $e');
return false;
return success;
}
//
return false;
}
///
Map<String, dynamic>? _parseCallInfo(EMMessage message) {
try {
if (message.body.type == MessageType.CUSTOM) {
final customBody = message.body as EMCustomMessageBody;
if (customBody.event == 'call' && customBody.params != null) {
final params = customBody.params!;
return {
'callType': params['callType'] ?? 'voice',
'callStatus': params['callStatus'] ?? 'missed',
'callDuration': params['callDuration'] != null
? int.tryParse(params['callDuration']!)
: null,
'channelId': params['channelId'],
};
}
if (message.body.type == MessageType.CUSTOM) {
final customBody = message.body as EMCustomMessageBody;
if (customBody.event == 'call' && customBody.params != null) {
final params = customBody.params!;
return {
'callType': params['callType'] ?? 'voice',
'callStatus': params['callStatus'] ?? 'missed',
'callDuration': params['callDuration'] != null
? int.tryParse(params['callDuration']!)
: null,
'channelId': params['channelId'],
};
}
} catch (e) {
print('解析通话信息失败: $e');
}
return null;
}
@ -648,14 +570,9 @@ class CallController extends GetxController {
return; //
}
try {
_isPlayingCallAudio = true;
print('🔊 [CallController] 开始播放来电铃声');
await _callAudioPlayer.play(AssetSource(Assets.audioCall.replaceFirst('assets/', '')));
} catch (e) {
print('❌ [CallController] 播放来电铃声失败: $e');
_isPlayingCallAudio = false;
}
_isPlayingCallAudio = true;
print('🔊 [CallController] 开始播放来电铃声');
await _callAudioPlayer.play(AssetSource(Assets.audioCall.replaceFirst('assets/', '')));
}
///
@ -665,13 +582,9 @@ class CallController extends GetxController {
return; //
}
try {
_isPlayingCallAudio = false;
print('🔇 [CallController] 停止播放来电铃声');
await _callAudioPlayer.stop();
} catch (e) {
print('❌ [CallController] 停止播放来电铃声失败: $e');
}
_isPlayingCallAudio = false;
print('🔇 [CallController] 停止播放来电铃声');
await _callAudioPlayer.stop();
}
Future<void> joinChannel(String channelName) async {
@ -679,6 +592,25 @@ class CallController extends GetxController {
final base = response.data;
if (base.isSuccess && base.data != null) {
rtcChannel.value = base.data;
// RTM
await RTMManager.instance.subscribe(channelName);
//
final callSession = currentCall.value;
final callType = callSession?.callType == CallType.video ? 'video' : 'voice';
// RTM UID
await RTMManager.instance.publishChannelMessage(
channelName: channelName,
message: json.encode({
'type': 'call_message',
'uid': base.data!.uid,
'callType': callType,
'event': 'accept',
}),
);
await _joinRtcChannel(
base.data!.token,
channelName,
@ -694,31 +626,28 @@ class CallController extends GetxController {
int uid,
ClientRoleType roleType,
) async {
try {
final granted = await _ensureRtcPermissions();
if (!granted) return;
await RTCManager.instance.joinChannel(
token: token,
channelId: channelName,
uid: uid,
role: roleType,
rtcType: RTCType.call,
);
final data = {
'channelId': channelName,
'seatNumber': 1,
'isMicrophoneOn': true,
'isVideoOn': true,
};
final response = await _networkService.rtcApi.connectRtcChannel(data);
if (!response.data.isSuccess) {
SmartDialog.showToast(response.data.message);
return;
}
SmartDialog.showToast('加入通话成功');
} catch (e) {
SmartDialog.showToast('加入频道失败:$e');
final granted = await _ensureRtcPermissions();
if (!granted) return;
await RTCManager.instance.joinChannel(
token: token,
channelId: channelName,
uid: uid,
role: roleType,
rtcType: RTCType.call,
);
final data = {
'channelId': channelName,
'seatNumber': 1,
'isMicrophoneOn': true,
'isVideoOn': true,
};
final response = await _networkService.rtcApi.connectRtcChannel(data);
if (!response.data.isSuccess) {
SmartDialog.showToast(response.data.message);
return;
}
SmartDialog.showToast('加入通话成功');
}
Future<bool> _ensureRtcPermissions() async {
@ -742,49 +671,27 @@ class CallController extends GetxController {
///
Future<void> toggleMic() async {
try {
isMicMuted.value = !isMicMuted.value;
await RTCManager.instance.muteLocalAudio(isMicMuted.value);
print('📞 [CallController] 麦克风${isMicMuted.value ? "已静音" : "已取消静音"}');
} catch (e) {
print('❌ [CallController] 切换麦克风状态失败: $e');
//
isMicMuted.value = !isMicMuted.value;
}
isMicMuted.value = !isMicMuted.value;
await RTCManager.instance.muteLocalAudio(isMicMuted.value);
print('📞 [CallController] 麦克风${isMicMuted.value ? "已静音" : "已取消静音"}');
}
///
Future<void> toggleSpeaker() async {
try {
isSpeakerOn.value = !isSpeakerOn.value;
await RTCManager.instance.setEnableSpeakerphone(isSpeakerOn.value);
print('📞 [CallController] 扬声器${isSpeakerOn.value ? "已开启" : "已关闭"}');
} catch (e) {
print('❌ [CallController] 切换扬声器状态失败: $e');
//
isSpeakerOn.value = !isSpeakerOn.value;
}
isSpeakerOn.value = !isSpeakerOn.value;
await RTCManager.instance.setEnableSpeakerphone(isSpeakerOn.value);
print('📞 [CallController] 扬声器${isSpeakerOn.value ? "已开启" : "已关闭"}');
}
///
Future<void> hangUpCall() async {
try {
// RTC频道
await RTCManager.instance.leaveChannel();
//
await endCall(callDuration: callDurationSeconds.value);
print('✅ [CallController] 通话已挂断');
} catch (e) {
print('❌ [CallController] 挂断通话失败: $e');
// 使
try {
await endCall(callDuration: callDurationSeconds.value);
} catch (e2) {
print('❌ [CallController] 结束通话失败: $e2');
}
}
// RTC频道
await RTCManager.instance.leaveChannel();
//
await endCall(callDuration: callDurationSeconds.value);
print('✅ [CallController] 通话已挂断');
}
@override

147
lib/pages/message/video_call_page.dart

@ -110,32 +110,28 @@ class _VideoCallPageState extends State<VideoCallPage> {
}
// userData ConversationController
try {
if (Get.isRegistered<ConversationController>()) {
final conversationController = Get.find<ConversationController>();
//
final cachedUserInfo = conversationController.getCachedUserInfo(widget.targetUserId);
if (cachedUserInfo != null && (cachedUserInfo.nickName != null || cachedUserInfo.avatarUrl != null)) {
setState(() {
_targetUserName = cachedUserInfo.nickName ?? widget.targetUserId;
_targetAvatarUrl = cachedUserInfo.avatarUrl;
});
return;
}
if (Get.isRegistered<ConversationController>()) {
final conversationController = Get.find<ConversationController>();
//
final cachedUserInfo = conversationController.getCachedUserInfo(widget.targetUserId);
if (cachedUserInfo != null && (cachedUserInfo.nickName != null || cachedUserInfo.avatarUrl != null)) {
setState(() {
_targetUserName = cachedUserInfo.nickName ?? widget.targetUserId;
_targetAvatarUrl = cachedUserInfo.avatarUrl;
});
return;
}
// IM
final userInfo = await conversationController.loadContact(widget.targetUserId);
if (userInfo != null && (userInfo.nickName != null || userInfo.avatarUrl != null)) {
setState(() {
_targetUserName = userInfo.nickName ?? widget.targetUserId;
_targetAvatarUrl = userInfo.avatarUrl;
});
return;
}
// IM
final userInfo = await conversationController.loadContact(widget.targetUserId);
if (userInfo != null && (userInfo.nickName != null || userInfo.avatarUrl != null)) {
setState(() {
_targetUserName = userInfo.nickName ?? widget.targetUserId;
_targetAvatarUrl = userInfo.avatarUrl;
});
return;
}
} catch (e) {
print('⚠️ [VideoCallPage] 加载用户信息失败: $e');
}
// 使
@ -619,73 +615,54 @@ class _VideoCallPageState extends State<VideoCallPage> {
///
Future<void> _acceptCall() async {
try {
if (widget.callMessage == null) {
SmartDialog.showToast('未找到通话邀请消息');
return;
}
if (widget.callMessage == null) {
SmartDialog.showToast('未找到通话邀请消息');
return;
}
// ChatController
ChatController? chatController;
try {
final tag = 'chat_${widget.targetUserId}';
if (Get.isRegistered<ChatController>(tag: tag)) {
chatController = Get.find<ChatController>(tag: tag);
}
} catch (e) {
print('⚠️ [VideoCallPage] 获取ChatController失败: $e');
}
final accepted = await _callController.acceptCall(
message: widget.callMessage!,
chatController: chatController,
);
if (accepted) {
// UI会自动更新
print('✅ [VideoCallPage] 通话已接通');
} else {
SmartDialog.showToast('接听失败');
}
} catch (e) {
print('❌ [VideoCallPage] 接听通话失败: $e');
SmartDialog.showToast('接听失败: $e');
// ChatController
ChatController? chatController;
final tag = 'chat_${widget.targetUserId}';
if (Get.isRegistered<ChatController>(tag: tag)) {
chatController = Get.find<ChatController>(tag: tag);
}
final accepted = await _callController.acceptCall(
message: widget.callMessage!,
chatController: chatController,
);
if (accepted) {
// UI会自动更新
print('✅ [VideoCallPage] 通话已接通');
} else {
SmartDialog.showToast('接听失败');
}
}
///
Future<void> _rejectCall() async {
try {
// ChatController
ChatController? chatController;
try {
final tag = 'chat_${widget.targetUserId}';
if (Get.isRegistered<ChatController>(tag: tag)) {
chatController = Get.find<ChatController>(tag: tag);
}
} catch (e) {
print('⚠️ [VideoCallPage] 获取ChatController失败: $e');
}
if (widget.callMessage == null) {
// 使
await _callController.endCall(callDuration: 0);
Get.back();
return;
}
final rejected = await _callController.rejectCall(
message: widget.callMessage!,
chatController: chatController,
);
if (rejected) {
//
Get.back();
}
} catch (e) {
print('❌ [VideoCallPage] 拒绝通话失败: $e');
// 使
// ChatController
ChatController? chatController;
final tag = 'chat_${widget.targetUserId}';
if (Get.isRegistered<ChatController>(tag: tag)) {
chatController = Get.find<ChatController>(tag: tag);
}
if (widget.callMessage == null) {
// 使
await _callController.endCall(callDuration: 0);
Get.back();
return;
}
final rejected = await _callController.rejectCall(
message: widget.callMessage!,
chatController: chatController,
);
if (rejected) {
//
Get.back();
}
}

16
lib/service/live_chat_message_service.dart

@ -3,6 +3,7 @@ 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';
@ -75,6 +76,21 @@ class LiveChatMessageService {
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}');
}
}
return;
}
//
if (messageData['type'] == 'chat_message') {
final chatMessage = LiveChatMessage.fromJson(messageData);

Loading…
Cancel
Save