From 54e8782915cef141ed5bbb4c0c5993a7f9671a80 Mon Sep 17 00:00:00 2001 From: dev-12 Date: Mon, 27 Oct 2025 13:11:07 +0530 Subject: [PATCH] refactor: use batch request from gplay to reduce token uses --- .../apps/data/application/apps/AppsApiImpl.kt | 6 ++- .../data/playstore/PlayStoreRepository.kt | 19 ++++++---- .../e/apps/data/updates/UpdatesManagerImpl.kt | 38 ++++--------------- .../e/apps/UpdateManagerImptTest.kt | 8 ++++ 4 files changed, 31 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt index d40c13f5f..b2ed05a49 100644 --- a/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt @@ -27,6 +27,7 @@ import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.isUnFiltered import foundation.e.apps.data.handleNetworkResult +import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.ui.applicationlist.ApplicationDiffUtil import javax.inject.Inject @@ -102,8 +103,9 @@ class AppsApiImpl @Inject constructor( ): Pair, ResultStatus> { val applicationList = mutableListOf() - for (packageName in packageNameList) { - val app = stores.getStore(Source.PLAY_STORE)?.getAppDetails(packageName) ?: Application() + val playStore = stores.getStore(Source.PLAY_STORE) as? PlayStoreRepository + val apps = playStore?.getAppsDetails(packageNameList).orEmpty() + for (app in apps) { handleFilteredApps(app, applicationList) } diff --git a/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt b/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt index 132eef9d6..86c46a9ab 100644 --- a/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt @@ -154,30 +154,33 @@ class PlayStoreRepository @Inject constructor( return categoryList } - override suspend fun getAppDetails(packageName: String): Application = + suspend fun getAppsDetails(packages: List): List = withContext(Dispatchers.IO) { - var appDetails: GplayApp - appDetails = getAppDetailsHelper().getAppByPackageName(packageName) + var apps = getAppDetailsHelper().getAppByPackageName(packages) - if (!isEmulator() && appDetails.versionCode == 0L + if (!isEmulator() && apps.any { it.versionCode == 0L } && authenticatorRepository.getGPlayAuthOrThrow().isAnonymous) { // Google Play returns limited result ( i.e. version code being 0) with a stale token, // so we need to refresh authentication to get a new token. - Timber.i("Version code is 0 for ${appDetails.packageName}.") + Timber.i("Version code is 0.") refreshPlayStoreAuthentication() - appDetails = getAppDetailsHelper().getAppByPackageName(packageName) + apps = getAppDetailsHelper().getAppByPackageName(packages) - if (appDetails.versionCode == 0L) { + if (apps.any { it.versionCode == 0L }) { Timber.w("After refreshing auth, version code is still 0. Giving up installation.") throw IllegalStateException("App version code cannot be 0") } } - appDetails.toApplication(context) + apps.map { it.toApplication(context) } } + override suspend fun getAppDetails(packageName: String): Application = + getAppsDetails(buildList { add(packageName) }).firstOrNull() + ?: error("No app details found for package: $packageName") + private fun getAppDetailsHelper(): AppDetailsHelper { val authData = authenticatorRepository.getGPlayAuthOrThrow() val appDetailsHelper = AppDetailsHelper(authData).using(gPlayHttpClient) diff --git a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt index c7efd3944..1966edd13 100644 --- a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt @@ -21,24 +21,21 @@ package foundation.e.apps.data.updates import android.content.Context import android.content.pm.ApplicationInfo import dagger.hilt.android.qualifiers.ApplicationContext +import foundation.e.apps.data.application.ApplicationRepository +import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.blockedApps.BlockedAppRepository import foundation.e.apps.data.cleanapk.ApkSignatureManager import foundation.e.apps.data.enums.ResultStatus +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.isUnFiltered import foundation.e.apps.data.faultyApps.FaultyAppRepository import foundation.e.apps.data.fdroid.FDroidRepository -import foundation.e.apps.data.application.ApplicationRepository -import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.enums.Source import foundation.e.apps.data.gitlab.SystemAppsUpdatesRepository import foundation.e.apps.data.handleNetworkResult import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.install.pkg.AppLoungePackageManager import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject @@ -264,33 +261,14 @@ class UpdatesManagerImpl @Inject constructor( return apiResult.second } - /** - * Bulk info from gplay api [PlayStoreRepositoryImpl.getAppsDetails] is not providing correct - * geo restriction status of apps. So we get all individual app information asynchronously. - * Example: in.startv.hotstar.dplus - * Issue: https://gitlab.e.foundation/e/backlog/-/issues/7135 - */ private suspend fun getGPlayUpdates( packageNames: List, ): Pair, ResultStatus> { - - val appsResults = coroutineScope { - val deferredResults = packageNames.map { packageName -> - async { - applicationRepository.getApplicationDetails( - "", - packageName, - Source.PLAY_STORE - ) - } - } - deferredResults.awaitAll() - } - - val status = appsResults.find { it.second != ResultStatus.OK }?.second ?: ResultStatus.OK - val appsList = appsResults.filter { it.first.package_name.isNotEmpty() }.map { it.first } - - return Pair(appsList, status) + val appsResults = applicationRepository.getApplicationDetails( + packageNames, + Source.PLAY_STORE + ) + return Pair(appsResults.first, appsResults.second) } /** diff --git a/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt b/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt index 003e516c7..3644391fa 100644 --- a/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt +++ b/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt @@ -380,6 +380,14 @@ class UpdateManagerImptTest { ) ).thenReturn(openSourceUpdates) + Mockito.`when`( + applicationRepository.getApplicationDetails( + any(), + eq(Source.PLAY_STORE) + ) + ).thenReturn(gplayUpdates) + + Mockito.`when`(applicationRepository.getSelectedAppTypes()) .thenReturn(selectedApplicationSources) -- GitLab