From 520f9ab8f14f931bb2291af56a999f2b83290f3c Mon Sep 17 00:00:00 2001 From: Jolie <412895109@qq.com> Date: Wed, 31 Dec 2025 07:48:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(call):=20=E6=B7=BB=E5=8A=A0=E9=80=9A?= =?UTF-8?q?=E8=AF=9D=E8=B6=85=E6=97=B6=E8=AE=A1=E6=97=B6=E5=99=A8=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现30秒超时计时器,自动取消未接听的通话 - 在发起通话时启动超时计时器 - 在对方接听、拒绝或挂断时停止超时计时器 - 添加_startCallTimeoutTimer和_stopCallTimeoutTimer方法 - 在通话结束和控制器关闭时清理超时计时器 - 优化通话流程中的计时器管理逻辑 --- lib/controller/message/call_controller.dart | 42 ++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/controller/message/call_controller.dart b/lib/controller/message/call_controller.dart index fd5c727..f5f826a 100644 --- a/lib/controller/message/call_controller.dart +++ b/lib/controller/message/call_controller.dart @@ -84,6 +84,9 @@ class CallController extends GetxController { int _callDurationSeconds = 0; final RxInt callDurationSeconds = RxInt(0); + // 通话超时计时器(发起方等待对方接听的30秒超时) + Timer? _callTimeoutTimer; + // 远端用户UID(用于显示远端视频) final Rxn remoteUid = Rxn(); @@ -155,6 +158,8 @@ class CallController extends GetxController { '📞 [CallController] 收到 accept 消息,设置 remoteUid: ${remoteUid.value}', ); } + // 取消超时计时器(对方已接听) + _stopCallTimeoutTimer(); // 发起方收到 accept 消息后,启动通话计时器 _startCallTimer(); print('📞 [CallController] 收到 accept 消息,已启动通话计时器'); @@ -170,6 +175,8 @@ class CallController extends GetxController { } else if (event == 'reject') { // 发起方收到 reject 消息,执行退出逻辑 print('📞 [CallController] 收到 reject 消息,执行退出逻辑'); + // 取消超时计时器(对方已拒绝) + _stopCallTimeoutTimer(); final channelId = messageData['channelId'] as String?; if (channelId != null && channelId.isNotEmpty) { RTMManager.instance.unsubscribe(channelId); @@ -323,6 +330,9 @@ class CallController extends GetxController { await RTMManager.instance.subscribe(channelData.channelId); print('✅ [CallController] 已订阅 RTM 频道: ${channelData.channelId}'); + // 启动30秒超时计时器(如果30秒内对方未接听,自动取消通话) + _startCallTimeoutTimer(); + return true; } @@ -472,8 +482,9 @@ class CallController extends GetxController { // 停止播放来电铃声(通话结束) stopCallAudio(); - // 停止计时 + // 停止计时和超时计时器 _stopCallTimer(); + _stopCallTimeoutTimer(); // 清理通话会话和远端用户UID currentCall.value = null; @@ -508,6 +519,28 @@ class CallController extends GetxController { callDurationSeconds.value = 0; } + /// 启动通话超时计时器(30秒后如果对方未接听,自动取消通话) + void _startCallTimeoutTimer() { + _callTimeoutTimer?.cancel(); + _callTimeoutTimer = Timer(Duration(seconds: 30), () { + final callSession = currentCall.value; + // 如果是发起方且对方未接听(通话时长仍为0且remoteUid为null),自动取消通话 + if (callSession != null && + callSession.isInitiator && + callDurationSeconds.value == 0 && + remoteUid.value == null) { + print('⏰ [CallController] 30秒超时,对方未接听,自动取消通话'); + hangUpCall(); + } + }); + } + + /// 停止通话超时计时器 + void _stopCallTimeoutTimer() { + _callTimeoutTimer?.cancel(); + _callTimeoutTimer = null; + } + /// 发送通话消息 Future _sendCallMessage({ required String targetUserId, @@ -685,6 +718,9 @@ class CallController extends GetxController { Future hangUpCall() async { final callSession = currentCall.value; + // 取消超时计时器 + _stopCallTimeoutTimer(); + // 如果是发起方且处于呼叫中状态(对方还没接听),先调用取消接口 if (callSession != null && callSession.isInitiator && @@ -744,6 +780,9 @@ class CallController extends GetxController { SmartDialog.dismiss(); print('✅ [CallController] 已关闭视频通话邀请弹框'); + // 取消超时计时器 + _stopCallTimeoutTimer(); + // 停止播放来电铃声 stopCallAudio(); @@ -777,6 +816,7 @@ class CallController extends GetxController { void onClose() { stopCallAudio(); _stopCallTimer(); + _stopCallTimeoutTimer(); currentCall.value = null; rtcChannel.value = null; remoteUid.value = null;