feat(ui): add New Chat to History (#1124)

This commit is contained in:
M57 authored and GitHub committed 2026-09-15 11:06:24 +03:00
1 parent 66ca470880
commit 71463a5a9a
4 files changed
+50 -1

No files matched your search

@@ -12,6 +12,10 @@ data class PendingChatNavigation(
val requestId: Long,
)
data class PendingNewChatNavigation(
val requestId: Long,
)
/**
* Central navigation controller with deduplication guard.
*
@@ -27,9 +31,12 @@ object NavigationController {
var backStack: NavBackStack<NavKey>? = null
var pendingChatNavigation: PendingChatNavigation? by mutableStateOf(null)
private set
var pendingNewChatNavigation: PendingNewChatNavigation? by mutableStateOf(null)
private set
val pendingSessionId: String? get() = pendingChatNavigation?.sessionId
private var nextChatNavigationRequestId = 0L
private var nextNewChatNavigationRequestId = 0L
/**
* Top-level primary screens (all drawer-accessible screens).
@@ -73,6 +80,14 @@ object NavigationController {
queueChatNavigation(sessionId, scrollToBottom = true)
}
fun openNewChat() {
pendingNewChatNavigation =
PendingNewChatNavigation(
requestId = ++nextNewChatNavigationRequestId,
)
navigateTo(ChatScreen)
}
private fun queueChatNavigation(
sessionId: String,
scrollToBottom: Boolean,
@@ -90,6 +105,9 @@ object NavigationController {
fun consumePendingChatNavigation(): PendingChatNavigation? =
pendingChatNavigation.also { pendingChatNavigation = null }
fun consumePendingNewChatNavigation(): PendingNewChatNavigation? =
pendingNewChatNavigation.also { pendingNewChatNavigation = null }
fun consumePendingSessionId(): String? = consumePendingChatNavigation()?.sessionId
/** Clear the stack and navigate to the given screen atomically. */
@@ -45,9 +45,15 @@ fun ChatLifecycleEffects(
// Switch to session from notification/history
val pendingNavigation = NavigationController.pendingChatNavigation
LaunchedEffect(sessionId, pendingNavigation, connectionStatus) {
val pendingNewChatNavigation = NavigationController.pendingNewChatNavigation
LaunchedEffect(sessionId, pendingNavigation, pendingNewChatNavigation, connectionStatus) {
if (connectionStatus != ConnectionStatus.CONNECTED) return@LaunchedEffect
val newChatRequest = NavigationController.consumePendingNewChatNavigation()
val request = NavigationController.consumePendingChatNavigation()
if (newChatRequest != null) {
viewModel.createNewSession()
return@LaunchedEffect
}
val target = request?.sessionId ?: sessionId
if (!target.isNullOrBlank()) {
viewModel.switchSession(target)
@@ -34,6 +34,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.CallSplit
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Code
@@ -466,6 +467,15 @@ fun SessionsScreen(
isRefreshing = state.isLoading,
onRefresh = { viewModel.loadSessions() },
actions = {
IconButton(
onClick = { NavigationController.openNewChat() },
modifier = Modifier.testTag("sessions_action_new_chat"),
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = stringResource(R.string.content_desc_new_chat),
)
}
if (state.hasHiddenSessions) {
IconButton(
onClick = { viewModel.toggleShowHidden() },