|
@@ -1,138 +1,31 @@
|
|
|
package com.zaojiao.app.ui
|
|
|
|
|
|
-import androidx.compose.foundation.layout.Box
|
|
|
-import androidx.compose.foundation.layout.Column
|
|
|
-import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
|
-import androidx.compose.foundation.layout.WindowInsets
|
|
|
-import androidx.compose.foundation.layout.consumeWindowInsets
|
|
|
-import androidx.compose.foundation.layout.fillMaxSize
|
|
|
-import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
-import androidx.compose.foundation.layout.padding
|
|
|
-import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
-import androidx.compose.material3.Icon
|
|
|
-import androidx.compose.material3.MaterialTheme
|
|
|
-import androidx.compose.material3.NavigationBar
|
|
|
-import androidx.compose.material3.NavigationBarItem
|
|
|
-import androidx.compose.material3.Scaffold
|
|
|
-import androidx.compose.material3.SnackbarHost
|
|
|
-import androidx.compose.material3.SnackbarHostState
|
|
|
-import androidx.compose.material3.Text
|
|
|
import androidx.compose.runtime.Composable
|
|
|
-import androidx.compose.runtime.remember
|
|
|
-import androidx.compose.ui.ExperimentalComposeUiApi
|
|
|
-import androidx.compose.ui.Modifier
|
|
|
-import androidx.compose.ui.composed
|
|
|
-import androidx.compose.ui.draw.drawWithContent
|
|
|
-import androidx.compose.ui.geometry.Offset
|
|
|
-import androidx.compose.ui.graphics.Color
|
|
|
-import androidx.compose.ui.platform.testTag
|
|
|
-import androidx.compose.ui.semantics.semantics
|
|
|
-import androidx.compose.ui.semantics.testTagsAsResourceId
|
|
|
-import androidx.compose.ui.unit.dp
|
|
|
-import androidx.navigation.NavDestination
|
|
|
-import androidx.navigation.NavDestination.Companion.hierarchy
|
|
|
-import com.zaojiao.app.navigation.HomeDestination
|
|
|
-import com.zaojiao.app.navigation.NavHost
|
|
|
+import androidx.compose.runtime.LaunchedEffect
|
|
|
+import androidx.navigation.compose.composable
|
|
|
+import com.zaojiao.app.core.auth.ui.LoginPage
|
|
|
+import com.zaojiao.app.core.nav.LJGNavHost
|
|
|
+import com.zaojiao.app.core.nav.LJGNavigator
|
|
|
+import com.zaojiao.app.feat.home.HomePage
|
|
|
|
|
|
-@OptIn(
|
|
|
- ExperimentalMaterial3Api::class,
|
|
|
- ExperimentalLayoutApi::class,
|
|
|
- ExperimentalComposeUiApi::class,
|
|
|
-)
|
|
|
@Composable
|
|
|
fun App(
|
|
|
appState: AppState = rememberAppState()
|
|
|
) {
|
|
|
- val snackbarHostState = remember { SnackbarHostState() }
|
|
|
-
|
|
|
- Scaffold(
|
|
|
- modifier = Modifier.semantics {
|
|
|
- testTagsAsResourceId = true
|
|
|
- },
|
|
|
- containerColor = Color.Transparent,
|
|
|
- contentColor = MaterialTheme.colorScheme.onBackground,
|
|
|
- contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
|
|
- snackbarHost = { SnackbarHost(snackbarHostState) },
|
|
|
- bottomBar = {
|
|
|
- AppBottomBar(
|
|
|
- destinations = appState.homeDestinations,
|
|
|
- onNavigateToDestination = appState::navigateToHomeDestination,
|
|
|
- currentDestination = appState.currentDestination,
|
|
|
- modifier = Modifier.testTag("NiaBottomBar"),
|
|
|
- )
|
|
|
- },
|
|
|
- ) { padding ->
|
|
|
- Box(modifier = Modifier
|
|
|
- .fillMaxSize()
|
|
|
- .padding(padding)
|
|
|
- .consumeWindowInsets(padding)) {
|
|
|
- NavHost(appState = appState)
|
|
|
- }
|
|
|
+ LaunchedEffect(appState) {
|
|
|
+ LJGNavigator.handleNavigationCommands(appState.navController)
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-@Composable
|
|
|
-private fun AppBottomBar(
|
|
|
- destinations: List<HomeDestination>,
|
|
|
- onNavigateToDestination: (HomeDestination) -> Unit,
|
|
|
- currentDestination: NavDestination?,
|
|
|
- modifier: Modifier = Modifier,
|
|
|
-) {
|
|
|
- MaterialTheme.colorScheme.onSurfaceVariant
|
|
|
|
|
|
- NavigationBar(
|
|
|
- modifier = modifier,
|
|
|
- contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
|
- tonalElevation = 0.dp,
|
|
|
+ LJGNavHost(
|
|
|
+ navHostController = appState.navController,
|
|
|
+ startDestination = "/"
|
|
|
) {
|
|
|
- destinations.forEach { destination ->
|
|
|
- val selected = currentDestination.isTopLevelDestinationInHierarchy(destination)
|
|
|
-
|
|
|
- NavigationBarItem(
|
|
|
- selected = selected,
|
|
|
- onClick = { onNavigateToDestination(destination) },
|
|
|
- enabled = true,
|
|
|
- icon = {
|
|
|
- if (selected) {
|
|
|
- Icon(
|
|
|
- imageVector = destination.selectedIcon,
|
|
|
- contentDescription = null,
|
|
|
- )
|
|
|
- } else {
|
|
|
- Icon(
|
|
|
- imageVector = destination.unselectedIcon,
|
|
|
- contentDescription = null,
|
|
|
- )
|
|
|
- }
|
|
|
- },
|
|
|
- alwaysShowLabel = true,
|
|
|
- label = { Text(text = destination.iconTitle) },
|
|
|
- modifier = Modifier.notificationDot(),
|
|
|
- )
|
|
|
+ composable(route = "/") {
|
|
|
+ HomePage()
|
|
|
}
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-private fun Modifier.notificationDot(): Modifier =
|
|
|
- composed {
|
|
|
- val tertiaryColor = MaterialTheme.colorScheme.tertiary
|
|
|
- drawWithContent {
|
|
|
- drawContent()
|
|
|
- drawCircle(
|
|
|
- tertiaryColor,
|
|
|
- radius = 5.dp.toPx(),
|
|
|
- // This is based on the dimensions of the NavigationBar's "indicator pill";
|
|
|
- // however, its parameters are private, so we must depend on them implicitly
|
|
|
- // (NavigationBarTokens.ActiveIndicatorWidth = 64.dp)
|
|
|
- center = center + Offset(
|
|
|
- 64.dp.toPx() * .45f,
|
|
|
- 32.dp.toPx() * -.45f - 6.dp.toPx(),
|
|
|
- ),
|
|
|
- )
|
|
|
+ composable(route = "/login/sms") {
|
|
|
+ LoginPage()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-private fun NavDestination?.isTopLevelDestinationInHierarchy(destination: HomeDestination) =
|
|
|
- this?.hierarchy?.any {
|
|
|
- it.route?.contains(destination.name, true) ?: false
|
|
|
- } ?: false
|
|
|
+}
|