Adds ability to leave a spectated game on both Android and Desktop:
- Added stopSpectating() to ChessLobbyLogic (removes from state + stops polling)
- Both ViewModels now delegate to logic.stopSpectating() instead of bypassing it
- LiveChessGameScreen accepts onLeaveSpectating callback shown in spectator info area
- Android: Leave Game button pops back stack and stops spectating
- Desktop: Leave Game button clears selectedGameId (returns to lobby) and stops spectating
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Add ChessPlayerChip.kt with three shared composables:
- ChessPlayerChip: single player avatar + name with active border
- ChessPlayerVsHeader: mirrored White vs Black header above the board
- OverlappingAvatars: compact overlapping circular avatars for list cards
Wire avatars into:
- LiveChessGameScreen: vs header with active player green border
- DesktopChessGameLayout: vs header above the chess board
- Android & Desktop lobby cards: overlapping avatars in ActiveGameCard,
ChallengeCard, and OutgoingChallengeCard avatar slots
Uses existing UserAvatar (coil3 AsyncImage + Robohash fallback) from
commons for KMP compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skip adding games to spectatingGames when the user is a participant
(playerPubkey or opponentPubkey matches userPubkey) or when the game
is already finished.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire onGameEndDismiss callback so the "Continue" button on game end
overlay moves the game to the completed list. Add auto-detection of
finished games during polling refresh so games transition even if the
user navigates away without clicking the button. Discovered games that
are already finished now go straight to completed instead of appearing
in the active list.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The board was non-interactive for participants during pending challenges
on Android because canMakeMoves factored in isPendingChallenge. Desktop
passed isSpectator directly without the pending check, so it worked.
Remove isPendingChallenge from the board interactivity gate to match
Desktop behavior. The header still shows "Challenge Pending" status,
and this also fixes a secondary issue where the isPendingChallenge flag
could get stuck when replaceGameState preserved the old state via its
open-challenge workaround.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 'main' of https://github.com/vitorpamplona/amethyst:
New Crowdin translations by GitHub Action
update translations: CZ, DE, PT, SE
New Crowdin translations by GitHub Action
JesterContent fields version, fen, and history were omitted from
serialized JSON because kotlinx.serialization skips default values.
Jester's isStartGameEvent checks arrayEquals(json.history, []) which
fails when the field is absent (undefined !== []).
Added @EncodeDefault to version, fen, and history so they are always
included in the JSON output regardless of value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jester.nyo.dev uses offchain.pub as one of its relays. Adding it gives
us 2 shared relays (relay.damus.io + offchain.pub) instead of 1,
improving challenge visibility between Amethyst and Jester clients.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChessEngine.makeMove() now normalizes SAN notation before passing to
chesslib, fixing games against jester.nyo.dev and other clients that
use different notation:
- Castling: 0-0 → O-O, 0-0-0 → O-O-O (zeros to letters)
- Annotations: strips !, ?, !!, ??, !?, ?! suffixes
Previously, chesslib rejected 0-0/0-0-0 causing ChessStateReconstructor
to mark games as desynced and skip remaining moves. Games appeared
permanently stuck, even after app restart.
Also fixes discoverUserGames() silently dropping games classified as
spectator — now adds them to spectatingGames instead.
23 new interop tests covering SAN variants, reconstruction, spectator
detection, and missing start event handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>