refactor: split remote relay into own module, add lifecycle reconnect

- Move handle_remote_relay from remote_input.rs to remote_relay.rs
- Android: lifecycle-aware WebSocket reconnection on app resume
- Cleaner module boundaries between xdotool input and browser relay

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-04-02 11:01:38 +01:00
parent 7409cdaac2
commit 1690f67acf
4 changed files with 111 additions and 86 deletions

View File

@@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.CircleShape
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
import androidx.compose.runtime.mutableStateOf
@@ -28,6 +27,9 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.compose.ui.unit.dp
import com.archipelago.app.data.ServerPreferences
import com.archipelago.app.network.ConnectionState
@@ -60,10 +62,32 @@ fun RemoteInputScreen(onBack: () -> Unit) {
val ws = remember { InputWebSocket(scope) }
val connectionState by ws.state.collectAsState()
val lifecycleOwner = LocalLifecycleOwner.current
BackHandler { onBack() }
DisposableEffect(Unit) { onDispose { ws.disconnect() } }
LaunchedEffect(activeServer) { activeServer?.let { ws.connect(it.toUrl(), it.password) } }
// Connect on server change + reconnect when app resumes from background
DisposableEffect(lifecycleOwner, activeServer) {
val server = activeServer
if (server != null) {
ws.connect(server.toUrl(), server.password)
}
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME && server != null) {
val state = ws.state.value
if (state != ConnectionState.CONNECTED && state != ConnectionState.CONNECTING) {
ws.connect(server.toUrl(), server.password)
}
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
ws.disconnect()
}
}
Box(
Modifier