Files
aiturk-mobil/app/src/main/java/com/m57/hermescontrol/NavigationController.kt
T
M57 64a047f095 feat: move session history to a dedicated history screen (#175)
* feat: move session history to a dedicated history screen

Closes #159.

* fix(ci): fix ktlint style issues and unresolved NavigationController reference
2026-06-20 22:27:54 +03:00

74 lines
2.3 KiB
Kotlin

package com.m57.hermescontrol
import androidx.navigation3.runtime.NavBackStack
import androidx.navigation3.runtime.NavKey
/**
* Central navigation controller with deduplication guard.
*
* Primary screens (bottom nav tabs) clear the back stack and become the new
* root — this matches Material's bottom-nav pattern where each tab has its own
* back stack history (simplified: we just clear).
*
* B7 (Jun 18 2026): Never call `backStack.add()` directly from UI callbacks.
* Always route through [navigateTo] to prevent stacking duplicate screen
* entries that compete for touch events.
*/
object NavigationController {
var backStack: NavBackStack<NavKey>? = null
var pendingSessionId: String? = null
// Bottom-nav primary screens — dynamic, updated by Navigation.kt via
// updatePrimaryScreens() when the user customises the bottom nav bar.
// Default matches the default 5 bottom-nav items.
private val primaryScreens: MutableSet<NavKey> =
mutableSetOf(
ChatScreen,
SkillsScreen,
CronJobsScreen,
SystemScreen,
SettingsScreen,
)
/** Returns whether the given key is a primary (bottom-nav) screen. */
fun isPrimaryScreen(key: NavKey): Boolean = key in primaryScreens
/** Replace the primary screen set. Called by Navigation.kt when the
* bottom-nav item config changes. */
fun updatePrimaryScreens(keys: Set<NavKey>) {
primaryScreens.clear()
primaryScreens.addAll(keys)
}
fun navigateTo(key: NavKey) {
val stack = backStack ?: return
if (stack.lastOrNull() == key) return
if (isPrimaryScreen(key)) {
stack.clear()
}
stack.add(key)
}
/** Clear the stack and navigate to the given screen atomically. */
fun resetTo(screen: NavKey) {
val stack = backStack ?: return
stack.clear()
stack.add(screen)
}
/**
* Navigate back one step, or fall back to [fallback] when the stack has only one item.
* Never leaves the stack empty.
*/
fun goBack(fallback: NavKey = ChatScreen) {
val stack = backStack ?: return
if (stack.size > 1) {
stack.removeLastOrNull()
} else if (stack.size == 1) {
stack.clear()
stack.add(fallback)
}
}
}