diff --git a/app/src/main/java/org/prolibertate/games/net/LanTransport.kt b/app/src/main/java/org/prolibertate/games/net/LanTransport.kt index 0d1c6e4..1976c05 100644 --- a/app/src/main/java/org/prolibertate/games/net/LanTransport.kt +++ b/app/src/main/java/org/prolibertate/games/net/LanTransport.kt @@ -135,9 +135,17 @@ class LanTransport(private val context: Context) : Transport { awaitClose { acceptJob.cancel() - stopAdvertising() + // Only what this call set up. Hosting stopped and started again + // runs this for the old host after the new one has begun, and + // letting it clear the shared fields would unregister the new + // host's advertisement and blank the address it shows. + runCatching { nsdManager.unregisterService(listener) } + if (registrationListener === listener) registrationListener = null runCatching { server.close() } - _endpoint.value = null + if (serverSocket === server) { + serverSocket = null + _endpoint.value = null + } } } diff --git a/app/src/main/java/org/prolibertate/games/net/ScorekeeperSession.kt b/app/src/main/java/org/prolibertate/games/net/ScorekeeperSession.kt index 850485e..15fc8e9 100644 --- a/app/src/main/java/org/prolibertate/games/net/ScorekeeperSession.kt +++ b/app/src/main/java/org/prolibertate/games/net/ScorekeeperSession.kt @@ -70,6 +70,13 @@ class ScorekeeperSession( val discovered: List = emptyList(), /** Host: where this device is listening, for reading out. */ val endpoint: HostEndpoint? = null, + /** + * Host: links accepted, and hellos read off them. For telling "nobody + * reached this phone" from "they reached it and were not understood", + * which look the same from the other end. + */ + val connections: Int = 0, + val hellos: Int = 0, val message: String? = null, ) @@ -142,6 +149,7 @@ class ScorekeeperSession( } private fun listenToGuest(connection: Connection) { + _state.update { it.copy(connections = it.connections + 1) } jobs += scope.launch { connection.incoming.collect { message -> synchronized(lock) { onHostMessage(connection, message) } @@ -192,6 +200,7 @@ class ScorekeeperSession( } private fun onHello(connection: Connection, hello: Hello) { + _state.update { it.copy(hellos = it.hellos + 1) } val refusal = when { hello.purpose != PURPOSE_SCOREKEEPER -> "That is a score sheet, not a game." hello.protocol != PROTOCOL_VERSION -> "Different app version — update both devices." @@ -377,6 +386,7 @@ class ScorekeeperSession( link = connection heardBack = false replica.reset() + _state.update { it.copy(message = "Connected. Waiting for ${it.hostName} to answer…") } } val hello = Hello(peerId = deviceId, displayName = joinedName, purpose = PURPOSE_SCOREKEEPER) linkJob = scope.launch { diff --git a/app/src/main/java/org/prolibertate/games/ui/ScorekeeperScreen.kt b/app/src/main/java/org/prolibertate/games/ui/ScorekeeperScreen.kt index e98873f..ee5a203 100644 --- a/app/src/main/java/org/prolibertate/games/ui/ScorekeeperScreen.kt +++ b/app/src/main/java/org/prolibertate/games/ui/ScorekeeperScreen.kt @@ -173,6 +173,9 @@ fun ScorekeeperScreen( actions = { when (role) { Role.NONE -> if (sheet.started && !joining) { + // A sheet already on the go is no reason to hide the way to + // somebody else's. + TextButton(onClick = { joining = true }) { Text("Join") } TextButton(onClick = { session.startHosting(playerName, local) showShare = true @@ -182,7 +185,13 @@ fun ScorekeeperScreen( Role.HOST -> { TextButton(onClick = { showShare = true }) { - Text(if (shared.guests.isEmpty()) "Sharing" else "Sharing (${shared.guests.size})") + Text( + when { + shared.requests.isNotEmpty() -> "Sharing · ${shared.requests.size} waiting" + shared.guests.isNotEmpty() -> "Sharing (${shared.guests.size})" + else -> "Sharing" + } + ) } if (sheet.started) { TextButton(onClick = { confirmNewGame = true }) { Text("New game") } @@ -259,7 +268,8 @@ fun ScorekeeperScreen( onDeny = { session.deny(request.id) }, ) } - if (showShare) { + // Not under a request: two dialogs stacked is how an answer gets missed. + if (showShare && shared.requests.isEmpty()) { ShareDialog( shared = shared, onRemove = { session.remove(it) }, diff --git a/app/src/main/java/org/prolibertate/games/ui/ScorekeeperShareUi.kt b/app/src/main/java/org/prolibertate/games/ui/ScorekeeperShareUi.kt index 85acf21..6015589 100644 --- a/app/src/main/java/org/prolibertate/games/ui/ScorekeeperShareUi.kt +++ b/app/src/main/java/org/prolibertate/games/ui/ScorekeeperShareUi.kt @@ -210,6 +210,10 @@ internal fun ShareDialog( style = MaterialTheme.typography.bodySmall, ) } + Text( + text = "Links received: ${shared.connections} · join requests: ${shared.hellos}", + style = MaterialTheme.typography.labelSmall, + ) Divider() Text("On the sheet", fontWeight = FontWeight.Bold) if (shared.guests.isEmpty()) {