Compare commits

...

3 Commits

Author SHA1 Message Date
semantic-release-bot
6d14dd8b47 chore(release): 3.17.8 [skip ci]
## [3.17.8](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.17.7...v3.17.8) (2025-10-15)

### Bug Fixes

* **arcade:** preserve game settings when returning to game selection ([0ee7739](0ee7739091))
2025-10-15 17:42:27 +00:00
Thomas Hallock
0ee7739091 fix(arcade): preserve game settings when returning to game selection
When users clicked "back to game selection", the clearRoomGameApi function
was sending both gameName: null AND gameConfig: null to the server. This
destroyed all saved game settings (like gameType, difficulty, etc.).

Now clearRoomGameApi only sends gameName: null and preserves gameConfig,
so settings persist when users select a game again.

Root cause discovered via comprehensive database-level logging that traced
the exact data flow through the system.

Fixes settings persistence bug in room mode.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 12:41:36 -05:00
Thomas Hallock
5c135358fc debug(arcade): add comprehensive database-level logging for gameConfig
Add detailed logging at every layer to trace gameConfig through the system:

Server-side (Settings API):
- Log incoming PATCH request body
- Log database state BEFORE update
- Log what will be written to database
- Log database state AFTER update

Server-side (Current Room API):
- Log what's READ from database when fetching room

Client-side:
- Track roomData.gameConfig changes with useEffect

This will show us exactly when and where gameConfig is being overwritten.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 12:36:36 -05:00
6 changed files with 87 additions and 2 deletions

View File

@@ -1,3 +1,10 @@
## [3.17.8](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.17.7...v3.17.8) (2025-10-15)
### Bug Fixes
* **arcade:** preserve game settings when returning to game selection ([0ee7739](https://github.com/antialias/soroban-abacus-flashcards/commit/0ee7739091d60580d2f98cfe288b8586b03348f3))
## [3.17.7](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.17.6...v3.17.7) (2025-10-15)

View File

@@ -27,6 +27,36 @@ export async function PATCH(req: NextRequest, context: RouteContext) {
const viewerId = await getViewerId()
const body = await req.json()
console.log(
'[Settings API] PATCH request received:',
JSON.stringify(
{
roomId,
body,
},
null,
2
)
)
// Read current room state from database BEFORE any changes
const [currentRoom] = await db
.select()
.from(schema.arcadeRooms)
.where(eq(schema.arcadeRooms.id, roomId))
console.log(
'[Settings API] Current room state in database BEFORE update:',
JSON.stringify(
{
gameName: currentRoom?.gameName,
gameConfig: currentRoom?.gameConfig,
},
null,
2
)
)
// Check if user is the host
const members = await getRoomMembers(roomId)
const currentMember = members.find((m) => m.userId === viewerId)
@@ -97,6 +127,11 @@ export async function PATCH(req: NextRequest, context: RouteContext) {
updateData.gameConfig = body.gameConfig
}
console.log(
'[Settings API] Update data to be written to database:',
JSON.stringify(updateData, null, 2)
)
// If game is being changed (or cleared), delete the existing arcade session
// This ensures a fresh session will be created with the new game settings
if (body.gameName !== undefined) {
@@ -111,6 +146,18 @@ export async function PATCH(req: NextRequest, context: RouteContext) {
.where(eq(schema.arcadeRooms.id, roomId))
.returning()
console.log(
'[Settings API] Room state in database AFTER update:',
JSON.stringify(
{
gameName: updatedRoom.gameName,
gameConfig: updatedRoom.gameConfig,
},
null,
2
)
)
// Broadcast game change to all room members
if (body.gameName !== undefined) {
const io = await getSocketIO()

View File

@@ -28,6 +28,19 @@ export async function GET() {
return NextResponse.json({ error: 'Room not found' }, { status: 404 })
}
console.log(
'[Current Room API] Room data READ from database:',
JSON.stringify(
{
roomId,
gameName: room.gameName,
gameConfig: room.gameConfig,
},
null,
2
)
)
// Get members
const members = await getRoomMembers(roomId)

View File

@@ -248,6 +248,22 @@ export function RoomMemoryPairsProvider({ children }: { children: ReactNode }) {
// Derive game mode from active player count
const gameMode = activePlayerCount > 1 ? 'multiplayer' : 'single'
// Track roomData.gameConfig changes
useEffect(() => {
console.log(
'[RoomMemoryPairsProvider] roomData.gameConfig changed:',
JSON.stringify(
{
gameConfig: roomData?.gameConfig,
roomId: roomData?.id,
gameName: roomData?.gameName,
},
null,
2
)
)
}, [roomData?.gameConfig, roomData?.id, roomData?.gameName])
// Merge saved game config from room with initialState
// Settings are scoped by game name to preserve settings when switching games
const mergedInitialState = useMemo(() => {

View File

@@ -634,6 +634,8 @@ export function useSetRoomGame() {
/**
* Clear/reset game for a room (host only)
* This only clears gameName (returns to game selection) but preserves gameConfig
* so settings persist when the user selects a game again.
*/
async function clearRoomGameApi(roomId: string): Promise<void> {
const response = await fetch(`/api/arcade/rooms/${roomId}/settings`, {
@@ -641,7 +643,7 @@ async function clearRoomGameApi(roomId: string): Promise<void> {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
gameName: null,
gameConfig: null,
// DO NOT send gameConfig: null - we want to preserve settings!
}),
})

View File

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