Loading app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +11 −24 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import foundation.e.apps.api.fused.data.FusedHome 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.api.gplay.utils.GPlayHttpClient import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil import foundation.e.apps.login.AuthObject import foundation.e.apps.login.LoginSourceRepository Loading Loading @@ -884,7 +883,7 @@ class FusedAPIImpl @Inject constructor( it.updateFilterLevel(authData) } }) Timber.d("getAppDetails: $status") return Pair(response ?: FusedApp(), status) } Loading Loading @@ -1085,34 +1084,20 @@ class FusedAPIImpl @Inject constructor( } } private suspend fun FusedAPIImpl.executeBlockHandlingException( private suspend fun executeBlockHandlingException( block: suspend (authData: AuthData?) -> Unit, ): AuthObject? { return try { block(null) handleUnauthorizedAuthData(block) gPlayAPIRepository.handleUnauthorizedAuthData(block) { loginSourceRepository.validateAuthObject() } } catch (e: ApiException.AppNotFound) { Timber.w(e) handleUnauthorizedAuthData(block) ?: throw e } } private suspend fun handleUnauthorizedAuthData( block: suspend (authData: AuthData?) -> Unit ): AuthObject? { if (!GPlayHttpClient.IS_AUTH_VALID) { val loginSources = loginSourceRepository.getAuthObjects() loginSources.find { it is AuthObject.GPlayAuth }?.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 gPlayAPIRepository.handleUnauthorizedAuthData(block) { loginSourceRepository.validateAuthObject() } ?: throw e } catch (e: Exception) { throw e } } return null } private fun updateCategoryDrawable( category: FusedCategory, Loading Loading @@ -1262,7 +1247,9 @@ class FusedAPIImpl @Inject constructor( authData: AuthData ): LiveData<Pair<List<FusedApp>, Boolean>> { val searchResults = gPlayAPIRepository.getSearchResults(query, authData, ::replaceWithFDroid) gPlayAPIRepository.getSearchResults(query, authData, ::replaceWithFDroid) { loginSourceRepository.validateAuthObject() } return searchResults.map { Pair( it.first, Loading app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt +24 −4 Original line number Diff line number Diff line Loading @@ -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<SearchSuggestEntry> { val searchData = mutableListOf<SearchSuggestEntry>() Loading @@ -62,6 +66,7 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli query: String, authData: AuthData, replaceWithFDroid: suspend (App) -> FusedApp, authValidator: suspend () -> AuthObject? ): LiveData<Pair<List<FusedApp>, Boolean>> { /* * Send livedata to improve UI performance, so we don't have to wait for loading all results. Loading @@ -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<FusedApp>() val INITIAL_LIMIT = 4 Loading @@ -91,7 +103,15 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli var nextSubBundleSet: MutableSet<SearchBundle.SubBundle> 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() Loading app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt +11 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -40,8 +42,9 @@ class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPII query: String, authData: AuthData, replaceWithFDroid: suspend (App) -> FusedApp, authValidator: suspend () -> AuthObject? ): LiveData<Pair<List<FusedApp>, Boolean>> { return gPlayAPIImpl.getSearchResults(query, authData, replaceWithFDroid) return gPlayAPIImpl.getSearchResults(query, authData, replaceWithFDroid, authValidator) } suspend fun getOnDemandModule( Loading Loading @@ -109,4 +112,11 @@ class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPII suspend fun listApps(browseUrl: String, authData: AuthData): List<App> { return gPlayAPIImpl.listApps(browseUrl, authData) } suspend fun handleUnauthorizedAuthData( block: suspend (authData: AuthData?) -> Unit, authDataFetcher: suspend () -> AuthObject? ): AuthObject? { return GplayUtils.handleUnauthorizedAuthData(block, authDataFetcher) } } app/src/main/java/foundation/e/apps/api/gplay/utils/GplayUtils.kt 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * 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 <https://www.gnu.org/licenses/>. */ 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 app/src/main/java/foundation/e/apps/login/AuthValidator.kt 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * 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 <https://www.gnu.org/licenses/>. */ package foundation.e.apps.login interface AuthValidator { suspend fun validateAuth(): AuthObject? } No newline at end of file Loading
app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +11 −24 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import foundation.e.apps.api.fused.data.FusedHome 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.api.gplay.utils.GPlayHttpClient import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil import foundation.e.apps.login.AuthObject import foundation.e.apps.login.LoginSourceRepository Loading Loading @@ -884,7 +883,7 @@ class FusedAPIImpl @Inject constructor( it.updateFilterLevel(authData) } }) Timber.d("getAppDetails: $status") return Pair(response ?: FusedApp(), status) } Loading Loading @@ -1085,34 +1084,20 @@ class FusedAPIImpl @Inject constructor( } } private suspend fun FusedAPIImpl.executeBlockHandlingException( private suspend fun executeBlockHandlingException( block: suspend (authData: AuthData?) -> Unit, ): AuthObject? { return try { block(null) handleUnauthorizedAuthData(block) gPlayAPIRepository.handleUnauthorizedAuthData(block) { loginSourceRepository.validateAuthObject() } } catch (e: ApiException.AppNotFound) { Timber.w(e) handleUnauthorizedAuthData(block) ?: throw e } } private suspend fun handleUnauthorizedAuthData( block: suspend (authData: AuthData?) -> Unit ): AuthObject? { if (!GPlayHttpClient.IS_AUTH_VALID) { val loginSources = loginSourceRepository.getAuthObjects() loginSources.find { it is AuthObject.GPlayAuth }?.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 gPlayAPIRepository.handleUnauthorizedAuthData(block) { loginSourceRepository.validateAuthObject() } ?: throw e } catch (e: Exception) { throw e } } return null } private fun updateCategoryDrawable( category: FusedCategory, Loading Loading @@ -1262,7 +1247,9 @@ class FusedAPIImpl @Inject constructor( authData: AuthData ): LiveData<Pair<List<FusedApp>, Boolean>> { val searchResults = gPlayAPIRepository.getSearchResults(query, authData, ::replaceWithFDroid) gPlayAPIRepository.getSearchResults(query, authData, ::replaceWithFDroid) { loginSourceRepository.validateAuthObject() } return searchResults.map { Pair( it.first, Loading
app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt +24 −4 Original line number Diff line number Diff line Loading @@ -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<SearchSuggestEntry> { val searchData = mutableListOf<SearchSuggestEntry>() Loading @@ -62,6 +66,7 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli query: String, authData: AuthData, replaceWithFDroid: suspend (App) -> FusedApp, authValidator: suspend () -> AuthObject? ): LiveData<Pair<List<FusedApp>, Boolean>> { /* * Send livedata to improve UI performance, so we don't have to wait for loading all results. Loading @@ -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<FusedApp>() val INITIAL_LIMIT = 4 Loading @@ -91,7 +103,15 @@ class GPlayAPIImpl @Inject constructor(private val gPlayHttpClient: GPlayHttpCli var nextSubBundleSet: MutableSet<SearchBundle.SubBundle> 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() Loading
app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt +11 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -40,8 +42,9 @@ class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPII query: String, authData: AuthData, replaceWithFDroid: suspend (App) -> FusedApp, authValidator: suspend () -> AuthObject? ): LiveData<Pair<List<FusedApp>, Boolean>> { return gPlayAPIImpl.getSearchResults(query, authData, replaceWithFDroid) return gPlayAPIImpl.getSearchResults(query, authData, replaceWithFDroid, authValidator) } suspend fun getOnDemandModule( Loading Loading @@ -109,4 +112,11 @@ class GPlayAPIRepository @Inject constructor(private val gPlayAPIImpl: GPlayAPII suspend fun listApps(browseUrl: String, authData: AuthData): List<App> { return gPlayAPIImpl.listApps(browseUrl, authData) } suspend fun handleUnauthorizedAuthData( block: suspend (authData: AuthData?) -> Unit, authDataFetcher: suspend () -> AuthObject? ): AuthObject? { return GplayUtils.handleUnauthorizedAuthData(block, authDataFetcher) } }
app/src/main/java/foundation/e/apps/api/gplay/utils/GplayUtils.kt 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * 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 <https://www.gnu.org/licenses/>. */ 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
app/src/main/java/foundation/e/apps/login/AuthValidator.kt 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * 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 <https://www.gnu.org/licenses/>. */ package foundation.e.apps.login interface AuthValidator { suspend fun validateAuth(): AuthObject? } No newline at end of file