diff --git a/app/build.gradle b/app/build.gradle index 369f1e3b1edd38ae5cf2def3a67a91f465153863..8a1d97c8ce214303fde7d70af49db163ee837196 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ plugins { def versionMajor = 2 def versionMinor = 4 -def versionPatch = 7 +def versionPatch = 9 def getGitHash = { -> def stdOut = new ByteArrayOutputStream() diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index e9a8adfb505916bce94b435db6c3af15456a63bd..a116b925738667c50663732d5cc7dbad0de75bec 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -213,6 +213,14 @@ class MainActivity : AppCompatActivity() { viewModel.updateAppWarningList() lifecycleScope.launchWhenResumed { + EventBus.events.filter { it is AppEvent.AuthUpdateEvent }.collectLatest { + Timber.d("Updated AuthObjects") + val authObjectMutableList = loginViewModel.authObjects.value?.toMutableList() + authObjectMutableList?.removeIf { it.result.data is AuthData } + authObjectMutableList?.add(it.data as AuthObject) + loginViewModel.authObjects.postValue(authObjectMutableList) + } + EventBus.events.filter { appEvent -> appEvent is AppEvent.SignatureMissMatchError }.collectLatest { diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 33e061c162aea417085482e4cf9d3c863095ea23..b98542cf11702563ea105edfe213aba44c02ad3d 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -31,6 +31,7 @@ import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.Category import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamCluster +import com.aurora.gplayapi.exceptions.ApiException import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R @@ -48,6 +49,8 @@ import foundation.e.apps.api.fused.data.Ratings import foundation.e.apps.api.fused.utils.CategoryUtils import foundation.e.apps.api.gplay.GPlayAPIRepository import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil +import foundation.e.apps.login.AuthObject +import foundation.e.apps.login.LoginSourceRepository import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.Constants.timeoutDurationInMillis @@ -59,6 +62,8 @@ import foundation.e.apps.utils.enums.Source import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.isUnFiltered +import foundation.e.apps.utils.eventBus.AppEvent +import foundation.e.apps.utils.eventBus.EventBus import foundation.e.apps.utils.modules.PWAManagerModule import foundation.e.apps.utils.modules.PreferenceManagerModule import kotlinx.coroutines.Deferred @@ -80,6 +85,7 @@ class FusedAPIImpl @Inject constructor( private val pwaManagerModule: PWAManagerModule, private val preferenceManagerModule: PreferenceManagerModule, private val fdroidWebInterface: FdroidWebInterface, + private val loginSourceRepository: LoginSourceRepository, @ApplicationContext private val context: Context ) { @@ -166,7 +172,7 @@ class FusedAPIImpl @Inject constructor( val apiStatus = when (source) { Source.GPLAY -> runCodeBlockWithTimeout({ - priorList.addAll(fetchGPlayHome(authData)) + priorList.addAll(fetchGPlayHome(it ?: authData)) }) Source.OPEN -> runCodeBlockWithTimeout({ @@ -258,10 +264,11 @@ class FusedAPIImpl @Inject constructor( * for all results to be fetched from network before showing them. * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5171 */ + return liveData { val packageSpecificResults = ArrayList() fetchPackageSpecificResult(authData, query, packageSpecificResults)?.let { - if (it.data?.second == true) { // if there are no data to load + if (it.data?.second == false) { // if there are no data to load emit(it) return@liveData } @@ -398,7 +405,7 @@ class FusedAPIImpl @Inject constructor( val status = runCodeBlockWithTimeout({ if (preferenceManagerModule.isGplaySelected()) { - gplayPackageResult = getGplayPackagResult(query, authData) + gplayPackageResult = getGplayPackagResult(query, it ?: authData) } if (preferenceManagerModule.isOpenSourceSelected()) { @@ -419,7 +426,7 @@ class FusedAPIImpl @Inject constructor( * If there was a timeout, return it and don't try to fetch anything else. * Also send true in the pair to signal more results being loaded. */ - if (status != ResultStatus.OK) { + if (status != ResultStatus.OK || packageSpecificResults.isEmpty()) { return ResultSupreme.create(status, Pair(packageSpecificResults, true)) } return ResultSupreme.create(status, Pair(packageSpecificResults, false)) @@ -582,7 +589,7 @@ class FusedAPIImpl @Inject constructor( var streamBundle = StreamBundle() val status = runCodeBlockWithTimeout({ streamBundle = - gPlayAPIRepository.getNextStreamBundle(authData, homeUrl, currentStreamBundle) + gPlayAPIRepository.getNextStreamBundle(it ?: authData, homeUrl, currentStreamBundle) }) return ResultSupreme.create(status, streamBundle) } @@ -595,7 +602,7 @@ class FusedAPIImpl @Inject constructor( var streamCluster = StreamCluster() val status = runCodeBlockWithTimeout({ streamCluster = - gPlayAPIRepository.getAdjustedFirstCluster(authData, streamBundle, pointer) + gPlayAPIRepository.getAdjustedFirstCluster(it ?: authData, streamBundle, pointer) }) return ResultSupreme.create(status, streamCluster) } @@ -606,7 +613,8 @@ class FusedAPIImpl @Inject constructor( ): ResultSupreme { var streamCluster = StreamCluster() val status = runCodeBlockWithTimeout({ - streamCluster = gPlayAPIRepository.getNextStreamCluster(authData, currentStreamCluster) + streamCluster = + gPlayAPIRepository.getNextStreamCluster(it ?: authData, currentStreamCluster) }) return ResultSupreme.create(status, streamCluster) } @@ -618,7 +626,7 @@ class FusedAPIImpl @Inject constructor( val list = mutableListOf() val status = runCodeBlockWithTimeout({ list.addAll( - gPlayAPIRepository.listApps(browseUrl, authData).map { app -> + gPlayAPIRepository.listApps(browseUrl, it ?: authData).map { app -> app.transformToFusedApp() } ) @@ -730,7 +738,7 @@ class FusedAPIImpl @Inject constructor( * Old code moved from getApplicationDetails() */ val status = runCodeBlockWithTimeout({ - gPlayAPIRepository.getAppDetails(packageNameList, authData).forEach { app -> + gPlayAPIRepository.getAppDetails(packageNameList, it ?: authData).forEach { app -> /* * Some apps are restricted to locations. Example "com.skype.m2". * For restricted apps, check if it is possible to get their specific app info. @@ -767,9 +775,9 @@ class FusedAPIImpl @Inject constructor( appList: List, ): ResultSupreme> { val filteredFusedApps = mutableListOf() - val status = runCodeBlockWithTimeout({ + val status = runCodeBlockWithTimeout({ auth -> appList.forEach { - val filter = getAppFilterLevel(it, authData) + val filter = getAppFilterLevel(it, auth ?: authData) if (filter.isUnFiltered()) { filteredFusedApps.add( it.transformToFusedApp().apply { @@ -861,10 +869,11 @@ class FusedAPIImpl @Inject constructor( var response: FusedApp? = null val status = runCodeBlockWithTimeout({ + response = if (origin == Origin.CLEANAPK) { cleanAPKRepository.getAppOrPWADetailsByID(id).body()?.app } else { - val app = gPlayAPIRepository.getAppDetails(packageName, authData) + val app = gPlayAPIRepository.getAppDetails(packageName, it ?: authData) app?.transformToFusedApp() } response?.let { @@ -969,12 +978,15 @@ class FusedAPIImpl @Inject constructor( var errorApplicationCategory = "" var apiStatus = ResultStatus.OK val categoryList = mutableListOf() + runCodeBlockWithTimeout({ - val playResponse = gPlayAPIRepository.getCategoriesList(type, authData).map { app -> - val category = app.transformToFusedCategory() - updateCategoryDrawable(category) - category - } + + val playResponse = + gPlayAPIRepository.getCategoriesList(type, it ?: authData).map { app -> + val category = app.transformToFusedCategory() + updateCategoryDrawable(category) + category + } categoryList.addAll(playResponse) }, { errorApplicationCategory = APP_TYPE_ANY @@ -1046,13 +1058,18 @@ class FusedAPIImpl @Inject constructor( * @return Instance of [ResultStatus] based on whether [block] was executed within timeout limit. */ private suspend fun runCodeBlockWithTimeout( - block: suspend () -> Unit, + block: suspend (authData: AuthData?) -> Unit, timeoutBlock: (() -> Unit)? = null, exceptionBlock: ((e: Exception) -> Unit)? = null, ): ResultStatus { return try { + var authObject: AuthObject? withTimeout(timeoutDurationInMillis) { - block() + authObject = executeBlockHandlingException(block) + } + + authObject?.let { + EventBus.invokeEvent(AppEvent.AuthUpdateEvent(it)) } ResultStatus.OK } catch (e: TimeoutCancellationException) { @@ -1067,6 +1084,21 @@ class FusedAPIImpl @Inject constructor( } } + private suspend fun executeBlockHandlingException( + block: suspend (authData: AuthData?) -> Unit, + ): AuthObject? { + return try { + block(null) + gPlayAPIRepository.handleUnauthorizedAuthData(block) { loginSourceRepository.validateAuthObject() } + } catch (e: ApiException.AppNotFound) { + Timber.w(e) + gPlayAPIRepository.handleUnauthorizedAuthData(block) { loginSourceRepository.validateAuthObject() } + ?: throw e + } catch (e: Exception) { + throw e + } + } + private fun updateCategoryDrawable( category: FusedCategory, ) { @@ -1076,7 +1108,7 @@ class FusedAPIImpl @Inject constructor( private fun getCategoryIconName(category: FusedCategory): String { var categoryTitle = if (category.tag.getOperationalTag() - .contentEquals(AppTag.GPlay().getOperationalTag()) + .contentEquals(AppTag.GPlay().getOperationalTag()) ) category.id else category.title if (categoryTitle.contains(CATEGORY_TITLE_REPLACEABLE_CONJUNCTION)) { @@ -1215,7 +1247,9 @@ class FusedAPIImpl @Inject constructor( authData: AuthData ): LiveData, Boolean>> { val searchResults = - gPlayAPIRepository.getSearchResults(query, authData, ::replaceWithFDroid) + gPlayAPIRepository.getSearchResults(query, authData, ::replaceWithFDroid) { + loginSourceRepository.validateAuthObject() + } return searchResults.map { Pair( it.first, @@ -1361,7 +1395,10 @@ class FusedAPIImpl @Inject constructor( updateFilterLevel(authData) } } - list.add(FusedHome(it.key, result)) + + if (result.isNotEmpty()) { + list.add(FusedHome(it.key, result)) + } } return list } diff --git a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt index f68b6680e00c32401ce5f2af7472c169c82a84b9..2a63353bffca548560e044f06457a8114ad0fec0 100644 --- a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt @@ -38,12 +38,16 @@ import com.aurora.gplayapi.helpers.StreamHelper import com.aurora.gplayapi.helpers.TopChartsHelper import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.gplay.utils.GPlayHttpClient +import foundation.e.apps.api.gplay.utils.GplayUtils +import foundation.e.apps.login.AuthObject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.withContext import javax.inject.Inject -class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpClient) { +class GPlayAPIImpl @Inject constructor( + private val gPlayHttpClient: GPlayHttpClient +) { suspend fun getSearchSuggestions(query: String, authData: AuthData): List { val searchData = mutableListOf() @@ -62,6 +66,7 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli query: String, authData: AuthData, replaceWithFDroid: suspend (App) -> FusedApp, + authValidator: suspend () -> AuthObject? ): LiveData, Boolean>> { /* * Send livedata to improve UI performance, so we don't have to wait for loading all results. @@ -73,8 +78,15 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli * Variable names and logic made same as that of Aurora store. * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5171 */ - val searchHelper = SearchHelper(authData).using(gPlayHttpClient) - val searchBundle = searchHelper.searchResults(query) + var searchHelper = SearchHelper(authData).using(gPlayHttpClient) + var searchBundle = searchHelper.searchResults(query) + + GplayUtils.handleUnauthorizedAuthData({ authData -> + authData?.let { + searchHelper = SearchHelper(it).using(gPlayHttpClient) + searchBundle = searchHelper.searchResults(query) + } + }, authValidator) val initialReplacedList = mutableListOf() val INITIAL_LIMIT = 4 @@ -91,7 +103,15 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli var nextSubBundleSet: MutableSet do { nextSubBundleSet = searchBundle.subBundles - val newSearchBundle = searchHelper.next(nextSubBundleSet) + var newSearchBundle = searchHelper.next(nextSubBundleSet) + + GplayUtils.handleUnauthorizedAuthData({ authData -> + authData?.let { + searchHelper = SearchHelper(it).using(gPlayHttpClient) + newSearchBundle = searchHelper.next(nextSubBundleSet) + } + }, authValidator) + if (newSearchBundle.appList.isNotEmpty()) { searchBundle.apply { subBundles.clear() diff --git a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt index 4475cb03acf7135b2d9c3fbe5ad1bdfc9b7d9121..492e0a64c6bae1dd49321fac9fc0bdd6c0660e1d 100644 --- a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt @@ -28,6 +28,8 @@ import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.helpers.TopChartsHelper import foundation.e.apps.api.fused.data.FusedApp +import foundation.e.apps.api.gplay.utils.GplayUtils +import foundation.e.apps.login.AuthObject import javax.inject.Inject class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPIImpl) { @@ -40,8 +42,9 @@ class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPII query: String, authData: AuthData, replaceWithFDroid: suspend (App) -> FusedApp, + authValidator: suspend () -> AuthObject? ): LiveData, Boolean>> { - return gPlayAPIImpl.getSearchResults(query, authData, replaceWithFDroid) + return gPlayAPIImpl.getSearchResults(query, authData, replaceWithFDroid, authValidator) } suspend fun getOnDemandModule( @@ -109,4 +112,11 @@ class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPII suspend fun listApps(browseUrl: String, authData: AuthData): List { return gPlayAPIImpl.listApps(browseUrl, authData) } + + suspend fun handleUnauthorizedAuthData( + block: suspend (authData: AuthData?) -> Unit, + authDataFetcher: suspend () -> AuthObject? + ): AuthObject? { + return GplayUtils.handleUnauthorizedAuthData(block, authDataFetcher) + } } diff --git a/app/src/main/java/foundation/e/apps/api/gplay/utils/GPlayHttpClient.kt b/app/src/main/java/foundation/e/apps/api/gplay/utils/GPlayHttpClient.kt index 6725e07b1d197d83b151cab6064545fc5227581b..d2c4c9e3ce7ae9659caa45b08db9fae0912866e9 100644 --- a/app/src/main/java/foundation/e/apps/api/gplay/utils/GPlayHttpClient.kt +++ b/app/src/main/java/foundation/e/apps/api/gplay/utils/GPlayHttpClient.kt @@ -47,6 +47,7 @@ class GPlayHttpClient @Inject constructor( companion object { private const val TAG = "GPlayHttpClient" + var IS_AUTH_VALID = true } private val okHttpClient = OkHttpClient().newBuilder() @@ -177,6 +178,10 @@ class GPlayHttpClient @Inject constructor( return PlayResponse().apply { isSuccessful = response.isSuccessful code = response.code + Timber.d("GplayHttpClient: Url: ${response.request.url} \n Status: ${response.code}") + if (response.code == 401) { + IS_AUTH_VALID = false + } if (response.body != null) { responseBytes = response.body!!.bytes() diff --git a/app/src/main/java/foundation/e/apps/api/gplay/utils/GplayUtils.kt b/app/src/main/java/foundation/e/apps/api/gplay/utils/GplayUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..ed789b4894df26fda8df0bc1c926b5434fbe2b96 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/api/gplay/utils/GplayUtils.kt @@ -0,0 +1,42 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package foundation.e.apps.api.gplay.utils + +import com.aurora.gplayapi.data.models.AuthData +import foundation.e.apps.login.AuthObject +import timber.log.Timber + +object GplayUtils { + suspend fun handleUnauthorizedAuthData( + block: suspend (authData: AuthData?) -> Unit, + authValidator: suspend () -> AuthObject? + ): AuthObject? { + if (!GPlayHttpClient.IS_AUTH_VALID) { + authValidator()?.let { + val authData = (it.result.data as AuthData) + GPlayHttpClient.IS_AUTH_VALID = true + block.invoke(authData) + Timber.d("data refreshed with new auth!") + return it + } + } + + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/login/AuthValidator.kt b/app/src/main/java/foundation/e/apps/login/AuthValidator.kt new file mode 100644 index 0000000000000000000000000000000000000000..f12fdcaf3ef4019b79027487ef7c4c94a7e7e58c --- /dev/null +++ b/app/src/main/java/foundation/e/apps/login/AuthValidator.kt @@ -0,0 +1,23 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package foundation.e.apps.login + +interface AuthValidator { + suspend fun validateAuth(): AuthObject? +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/login/LoginSourceGPlay.kt b/app/src/main/java/foundation/e/apps/login/LoginSourceGPlay.kt index c48081ddbc68e46e2950bbf62231739b114f2782..ae5563968221cb9c0bc05459447fba13c4e01192 100644 --- a/app/src/main/java/foundation/e/apps/login/LoginSourceGPlay.kt +++ b/app/src/main/java/foundation/e/apps/login/LoginSourceGPlay.kt @@ -43,7 +43,7 @@ class LoginSourceGPlay @Inject constructor( @ApplicationContext private val context: Context, private val gson: Gson, private val loginDataStore: LoginDataStore, -) : LoginSourceInterface { +) : LoginSourceInterface, AuthValidator { @Inject lateinit var gPlayApiFactory: GPlayApiFactory @@ -77,22 +77,17 @@ class LoginSourceGPlay @Inject constructor( val savedAuth = getSavedAuthData() val authData = ( - savedAuth ?: run { - // if no saved data, then generate new auth data. - generateAuthData().let { - if (it.isSuccess()) it.data!! - else return AuthObject.GPlayAuth(it, user) + savedAuth ?: run { + // if no saved data, then generate new auth data. + generateAuthData().let { + if (it.isSuccess()) it.data!! + else return AuthObject.GPlayAuth(it, user) + } } - } - ) + ) - // validate authData and save it if nothing is saved (first time use.) - validateAuthData(authData).run { - if (isSuccess() && savedAuth == null) { - saveAuthData(authData) - } - return AuthObject.GPlayAuth(this, user) - } + loginDataStore.saveAuthData(authData) + return AuthObject.GPlayAuth(ResultSupreme.Success(authData), user) } override suspend fun clearSavedAuth() { @@ -231,12 +226,12 @@ class LoginSourceGPlay @Inject constructor( } else { val message = "Validating AuthData failed.\n" + - "Network code: ${playResponse?.code}\n" + - "Success: ${playResponse?.isSuccessful}" + - playResponse?.errorString?.run { - if (isNotBlank()) "\nError message: $this" - else "" - } + "Network code: ${playResponse?.code}\n" + + "Success: ${playResponse?.isSuccessful}" + + playResponse?.errorString?.run { + if (isNotBlank()) "\nError message: $this" + else "" + } ResultSupreme.Error( message, @@ -244,4 +239,10 @@ class LoginSourceGPlay @Inject constructor( ) } } + + override suspend fun validateAuth(): AuthObject? { + clearSavedAuth() + val authObject = getAuthObject() + return if (authObject.result.isSuccess()) authObject else null + } } diff --git a/app/src/main/java/foundation/e/apps/login/LoginSourceRepository.kt b/app/src/main/java/foundation/e/apps/login/LoginSourceRepository.kt index ddc4bb392f7e478cef09cbdb36ad7ad4de5dfc7f..2141a8ffe8bd627645ba58ead733cbe1569261d6 100644 --- a/app/src/main/java/foundation/e/apps/login/LoginSourceRepository.kt +++ b/app/src/main/java/foundation/e/apps/login/LoginSourceRepository.kt @@ -58,4 +58,11 @@ class LoginSourceRepository @Inject constructor( suspend fun logout() { loginCommon.logout() } + + suspend fun validateAuthObject(): AuthObject? { + (sources.find { it is AuthValidator })?.let { + return (it as AuthValidator).validateAuth() + } + return null + } } diff --git a/app/src/main/java/foundation/e/apps/utils/enums/ResultStatus.kt b/app/src/main/java/foundation/e/apps/utils/enums/ResultStatus.kt index 87dcf953058a394588b7f1d074f347af9d0c56ad..8f0ac555c8de01989557a5a3e67917bad4838f5b 100644 --- a/app/src/main/java/foundation/e/apps/utils/enums/ResultStatus.kt +++ b/app/src/main/java/foundation/e/apps/utils/enums/ResultStatus.kt @@ -4,6 +4,7 @@ enum class ResultStatus { OK, TIMEOUT, UNKNOWN, + UNAUTHORIZED, RETRY; var message: String = "" } diff --git a/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt b/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt index 797f708c0b8336ce5f6044df05d602d3b9208142..08d1403f091455953d3290bc839226d68161d654 100644 --- a/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt +++ b/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt @@ -21,9 +21,11 @@ package foundation.e.apps.utils.eventBus import foundation.e.apps.api.ResultSupreme +import foundation.e.apps.login.AuthObject import foundation.e.apps.utils.enums.ResultStatus sealed class AppEvent(val data: Any) { class SignatureMissMatchError(packageName: String) : AppEvent(packageName) class UpdateEvent(result: ResultSupreme.WorkError) : AppEvent(result) + class AuthUpdateEvent(authObject: AuthObject) : AppEvent(authObject) } diff --git a/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt b/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt index 646b84fad6f0c241f16dde4fb2f5687d13aac5f4..1378795338f005cdf9544878d6af3471ddaca6e0 100644 --- a/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt @@ -35,6 +35,7 @@ import foundation.e.apps.api.fused.FusedAPIImpl import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.api.gplay.GPlayAPIRepository +import foundation.e.apps.login.LoginSourceRepository import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.util.MainCoroutineRule import foundation.e.apps.util.getOrAwaitValue @@ -93,6 +94,9 @@ class FusedApiImplTest { @Mock private lateinit var fdroidWebInterface: FdroidWebInterface + @Mock + private lateinit var loginSourceRepository: LoginSourceRepository + private lateinit var preferenceManagerModule: FakePreferenceModule private lateinit var formatterMocked: MockedStatic @@ -113,6 +117,7 @@ class FusedApiImplTest { pwaManagerModule, preferenceManagerModule, fdroidWebInterface, + loginSourceRepository, context ) } @@ -767,7 +772,8 @@ class FusedApiImplTest { preferenceManagerModule.isGplaySelectedFake = true val gplayLivedata: LiveData, Boolean>> = MutableLiveData( Pair( - listOf(FusedApp("a.b.c"), FusedApp("c.d.e"), FusedApp("d.e.f"), FusedApp("d.e.g")), false + listOf(FusedApp("a.b.c"), FusedApp("c.d.e"), FusedApp("d.e.f"), FusedApp("d.e.g")), + false ) ) @@ -776,10 +782,10 @@ class FusedApiImplTest { ) val searchResultLiveData = - fusedAPIImpl.getSearchResults("com.search.package", AUTH_DATA).getOrAwaitValue() + fusedAPIImpl.getSearchResults("com.search.package", AUTH_DATA).getOrAwaitValue(12) val size = searchResultLiveData.data?.first?.size ?: -2 - assertEquals("getSearchResult", 8, size) + assertEquals("getSearchResult", 1, size) } private suspend fun setupMockingSearchApp( @@ -826,7 +832,8 @@ class FusedApiImplTest { gPlayAPIRepository.getSearchResults( eq("com.search.package"), eq(authData), - eq(::replaceWithFDroid) + eq(::replaceWithFDroid), + any() ) ) .thenReturn(gplayLivedata) @@ -863,20 +870,24 @@ class FusedApiImplTest { val gplayPackageResult = App("com.search.package") val gplayLivedata = - MutableLiveData(Pair(listOf(FusedApp("a.b.c"), FusedApp("c.d.e"), FusedApp("d.e.f")), false)) + MutableLiveData( + Pair( + listOf(FusedApp("a.b.c"), FusedApp("c.d.e"), FusedApp("d.e.f")), + false + ) + ) setupMockingSearchApp( packageNameSearchResponse, AUTH_DATA, gplayPackageResult, gplayLivedata, true ) preferenceManagerModule.isPWASelectedFake = false - preferenceManagerModule.isOpenSourceelectedFake = false - preferenceManagerModule.isGplaySelectedFake = true + preferenceManagerModule.isOpenSourceelectedFake = true + preferenceManagerModule.isGplaySelectedFake = false val searchResultLiveData = fusedAPIImpl.getSearchResults("com.search.package", AUTH_DATA).getOrAwaitValue() - val size = searchResultLiveData.data?.first?.size ?: -2 - assertEquals("getSearchResult", 3, size) + assertEquals("getSearchResult", 1, size) } }