Browse Source

feat(call): 添加远端用户UID管理和视频通话页面优化

- 在CallController中添加remoteUid用于跟踪远端用户
- 在通话开始和结束时清空远端用户UID状态
- 修改IMManager中通话状态判断逻辑,支持waitCalling状态
- 在RTCManager中集成CallController的remoteUid更新机制
- 重构VideoCallPage使用Obx监听远端用户变化
- 实现远端视频视图显示和本地视频视图切换逻辑
- 添加视频通话中的调试日志输出
master
Jolie 3 months ago
parent
commit
9ab0dc65c5
4 changed files with 98 additions and 13 deletions
  1. 12
      lib/controller/message/call_controller.dart
  2. 3
      lib/im/im_manager.dart
  3. 74
      lib/pages/message/video_call_page.dart
  4. 22
      lib/rtc/rtc_manager.dart

12
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<int> remoteUid = Rxn<int>();
//
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();

3
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<String, dynamic>? attributes;
try {

74
lib/pages/message/video_call_page.dart

@ -320,19 +320,71 @@ class _VideoCallPageState extends State<VideoCallPage> {
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,

22
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<RoomController>();
await roomController.fetchRtcChannelDetail(channelId);
}
} else if (type == RTCType.call) {
// CallController
print('📞 [RTCManager] 通话场景:检测到用户加入,UID:$remoteUid');
if (Get.isRegistered<CallController>()) {
final callController = Get.find<CallController>();
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<int>.unmodifiable(_remoteUserIds);
// CallController remoteUid
if (type == RTCType.call && Get.isRegistered<CallController>()) {
final callController = Get.find<CallController>();
if (callController.remoteUid.value == null) {
callController.remoteUid.value = remoteUid;
print('📞 [RTCManager] _handleRemoteUserJoined: 已同步 remoteUid 到 CallController: $remoteUid');
}
}
}
void _handleRemoteUserOffline(int remoteUid) {

Loading…
Cancel
Save