Loading .gitlab-ci.yml +5 −1 Original line number Diff line number Diff line Loading @@ -43,13 +43,15 @@ ktlintDebug: # Release build related jobs # Default configuration for release builds # Only on "master" and "merge_request_event" # Only on "master", "merge_request_event" and protected branches buildRelease: stage: release allow_failure: false rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' when: always - if: '$CI_COMMIT_REF_PROTECTED == "true"' when: always - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: always script: Loading @@ -69,6 +71,8 @@ buildRelease: rules: - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: always - if: '$CI_COMMIT_REF_PROTECTED == "true"' when: always buildReleaseDev: extends: .releaseSigned Loading app/build.gradle +7 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ plugins { } def versionMajor = 2 def versionMinor = 2 def versionMinor = 3 def versionPatch = 0 android { Loading Loading @@ -66,6 +66,12 @@ android { signingConfig signingConfigs.releaseStableConfig proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } applicationVariants.all { variant -> variant.outputs.all { output -> outputFileName = "AppLounge-${variant.versionName}-${variant.buildType.name}.apk" } } } buildFeatures { viewBinding true Loading app/src/main/java/foundation/e/apps/AppProgressViewModel.kt +16 −4 Original line number Diff line number Diff line Loading @@ -19,15 +19,19 @@ class AppProgressViewModel @Inject constructor( suspend fun calculateProgress( fusedApp: FusedApp?, progress: DownloadProgress ): Pair<Long, Long> { ): Int { fusedApp?.let { app -> val appDownload = fusedManagerRepository.getDownloadList() .singleOrNull { it.id.contentEquals(app._id) && it.packageName.contentEquals(app.package_name) } ?: return Pair(1, 0) ?: return 0 if (!appDownload.id.contentEquals(app._id) || !appDownload.packageName.contentEquals(app.package_name)) { return@let } if (!isProgressValidForApp(fusedApp, progress)) { return -1 } val downloadingMap = progress.totalSizeBytes.filter { item -> appDownload.downloadIdMap.keys.contains(item.key) } Loading @@ -36,8 +40,16 @@ class AppProgressViewModel @Inject constructor( appDownload.downloadIdMap.keys.contains(item.key) }.values.sum() return Pair(totalSizeBytes, downloadedSoFar) return ((downloadedSoFar / totalSizeBytes.toDouble()) * 100).toInt() } return Pair(1, 0) return 0 } private suspend fun isProgressValidForApp( fusedApp: FusedApp, downloadProgress: DownloadProgress ): Boolean { val download = fusedManagerRepository.getFusedDownload(downloadProgress.downloadId) return download.id == fusedApp._id } } app/src/main/java/foundation/e/apps/MainActivity.kt +15 −48 Original line number Diff line number Diff line Loading @@ -44,9 +44,8 @@ import foundation.e.apps.purchase.AppPurchaseFragmentDirections import foundation.e.apps.setup.signin.SignInViewModel import foundation.e.apps.updates.UpdatesNotifier import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import foundation.e.apps.utils.parentFragment.TimeoutFragment import foundation.e.apps.utils.modules.CommonUtilsModule import foundation.e.apps.utils.parentFragment.TimeoutFragment import kotlinx.coroutines.launch import timber.log.Timber import java.io.File Loading @@ -54,6 +53,7 @@ import java.util.UUID @AndroidEntryPoint class MainActivity : AppCompatActivity() { private lateinit var signInViewModel: SignInViewModel private lateinit var binding: ActivityMainBinding private val TAG = MainActivity::class.java.simpleName private lateinit var viewModel: MainActivityViewModel Loading @@ -72,7 +72,7 @@ class MainActivity : AppCompatActivity() { var hasInternet = true viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java] val signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java] signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java] // navOptions and activityNavController for TOS and SignIn Fragments val navOptions = NavOptions.Builder() Loading @@ -86,30 +86,6 @@ class MainActivity : AppCompatActivity() { } } fun generateAuthDataBasedOnUserType(user: String) { if (user.isNotBlank() && viewModel.tocStatus.value == true) { when (User.valueOf(user)) { User.ANONYMOUS -> { if (viewModel.authDataJson.value.isNullOrEmpty() && !viewModel.authRequestRunning) { Timber.d( "Fetching new authentication data") viewModel.setFirstTokenFetchTime() viewModel.getAuthData() } } User.UNAVAILABLE -> { viewModel.destroyCredentials(null) } User.GOOGLE -> { if (viewModel.authData.value == null && !viewModel.authRequestRunning) { Timber.d( "Fetching new authentication data") viewModel.setFirstTokenFetchTime() signInViewModel.fetchAuthData() } } } } } viewModel.internetConnection.observe(this) { isInternetAvailable -> hasInternet = isInternetAvailable if (isInternetAvailable) { Loading @@ -117,7 +93,7 @@ class MainActivity : AppCompatActivity() { binding.fragment.visibility = View.VISIBLE viewModel.userType.observe(this) { user -> generateAuthDataBasedOnUserType(user) viewModel.handleAuthDataJson() } signInViewModel.authLiveData.observe(this) { Loading @@ -126,34 +102,25 @@ class MainActivity : AppCompatActivity() { // Watch and refresh authentication data viewModel.authDataJson.observe(this) { if (!it.isNullOrEmpty()) { viewModel.generateAuthData() Timber.d( "Authentication data is available!") } viewModel.handleAuthDataJson() } } } viewModel.authValidity.observe(this) { if (it != true) { Timber.d( "Authentication data validation failed!") viewModel.destroyCredentials { user -> if (viewModel.isTimeEligibleForTokenRefresh()) { generateAuthDataBasedOnUserType(user) } else { Timber.d( "Timeout validating auth data!") viewModel.handleAuthValidity(it) { Log.d(TAG, "Timeout validating auth data!") val lastFragment = navHostFragment.childFragmentManager.fragments[0] if (lastFragment is TimeoutFragment) { Timber.d( "Displaying timeout from MainActivity on fragment: " + lastFragment::class.java.name) Log.d( TAG, "Displaying timeout from MainActivity on fragment: " + lastFragment::class.java.name ) lastFragment.onTimeout() } } } } else { Timber.d( "Authentication data is valid!") } } navController.addOnDestinationChangedListener { _, destination, _ -> if (!hasInternet) { Loading app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +114 −9 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package foundation.e.apps import android.app.Activity import android.content.Context import android.graphics.Bitmap import android.os.Build Loading @@ -41,13 +40,12 @@ import com.google.gson.Gson import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.api.cleanapk.blockedApps.BlockedAppRepository import foundation.e.apps.api.ecloud.EcloudRepository import foundation.e.apps.api.fused.FusedAPIImpl import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.gplay.utils.AC2DMTask import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.manager.workmanager.InstallWorkManager import foundation.e.apps.utils.enums.Origin import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Type Loading @@ -56,6 +54,7 @@ import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.DataStoreModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import ru.beryukhov.reactivenetwork.ReactiveNetwork import timber.log.Timber import java.io.ByteArrayOutputStream Loading @@ -70,6 +69,7 @@ class MainActivityViewModel @Inject constructor( private val pkgManagerModule: PkgManagerModule, private val ecloudRepository: EcloudRepository, private val blockedAppRepository: BlockedAppRepository, private val aC2DMTask: AC2DMTask, ) : ViewModel() { val authDataJson: LiveData<String> = dataStoreModule.authData.asLiveData() Loading @@ -93,6 +93,8 @@ class MainActivityViewModel @Inject constructor( */ var firstAuthDataFetchTime = 0L var isTokenValidationCompletedOnce = false // Downloads val downloadList = fusedManagerRepository.getDownloadLiveList() var installInProgress = false Loading @@ -107,15 +109,16 @@ class MainActivityViewModel @Inject constructor( companion object { private const val TAG = "MainActivityViewModel" private var isGoogleLoginRunning = false } fun setFirstTokenFetchTime() { private fun setFirstTokenFetchTime() { if (firstAuthDataFetchTime == 0L) { firstAuthDataFetchTime = SystemClock.uptimeMillis() } } fun isTimeEligibleForTokenRefresh(): Boolean { private fun isTimeEligibleForTokenRefresh(): Boolean { return (SystemClock.uptimeMillis() - firstAuthDataFetchTime) <= timeoutDurationInMillis } Loading Loading @@ -198,13 +201,116 @@ class MainActivityViewModel @Inject constructor( } fun generateAuthData() { val data = gson.fromJson(authDataJson.value, AuthData::class.java) val data = jsonToAuthData() _authData.value = data } private fun jsonToAuthData() = gson.fromJson(authDataJson.value, AuthData::class.java) fun validateAuthData() { viewModelScope.launch { authValidity.postValue(isAuthValid(data)) jsonToAuthData()?.let { val isAuthValid = isAuthValid(it) authValidity.postValue(isAuthValid) authRequestRunning = false } } } fun handleAuthDataJson() { val user = userType.value val json = authDataJson.value if (user == null || json == null) { return } if (!isUserLoggedIn(user, json)) { generateAuthDataBasedOnUserType(user) } else if (isEligibleToValidateJson(json)) { validateAuthData() Log.d(TAG, ">>> Authentication data is available!") } } private fun isUserLoggedIn(user: String, json: String) = user.isNotEmpty() && !user.contentEquals(User.UNAVAILABLE.name) && json.isNotEmpty() private fun isEligibleToValidateJson(authDataJson: String?) = !authDataJson.isNullOrEmpty() && !userType.value.isNullOrEmpty() && !userType.value.contentEquals( User.UNAVAILABLE.name ) fun handleAuthValidity(isValid: Boolean, handleTimeoOut: () -> Unit) { if (isGoogleLoginRunning) { return } isTokenValidationCompletedOnce = true if (isValid) { Log.d(TAG, "Authentication data is valid!") generateAuthData() return } Log.d(TAG, ">>> Authentication data validation failed!") destroyCredentials { user -> if (isTimeEligibleForTokenRefresh()) { generateAuthDataBasedOnUserType(user) } else { handleTimeoOut() } } } private fun generateAuthDataBasedOnUserType(user: String) { if (user.isEmpty() || tocStatus.value == false || isGoogleLoginRunning) { return } when (User.valueOf(user)) { User.ANONYMOUS -> { if (authDataJson.value.isNullOrEmpty() && !authRequestRunning) { Log.d(TAG, ">>> Fetching new authentication data") setFirstTokenFetchTime() getAuthData() } } User.UNAVAILABLE -> { destroyCredentials(null) } User.GOOGLE -> { if (authData.value == null && !authRequestRunning) { Log.d(TAG, ">>> Fetching new authentication data") setFirstTokenFetchTime() doFetchAuthData() } } } } private suspend fun doFetchAuthData(email: String, oauthToken: String) { var responseMap: Map<String, String> withContext(Dispatchers.IO) { val response = aC2DMTask.getAC2DMResponse(email, oauthToken) responseMap = response responseMap["Token"]?.let { if (fusedAPIRepository.fetchAuthData(email, it) == null) { dataStoreModule.clearUserType() _errorMessageStringResource.value = R.string.unknown_error } } } } private fun doFetchAuthData() { viewModelScope.launch { isGoogleLoginRunning = true val email = dataStoreModule.getEmail() val oauthToken = dataStoreModule.getAASToken() if (email.isNotEmpty() && oauthToken.isNotEmpty()) { doFetchAuthData(email, oauthToken) } isGoogleLoginRunning = false } } private suspend fun isAuthValid(authData: AuthData): Boolean { return fusedAPIRepository.validateAuthData(authData) Loading Loading @@ -385,7 +491,6 @@ class MainActivityViewModel @Inject constructor( val fusedDownload = fusedManagerRepository.getFusedDownload(packageName = app.package_name) fusedManagerRepository.cancelDownload(fusedDownload) InstallWorkManager.cancelWork(app.name) } } Loading Loading
.gitlab-ci.yml +5 −1 Original line number Diff line number Diff line Loading @@ -43,13 +43,15 @@ ktlintDebug: # Release build related jobs # Default configuration for release builds # Only on "master" and "merge_request_event" # Only on "master", "merge_request_event" and protected branches buildRelease: stage: release allow_failure: false rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' when: always - if: '$CI_COMMIT_REF_PROTECTED == "true"' when: always - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: always script: Loading @@ -69,6 +71,8 @@ buildRelease: rules: - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: always - if: '$CI_COMMIT_REF_PROTECTED == "true"' when: always buildReleaseDev: extends: .releaseSigned Loading
app/build.gradle +7 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ plugins { } def versionMajor = 2 def versionMinor = 2 def versionMinor = 3 def versionPatch = 0 android { Loading Loading @@ -66,6 +66,12 @@ android { signingConfig signingConfigs.releaseStableConfig proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } applicationVariants.all { variant -> variant.outputs.all { output -> outputFileName = "AppLounge-${variant.versionName}-${variant.buildType.name}.apk" } } } buildFeatures { viewBinding true Loading
app/src/main/java/foundation/e/apps/AppProgressViewModel.kt +16 −4 Original line number Diff line number Diff line Loading @@ -19,15 +19,19 @@ class AppProgressViewModel @Inject constructor( suspend fun calculateProgress( fusedApp: FusedApp?, progress: DownloadProgress ): Pair<Long, Long> { ): Int { fusedApp?.let { app -> val appDownload = fusedManagerRepository.getDownloadList() .singleOrNull { it.id.contentEquals(app._id) && it.packageName.contentEquals(app.package_name) } ?: return Pair(1, 0) ?: return 0 if (!appDownload.id.contentEquals(app._id) || !appDownload.packageName.contentEquals(app.package_name)) { return@let } if (!isProgressValidForApp(fusedApp, progress)) { return -1 } val downloadingMap = progress.totalSizeBytes.filter { item -> appDownload.downloadIdMap.keys.contains(item.key) } Loading @@ -36,8 +40,16 @@ class AppProgressViewModel @Inject constructor( appDownload.downloadIdMap.keys.contains(item.key) }.values.sum() return Pair(totalSizeBytes, downloadedSoFar) return ((downloadedSoFar / totalSizeBytes.toDouble()) * 100).toInt() } return Pair(1, 0) return 0 } private suspend fun isProgressValidForApp( fusedApp: FusedApp, downloadProgress: DownloadProgress ): Boolean { val download = fusedManagerRepository.getFusedDownload(downloadProgress.downloadId) return download.id == fusedApp._id } }
app/src/main/java/foundation/e/apps/MainActivity.kt +15 −48 Original line number Diff line number Diff line Loading @@ -44,9 +44,8 @@ import foundation.e.apps.purchase.AppPurchaseFragmentDirections import foundation.e.apps.setup.signin.SignInViewModel import foundation.e.apps.updates.UpdatesNotifier import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import foundation.e.apps.utils.parentFragment.TimeoutFragment import foundation.e.apps.utils.modules.CommonUtilsModule import foundation.e.apps.utils.parentFragment.TimeoutFragment import kotlinx.coroutines.launch import timber.log.Timber import java.io.File Loading @@ -54,6 +53,7 @@ import java.util.UUID @AndroidEntryPoint class MainActivity : AppCompatActivity() { private lateinit var signInViewModel: SignInViewModel private lateinit var binding: ActivityMainBinding private val TAG = MainActivity::class.java.simpleName private lateinit var viewModel: MainActivityViewModel Loading @@ -72,7 +72,7 @@ class MainActivity : AppCompatActivity() { var hasInternet = true viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java] val signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java] signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java] // navOptions and activityNavController for TOS and SignIn Fragments val navOptions = NavOptions.Builder() Loading @@ -86,30 +86,6 @@ class MainActivity : AppCompatActivity() { } } fun generateAuthDataBasedOnUserType(user: String) { if (user.isNotBlank() && viewModel.tocStatus.value == true) { when (User.valueOf(user)) { User.ANONYMOUS -> { if (viewModel.authDataJson.value.isNullOrEmpty() && !viewModel.authRequestRunning) { Timber.d( "Fetching new authentication data") viewModel.setFirstTokenFetchTime() viewModel.getAuthData() } } User.UNAVAILABLE -> { viewModel.destroyCredentials(null) } User.GOOGLE -> { if (viewModel.authData.value == null && !viewModel.authRequestRunning) { Timber.d( "Fetching new authentication data") viewModel.setFirstTokenFetchTime() signInViewModel.fetchAuthData() } } } } } viewModel.internetConnection.observe(this) { isInternetAvailable -> hasInternet = isInternetAvailable if (isInternetAvailable) { Loading @@ -117,7 +93,7 @@ class MainActivity : AppCompatActivity() { binding.fragment.visibility = View.VISIBLE viewModel.userType.observe(this) { user -> generateAuthDataBasedOnUserType(user) viewModel.handleAuthDataJson() } signInViewModel.authLiveData.observe(this) { Loading @@ -126,34 +102,25 @@ class MainActivity : AppCompatActivity() { // Watch and refresh authentication data viewModel.authDataJson.observe(this) { if (!it.isNullOrEmpty()) { viewModel.generateAuthData() Timber.d( "Authentication data is available!") } viewModel.handleAuthDataJson() } } } viewModel.authValidity.observe(this) { if (it != true) { Timber.d( "Authentication data validation failed!") viewModel.destroyCredentials { user -> if (viewModel.isTimeEligibleForTokenRefresh()) { generateAuthDataBasedOnUserType(user) } else { Timber.d( "Timeout validating auth data!") viewModel.handleAuthValidity(it) { Log.d(TAG, "Timeout validating auth data!") val lastFragment = navHostFragment.childFragmentManager.fragments[0] if (lastFragment is TimeoutFragment) { Timber.d( "Displaying timeout from MainActivity on fragment: " + lastFragment::class.java.name) Log.d( TAG, "Displaying timeout from MainActivity on fragment: " + lastFragment::class.java.name ) lastFragment.onTimeout() } } } } else { Timber.d( "Authentication data is valid!") } } navController.addOnDestinationChangedListener { _, destination, _ -> if (!hasInternet) { Loading
app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +114 −9 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package foundation.e.apps import android.app.Activity import android.content.Context import android.graphics.Bitmap import android.os.Build Loading @@ -41,13 +40,12 @@ import com.google.gson.Gson import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.api.cleanapk.blockedApps.BlockedAppRepository import foundation.e.apps.api.ecloud.EcloudRepository import foundation.e.apps.api.fused.FusedAPIImpl import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.gplay.utils.AC2DMTask import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.manager.workmanager.InstallWorkManager import foundation.e.apps.utils.enums.Origin import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Type Loading @@ -56,6 +54,7 @@ import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.DataStoreModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import ru.beryukhov.reactivenetwork.ReactiveNetwork import timber.log.Timber import java.io.ByteArrayOutputStream Loading @@ -70,6 +69,7 @@ class MainActivityViewModel @Inject constructor( private val pkgManagerModule: PkgManagerModule, private val ecloudRepository: EcloudRepository, private val blockedAppRepository: BlockedAppRepository, private val aC2DMTask: AC2DMTask, ) : ViewModel() { val authDataJson: LiveData<String> = dataStoreModule.authData.asLiveData() Loading @@ -93,6 +93,8 @@ class MainActivityViewModel @Inject constructor( */ var firstAuthDataFetchTime = 0L var isTokenValidationCompletedOnce = false // Downloads val downloadList = fusedManagerRepository.getDownloadLiveList() var installInProgress = false Loading @@ -107,15 +109,16 @@ class MainActivityViewModel @Inject constructor( companion object { private const val TAG = "MainActivityViewModel" private var isGoogleLoginRunning = false } fun setFirstTokenFetchTime() { private fun setFirstTokenFetchTime() { if (firstAuthDataFetchTime == 0L) { firstAuthDataFetchTime = SystemClock.uptimeMillis() } } fun isTimeEligibleForTokenRefresh(): Boolean { private fun isTimeEligibleForTokenRefresh(): Boolean { return (SystemClock.uptimeMillis() - firstAuthDataFetchTime) <= timeoutDurationInMillis } Loading Loading @@ -198,13 +201,116 @@ class MainActivityViewModel @Inject constructor( } fun generateAuthData() { val data = gson.fromJson(authDataJson.value, AuthData::class.java) val data = jsonToAuthData() _authData.value = data } private fun jsonToAuthData() = gson.fromJson(authDataJson.value, AuthData::class.java) fun validateAuthData() { viewModelScope.launch { authValidity.postValue(isAuthValid(data)) jsonToAuthData()?.let { val isAuthValid = isAuthValid(it) authValidity.postValue(isAuthValid) authRequestRunning = false } } } fun handleAuthDataJson() { val user = userType.value val json = authDataJson.value if (user == null || json == null) { return } if (!isUserLoggedIn(user, json)) { generateAuthDataBasedOnUserType(user) } else if (isEligibleToValidateJson(json)) { validateAuthData() Log.d(TAG, ">>> Authentication data is available!") } } private fun isUserLoggedIn(user: String, json: String) = user.isNotEmpty() && !user.contentEquals(User.UNAVAILABLE.name) && json.isNotEmpty() private fun isEligibleToValidateJson(authDataJson: String?) = !authDataJson.isNullOrEmpty() && !userType.value.isNullOrEmpty() && !userType.value.contentEquals( User.UNAVAILABLE.name ) fun handleAuthValidity(isValid: Boolean, handleTimeoOut: () -> Unit) { if (isGoogleLoginRunning) { return } isTokenValidationCompletedOnce = true if (isValid) { Log.d(TAG, "Authentication data is valid!") generateAuthData() return } Log.d(TAG, ">>> Authentication data validation failed!") destroyCredentials { user -> if (isTimeEligibleForTokenRefresh()) { generateAuthDataBasedOnUserType(user) } else { handleTimeoOut() } } } private fun generateAuthDataBasedOnUserType(user: String) { if (user.isEmpty() || tocStatus.value == false || isGoogleLoginRunning) { return } when (User.valueOf(user)) { User.ANONYMOUS -> { if (authDataJson.value.isNullOrEmpty() && !authRequestRunning) { Log.d(TAG, ">>> Fetching new authentication data") setFirstTokenFetchTime() getAuthData() } } User.UNAVAILABLE -> { destroyCredentials(null) } User.GOOGLE -> { if (authData.value == null && !authRequestRunning) { Log.d(TAG, ">>> Fetching new authentication data") setFirstTokenFetchTime() doFetchAuthData() } } } } private suspend fun doFetchAuthData(email: String, oauthToken: String) { var responseMap: Map<String, String> withContext(Dispatchers.IO) { val response = aC2DMTask.getAC2DMResponse(email, oauthToken) responseMap = response responseMap["Token"]?.let { if (fusedAPIRepository.fetchAuthData(email, it) == null) { dataStoreModule.clearUserType() _errorMessageStringResource.value = R.string.unknown_error } } } } private fun doFetchAuthData() { viewModelScope.launch { isGoogleLoginRunning = true val email = dataStoreModule.getEmail() val oauthToken = dataStoreModule.getAASToken() if (email.isNotEmpty() && oauthToken.isNotEmpty()) { doFetchAuthData(email, oauthToken) } isGoogleLoginRunning = false } } private suspend fun isAuthValid(authData: AuthData): Boolean { return fusedAPIRepository.validateAuthData(authData) Loading Loading @@ -385,7 +491,6 @@ class MainActivityViewModel @Inject constructor( val fusedDownload = fusedManagerRepository.getFusedDownload(packageName = app.package_name) fusedManagerRepository.cancelDownload(fusedDownload) InstallWorkManager.cancelWork(app.name) } } Loading