Compare commits

...

2 Commits

Author SHA1 Message Date
semantic-release-bot
9dac9b7a36 chore(release): 3.16.0 [skip ci]
## [3.16.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.15.2...v3.16.0) (2025-10-15)

### Features

* **arcade:** broadcast game selection changes to all room members ([b99e754](b99e754395))
2025-10-15 14:44:39 +00:00
Thomas Hallock
b99e754395 feat(arcade): broadcast game selection changes to all room members
Fix issue where game selection by the host was not synchronized to other
room members. When the host selects a game, all players now see the change
in real-time via socket.io.

Server changes:
- Add 'room-game-changed' socket broadcast when gameName is updated
- Emit to all members in the room channel when game is set/changed

Client changes:
- Add socket listener for 'room-game-changed' event in useRoomData
- Update local cache when game change is received
- Room page automatically re-renders with new game selection

This ensures all players stay synchronized when the host selects or changes
the game for the room.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 09:42:39 -05:00
4 changed files with 44 additions and 1 deletions

View File

@@ -1,3 +1,10 @@
## [3.16.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.15.2...v3.16.0) (2025-10-15)
### Features
* **arcade:** broadcast game selection changes to all room members ([b99e754](https://github.com/antialias/soroban-abacus-flashcards/commit/b99e7543952bb0d47f42e79dc4226b3c1280a0ee))
## [3.15.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.15.1...v3.15.2) (2025-10-15)

View File

@@ -111,6 +111,23 @@ export async function PATCH(req: NextRequest, context: RouteContext) {
.where(eq(schema.arcadeRooms.id, roomId))
.returning()
// Broadcast game change to all room members
if (body.gameName !== undefined) {
const io = await getSocketIO()
if (io) {
try {
console.log(`[Settings API] Broadcasting game change to room ${roomId}: ${body.gameName}`)
io.to(`room:${roomId}`).emit('room-game-changed', {
roomId,
gameName: body.gameName,
gameConfig: body.gameConfig || {},
})
} catch (socketError) {
console.error('[Settings API] Failed to broadcast game change:', socketError)
}
}
}
// If setting to retired, expel all non-owner members
if (body.accessMode === 'retired') {
const nonOwnerMembers = members.filter((m) => !m.isCreator)

View File

@@ -446,6 +446,23 @@ export function useRoomData() {
})
}
const handleRoomGameChanged = (data: {
roomId: string
gameName: string | null
gameConfig: Record<string, unknown>
}) => {
console.log('[useRoomData] Room game changed:', data)
if (data.roomId === roomData?.id) {
queryClient.setQueryData<RoomData | null>(roomKeys.current(), (prev) => {
if (!prev) return null
return {
...prev,
gameName: data.gameName,
}
})
}
}
socket.on('room-joined', handleRoomJoined)
socket.on('member-joined', handleMemberJoined)
socket.on('member-left', handleMemberLeft)
@@ -455,6 +472,7 @@ export function useRoomData() {
socket.on('report-submitted', handleReportSubmitted)
socket.on('room-invitation-received', handleInvitationReceived)
socket.on('join-request-submitted', handleJoinRequestSubmitted)
socket.on('room-game-changed', handleRoomGameChanged)
return () => {
socket.off('room-joined', handleRoomJoined)
@@ -466,6 +484,7 @@ export function useRoomData() {
socket.off('report-submitted', handleReportSubmitted)
socket.off('room-invitation-received', handleInvitationReceived)
socket.off('join-request-submitted', handleJoinRequestSubmitted)
socket.off('room-game-changed', handleRoomGameChanged)
}
}, [socket, roomData?.id, queryClient])

View File

@@ -1,6 +1,6 @@
{
"name": "soroban-monorepo",
"version": "3.15.2",
"version": "3.16.0",
"private": true,
"description": "Beautiful Soroban Flashcard Generator - Monorepo",
"workspaces": [