2

Why is my token-based auth not navigating to the home screen after a successful...

 1 year ago
source link: https://stackoverflow.com/questions/73557074/why-is-my-token-based-auth-not-navigating-to-the-home-screen-after-a-successful
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Why is my token-based auth not navigating to the home screen after a successful login?

Asked yesterday
Modified yesterday
Viewed 36 times

I just built a token based login function in material3 jetpack compose that will save the token if the login is successful. I tried following an article on how to save the auth token from API. I am using Laravel sanctum as my auth API.

I am confused with this problem because the function is working as it displays the login failed dialog if the credentials is incorrect as it supposed to be, however, it doesn't navigate to the home screen if the credentials is correct. I don't know what is the exact problem here because there are no errors thrown in the logcat during runtime.

This is my LoginViewModel.kt, it handles the logic of my login function

class LoginViewModel(application : Application) : AndroidViewModel(application)
{
      val isSuccessLoading = mutableStateOf(false)
      val loginFailedDialog = mutableStateOf(false)
      val progressBar = mutableStateOf(false)
      val loginRequestLiveData = MutableLiveData<Boolean>()
      private lateinit var sessionManager: SessionManager
      private lateinit var apiClient: ApiClient
      @SuppressLint("StaticFieldLeak")
      private val context = getApplication<Application>().applicationContext
    
      fun login(email: String,
                password: String,
                device_name : String = "android")
      {
        sessionManager = SessionManager(context)
        apiClient = ApiClient()
    
        viewModelScope.launch(Dispatchers.IO) {
            val loginInfo = LoginRequest(email, password, device_name)
            progressBar.value = true
    
            apiClient.getApiService(context).login(loginInfo)
                .enqueue(object : Callback<LoginResponse> {
                override fun onResponse(
                        call : Call<LoginResponse> ,
                        response : Response<LoginResponse>
                                       )
                {
                    val loginResponse = response.body()
    
                    if (loginResponse?.statusCode == 200 && loginResponse.user != null)
                    {
                        sessionManager.saveAuthToken(loginResponse.authToken)
                        viewModelScope.launch {
                            delay(500L)
                            isSuccessLoading.value = true
                        }
                    }
                    else
                    {
                        response.errorBody()?.let { error ->
                            viewModelScope.launch {
                                loginFailedDialog.value = true
                                delay(3500L)
                                loginFailedDialog.value = false
                                error.close()
                            }
                        }
                    }
                    loginRequestLiveData.postValue(response.isSuccessful)
                    progressBar.value = false
                }
    
                override fun onFailure(call : Call<LoginResponse> , t : Throwable)
                {
                    Log.d("Logging" , "Error Authentication" , t)
                    progressBar.value = false
                }
            })
        }
      }
    }

Then here is my MainActivity.kt:

@AndroidEntryPoint
class MainActivity : ComponentActivity()
    {
      override fun onCreate(savedInstanceState : Bundle?)
      {
        super.onCreate(savedInstanceState)
        val loginViewModel = LoginViewModel(application)
        setContent {
            MobileApp(loginViewModel)
        }
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content)) { view , insets ->
            val bottom = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
            view.updatePadding(bottom = bottom)
            insets
        }
      }
    }


@Composable
fun MobileApp(loginViewModel : LoginViewModel){
      val navController = rememberNavController()
      val scrollState = rememberScrollState()
    
      NavHost(navController = navController ,
              startDestination = AuthScreens.Splash.route)
      {

        //Splash screen
        composable(route = AuthScreens.Splash.route){
            SplashScreen(navController = navController)
        }

        //Login screen
        composable(route = AuthScreens.Login.route){
            val forgotDialog = remember { mutableStateOf(false)}
            val loginError =  loginViewModel.loginFailedDialog.value
            val loadingProgressBar = loginViewModel.progressBar.value

            if (loginViewModel.isSuccessLoading.value) {
                LaunchedEffect(key1 = Unit) {
                    navController.navigate(route = AuthScreens.AppScaffold.route) {
                        popUpTo(route = AuthScreens.Login.route) {
                            inclusive = true
                        }
                    }
                }
            } else {
                LoginScreen(
                        navController = navController ,
                        scrollState =  scrollState ,
                        onclickLogin =  loginViewModel::login ,
                        forgotDialog =  forgotDialog ,
                        loginError =  loginError ,
                        loadingProgressBar = loadingProgressBar)
            }
        }

        //Registration screen
        composable(route = AuthScreens.Register.route) {
            RegistrationScreen(navController = navController , scrollState = scrollState)
        }
        
        //App scaffold
        composable(route = AuthScreens.AppScaffold.route){
            AppScaffold(navController = navController)
        }

      }
    }

Then here is the AppScaffold:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppScaffold(navController : NavController)
    {
      Scaffold(//scaffold params)
      {
        NavigationHost(navController = navController)
      }
    }

Then the navigation host:

@Composable
fun NavigationHost(navController : NavController)
    {
      NavHost(navController = navController as NavHostController ,
            startDestination = MainScreens.Home.route) 
      {
        composable(route = MainScreens.Home.route) {
            HomeScreen(navController = navController)
        }
      }
    }

I don't know if it is because of my LoginResponse. My LoginResponse data class looks like this

data class LoginResponse(
        @SerializedName("status_code") var statusCode : Int ,
        @SerializedName("auth_token") var authToken : String ,
        @SerializedName("user") var user : User?)

and here is the return if the login is successful using postman

{
  "token": "137|HCFJvwPeNKgZihNSwztPqnfwSntwSzVhkaaYZGX7"
}

Can someone help me with this problem?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK