From 3f0d1aa60f1fd184b2a32442b5fd507d7aa43551 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 00:46:44 +0000 Subject: [PATCH] fix: add event dedup, back button handling, and wake lock for calls - Deduplicate signaling events via processedEventIds set in CallManager to prevent duplicate processing from multiple relays - BackHandler on CallScreen calls hangup() before navigating back - KeepScreenOn composable adds FLAG_KEEP_SCREEN_ON during calls and clears it on dispose https://claude.ai/code/session_017hZm7yu7CzmcQgZGSaqSXS --- .../amethyst/ui/call/CallScreen.kt | 24 ++++++++++++++++++- .../amethyst/commons/call/CallManager.kt | 3 +++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/call/CallScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/call/CallScreen.kt index 0e531a8df..4f7ef31bd 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/call/CallScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/call/CallScreen.kt @@ -20,6 +20,8 @@ */ package com.vitorpamplona.amethyst.ui.call +import android.view.WindowManager +import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -40,6 +42,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -50,6 +53,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -73,7 +77,13 @@ fun CallScreen( ) { val callState by callManager.state.collectAsState() val scope = rememberCoroutineScope() - val context = androidx.compose.ui.platform.LocalContext.current + val context = LocalContext.current + + BackHandler(enabled = callState !is CallState.Idle && callState !is CallState.Ended) { + scope.launch { callManager.hangup() } + } + + KeepScreenOn() when (val state = callState) { is CallState.Idle -> { @@ -363,3 +373,15 @@ private fun formatDuration(seconds: Long): String { val secs = seconds % 60 return "%02d:%02d".format(mins, secs) } + +@Composable +private fun KeepScreenOn() { + val context = LocalContext.current + DisposableEffect(Unit) { + val window = (context as? android.app.Activity)?.window + window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + onDispose { + window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/call/CallManager.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/call/CallManager.kt index 0ad79e1f3..fd77b4d99 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/call/CallManager.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/call/CallManager.kt @@ -56,6 +56,7 @@ class CallManager( private var timeoutJob: Job? = null private var resetJob: Job? = null + private val processedEventIds = mutableSetOf() companion object { const val CALL_TIMEOUT_MS = 60_000L // 60 seconds ringing timeout @@ -198,6 +199,7 @@ class CallManager( fun onSignalingEvent(event: Event) { if (isEventTooOld(event)) return + if (!processedEventIds.add(event.id)) return when (event) { is CallOfferEvent -> onIncomingCallEvent(event) @@ -234,6 +236,7 @@ class CallManager( cancelTimeout() resetJob?.cancel() resetJob = null + processedEventIds.clear() } private fun transitionToEnded(