diff --git a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/App.kt b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/App.kt index a83143b..afb8328 100644 --- a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/App.kt +++ b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/App.kt @@ -2,7 +2,6 @@ package app.folio import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.safeDrawing @@ -17,6 +16,12 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.navigation.NavDestination.Companion.hasRoute +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController +import androidx.navigation.toRoute import app.folio.di.AppGraph import app.folio.di.LocalAppGraph import app.folio.feature.account.AddAccountRoute @@ -61,24 +66,35 @@ fun App(graphBuilder: suspend () -> AppGraph) { @Composable private fun AppContent() { val graph = LocalAppGraph.current - val session by graph.repository.session.collectAsState() - val route by graph.navigator.current.collectAsState() + val navController = rememberNavController() - LaunchedEffect(session, route) { - if (session == null && route !is Route.Login) { + LaunchedEffect(navController) { graph.navigator.attach(navController) } + + val session by graph.repository.session.collectAsState() + val currentEntry by navController.currentBackStackEntryAsState() + val onLogin = currentEntry?.destination?.hasRoute(Route.Login::class) == true + + LaunchedEffect(session, onLogin) { + if (session == null && !onLogin) { graph.navigator.replace(Route.Login) - } else if (session != null && route is Route.Login) { + } else if (session != null && onLogin) { graph.navigator.replace(Route.Home) } } - Column(Modifier.fillMaxSize()) { - when (val r = route) { - Route.Login -> LoginRoute() - Route.Home -> HomeRoute() - Route.AddAccount -> AddAccountRoute() - is Route.Ledger -> LedgerRoute(accountId = r.accountId) - is Route.AddTransaction -> AddTransactionRoute(accountId = r.accountId) + NavHost( + navController = navController, + startDestination = Route.Home, + modifier = Modifier.fillMaxSize(), + ) { + composable { LoginRoute() } + composable { HomeRoute() } + composable { AddAccountRoute() } + composable { entry -> + LedgerRoute(accountId = entry.toRoute().accountId) + } + composable { entry -> + AddTransactionRoute(accountId = entry.toRoute().accountId) } } } diff --git a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/di/AppGraph.kt b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/di/AppGraph.kt index a8a8bbf..8de68f2 100644 --- a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/di/AppGraph.kt +++ b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/di/AppGraph.kt @@ -10,7 +10,6 @@ import app.folio.feature.home.HomeViewModel import app.folio.feature.ledger.AddTransactionViewModel import app.folio.feature.ledger.LedgerViewModel import app.folio.navigation.Navigator -import app.folio.navigation.Route import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Binds import dev.zacsweers.metro.DependencyGraph @@ -33,7 +32,7 @@ interface AppGraph { @SingleIn(AppScope::class) @Provides - fun provideNavigator(): Navigator = Navigator(initial = Route.Home) + fun provideNavigator(): Navigator = Navigator() @DependencyGraph.Factory fun interface Factory { diff --git a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/navigation/Navigator.kt b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/navigation/Navigator.kt index 823e389..9d218da 100644 --- a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/navigation/Navigator.kt +++ b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/navigation/Navigator.kt @@ -1,30 +1,31 @@ package app.folio.navigation -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow +import androidx.navigation.NavHostController -class Navigator(initial: Route = Route.Home) { - private val stack = ArrayDeque().apply { addLast(initial) } - private val _current = MutableStateFlow(initial) - val current: StateFlow = _current.asStateFlow() +class Navigator { + private var controller: NavHostController? = null + + fun attach(controller: NavHostController) { + this.controller = controller + } fun push(route: Route) { - stack.addLast(route) - _current.value = route + controller?.navigate(route) { + launchSingleTop = true + } } fun replace(route: Route) { - stack.clear() - stack.addLast(route) - _current.value = route + val nav = controller ?: return + nav.navigate(route) { + popUpTo(nav.graph.id) { inclusive = true } + launchSingleTop = true + } } fun back(fallback: Route) { - if (stack.size > 1) { - stack.removeLast() - _current.value = stack.last() - } else { + val nav = controller ?: return + if (!nav.popBackStack()) { replace(fallback) } }