Merge pull request #35 from adrianoftyriel/fix/scorekeeper-join-diagnostics
Scorekeeper sharing: join from any sheet, show waiting requests, diagnostics
This commit is contained in:
@@ -135,9 +135,17 @@ class LanTransport(private val context: Context) : Transport {
|
|||||||
|
|
||||||
awaitClose {
|
awaitClose {
|
||||||
acceptJob.cancel()
|
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() }
|
runCatching { server.close() }
|
||||||
_endpoint.value = null
|
if (serverSocket === server) {
|
||||||
|
serverSocket = null
|
||||||
|
_endpoint.value = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,13 @@ class ScorekeeperSession(
|
|||||||
val discovered: List<DiscoveredHost> = emptyList(),
|
val discovered: List<DiscoveredHost> = emptyList(),
|
||||||
/** Host: where this device is listening, for reading out. */
|
/** Host: where this device is listening, for reading out. */
|
||||||
val endpoint: HostEndpoint? = null,
|
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,
|
val message: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -142,6 +149,7 @@ class ScorekeeperSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun listenToGuest(connection: Connection) {
|
private fun listenToGuest(connection: Connection) {
|
||||||
|
_state.update { it.copy(connections = it.connections + 1) }
|
||||||
jobs += scope.launch {
|
jobs += scope.launch {
|
||||||
connection.incoming.collect { message ->
|
connection.incoming.collect { message ->
|
||||||
synchronized(lock) { onHostMessage(connection, message) }
|
synchronized(lock) { onHostMessage(connection, message) }
|
||||||
@@ -192,6 +200,7 @@ class ScorekeeperSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onHello(connection: Connection, hello: Hello) {
|
private fun onHello(connection: Connection, hello: Hello) {
|
||||||
|
_state.update { it.copy(hellos = it.hellos + 1) }
|
||||||
val refusal = when {
|
val refusal = when {
|
||||||
hello.purpose != PURPOSE_SCOREKEEPER -> "That is a score sheet, not a game."
|
hello.purpose != PURPOSE_SCOREKEEPER -> "That is a score sheet, not a game."
|
||||||
hello.protocol != PROTOCOL_VERSION -> "Different app version — update both devices."
|
hello.protocol != PROTOCOL_VERSION -> "Different app version — update both devices."
|
||||||
@@ -377,6 +386,7 @@ class ScorekeeperSession(
|
|||||||
link = connection
|
link = connection
|
||||||
heardBack = false
|
heardBack = false
|
||||||
replica.reset()
|
replica.reset()
|
||||||
|
_state.update { it.copy(message = "Connected. Waiting for ${it.hostName} to answer…") }
|
||||||
}
|
}
|
||||||
val hello = Hello(peerId = deviceId, displayName = joinedName, purpose = PURPOSE_SCOREKEEPER)
|
val hello = Hello(peerId = deviceId, displayName = joinedName, purpose = PURPOSE_SCOREKEEPER)
|
||||||
linkJob = scope.launch {
|
linkJob = scope.launch {
|
||||||
|
|||||||
@@ -173,6 +173,9 @@ fun ScorekeeperScreen(
|
|||||||
actions = {
|
actions = {
|
||||||
when (role) {
|
when (role) {
|
||||||
Role.NONE -> if (sheet.started && !joining) {
|
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 = {
|
TextButton(onClick = {
|
||||||
session.startHosting(playerName, local)
|
session.startHosting(playerName, local)
|
||||||
showShare = true
|
showShare = true
|
||||||
@@ -182,7 +185,13 @@ fun ScorekeeperScreen(
|
|||||||
|
|
||||||
Role.HOST -> {
|
Role.HOST -> {
|
||||||
TextButton(onClick = { showShare = true }) {
|
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) {
|
if (sheet.started) {
|
||||||
TextButton(onClick = { confirmNewGame = true }) { Text("New game") }
|
TextButton(onClick = { confirmNewGame = true }) { Text("New game") }
|
||||||
@@ -259,7 +268,8 @@ fun ScorekeeperScreen(
|
|||||||
onDeny = { session.deny(request.id) },
|
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(
|
ShareDialog(
|
||||||
shared = shared,
|
shared = shared,
|
||||||
onRemove = { session.remove(it) },
|
onRemove = { session.remove(it) },
|
||||||
|
|||||||
@@ -210,6 +210,10 @@ internal fun ShareDialog(
|
|||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Text(
|
||||||
|
text = "Links received: ${shared.connections} · join requests: ${shared.hellos}",
|
||||||
|
style = MaterialTheme.typography.labelSmall,
|
||||||
|
)
|
||||||
Divider()
|
Divider()
|
||||||
Text("On the sheet", fontWeight = FontWeight.Bold)
|
Text("On the sheet", fontWeight = FontWeight.Bold)
|
||||||
if (shared.guests.isEmpty()) {
|
if (shared.guests.isEmpty()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user