From 36152243abc86abb07bfe9c2b2154071b74e9b1a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 1 May 2026 21:47:33 +0000 Subject: [PATCH] fix: tear down nest session on host Close the Room MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The host-leave confirmation dialog's Close the Room button only called finish(), relying on VM.onCleared() to release the AudioRecord. That runs late in the destroy lifecycle, so the system mic-in-use indicator stayed lit while the activity was queued for destruction. Adds NestViewModel.leave(), which mirrors onCleared() (sets closed, runs both teardowns with finalCleanup=true so closes route through cleanupScope/GlobalScope and survive Activity destruction). Wires it into the Close the Room callback only — the Just Leave and non-host Leave paths are unchanged per request. --- .../nests/room/screen/NestFullScreen.kt | 11 +++++++++++ .../commons/viewmodels/NestViewModel.kt | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt index ed6f90ea2..4e01702aa 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt @@ -372,6 +372,17 @@ internal fun NestFullScreen( R.string.nest_leave_host_close_failed, ) } + // Tear down the speaker session + listener + // BEFORE finishing the activity so the + // AudioRecord (and the system mic indicator) + // releases promptly. onCleared() alone runs + // late in the destroy lifecycle and can + // leave the mic held while the activity is + // queued for destruction. Only the + // "Close the Room" path triggers this — the + // "Just leave" and non-host leave paths + // still rely on onCleared. + viewModel.leave() onLeave() } }, diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt index e9c64fddf..60c7e6769 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt @@ -545,6 +545,24 @@ class NestViewModel( teardown(targetState = ConnectionUiState.Idle, finalCleanup = false) } + /** + * User-driven leave-the-activity teardown. Mirrors [onCleared]: marks + * the VM closed and routes both the speaker handle close (which + * releases the AudioRecord and clears the system mic indicator) and + * the listener close to [cleanupScope] so the teardown survives + * Activity destruction. Call this from the leave-the-room button + * BEFORE finishing the activity; relying on [onCleared] alone leaves + * a window where the AudioRecord stays held while the activity is + * paused / queued for destruction. + */ + fun leave() { + if (closed) return + closed = true + requestedSpeakers = emptySet() + teardownBroadcast(BroadcastUiState.Idle, finalCleanup = true) + teardown(targetState = ConnectionUiState.Closed, finalCleanup = true) + } + override fun onCleared() { closed = true teardownBroadcast(BroadcastUiState.Idle, finalCleanup = true)