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
This commit is contained in:
Claude
2026-04-02 00:46:44 +00:00
parent 8114739166
commit 3f0d1aa60f
2 changed files with 26 additions and 1 deletions
@@ -20,6 +20,8 @@
*/ */
package com.vitorpamplona.amethyst.ui.call package com.vitorpamplona.amethyst.ui.call
import android.view.WindowManager
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -40,6 +42,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -50,6 +53,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@@ -73,7 +77,13 @@ fun CallScreen(
) { ) {
val callState by callManager.state.collectAsState() val callState by callManager.state.collectAsState()
val scope = rememberCoroutineScope() 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) { when (val state = callState) {
is CallState.Idle -> { is CallState.Idle -> {
@@ -363,3 +373,15 @@ private fun formatDuration(seconds: Long): String {
val secs = seconds % 60 val secs = seconds % 60
return "%02d:%02d".format(mins, secs) 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)
}
}
}
@@ -56,6 +56,7 @@ class CallManager(
private var timeoutJob: Job? = null private var timeoutJob: Job? = null
private var resetJob: Job? = null private var resetJob: Job? = null
private val processedEventIds = mutableSetOf<String>()
companion object { companion object {
const val CALL_TIMEOUT_MS = 60_000L // 60 seconds ringing timeout const val CALL_TIMEOUT_MS = 60_000L // 60 seconds ringing timeout
@@ -198,6 +199,7 @@ class CallManager(
fun onSignalingEvent(event: Event) { fun onSignalingEvent(event: Event) {
if (isEventTooOld(event)) return if (isEventTooOld(event)) return
if (!processedEventIds.add(event.id)) return
when (event) { when (event) {
is CallOfferEvent -> onIncomingCallEvent(event) is CallOfferEvent -> onIncomingCallEvent(event)
@@ -234,6 +236,7 @@ class CallManager(
cancelTimeout() cancelTimeout()
resetJob?.cancel() resetJob?.cancel()
resetJob = null resetJob = null
processedEventIds.clear()
} }
private fun transitionToEnded( private fun transitionToEnded(