Fixes for back button navigation and black screen

This commit is contained in:
Harish Vishwakarma 2026-03-23 18:36:08 +05:30
parent 5f957d96f7
commit 5fb7e01dbf
5 changed files with 47 additions and 22 deletions

View File

@ -134,6 +134,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import io.ktor.client.request.get import io.ktor.client.request.get
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -147,6 +148,9 @@ class MainActivityViewModel @Inject constructor(
val nextDestination = MutableStateFlow<String?>(null) val nextDestination = MutableStateFlow<String?>(null)
var isConnected = MutableStateFlow(false) var isConnected = MutableStateFlow(false)
val isReady = MutableStateFlow(false) val isReady = MutableStateFlow(false)
// Controls when we allow the first UI draw.
// Authentication/navigation readiness is represented by `isReady`.
val isUiReady = MutableStateFlow(false)
val couldNotLogIn = MutableStateFlow(false) val couldNotLogIn = MutableStateFlow(false)
private fun hasInternetConnection(): Boolean { private fun hasInternetConnection(): Boolean {
@ -184,11 +188,9 @@ class MainActivityViewModel @Inject constructor(
isReady.emit(true) isReady.emit(true)
} }
private fun doPreStartupTasks() { private fun doPostStartupTasks() {
Log.d("MainActivity", "Performing pre-startup tasks") Log.d("MainActivity", "Performing post-startup tasks")
viewModelScope.launch { viewModelScope.launch {
Log.d("MainActivity", "Hydrating Experiments from KV")
Experiments.hydrateWithKv()
Log.d("MainActivity", "Performing health check") Log.d("MainActivity", "Performing health check")
doHealthCheck() doHealthCheck()
Log.d("MainActivity", "Performing update geo state") Log.d("MainActivity", "Performing update geo state")
@ -225,6 +227,8 @@ class MainActivityViewModel @Inject constructor(
fun checkLoggedInState() { fun checkLoggedInState() {
viewModelScope.launch { viewModelScope.launch {
Log.d("MainActivity", "Checking logged in state") Log.d("MainActivity", "Checking logged in state")
Log.d("MainActivity", "Hydrating Experiments from KV")
Experiments.hydrateWithKv()
isConnected.emit(hasInternetConnection()) isConnected.emit(hasInternetConnection())
@ -339,8 +343,13 @@ class MainActivityViewModel @Inject constructor(
init { init {
Log.d("MainActivity", "Starting up") Log.d("MainActivity", "Starting up")
doPreStartupTasks() // Do not block initial rendering on slow network/login checks.
isUiReady.value = true
checkLoggedInState() checkLoggedInState()
viewModelScope.launch {
isReady.first { it }
doPostStartupTasks()
}
} }
} }
@ -419,7 +428,7 @@ class MainActivity : AppCompatActivity() {
object : ViewTreeObserver.OnPreDrawListener { object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean { override fun onPreDraw(): Boolean {
// Check whether the initial data is ready. // Check whether the initial data is ready.
return if (viewModel.isReady.value) { return if (viewModel.isUiReady.value) {
// The content is ready. Start drawing. // The content is ready. Start drawing.
content.viewTreeObserver.removeOnPreDrawListener(this) content.viewTreeObserver.removeOnPreDrawListener(this)
true true

View File

@ -3,9 +3,11 @@ package chat.zekochat.screens
import android.app.Activity import android.app.Activity
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -47,5 +49,12 @@ fun DefaultDestinationScreen(
} }
} }
if (nextDestination == null) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CircularProgressIndicator()
}
return
}
Box(Modifier.fillMaxSize()) Box(Modifier.fillMaxSize())
} }

View File

@ -45,6 +45,22 @@ fun ChoosePlatformScreen(navController: NavController) {
val apiUrlValue = remember { val apiUrlValue = remember {
mutableStateOf("") mutableStateOf("")
} }
fun continueWithSelectedPlatform() {
if (apiUrlValue.value.isNotEmpty()) {
when (apiUrlValue.value) {
ApplicationPlatform.PEP.baseUrl -> PeptideAPI.setPlatform(
ApplicationPlatform.PEP
)
ApplicationPlatform.REVOLT.baseUrl -> PeptideAPI.setPlatform(
ApplicationPlatform.REVOLT
)
else -> return
}
}
navController.navigate("login/greeting")
}
Column( Column(
modifier = Modifier modifier = Modifier
@ -118,6 +134,7 @@ fun ChoosePlatformScreen(navController: NavController) {
.size(72.dp) .size(72.dp)
.clickable { .clickable {
apiUrlValue.value = ApplicationPlatform.PEP.baseUrl apiUrlValue.value = ApplicationPlatform.PEP.baseUrl
continueWithSelectedPlatform()
}, },
) { ) {
Box( Box(
@ -152,6 +169,7 @@ fun ChoosePlatformScreen(navController: NavController) {
.size(72.dp) .size(72.dp)
.clickable { .clickable {
apiUrlValue.value = ApplicationPlatform.REVOLT.baseUrl apiUrlValue.value = ApplicationPlatform.REVOLT.baseUrl
continueWithSelectedPlatform()
}, },
) { ) {
Box( Box(
@ -199,20 +217,7 @@ fun ChoosePlatformScreen(navController: NavController) {
.padding(vertical = 8.dp) .padding(vertical = 8.dp)
) )
SquareButton( SquareButton(
onClick = { onClick = ::continueWithSelectedPlatform,
if(apiUrlValue.value.isNotEmpty()){
when(apiUrlValue.value){
ApplicationPlatform.PEP.baseUrl -> PeptideAPI.setPlatform(
ApplicationPlatform.PEP
)
ApplicationPlatform.REVOLT.baseUrl -> PeptideAPI.setPlatform(
ApplicationPlatform.REVOLT
)
else -> return@SquareButton
}
}
navController.navigate("login/greeting")
},
modifier = Modifier modifier = Modifier
.padding(top = 32.dp, bottom = 16.dp) .padding(top = 32.dp, bottom = 16.dp)
.fillMaxWidth() .fillMaxWidth()

View File

@ -198,7 +198,8 @@ fun LoginScreen(navController: NavController, viewModel: LoginViewModel = hiltVi
"home" -> { "home" -> {
navController.navigate("chat") { navController.navigate("chat") {
popUpTo("login/greeting") { inclusive = true } // Clear auth flow history while keeping graph/state restoration stable.
popUpTo("choose-platform") { inclusive = true }
} }
} }

View File

@ -149,7 +149,8 @@ fun MfaScreen(
LaunchedEffect(viewModel.navigateToHome) { LaunchedEffect(viewModel.navigateToHome) {
if (viewModel.navigateToHome) { if (viewModel.navigateToHome) {
navController.navigate("chat") { navController.navigate("chat") {
popUpTo("login/greeting") { inclusive = true } // Clear auth flow history while keeping graph/state restoration stable.
popUpTo("choose-platform") { inclusive = true }
} }
} }
} }