feat(chess): finished games section below active games in lobby
Adds a "Finished Games" section to the Android chess lobby screen, showing up to 10 completed games with opponent avatars, result (Won/Lost/Draw), and move count. The section only appears when completedGames is non-empty, matching the Desktop implementation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+52
-1
@@ -67,6 +67,7 @@ import com.vitorpamplona.amethyst.commons.chess.ActiveGameCard
|
||||
import com.vitorpamplona.amethyst.commons.chess.ChallengeCard
|
||||
import com.vitorpamplona.amethyst.commons.chess.ChessChallenge
|
||||
import com.vitorpamplona.amethyst.commons.chess.ChessSyncBanner
|
||||
import com.vitorpamplona.amethyst.commons.chess.CompletedGameCard
|
||||
import com.vitorpamplona.amethyst.commons.chess.NewChessGameDialog
|
||||
import com.vitorpamplona.amethyst.commons.chess.OutgoingChallengeCard
|
||||
import com.vitorpamplona.amethyst.commons.chess.OverlappingAvatars
|
||||
@@ -295,13 +296,15 @@ fun ChessLobbyContent(
|
||||
val spectatingGames by chessViewModel.spectatingGames.collectAsState()
|
||||
val publicGames by chessViewModel.publicGames.collectAsState()
|
||||
val challenges by chessViewModel.challenges.collectAsState()
|
||||
val completedGames by chessViewModel.completedGames.collectAsState()
|
||||
val userPubkey = accountViewModel.account.userProfile().pubkeyHex
|
||||
|
||||
val hasContent =
|
||||
activeGames.isNotEmpty() ||
|
||||
spectatingGames.isNotEmpty() ||
|
||||
publicGames.isNotEmpty() ||
|
||||
challenges.isNotEmpty()
|
||||
challenges.isNotEmpty() ||
|
||||
completedGames.isNotEmpty()
|
||||
|
||||
if (!hasContent) {
|
||||
// Empty state - use LazyColumn so pull-to-refresh works
|
||||
@@ -560,6 +563,54 @@ fun ChessLobbyContent(
|
||||
}
|
||||
}
|
||||
|
||||
// Finished games section
|
||||
if (completedGames.isNotEmpty()) {
|
||||
item {
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
"Finished Games",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
|
||||
items(
|
||||
completedGames.distinctBy { it.gameId }.take(10),
|
||||
key = { "completed-${it.gameId}-${it.completedAt}" },
|
||||
) { game ->
|
||||
val opponentPubkey =
|
||||
if (game.whitePubkey == userPubkey) game.blackPubkey else game.whitePubkey
|
||||
val opponentUser =
|
||||
remember(opponentPubkey) {
|
||||
accountViewModel.checkGetOrCreateUser(opponentPubkey)
|
||||
}
|
||||
val opponentName =
|
||||
opponentUser?.toBestDisplayName()
|
||||
?: game.blackDisplayName
|
||||
?: game.whiteDisplayName
|
||||
?: opponentPubkey.take(8)
|
||||
CompletedGameCard(
|
||||
opponentName = opponentName,
|
||||
result = game.result,
|
||||
didUserWin = game.didUserWin(userPubkey),
|
||||
isDraw = game.isDraw,
|
||||
moveCount = game.moveCount,
|
||||
avatar = {
|
||||
OverlappingAvatars(
|
||||
avatar1Hex = userPubkey,
|
||||
avatar2Hex = opponentPubkey,
|
||||
avatar1Url =
|
||||
remember(userPubkey) {
|
||||
accountViewModel.checkGetOrCreateUser(userPubkey)
|
||||
}?.profilePicture(),
|
||||
avatar2Url = opponentUser?.profilePicture(),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom padding for FAB
|
||||
item {
|
||||
Spacer(Modifier.height(80.dp))
|
||||
|
||||
Reference in New Issue
Block a user