diff --git a/lib/controller/message/call_controller.dart b/lib/controller/message/call_controller.dart index a4a1e22..c41b5c7 100644 --- a/lib/controller/message/call_controller.dart +++ b/lib/controller/message/call_controller.dart @@ -80,6 +80,9 @@ class CallController extends GetxController { int _callDurationSeconds = 0; final RxInt callDurationSeconds = RxInt(0); + // 远端用户UID(用于显示远端视频) + final Rxn remoteUid = Rxn(); + // 音频播放器(用于播放来电铃声) final AudioPlayer _callAudioPlayer = AudioPlayer(); bool _isPlayingCallAudio = false; @@ -169,6 +172,9 @@ class CallController extends GetxController { SmartDialog.showToast('已有通话正在进行中'); return false; } + + // 清空之前的远端用户UID + remoteUid.value = null; print('📞 [CallController] 发起${callType == CallType.video ? "视频" : "语音"}通话,目标用户: $targetUserId'); @@ -266,6 +272,9 @@ class CallController extends GetxController { final callType = callTypeStr == 'video' ? CallType.video : CallType.voice; print('📞 [CallController] 接听${callType == CallType.video ? "视频" : "语音"}通话'); + + // 清空之前的远端用户UID + remoteUid.value = null; // 创建通话会话 final session = CallSession( @@ -433,8 +442,9 @@ class CallController extends GetxController { ); } - // 清理通话会话 + // 清理通话会话和远端用户UID currentCall.value = null; + remoteUid.value = null; // TODO: 这里可以集成实际的通话SDK,结束通话 // 例如:await RTCManager.instance.endCall(); diff --git a/lib/im/im_manager.dart b/lib/im/im_manager.dart index c75e738..e49ebfb 100644 --- a/lib/im/im_manager.dart +++ b/lib/im/im_manager.dart @@ -218,6 +218,7 @@ class IMManager { // 从消息扩展字段中解析用户信息并缓存 for (var message in messages) { if (message.direction == MessageDirection.RECEIVE && message.onlineState) { + _parseUserInfoFromMessageExt(message); // 检查发送者是否是当前正在聊天的用户,如果不是则显示弹框 // 只有在 APP 处于前台时才显示弹框,后台时显示本地通知 @@ -1455,7 +1456,7 @@ class IMManager { // 如果解析到通话信息,检查是否需要显示视频通话邀请弹框 if (callInfo != null && callType != null && callStatus != null) { // 只处理视频通话且状态为 missed 或 calling 的消息(新邀请) - if ((callType == 'video' || callType == 'voice') && (callStatus == 'missed' || callStatus == 'calling')) { + if ((callType == 'video' || callType == 'voice') && (callStatus == 'waitCalling' || callStatus == 'calling')) { // 获取用户信息 Map? attributes; try { diff --git a/lib/pages/message/video_call_page.dart b/lib/pages/message/video_call_page.dart index bb354dc..e1eb0b6 100644 --- a/lib/pages/message/video_call_page.dart +++ b/lib/pages/message/video_call_page.dart @@ -320,19 +320,71 @@ class _VideoCallPageState extends State { final callSession = _callController.currentCall.value; final isVideoCall = callSession != null && callSession.callType == CallType.video; - // 如果是视频通话,显示本地视频视图 - if (isVideoCall && _localVideoViewController != null) { - Get.log('显示本地视频视图$_localVideoViewController'); - return SizedBox( - width: double.infinity, - height: 1.sh, - child: AgoraVideoView( - controller: _localVideoViewController!, - ), - ); + // 使用 Obx 监听远端用户 UID 的变化 + if (isVideoCall) { + return Obx(() { + // 同时监听 CallController.remoteUid 和 RTCManager.remoteUsersNotifier + var remoteUid = _callController.remoteUid.value; + final remoteUsers = _rtcManager.remoteUsersNotifier.value; // 触发 Obx 监听 + + print('📞 [VideoCallPage] Obx 重建,CallController.remoteUid: ${_callController.remoteUid.value}, remoteUsers: $remoteUsers, isVideoCall: $isVideoCall'); + + // 如果 remoteUid 为空,尝试从 RTCManager 的远端用户列表中获取 + if (remoteUid == null && remoteUsers.isNotEmpty) { + remoteUid = remoteUsers.first; + // 同步到 CallController + _callController.remoteUid.value = remoteUid; + print('📞 [VideoCallPage] 从 RTCManager.remoteUsersNotifier 获取到 remoteUid: $remoteUid'); + } + + // 如果远端用户已加入,显示远端视频视图(对方画面) + if (remoteUid != null) { + final engine = _rtcManager.engine; + print('📞 [VideoCallPage] remoteUid 不为 null: $remoteUid, engine: ${engine != null}'); + if (engine != null) { + print('📞 [VideoCallPage] 显示远端视频视图,UID:$remoteUid'); + final remoteVideoViewController = VideoViewController( + rtcEngine: engine, + canvas: VideoCanvas(uid: remoteUid), + ); + return SizedBox( + width: double.infinity, + height: 1.sh, + child: AgoraVideoView( + controller: remoteVideoViewController, + ), + ); + } else { + print('⚠️ [VideoCallPage] engine 为 null,无法显示远端视频'); + } + } else { + print('⚠️ [VideoCallPage] remoteUid 为 null,无法显示远端视频'); + } + + // 如果没有远端视频,显示本地视频视图(自己的画面) + if (_localVideoViewController != null) { + print('📞 [VideoCallPage] 显示本地视频视图'); + return SizedBox( + width: double.infinity, + height: 1.sh, + child: AgoraVideoView( + controller: _localVideoViewController!, + ), + ); + } + + // 如果本地视频也没有,显示模糊的头像背景 + print('📞 [VideoCallPage] 显示头像背景'); + return _buildAvatarBackground(); + }); } - // 否则显示模糊的头像背景 + // 非视频通话,显示模糊的头像背景 + return _buildAvatarBackground(); + } + + /// 构建头像背景 + Widget _buildAvatarBackground() { return SizedBox( width: double.infinity, height: 1.sh, diff --git a/lib/rtc/rtc_manager.dart b/lib/rtc/rtc_manager.dart index 10482de..7739770 100644 --- a/lib/rtc/rtc_manager.dart +++ b/lib/rtc/rtc_manager.dart @@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; import '../controller/discover/room_controller.dart'; +import '../controller/message/call_controller.dart'; import '../pages/discover/live_room_page.dart'; enum RTCType { @@ -170,6 +171,18 @@ class RTCManager { final roomController = Get.find(); await roomController.fetchRtcChannelDetail(channelId); } + } else if (type == RTCType.call) { + // 通话场景:通知 CallController 远端用户已加入 + print('📞 [RTCManager] 通话场景:检测到用户加入,UID:$remoteUid'); + if (Get.isRegistered()) { + final callController = Get.find(); + callController.remoteUid.value = remoteUid; + print('✅ [RTCManager] 通话场景:已设置 CallController.remoteUid = $remoteUid'); + } else { + print('⚠️ [RTCManager] CallController 未注册,无法设置 remoteUid'); + } + } else { + print('⚠️ [RTCManager] 未知的 RTC 类型:$type'); } if (onUserJoined != null) { @@ -540,6 +553,15 @@ class RTCManager { if (_remoteUserIds.contains(remoteUid)) return; _remoteUserIds.add(remoteUid); remoteUsersNotifier.value = List.unmodifiable(_remoteUserIds); + + // 如果是通话场景,同时更新 CallController 的 remoteUid + if (type == RTCType.call && Get.isRegistered()) { + final callController = Get.find(); + if (callController.remoteUid.value == null) { + callController.remoteUid.value = remoteUid; + print('📞 [RTCManager] _handleRemoteUserJoined: 已同步 remoteUid 到 CallController: $remoteUid'); + } + } } void _handleRemoteUserOffline(int remoteUid) {