* fix(ux): keep Settings highlighted in bottom nav on drill-down sub-pages (issue #637) Map Settings drill-down destinations (SettingsConnection, SettingsAppearance, SettingsChat, SettingsNavBar, SettingsBehavior, SettingsAbout) back to SettingsScreen for bottom-nav selection only - navigation is unaffected. - Add selectedBottomNavDestination() helper in Navigation.kt - Extract bar-height logic into Modifier.bottomNavigationHeight() (ICON_AND_TEXT now uses heightIn(min=80.dp) so the standard bar can grow) - BottomNavigationSelectionTest (JVM): selection mapping logic - BottomNavigationLayoutTest (androidTest): per-mode bar height assertions * docs(navigation): warn that new Settings sub-pages must be added to settingsDestinations Addresses agy review (PR #643): documents the fragility of the hardcoded settingsDestinations set so future Settings drill-down screens don't silently drop the bottom-nav highlight. The sealed-class/marker-interface refactor was declined as scope creep (issue #637 explicitly scopes Settings-only; keys are flat data objects). * fix: language selector --------- Co-authored-by: M57 <Hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
367d6e22f5
commit
e18b25d065
3 files changed
+154
-8
No files matched your search
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -68,6 +69,37 @@ import com.m57.hermescontrol.ui.authlogin.AuthLoginScreen as AuthLoginScreenCont
|
||||
import com.m57.hermescontrol.ui.landing.LandingScreen as LandingScreenContent
|
||||
import com.m57.hermescontrol.ui.pairing.PairingCodeEntryScreen as PairingCodeEntryScreenContent
|
||||
|
||||
// NOTE: if a new Settings drill-down screen is added, its NavKey MUST be added
|
||||
// here too, or the bottom-nav Settings highlight will drop on that sub-page.
|
||||
// (Keys are flat data objects, not a sealed hierarchy, so no type-based check
|
||||
// is possible without a larger refactor — see issue #637.)
|
||||
private val settingsDestinations: Set<NavKey> =
|
||||
setOf(
|
||||
SettingsScreen,
|
||||
SettingsConnection,
|
||||
SettingsAppearance,
|
||||
SettingsChat,
|
||||
SettingsNavBar,
|
||||
SettingsBehavior,
|
||||
SettingsAbout,
|
||||
)
|
||||
|
||||
/**
|
||||
* Keep Settings highlighted in the bottom nav while one of its drill-down
|
||||
* sub-pages is visible. Navigation is unaffected — this only maps the
|
||||
* *selection* key back to the Settings parent so the indicator doesn't drop.
|
||||
*/
|
||||
internal fun selectedBottomNavDestination(currentScreen: NavKey): NavKey =
|
||||
if (currentScreen in settingsDestinations) SettingsScreen else currentScreen
|
||||
|
||||
/** Maps a compact bottom-nav display mode to its bar height. */
|
||||
internal fun Modifier.bottomNavigationHeight(displayMode: BottomNavDisplayMode): Modifier =
|
||||
when (displayMode) {
|
||||
BottomNavDisplayMode.ICON_ONLY -> height(56.dp)
|
||||
BottomNavDisplayMode.TEXT_ONLY -> height(44.dp)
|
||||
BottomNavDisplayMode.ICON_AND_TEXT -> heightIn(min = 80.dp)
|
||||
}
|
||||
|
||||
private fun resolveBottomNavItems(names: List<String>): List<ScreenDefinition> =
|
||||
names.mapNotNull { name -> ScreenRegistry.ALL_SCREENS.firstOrNull { it.key::class.simpleName == name } }
|
||||
|
||||
@@ -173,6 +205,7 @@ fun MainNavigation(sessionId: String? = null) {
|
||||
NavigationController.backStack = backStack
|
||||
|
||||
val currentScreen = backStack.lastOrNull() ?: startScreen
|
||||
val selectedDestination = selectedBottomNavDestination(currentScreen)
|
||||
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
@@ -298,14 +331,8 @@ fun MainNavigation(sessionId: String? = null) {
|
||||
contentWindowInsets = WindowInsets.navigationBars,
|
||||
bottomBar = {
|
||||
if (showBottomBar) {
|
||||
val barHeight =
|
||||
when (bottomNavDisplayMode) {
|
||||
BottomNavDisplayMode.ICON_ONLY -> 56.dp
|
||||
BottomNavDisplayMode.TEXT_ONLY -> 44.dp
|
||||
BottomNavDisplayMode.ICON_AND_TEXT -> 80.dp
|
||||
}
|
||||
NavigationBar(
|
||||
modifier = Modifier.height(barHeight),
|
||||
modifier = Modifier.bottomNavigationHeight(bottomNavDisplayMode),
|
||||
) {
|
||||
bottomNavItems.forEach { item ->
|
||||
val showIcon =
|
||||
@@ -315,7 +342,7 @@ fun MainNavigation(sessionId: String? = null) {
|
||||
bottomNavDisplayMode == BottomNavDisplayMode.ICON_AND_TEXT ||
|
||||
bottomNavDisplayMode == BottomNavDisplayMode.TEXT_ONLY
|
||||
|
||||
val isSelected = currentScreen == item.key
|
||||
val isSelected = selectedDestination == item.key
|
||||
|
||||
NavigationBarItem(
|
||||
selected = isSelected,
|
||||
|
||||
Reference in new issue
Block a user