fix(notification): open tapped chat at bottom (#984)
Co-authored-by: M57 <41645758+Hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
19065f02df
commit
ce8fdc45bd
4 files changed
+65
-7
No files matched your search
@@ -96,6 +96,6 @@ class MainActivity : ComponentActivity() {
|
||||
if (intent?.action != ACTION_OPEN_CHAT_FROM_NOTIFICATION) return
|
||||
val sessionId = intent.getStringExtra(NotificationReplyReceiver.EXTRA_SESSION_ID)
|
||||
intent.removeExtra(NotificationReplyReceiver.EXTRA_SESSION_ID)
|
||||
sessionId?.takeIf { it.isNotBlank() }?.let(NavigationController::openChatSession)
|
||||
sessionId?.takeIf { it.isNotBlank() }?.let(NavigationController::openChatSessionFromNotification)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,12 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
||||
data class PendingChatNavigation(
|
||||
val sessionId: String,
|
||||
val scrollToBottom: Boolean,
|
||||
val requestId: Long,
|
||||
)
|
||||
|
||||
/**
|
||||
* Central navigation controller with deduplication guard.
|
||||
*
|
||||
@@ -19,8 +25,11 @@ import androidx.navigation3.runtime.NavKey
|
||||
*/
|
||||
object NavigationController {
|
||||
var backStack: NavBackStack<NavKey>? = null
|
||||
var pendingSessionId: String? by mutableStateOf(null)
|
||||
var pendingChatNavigation: PendingChatNavigation? by mutableStateOf(null)
|
||||
private set
|
||||
val pendingSessionId: String? get() = pendingChatNavigation?.sessionId
|
||||
|
||||
private var nextChatNavigationRequestId = 0L
|
||||
|
||||
// Top-level primary screens (Chat, Skills, Cron, System, Settings)
|
||||
private val primaryScreens: MutableSet<NavKey> =
|
||||
@@ -50,12 +59,31 @@ object NavigationController {
|
||||
}
|
||||
|
||||
fun openChatSession(sessionId: String) {
|
||||
queueChatNavigation(sessionId, scrollToBottom = false)
|
||||
}
|
||||
|
||||
fun openChatSessionFromNotification(sessionId: String) {
|
||||
queueChatNavigation(sessionId, scrollToBottom = true)
|
||||
}
|
||||
|
||||
private fun queueChatNavigation(
|
||||
sessionId: String,
|
||||
scrollToBottom: Boolean,
|
||||
) {
|
||||
if (sessionId.isBlank()) return
|
||||
pendingSessionId = sessionId
|
||||
pendingChatNavigation =
|
||||
PendingChatNavigation(
|
||||
sessionId = sessionId,
|
||||
scrollToBottom = scrollToBottom,
|
||||
requestId = ++nextChatNavigationRequestId,
|
||||
)
|
||||
navigateTo(ChatScreen)
|
||||
}
|
||||
|
||||
fun consumePendingSessionId(): String? = pendingSessionId.also { pendingSessionId = null }
|
||||
fun consumePendingChatNavigation(): PendingChatNavigation? =
|
||||
pendingChatNavigation.also { pendingChatNavigation = null }
|
||||
|
||||
fun consumePendingSessionId(): String? = consumePendingChatNavigation()?.sessionId
|
||||
|
||||
/** Clear the stack and navigate to the given screen atomically. */
|
||||
fun resetTo(screen: NavKey) {
|
||||
|
||||
@@ -44,13 +44,17 @@ fun ChatLifecycleEffects(
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
// Switch to session from notification/history
|
||||
val pendingSessionId = NavigationController.pendingSessionId
|
||||
LaunchedEffect(sessionId, pendingSessionId, connectionStatus) {
|
||||
val pendingNavigation = NavigationController.pendingChatNavigation
|
||||
LaunchedEffect(sessionId, pendingNavigation, connectionStatus) {
|
||||
if (connectionStatus != ConnectionStatus.CONNECTED) return@LaunchedEffect
|
||||
val target = NavigationController.consumePendingSessionId() ?: sessionId
|
||||
val request = NavigationController.consumePendingChatNavigation()
|
||||
val target = request?.sessionId ?: sessionId
|
||||
if (!target.isNullOrBlank()) {
|
||||
viewModel.switchSession(target)
|
||||
}
|
||||
if (request?.scrollToBottom == true) {
|
||||
scrollController.jumpToBottom(animated = false)
|
||||
}
|
||||
}
|
||||
|
||||
// Land instantly at the bottom on a session switch (issue #682).
|
||||
|
||||
Reference in new issue
Block a user