From e1d9ec788c4e0d6804eee1f3e862e4c7a461bacf Mon Sep 17 00:00:00 2001 From: help4bis Date: Fri, 3 Apr 2026 06:49:30 +1000 Subject: [PATCH] fix: disconnect LiveKit before clearing state event Element X stays connected because it sees the state event clear while we're still in the LiveKit room. Reversed the order: disconnect from LiveKit first (remote party sees us leave), then clear the state event. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/features/calls/data/livekit_service.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/features/calls/data/livekit_service.dart b/lib/features/calls/data/livekit_service.dart index c2bcd29..29eab0a 100644 --- a/lib/features/calls/data/livekit_service.dart +++ b/lib/features/calls/data/livekit_service.dart @@ -127,6 +127,8 @@ class LiveKitService { } /// Disconnect and dispose the active room, clearing the MatrixRTC state event. + /// Order: disconnect LiveKit first (so Element X sees us leave the SFU), + /// then clear the state event (so Element X knows the call session ended). Future disconnect() async { final room = _activeRoom; final matrixRoomId = _activeMatrixRoomId; @@ -134,7 +136,14 @@ class LiveKitService { _activeMatrixRoomId = null; _membershipId = null; - // Clear the call member state event so Element X sees the call ended + // Step 1: Leave LiveKit — Element X will see us disappear from the SFU + if (room != null) { + await room.disconnect(); + await room.dispose(); + debugPrint('[LiveKit] LiveKit room disconnected'); + } + + // Step 2: Clear the call.member state event — Element X sees call ended if (matrixRoomId != null) { try { final client = _ref.read(matrixClientProvider); @@ -147,11 +156,6 @@ class LiveKitService { debugPrint('[LiveKit] Failed to clear call member event: $e'); } } - - if (room != null) { - await room.disconnect(); - await room.dispose(); - } } /// Fetches a LiveKit JWT via the MSC4143 flow: