fix(games): add 'Join the game' escape to WaitingForPartner screen (B-004)
The generic WaitingForPartner screen only exited when the session became null, so a partner who landed there for an async game they could actually play (every current game is async — both play on their own device) was stuck waiting forever, recoverable only via Back to Games. Now the screen resolves the active session's game route and offers a primary 'Join the game' action that drops the user into the game (which auto-joins the session). Deterministic repro: QA starts How Well, Sam opens a different game -> one-game lock routes Sam to WaitingForPartner -> 'Join the game' -> How Well guess intro. Verified live. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
23c99233b4
commit
da7fc74faa
|
|
@ -47,7 +47,13 @@ data class WaitingForPartnerUiState(
|
|||
val isLoading: Boolean = true,
|
||||
val gameType: String = GameType.WHEEL,
|
||||
val partnerName: String = "Partner",
|
||||
val navigateTo: String? = null
|
||||
val navigateTo: String? = null,
|
||||
/**
|
||||
* Route into the partner's active game so this user can play their part, instead of being
|
||||
* stuck on this "waiting" screen. Every current game is async (both play on their own device),
|
||||
* so the partner who lands here can always join. Null only for an unknown game type. B-004.
|
||||
*/
|
||||
val joinRoute: String? = null
|
||||
)
|
||||
|
||||
@HiltViewModel
|
||||
|
|
@ -81,7 +87,8 @@ class WaitingForPartnerViewModel @Inject constructor(
|
|||
it.copy(
|
||||
isLoading = false,
|
||||
gameType = session.gameType,
|
||||
partnerName = partnerName
|
||||
partnerName = partnerName,
|
||||
joinRoute = gameTypeRoute(session.gameType)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -173,11 +180,30 @@ fun WaitingForPartnerScreen(
|
|||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
|
||||
Button(
|
||||
onClick = { onNavigate(AppRoute.PLAY) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text("Back to Games")
|
||||
// Primary action: join the partner's game and play your part. Without this the
|
||||
// screen was a dead-end for async games the user could actually play (B-004).
|
||||
state.joinRoute?.let { route ->
|
||||
Button(
|
||||
onClick = { onNavigate(route) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text("Join the game")
|
||||
}
|
||||
}
|
||||
if (state.joinRoute != null) {
|
||||
TextButton(
|
||||
onClick = { onNavigate(AppRoute.PLAY) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text("Back to Games")
|
||||
}
|
||||
} else {
|
||||
Button(
|
||||
onClick = { onNavigate(AppRoute.PLAY) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text("Back to Games")
|
||||
}
|
||||
}
|
||||
TextButton(onClick = viewModel::abandonPartnerGame) {
|
||||
Text(
|
||||
|
|
@ -200,6 +226,15 @@ private fun gameTypeLabel(gameType: String): String = when (gameType) {
|
|||
else -> gameType
|
||||
}
|
||||
|
||||
/** Entry route that joins the partner's active game (each game screen auto-joins on open). B-004. */
|
||||
private fun gameTypeRoute(gameType: String): String? = when (gameType) {
|
||||
GameType.WHEEL -> AppRoute.SPIN_WHEEL_RANDOM
|
||||
GameType.THIS_OR_THAT -> AppRoute.THIS_OR_THAT
|
||||
GameType.HOW_WELL -> AppRoute.HOW_WELL
|
||||
GameType.DESIRE_SYNC -> AppRoute.DESIRE_SYNC
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun gameTypeGlyphKey(gameType: String): String = when (gameType) {
|
||||
GameType.WHEEL -> "play"
|
||||
GameType.THIS_OR_THAT -> "question"
|
||||
|
|
|
|||
Loading…
Reference in New Issue