feat(mobile-next): 迁移 Android 一对一语音通话薄适配与入口
复用官方 OpenIMLive 信令与房间,换票改走账号服务 /api/rtc_token;入口仅音频,占线/超时/重复回调与销毁释放由公司层防护。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
2a817e77d8
commit
3832e080c4
@@ -0,0 +1,69 @@
|
||||
import 'dart:async';
|
||||
|
||||
/// 一对一语音会话防护:占线、超时、重复信令、销毁时释放计时器。
|
||||
/// 不自建第二套信令,只约束官方 OpenIMLive 的进出场。
|
||||
enum VoiceCallPhase { idle, outgoing, incoming, inCall }
|
||||
|
||||
class CallSessionGuard {
|
||||
CallSessionGuard({this.inviteTimeout = const Duration(seconds: 30)});
|
||||
|
||||
final Duration inviteTimeout;
|
||||
|
||||
VoiceCallPhase phase = VoiceCallPhase.idle;
|
||||
String? roomID;
|
||||
void Function()? onTimeout;
|
||||
|
||||
final Set<String> _seenKeys = <String>{};
|
||||
Timer? _timeout;
|
||||
|
||||
bool get isBusy => phase != VoiceCallPhase.idle;
|
||||
|
||||
bool acceptSignaling({required int customType, required String roomID}) {
|
||||
if (roomID.isEmpty) return false;
|
||||
return _seenKeys.add('$customType:$roomID');
|
||||
}
|
||||
|
||||
String? startOutgoing(String roomID) {
|
||||
if (isBusy) return 'busy';
|
||||
this.roomID = roomID;
|
||||
phase = VoiceCallPhase.outgoing;
|
||||
_armTimeout();
|
||||
return null;
|
||||
}
|
||||
|
||||
String? startIncoming(String roomID) {
|
||||
if (isBusy) return 'busy';
|
||||
this.roomID = roomID;
|
||||
phase = VoiceCallPhase.incoming;
|
||||
_armTimeout();
|
||||
return null;
|
||||
}
|
||||
|
||||
void markConnected() {
|
||||
if (!isBusy) return;
|
||||
_timeout?.cancel();
|
||||
_timeout = null;
|
||||
phase = VoiceCallPhase.inCall;
|
||||
}
|
||||
|
||||
bool sameRoom(String? other) =>
|
||||
other != null && other.isNotEmpty && other == roomID;
|
||||
|
||||
void dispose() {
|
||||
_timeout?.cancel();
|
||||
_timeout = null;
|
||||
_seenKeys.clear();
|
||||
phase = VoiceCallPhase.idle;
|
||||
roomID = null;
|
||||
onTimeout = null;
|
||||
}
|
||||
|
||||
void _armTimeout() {
|
||||
_timeout?.cancel();
|
||||
_timeout = Timer(inviteTimeout, () {
|
||||
if (phase == VoiceCallPhase.outgoing || phase == VoiceCallPhase.incoming) {
|
||||
onTimeout?.call();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user