* refactor(nav): remove bottom NavigationBar from Scaffold (#665) * refactor(theme): remove BottomNavDisplayMode enum (#666) * refactor(settings): remove nav bar customization page (#667) * chore: clean up unused imports after bottom nav removal (#668) * chore: remove dead bottom nav infrastructure after removal - Remove SettingsNavBar NavKey (NavigationKeys.kt) - Remove bottomNavItems field from ServerStoreState + migration code - Remove _bottomNavItemsFlow, getBottomNavItems, setBottomNavItems from AuthManager - Remove bottomNavItems handling from selfHealed() (ServerCollectionOps) - Remove redundant bottomBar={} from Scaffold (Navigation.kt) - Remove unused nav bar strings from values/strings.xml + values-ko/strings.xml - Remove content_desc_move_up/down/remove_item strings - Update SettingsViewModelTest.kt (drop stale getBottomNavItems mock) - Update ServerStoreTest.kt (remove bottomNavItems assertions) --------- Co-authored-by: M57 <Hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
c43904b2b8
commit
0edb67338d
17 files changed
-580
No files matched your search
@@ -8,7 +8,6 @@ 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
|
||||
@@ -22,9 +21,6 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalDrawerSheet
|
||||
import androidx.compose.material3.ModalNavigationDrawer
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationBarItemDefaults
|
||||
import androidx.compose.material3.NavigationDrawerItem
|
||||
import androidx.compose.material3.NavigationDrawerItemDefaults
|
||||
import androidx.compose.material3.Scaffold
|
||||
@@ -32,15 +28,12 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberDrawerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -52,7 +45,6 @@ import androidx.navigation3.ui.NavDisplay
|
||||
import com.m57.hermescontrol.data.local.AuthManager
|
||||
import com.m57.hermescontrol.data.ws.ConnectionStatus
|
||||
import com.m57.hermescontrol.data.ws.HermesWsClient
|
||||
import com.m57.hermescontrol.theme.BottomNavDisplayMode
|
||||
import com.m57.hermescontrol.theme.LocalHermesStatusColors
|
||||
import com.m57.hermescontrol.ui.common.DisableDrawerGestures
|
||||
import com.m57.hermescontrol.ui.common.DrawerGestureController
|
||||
@@ -62,46 +54,11 @@ import com.m57.hermescontrol.ui.settings.SettingsAppearancePage
|
||||
import com.m57.hermescontrol.ui.settings.SettingsBehaviorPage
|
||||
import com.m57.hermescontrol.ui.settings.SettingsChatPage
|
||||
import com.m57.hermescontrol.ui.settings.SettingsConnectionPage
|
||||
import com.m57.hermescontrol.ui.settings.SettingsNavBarPage
|
||||
import com.m57.hermescontrol.ui.settings.SettingsViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import com.m57.hermescontrol.ui.authlogin.AuthLoginScreen as AuthLoginScreenContent
|
||||
import com.m57.hermescontrol.ui.landing.LandingScreen as LandingScreenContent
|
||||
|
||||
// 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 } }
|
||||
|
||||
private fun appEntryProvider(
|
||||
sessionId: String?,
|
||||
openDrawer: () -> Unit,
|
||||
@@ -159,12 +116,6 @@ private fun appEntryProvider(
|
||||
viewModel = viewModel { SettingsViewModel() },
|
||||
)
|
||||
}
|
||||
entry<SettingsNavBar> {
|
||||
SettingsNavBarPage(
|
||||
onBack = { NavigationController.goBack() },
|
||||
viewModel = viewModel { SettingsViewModel() },
|
||||
)
|
||||
}
|
||||
entry<SettingsBehavior> {
|
||||
SettingsBehaviorPage(
|
||||
onBack = { NavigationController.goBack() },
|
||||
@@ -189,7 +140,6 @@ 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()
|
||||
|
||||
@@ -204,19 +154,6 @@ fun MainNavigation(sessionId: String? = null) {
|
||||
DrawerGestureController(drawerState, scope)
|
||||
}
|
||||
|
||||
val bottomNavItemsState by AuthManager.bottomNavItemsFlow.collectAsState()
|
||||
val bottomNavDisplayMode by AuthManager.bottomNavDisplayModeFlow.collectAsState()
|
||||
val bottomNavItems = resolveBottomNavItems(bottomNavItemsState)
|
||||
val bottomNavKeys = remember(bottomNavItems) { bottomNavItems.mapTo(mutableSetOf()) { it.key } }
|
||||
|
||||
LaunchedEffect(bottomNavKeys) {
|
||||
NavigationController.updatePrimaryScreens(bottomNavKeys)
|
||||
}
|
||||
|
||||
val showBottomBar =
|
||||
currentScreen != LandingScreen &&
|
||||
currentScreen != AuthLoginScreen
|
||||
|
||||
val openDrawer: () -> Unit = { scope.launch { drawerState.open() } }
|
||||
|
||||
CompositionLocalProvider(LocalDrawerGestureController provides gestureController) {
|
||||
@@ -312,60 +249,6 @@ fun MainNavigation(sessionId: String? = null) {
|
||||
) {
|
||||
Scaffold(
|
||||
contentWindowInsets = WindowInsets.navigationBars,
|
||||
bottomBar = {
|
||||
if (showBottomBar) {
|
||||
NavigationBar(
|
||||
modifier = Modifier.bottomNavigationHeight(bottomNavDisplayMode),
|
||||
) {
|
||||
bottomNavItems.forEach { item ->
|
||||
val showIcon =
|
||||
bottomNavDisplayMode == BottomNavDisplayMode.ICON_AND_TEXT ||
|
||||
bottomNavDisplayMode == BottomNavDisplayMode.ICON_ONLY
|
||||
val showLabel =
|
||||
bottomNavDisplayMode == BottomNavDisplayMode.ICON_AND_TEXT ||
|
||||
bottomNavDisplayMode == BottomNavDisplayMode.TEXT_ONLY
|
||||
|
||||
val isSelected = selectedDestination == item.key
|
||||
|
||||
NavigationBarItem(
|
||||
selected = isSelected,
|
||||
onClick = { NavigationController.navigateTo(item.key) },
|
||||
colors =
|
||||
if (bottomNavDisplayMode == BottomNavDisplayMode.TEXT_ONLY) {
|
||||
NavigationBarItemDefaults.colors(
|
||||
indicatorColor = Color.Transparent,
|
||||
)
|
||||
} else {
|
||||
NavigationBarItemDefaults.colors()
|
||||
},
|
||||
icon = {
|
||||
if (showIcon) {
|
||||
Icon(item.icon, contentDescription = stringResource(item.labelRes))
|
||||
} else {
|
||||
Text(
|
||||
text = stringResource(item.labelRes),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,
|
||||
)
|
||||
}
|
||||
},
|
||||
label =
|
||||
if (showLabel && showIcon) {
|
||||
{ Text(stringResource(item.labelRes)) }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
modifier =
|
||||
Modifier.testTag(
|
||||
"nav_${item.key::class.simpleName?.lowercase()?.removeSuffix(
|
||||
"screen",
|
||||
) ?: ""}",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
|
||||
Reference in new issue
Block a user