fix(#240): parse session_id from params root (#242)

* fix(#240): parse session_id from params root

Allows correct session mapping when opening app via notification.

* fix(#240): set MainActivity launchMode to singleTop

Prevents activity destruction and WebSocket reconnection when tapping notifications.

* fix(#240): save inline notification replies to Room database

* fix(#240): refresh current session when app comes to foreground

* fix(#240): use uppercase role string to match Mapper mapping expectations

* style: format NotificationReplyReceiver.kt to satisfy ktlint
This commit is contained in:
M57 authored and GitHub committed 2026-06-21 19:04:54 +03:00
1 parent d7ca7b084e
commit bfef3613fa
6 files changed
+60 -1

No files matched your search

@@ -35,7 +35,8 @@ object EventParser {
@Suppress("UNCHECKED_CAST")
val payload = params["payload"] as? Map<String, Any?>
val sessionId = payload?.get("session_id") as? String
// B7 (Jun 21 2026, kanban t_240): extract session_id from params first, fallback to payload
val sessionId = params["session_id"] as? String ?: payload?.get("session_id") as? String
return when (eventType) {
"gateway.ready" -> {
@@ -8,6 +8,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.RemoteInput
import com.m57.hermescontrol.R
import com.m57.hermescontrol.data.ws.HermesWsClient
import kotlinx.coroutines.launch
class NotificationReplyReceiver : BroadcastReceiver() {
companion object {
@@ -26,6 +27,32 @@ class NotificationReplyReceiver : BroadcastReceiver() {
if (!replyText.isNullOrBlank() && !sessionId.isNullOrBlank()) {
HermesWsClient.sendMessage(sessionId, replyText)
val pendingResult = goAsync()
kotlinx.coroutines.CoroutineScope(kotlinx.coroutines.Dispatchers.IO).launch {
try {
val db =
com.m57.hermescontrol.data.local.HermesDatabase
.get(context)
val dao = db.chatMessageDao()
val entity =
com.m57.hermescontrol.data.local.ChatMessageEntity(
id =
java.util.UUID
.randomUUID()
.toString(),
sessionId = sessionId,
role = "USER",
content = replyText,
timestamp = System.currentTimeMillis(),
)
dao.upsert(entity)
} catch (e: Exception) {
android.util.Log.e("NotificationReply", "Failed to save replied message to Room DB", e)
} finally {
pendingResult.finish()
}
}
val repliedNotification =
NotificationCompat
.Builder(context, ChatNotificationService.CHAT_CHANNEL_ID)
@@ -169,6 +169,7 @@ fun ChatScreen(
androidx.lifecycle.Lifecycle.Event.ON_START -> {
NotificationHelper.setAppForeground(context, true)
NotificationHelper.stop(context)
viewModel.refreshCurrentSession()
}
androidx.lifecycle.Lifecycle.Event.ON_STOP -> {
@@ -803,6 +803,12 @@ class ChatViewModel(
}
}
fun refreshCurrentSession() {
val sessionId = _uiState.value.currentSessionId ?: return
loadCachedMessages(sessionId)
loadSessionMessages(sessionId)
}
fun switchSession(sessionId: String) {
if (sessionId == _uiState.value.currentSessionId) return