fix(#240): notification tap race condition opens new chat instead of correct session (#241)

Two-pronged fix for the race between GatewayReady auto-creating a session
and ChatScreen LaunchedEffect calling switchSession:

1. ChatViewModel: added `initialSessionId` field. GatewayReady now checks
   this before auto-creating a session — if set, it calls switchSession
   instead. The field is set synchronously by ChatScreen via SideEffect
   during composition, before any WS event can be processed.

2. ChatScreen: LaunchedEffect now keys on state.connectionStatus and
   waits for CONNECTED before calling switchSession. This prevents the
   SESSION_RESUME message from being dropped (webSocket is null before
   onOpen, so send() is a silent no-op).

Fixes #240

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-06-21 18:32:29 +03:00
1 parent adc23e3540
commit d7ca7b084e
3 files changed
+62 -2

No files matched your search

@@ -128,6 +128,36 @@ class ChatViewModelTest {
verify { HermesWsClient.send(WsMethods.SESSION_CREATE, any(), any()) }
}
@Test
fun testGatewayReady_withInitialSessionId_switchesToIt() =
runTest {
val viewModel = ChatViewModel(app, startCleanup = false)
advanceUntilIdle()
// Set the initial session ID (normally done by ChatScreen SideEffect)
viewModel.initialSessionId = "session-from-notification"
mockConnectionStatus.value = ConnectionStatus.CONNECTED
mockEventsFlow.emit(WsEvent.GatewayReady(null))
advanceUntilIdle()
val state = viewModel.uiState.value
assertTrue(state.isConnected)
// Should NOT have called createNewSession — switchSession was used instead
assertEquals("session-from-notification", state.currentSessionId)
// Verify SESSION_RESUME was sent instead of SESSION_CREATE
verify { HermesWsClient.send(WsMethods.SESSION_LIST, any(), any()) }
verify {
HermesWsClient.send(
WsMethods.SESSION_RESUME,
mapOf("session_id" to "session-from-notification"),
any(),
)
}
// SESSION_CREATE must NOT be sent
verify(inverse = true) { HermesWsClient.send(WsMethods.SESSION_CREATE, any(), any()) }
}
@Test
fun testSessionCreateRpcResult() =
runTest {