fix(chess): filter own games from live list, dismissable errors, clickable avatars and completed games
- Filter user's own games from public "Live Games" list in lobby - Fix broken addSpectatingGame filter (playerPubkey is always viewerPubkey) - Add removeGame() to clean up stale entries when "Game not found" - Make player avatars clickable to open profile on game screen - Make completed game cards clickable to view final board state Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+3
@@ -288,6 +288,7 @@ fun CompletedGameCard(
|
||||
didUserWin: Boolean,
|
||||
isDraw: Boolean,
|
||||
moveCount: Int,
|
||||
onClick: (() -> Unit)? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
avatar: @Composable (() -> Unit)? = null,
|
||||
) {
|
||||
@@ -309,6 +310,8 @@ fun CompletedGameCard(
|
||||
}
|
||||
|
||||
Card(
|
||||
onClick = onClick ?: {},
|
||||
enabled = onClick != null,
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
) {
|
||||
Row(
|
||||
|
||||
+10
@@ -856,6 +856,16 @@ class ChessLobbyLogic(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a game from all lobby lists (active, spectating) and stop polling.
|
||||
* Used when a game fails to load ("Game not found") so the user can dismiss the stale entry.
|
||||
*/
|
||||
fun removeGame(gameId: String) {
|
||||
state.removeActiveGame(gameId)
|
||||
state.removeSpectatingGame(gameId)
|
||||
pollingDelegate.removeGameId(gameId)
|
||||
}
|
||||
|
||||
fun clearError() {
|
||||
state.setError(null)
|
||||
}
|
||||
|
||||
+5
-2
@@ -297,7 +297,8 @@ class ChessLobbyState(
|
||||
}
|
||||
|
||||
fun updatePublicGames(games: List<PublicGame>) {
|
||||
_publicGames.value = games
|
||||
// Filter out games where the user is a participant
|
||||
_publicGames.value = games.filter { it.whitePubkey != userPubkey && it.blackPubkey != userPubkey }
|
||||
}
|
||||
|
||||
fun addActiveGame(
|
||||
@@ -501,7 +502,9 @@ class ChessLobbyState(
|
||||
return
|
||||
}
|
||||
// Don't add own games to spectating list
|
||||
if (state.playerPubkey == userPubkey || state.opponentPubkey == userPubkey) {
|
||||
// Note: LiveChessGameState.playerPubkey is always viewerPubkey regardless of role,
|
||||
// so we check isSpectator instead to determine if the user is actually a participant
|
||||
if (!state.isSpectator) {
|
||||
return
|
||||
}
|
||||
// Don't add finished games to spectating list
|
||||
|
||||
+10
-1
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.commons.chess
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -64,6 +65,7 @@ fun ChessPlayerChip(
|
||||
avatarUrl: String?,
|
||||
isActive: Boolean = false,
|
||||
mirrored: Boolean = false,
|
||||
onClick: (() -> Unit)? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val avatar =
|
||||
@@ -102,7 +104,10 @@ fun ChessPlayerChip(
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = modifier.alpha(if (isActive) 1f else 0.6f),
|
||||
modifier =
|
||||
modifier
|
||||
.alpha(if (isActive) 1f else 0.6f)
|
||||
.then(if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
@@ -146,6 +151,8 @@ fun ChessPlayerVsHeader(
|
||||
blackHex: String,
|
||||
blackAvatarUrl: String?,
|
||||
isWhiteTurn: Boolean,
|
||||
onWhiteClick: (() -> Unit)? = null,
|
||||
onBlackClick: (() -> Unit)? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
@@ -163,6 +170,7 @@ fun ChessPlayerVsHeader(
|
||||
userHex = whiteHex,
|
||||
avatarUrl = whiteAvatarUrl,
|
||||
isActive = isWhiteTurn,
|
||||
onClick = onWhiteClick,
|
||||
)
|
||||
Text(
|
||||
text = "White",
|
||||
@@ -188,6 +196,7 @@ fun ChessPlayerVsHeader(
|
||||
avatarUrl = blackAvatarUrl,
|
||||
isActive = !isWhiteTurn,
|
||||
mirrored = true,
|
||||
onClick = onBlackClick,
|
||||
)
|
||||
Text(
|
||||
text = "Black",
|
||||
|
||||
+3
@@ -208,6 +208,7 @@ fun LiveChessGameScreen(
|
||||
blackName: String = "Black",
|
||||
blackHex: String = "",
|
||||
blackAvatarUrl: String? = null,
|
||||
onPlayerClick: ((pubkeyHex: String) -> Unit)? = null,
|
||||
) {
|
||||
// Observe state flows for automatic recomposition on updates
|
||||
val currentPosition by gameState.currentPosition.collectAsState()
|
||||
@@ -253,6 +254,8 @@ fun LiveChessGameScreen(
|
||||
blackHex = blackHex,
|
||||
blackAvatarUrl = blackAvatarUrl,
|
||||
isWhiteTurn = currentPosition.activeColor == Color.WHITE,
|
||||
onWhiteClick = onPlayerClick?.let { { it(whiteHex) } },
|
||||
onBlackClick = onPlayerClick?.let { { it(blackHex) } },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user