forked from eatvio/eatvio_app
feat(video_calls): repeated calls after call termination fix
This commit is contained in:
@@ -406,7 +406,11 @@ class VideoCallManager {
|
|||||||
|
|
||||||
Future<void> endCall() async {
|
Future<void> endCall() async {
|
||||||
final uuid = _snapshot.conversationUuid;
|
final uuid = _snapshot.conversationUuid;
|
||||||
final shouldNotifyBackend = !_callEndedNotified && uuid.isNotEmpty;
|
final shouldNotifyBackend = shouldNotifyCallEnded(
|
||||||
|
alreadyNotified: _callEndedNotified,
|
||||||
|
hasConversation: uuid.isNotEmpty,
|
||||||
|
peerStillInRoom: _roomHasRemoteUser(),
|
||||||
|
);
|
||||||
if (uuid.isNotEmpty) {
|
if (uuid.isNotEmpty) {
|
||||||
_callEndedNotified = true;
|
_callEndedNotified = true;
|
||||||
}
|
}
|
||||||
@@ -1099,6 +1103,14 @@ class VideoCallManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _roomHasRemoteUser() {
|
||||||
|
final room = _room;
|
||||||
|
if (room == null) return false;
|
||||||
|
return videoCallRoomStillHasRemoteUser(
|
||||||
|
room.remoteParticipants.values.map((participant) => participant.identity),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
bool get _canHandleCallAudio =>
|
bool get _canHandleCallAudio =>
|
||||||
_callStageEntered &&
|
_callStageEntered &&
|
||||||
!_liveKitDisposed &&
|
!_liveKitDisposed &&
|
||||||
|
|||||||
@@ -541,9 +541,20 @@ class VideoCallSessionCubit extends BaseCubit<VideoCallSessionState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> endCall() async {
|
Future<void> endCall() async {
|
||||||
await _screenWakeLock.release();
|
_suppressDisposeSideEffects = true;
|
||||||
await _systemPipCoordinator.disarm();
|
try {
|
||||||
await _videoCallManager.endCall();
|
await _screenWakeLock.release();
|
||||||
|
await _systemPipCoordinator.disarm();
|
||||||
|
await _videoCallManager.endCall();
|
||||||
|
if (isClosed) return;
|
||||||
|
// The idle snapshot is ignored while the call screen is still visible,
|
||||||
|
// so hang up has to clear the session before the route pops. Otherwise
|
||||||
|
// dispose keeps the call and the next token request rings both users.
|
||||||
|
emit(const VideoCallSessionState());
|
||||||
|
await _restoreSystemUiAfterCall();
|
||||||
|
} finally {
|
||||||
|
_suppressDisposeSideEffects = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void expandLocal() {
|
void expandLocal() {
|
||||||
|
|||||||
@@ -18,6 +18,18 @@ bool shouldForceEndCallAfterPeerLeft({
|
|||||||
return !videoCallRoomStillHasRemoteUser(remoteIdentities);
|
return !videoCallRoomStillHasRemoteUser(remoteIdentities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The participant who taps hang up must not report the end while the other
|
||||||
|
/// person is still in the room. That report and the remaining client's report
|
||||||
|
/// both see an empty room and each one rings the other user again.
|
||||||
|
bool shouldNotifyCallEnded({
|
||||||
|
required bool alreadyNotified,
|
||||||
|
required bool hasConversation,
|
||||||
|
required bool peerStillInRoom,
|
||||||
|
}) {
|
||||||
|
if (!hasConversation || alreadyNotified || peerStillInRoom) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool shouldForceEndCallAfterRoomDisconnect({
|
bool shouldForceEndCallAfterRoomDisconnect({
|
||||||
required bool callStageEntered,
|
required bool callStageEntered,
|
||||||
required bool sessionConnected,
|
required bool sessionConnected,
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import 'package:eatvio_app/features/video_calls/managers/video_call_manager.dart
|
|||||||
import 'package:eatvio_app/features/video_calls/services/video_call_foreground_coordinator.dart';
|
import 'package:eatvio_app/features/video_calls/services/video_call_foreground_coordinator.dart';
|
||||||
import 'package:eatvio_app/features/video_calls/services/video_call_lifecycle_binding.dart';
|
import 'package:eatvio_app/features/video_calls/services/video_call_lifecycle_binding.dart';
|
||||||
import 'package:eatvio_app/features/video_calls/repositories/video_call_repository.dart';
|
import 'package:eatvio_app/features/video_calls/repositories/video_call_repository.dart';
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart' as lk;
|
import 'package:livekit_client/livekit_client.dart' as lk;
|
||||||
@@ -53,6 +55,9 @@ void main() {
|
|||||||
mockRoom = MockRoom();
|
mockRoom = MockRoom();
|
||||||
when(mockRoom.connectionState).thenReturn(lk.ConnectionState.connected);
|
when(mockRoom.connectionState).thenReturn(lk.ConnectionState.connected);
|
||||||
when(mockRoom.localParticipant).thenReturn(null);
|
when(mockRoom.localParticipant).thenReturn(null);
|
||||||
|
when(
|
||||||
|
mockRoom.remoteParticipants,
|
||||||
|
).thenReturn(UnmodifiableMapView(<String, lk.RemoteParticipant>{}));
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
|
|||||||
@@ -66,6 +66,36 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('does not report the end while the other user is still in the room', () {
|
||||||
|
expect(
|
||||||
|
shouldNotifyCallEnded(
|
||||||
|
alreadyNotified: false,
|
||||||
|
hasConversation: true,
|
||||||
|
peerStillInRoom: true,
|
||||||
|
),
|
||||||
|
isFalse,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reports the end when this client is the last participant', () {
|
||||||
|
expect(
|
||||||
|
shouldNotifyCallEnded(
|
||||||
|
alreadyNotified: false,
|
||||||
|
hasConversation: true,
|
||||||
|
peerStillInRoom: false,
|
||||||
|
),
|
||||||
|
isTrue,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
shouldNotifyCallEnded(
|
||||||
|
alreadyNotified: true,
|
||||||
|
hasConversation: true,
|
||||||
|
peerStillInRoom: false,
|
||||||
|
),
|
||||||
|
isFalse,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('keeps a connection-loss screen when the link drops', () {
|
test('keeps a connection-loss screen when the link drops', () {
|
||||||
expect(
|
expect(
|
||||||
shouldForceEndCallAfterRoomDisconnect(
|
shouldForceEndCallAfterRoomDisconnect(
|
||||||
|
|||||||
Reference in New Issue
Block a user