fix: smart navigation waits for DataStore before routing
Use flow.first() instead of collectAsState(initial = null) to determine start destination. The previous approach fired immediately with the initial null value before DataStore loaded from disk, always routing to Setup. Now the loading screen suspends until preferences are actually read. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
54a5b38fc6
commit
ebdf72e2c1
2 changed files with 8 additions and 29 deletions
|
|
@ -8,7 +8,6 @@ import androidx.activity.enableEdgeToEdge
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import no.naiv.implausibly.data.AppPreferences
|
||||
import no.naiv.implausibly.data.repository.InstanceRepository
|
||||
import no.naiv.implausibly.data.repository.SiteRepository
|
||||
import no.naiv.implausibly.ui.navigation.AppNavHost
|
||||
import no.naiv.implausibly.ui.theme.ImplausiblyTheme
|
||||
import javax.inject.Inject
|
||||
|
|
@ -18,7 +17,6 @@ class MainActivity : ComponentActivity() {
|
|||
|
||||
@Inject lateinit var appPreferences: AppPreferences
|
||||
@Inject lateinit var instanceRepository: InstanceRepository
|
||||
@Inject lateinit var siteRepository: SiteRepository
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -27,8 +25,7 @@ class MainActivity : ComponentActivity() {
|
|||
ImplausiblyTheme {
|
||||
AppNavHost(
|
||||
appPreferences = appPreferences,
|
||||
instanceRepository = instanceRepository,
|
||||
siteRepository = siteRepository
|
||||
instanceRepository = instanceRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,19 +3,14 @@ package no.naiv.implausibly.ui.navigation
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import kotlinx.coroutines.flow.first
|
||||
import no.naiv.implausibly.data.AppPreferences
|
||||
import no.naiv.implausibly.data.repository.InstanceRepository
|
||||
import no.naiv.implausibly.data.repository.SiteRepository
|
||||
import no.naiv.implausibly.ui.common.LoadingIndicator
|
||||
import no.naiv.implausibly.ui.dashboard.DashboardScreen
|
||||
import no.naiv.implausibly.ui.setup.SetupScreen
|
||||
|
|
@ -25,42 +20,29 @@ import no.naiv.implausibly.ui.sites.SiteListScreen
|
|||
* App-level navigation host.
|
||||
*
|
||||
* On launch, checks DataStore for a previously selected instance/site.
|
||||
* If found, navigates directly to the dashboard (or site list if no site
|
||||
* is selected). Otherwise, shows the setup screen.
|
||||
* If found, navigates directly to the dashboard. Otherwise, shows setup.
|
||||
*/
|
||||
@Composable
|
||||
fun AppNavHost(
|
||||
appPreferences: AppPreferences,
|
||||
instanceRepository: InstanceRepository,
|
||||
siteRepository: SiteRepository
|
||||
instanceRepository: InstanceRepository
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
// Collect saved preferences to determine start destination
|
||||
val savedInstanceId by appPreferences.selectedInstanceId.collectAsState(initial = null)
|
||||
val savedSiteId by appPreferences.selectedSiteId.collectAsState(initial = null)
|
||||
var hasNavigated by remember { mutableStateOf(false) }
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = Routes.LOADING
|
||||
) {
|
||||
// Loading screen — resolves start destination from preferences
|
||||
composable(Routes.LOADING) {
|
||||
LoadingIndicator()
|
||||
|
||||
LaunchedEffect(savedInstanceId, savedSiteId) {
|
||||
// Wait for preferences to load (initial null vs actual null)
|
||||
// Once we have a value (even if null), navigate
|
||||
if (hasNavigated) return@LaunchedEffect
|
||||
hasNavigated = true
|
||||
|
||||
val instanceId = savedInstanceId
|
||||
val siteId = savedSiteId
|
||||
// Use flow.first() to suspend until DataStore actually loads
|
||||
LaunchedEffect(Unit) {
|
||||
val instanceId = appPreferences.selectedInstanceId.first()
|
||||
val siteId = appPreferences.selectedSiteId.first()
|
||||
|
||||
val destination = when {
|
||||
instanceId != null && siteId != null -> {
|
||||
// Verify the instance still exists
|
||||
val instance = instanceRepository.getById(instanceId)
|
||||
if (instance != null) {
|
||||
Routes.dashboard(instanceId, siteId)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue