Repository navigation
Rediseño, i18n y mejoras de partida - #4
Conversation
- Nueva interfaz de partida (asientos, dock de decisiones, registro) y landing/reglas rediseñadas con traducción es/en. - Iconos propios para las acciones, basados en los de las cartas, con tooltip (efecto, personaje y quién la bloquea) y panel de reglas dentro de la partida. - Reconexión: el navegador recuerda el asiento por sala, así que cerrar la pestaña y volver a abrir el enlace devuelve a la partida. - Carrusel de cartas de la landing sin barra de scroll, arrastrable con el ratón y con margen correcto en móvil. - Footer con iconos de GitHub y LinkedIn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a25c54f3e4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const tabKey = `${PLAYER_ID_KEY}:${room}`; | ||
| let id = sessionStorage.getItem(tabKey); |
There was a problem hiding this comment.
Migrate the existing session identity before generating a new one
When a player refreshes an ongoing game after this deployment, their existing identity is still stored under coup-player-id, but this function only reads coup-player-id:<room>. With no remembered seats yet, it generates a different ID and sends that in the join message, losing the player's existing seat and preventing reconnection to the started game. Preserve the legacy session ID when initializing the room-specific identity so upgrading does not strand active players.
Useful? React with 👍 / 👎.
| /** Another open tab of this browser is sitting in that seat right now. */ | ||
| function isSeatHeld(id: string) { | ||
| const beat = Number(localStorage.getItem(LOCK_PREFIX + id)); | ||
|
|
||
| return Date.now() - beat < LOCK_STALE_MS; |
There was a problem hiding this comment.
Avoid reclaiming seats solely because their heartbeat expired
If an open game tab is backgrounded and its timers are throttled or suspended for more than 12 seconds, its seat becomes eligible for reuse even though that tab has not left. Opening the same room in another tab then selects the original player's ID and joins as that player instead of creating a separate seat. The original tab also retains that ID in session storage, so resuming it does not resolve the collision. Seat reclamation needs an ownership check that distinguishes a closed tab from a temporarily suspended one rather than relying solely on this short heartbeat timeout.
Useful? React with 👍 / 👎.
| if (err.code && FATAL.has(err.code)) setFatal(text); | ||
| else addToast({ title: text, color: "danger", timeout: 3500 }); |
There was a problem hiding this comment.
Retain fatal-error handling for responses without a code
When the server rejects a join with a message-only error such as Game already started, this now displays a temporary toast and leaves the page showing Joining room… indefinitely instead of the rejection page. Both ServerMessage and SocketError still explicitly allow code to be absent, and the previous handler recognized these fatal messages without a code. Keep that fallback until coded errors are required by the protocol so compatible server responses still provide a usable failure state.
Useful? React with 👍 / 👎.
- La reserva de asiento usa la Web Locks API en lugar de un latido en localStorage: una pestaña en segundo plano con los temporizadores ralentizados o congelados conserva su asiento, y solo al cerrarse lo libera. Una pestaña duplicada recibe su propio asiento. - Se reutiliza el id por pestaña de versiones anteriores (coup-player-id), así quien recargue tras actualizar no pierde su sitio. - Los rechazos sin código de error (servidores antiguos) vuelven a mostrar la pantalla de error en lugar de quedarse en "Entrando en la sala…". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Qué incluye
Pruebas
tsc, lint yvitest, limpios.next buildde producción en Docker: todas las rutas responden.🤖 Generated with Claude Code