Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Verified Commit 2296199b authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

fix(login): allow transition to Home only when anonymous login successful

Previously, user was transitioned to Home screen from Signin screen without completing anonymous login. So, while the login was in progress and user is in Home screen, an attempt to install an app would fail because AuthData wouldn't be available by then.

Here, user is now transitioned to Home only when the anon. login is successful. For failure, they remain in Signin screen.

To prevent the progress indicator stuck in indefinite loading, the auto-retry had to be skipped and a new login-without-retry behaviour is introduced which is only being used for first-time login.
parent 25b98e6c
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ package foundation.e.apps.data.login.core
interface StoreAuthenticator {
    val storeType: StoreType
    suspend fun login(): StoreAuthResult
    suspend fun loginWithoutRetry(): StoreAuthResult = login()
    suspend fun logout()
    suspend fun isStoreActive(): Boolean
}
+13 −1
Original line number Diff line number Diff line
@@ -89,10 +89,22 @@ class PlayStoreAuthenticator @Inject constructor(
     * Main entry point to get GPlay auth data.
     */
    override suspend fun login(): StoreAuthResult {
        return loginWithRetry(retryOnFailure = true)
    }

    override suspend fun loginWithoutRetry(): StoreAuthResult {
        return loginWithRetry(retryOnFailure = false)
    }

    private suspend fun loginWithRetry(retryOnFailure: Boolean): StoreAuthResult {
        val user = sessionRepository.awaitUser()
        val validSavedAuth = authDataCache.awaitSavedAuthData()
        val authDataResult = if (validSavedAuth == null) {
            if (retryOnFailure) {
                retryWithBackoff { loginForUserType(user) }
            } else {
                loginForUserType(user)
            }
        } else {
            null
        }
+16 −1
Original line number Diff line number Diff line
@@ -51,6 +51,17 @@ class AuthenticatorRepository @Inject constructor(
    }

    override suspend fun fetchAuthObjects(authTypes: List<StoreType>): List<AuthObject> {
        return fetchAuthObjectsInternal(authTypes, retryOnFailure = true)
    }

    override suspend fun fetchAuthObjectsWithoutRetry(authTypes: List<StoreType>): List<AuthObject> {
        return fetchAuthObjectsInternal(authTypes, retryOnFailure = false)
    }

    private suspend fun fetchAuthObjectsInternal(
        authTypes: List<StoreType>,
        retryOnFailure: Boolean,
    ): List<AuthObject> {
        val authObjectsLocal = ArrayList<AuthObject>()

        for (authenticator in authenticators) {
@@ -59,7 +70,11 @@ class AuthenticatorRepository @Inject constructor(
                authenticator.logout()
            }

            val authResult = authenticator.login()
            val authResult = if (retryOnFailure) {
                authenticator.login()
            } else {
                authenticator.loginWithoutRetry()
            }
            authObjectsLocal.add(authResult.authObject)
            authResult.authDataToPersist?.let { playStoreAuthStore.saveAuthData(it) }
        }
+1 −0
Original line number Diff line number Diff line
@@ -22,4 +22,5 @@ import foundation.e.apps.data.login.core.StoreType

interface StoreAuthCoordinator {
    suspend fun fetchAuthObjects(authTypes: List<StoreType> = emptyList()): List<AuthObject>
    suspend fun fetchAuthObjectsWithoutRetry(authTypes: List<StoreType> = emptyList()): List<AuthObject>
}
+24 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import foundation.e.apps.domain.login.NoGoogleLoginUseCase
import foundation.e.apps.login.MicrogAccountFetchResult
import foundation.e.apps.login.MicrogAccountFetcher
import foundation.e.apps.login.StoreAuthCoordinator
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch
import javax.inject.Inject

@@ -66,6 +67,8 @@ class LoginViewModel @Inject constructor(
     * are loaded instead of null.
     */
    val authObjects: MutableLiveData<List<AuthObject>?> = MutableLiveData(null)
    val anonymousLoginInProgress: MutableLiveData<Boolean> = MutableLiveData(false)
    val anonymousLoginError: MutableLiveData<Int?> = MutableLiveData(null)
    var selectedMicrogAccount: String? = null

    /**
@@ -126,11 +129,29 @@ class LoginViewModel @Inject constructor(
     */
    fun initialAnonymousLogin(onUserSaved: () -> Unit) {
        viewModelScope.launch {
            anonymousLoginInProgress.postValue(true)
            try {
                anonymousLoginUseCase()
                val authObjectsLocal = storeAuthCoordinator.fetchAuthObjectsWithoutRetry()
                authObjects.postValue(authObjectsLocal)
                if (authObjectsLocal.any { it is AuthObject.GPlayAuth && it.result.isSuccess() }) {
                    onUserSaved()
            startLoginFlow()
                } else {
                    anonymousLoginError.postValue(R.string.anonymous_login_failed)
                }
            } catch (exception: CancellationException) {
                throw exception
            } catch (_: Exception) {
                anonymousLoginError.postValue(R.string.anonymous_login_failed)
            } finally {
                anonymousLoginInProgress.postValue(false)
            }
        }
    }

    fun onAnonymousLoginErrorHandled() {
        anonymousLoginError.value = null
    }

    /**
     * Call this to use GOOGLE login mode.
Loading