Loading app/src/main/java/foundation/e/apps/api/StoreApiRepository.kt 0 → 100644 +6 −0 Original line number Diff line number Diff line package foundation.e.apps.api interface StoreApiRepository { suspend fun getHomeScreenData(): Any fun getSearchResult(query: String): Any } No newline at end of file app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +9 −13 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.api.ResultSupreme import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.cleanapk.CleanAPKInterface import foundation.e.apps.api.cleanapk.CleanAPKRepository import foundation.e.apps.api.cleanapk.data.categories.Categories Loading @@ -48,6 +49,7 @@ 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.GplayRepository import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule Loading @@ -66,6 +68,7 @@ import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.withTimeout import timber.log.Timber import javax.inject.Inject import javax.inject.Named import javax.inject.Singleton @Singleton Loading @@ -76,6 +79,7 @@ class FusedAPIImpl @Inject constructor( private val pwaManagerModule: PWAManagerModule, private val preferenceManagerModule: PreferenceManagerModule, private val fdroidWebInterface: FdroidWebInterface, @Named("gplayRepository") private val gplayRepository: StoreApiRepository, @ApplicationContext private val context: Context ) { Loading Loading @@ -1320,24 +1324,16 @@ class FusedAPIImpl @Inject constructor( private suspend fun fetchGPlayHome(authData: AuthData): List<FusedHome> { val list = mutableListOf<FusedHome>() val homeElements = mutableMapOf( context.getString(R.string.topselling_free_apps) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topselling_free_games) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.GAME), context.getString(R.string.topgrossing_apps) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topgrossing_games) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.GAME), context.getString(R.string.movers_shakers_apps) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.APPLICATION), context.getString(R.string.movers_shakers_games) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.GAME), ) homeElements.forEach { val chart = it.value.keys.iterator().next() val type = it.value.values.iterator().next() val result = gPlayAPIRepository.getTopApps(type, chart, authData).map { app -> val gplayHomeData = gplayRepository.getHomeScreenData() as Map<String, List<App>> gplayHomeData.map { val fusedApps = it.value.map { app -> app.transformToFusedApp().apply { updateFilterLevel(authData) } } list.add(FusedHome(it.key, result)) list.add(FusedHome(it.key, fusedApps)) } Timber.d("===> $list") return list } Loading app/src/main/java/foundation/e/apps/api/gplay/GplayRepository.kt 0 → 100644 +148 −0 Original line number Diff line number Diff line package foundation.e.apps.api.gplay import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.LiveDataScope import androidx.lifecycle.liveData import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.SearchBundle import com.aurora.gplayapi.helpers.SearchHelper import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.api.gplay.utils.GPlayHttpClient import foundation.e.apps.login.LoginSourceRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import javax.inject.Inject class GplayRepository @Inject constructor( @ApplicationContext private val context: Context, private val gPlayHttpClient: GPlayHttpClient, private val loginSourceRepository: LoginSourceRepository ) : StoreApiRepository { override suspend fun getHomeScreenData(): Any { val homeScreenData = mutableMapOf<String, List<App>>() val homeElements = mutableMapOf( context.getString(R.string.topselling_free_apps) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topselling_free_games) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.GAME), context.getString(R.string.topgrossing_apps) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topgrossing_games) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.GAME), context.getString(R.string.movers_shakers_apps) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.APPLICATION), context.getString(R.string.movers_shakers_games) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.GAME), ) homeElements.forEach { val chart = it.value.keys.iterator().next() val type = it.value.values.iterator().next() val result = getTopApps(type, chart, loginSourceRepository.gplayAuth!!) homeScreenData[it.key] = result } return homeScreenData } override fun getSearchResult(query: String): LiveData<Pair<List<App>, Boolean>> { return liveData { withContext(Dispatchers.IO) { /* * Variable names and logic made same as that of Aurora store. * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5171 */ val searchHelper = SearchHelper(loginSourceRepository.gplayAuth!!).using(gPlayHttpClient) val searchBundle = searchHelper.searchResults(query) val initialReplacedList = mutableListOf<App>() val INITIAL_LIMIT = 4 emitReplacedList( this@liveData, initialReplacedList, INITIAL_LIMIT, searchBundle, true, ) var nextSubBundleSet: MutableSet<SearchBundle.SubBundle> do { nextSubBundleSet = searchBundle.subBundles val newSearchBundle = searchHelper.next(nextSubBundleSet) if (newSearchBundle.appList.isNotEmpty()) { searchBundle.apply { subBundles.clear() subBundles.addAll(newSearchBundle.subBundles) emitReplacedList( this@liveData, initialReplacedList, INITIAL_LIMIT, newSearchBundle, nextSubBundleSet.isNotEmpty(), ) } } } while (nextSubBundleSet.isNotEmpty()) /* * If initialReplacedList size is less than INITIAL_LIMIT, * it means the results were very less and nothing has been emitted so far. * Hence emit the list. */ if (initialReplacedList.size < INITIAL_LIMIT) { emit(Pair(initialReplacedList, false)) } } } } private suspend fun emitReplacedList( scope: LiveDataScope<Pair<List<App>, Boolean>>, accumulationList: MutableList<App>, accumulationLimit: Int, searchBundle: SearchBundle, moreToEmit: Boolean, ) { searchBundle.appList.forEach { when { accumulationList.size < accumulationLimit - 1 -> { /* * If initial limit is 4, add apps to list (without emitting) * till 2 apps. */ accumulationList.add(it) } accumulationList.size == accumulationLimit - 1 -> { /* * If initial limit is 4, and we have reached till 3 apps, * add the 4th app and emit the list. */ accumulationList.add(it) scope.emit(Pair(accumulationList, moreToEmit)) } accumulationList.size == accumulationLimit -> { /* * If initial limit is 4, and we have emitted 4 apps, * for all rest of the apps, emit each app one by one. */ scope.emit(Pair(listOf(it), moreToEmit)) } } } } private suspend fun getTopApps( type: TopChartsHelper.Type, chart: TopChartsHelper.Chart, authData: AuthData ): List<App> { val topApps = mutableListOf<App>() withContext(Dispatchers.IO) { val topChartsHelper = TopChartsHelper(authData).using(gPlayHttpClient) topApps.addAll(topChartsHelper.getCluster(type, chart).clusterAppList) } return topApps } } No newline at end of file app/src/main/java/foundation/e/apps/di/NamedRepositoryModule.kt 0 → 100644 +29 −0 Original line number Diff line number Diff line package foundation.e.apps.di import android.content.Context import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.gplay.GplayRepository import foundation.e.apps.api.gplay.utils.GPlayHttpClient import foundation.e.apps.login.LoginSourceRepository import javax.inject.Named import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module object NamedRepositoryModule { @Singleton @Provides @Named("gplayRepository") fun getGplayRepository( @ApplicationContext context: Context, gPlayHttpClient: GPlayHttpClient, loginSourceRepository: LoginSourceRepository ): StoreApiRepository { return GplayRepository(context, gPlayHttpClient, loginSourceRepository) } } No newline at end of file app/src/main/java/foundation/e/apps/login/LoginSourceRepository.kt +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package foundation.e.apps.login import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.utils.enums.User import javax.inject.Inject import javax.inject.Singleton Loading @@ -28,6 +29,7 @@ class LoginSourceRepository @Inject constructor( private val sources: List<LoginSourceInterface>, ) { var gplayAuth: AuthData? = null suspend fun getAuthObjects(clearAuthTypes: List<String> = listOf()): List<AuthObject> { val authObjectsLocal = ArrayList<AuthObject>() Loading @@ -37,6 +39,9 @@ class LoginSourceRepository @Inject constructor( if (source::class.java.simpleName in clearAuthTypes) { source.clearSavedAuth() } if (source is LoginSourceGPlay) { gplayAuth = source.getAuthObject().result.data } authObjectsLocal.add(source.getAuthObject()) } Loading Loading
app/src/main/java/foundation/e/apps/api/StoreApiRepository.kt 0 → 100644 +6 −0 Original line number Diff line number Diff line package foundation.e.apps.api interface StoreApiRepository { suspend fun getHomeScreenData(): Any fun getSearchResult(query: String): Any } No newline at end of file
app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +9 −13 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.api.ResultSupreme import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.cleanapk.CleanAPKInterface import foundation.e.apps.api.cleanapk.CleanAPKRepository import foundation.e.apps.api.cleanapk.data.categories.Categories Loading @@ -48,6 +49,7 @@ 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.GplayRepository import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule Loading @@ -66,6 +68,7 @@ import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.withTimeout import timber.log.Timber import javax.inject.Inject import javax.inject.Named import javax.inject.Singleton @Singleton Loading @@ -76,6 +79,7 @@ class FusedAPIImpl @Inject constructor( private val pwaManagerModule: PWAManagerModule, private val preferenceManagerModule: PreferenceManagerModule, private val fdroidWebInterface: FdroidWebInterface, @Named("gplayRepository") private val gplayRepository: StoreApiRepository, @ApplicationContext private val context: Context ) { Loading Loading @@ -1320,24 +1324,16 @@ class FusedAPIImpl @Inject constructor( private suspend fun fetchGPlayHome(authData: AuthData): List<FusedHome> { val list = mutableListOf<FusedHome>() val homeElements = mutableMapOf( context.getString(R.string.topselling_free_apps) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topselling_free_games) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.GAME), context.getString(R.string.topgrossing_apps) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topgrossing_games) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.GAME), context.getString(R.string.movers_shakers_apps) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.APPLICATION), context.getString(R.string.movers_shakers_games) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.GAME), ) homeElements.forEach { val chart = it.value.keys.iterator().next() val type = it.value.values.iterator().next() val result = gPlayAPIRepository.getTopApps(type, chart, authData).map { app -> val gplayHomeData = gplayRepository.getHomeScreenData() as Map<String, List<App>> gplayHomeData.map { val fusedApps = it.value.map { app -> app.transformToFusedApp().apply { updateFilterLevel(authData) } } list.add(FusedHome(it.key, result)) list.add(FusedHome(it.key, fusedApps)) } Timber.d("===> $list") return list } Loading
app/src/main/java/foundation/e/apps/api/gplay/GplayRepository.kt 0 → 100644 +148 −0 Original line number Diff line number Diff line package foundation.e.apps.api.gplay import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.LiveDataScope import androidx.lifecycle.liveData import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.SearchBundle import com.aurora.gplayapi.helpers.SearchHelper import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.api.gplay.utils.GPlayHttpClient import foundation.e.apps.login.LoginSourceRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import javax.inject.Inject class GplayRepository @Inject constructor( @ApplicationContext private val context: Context, private val gPlayHttpClient: GPlayHttpClient, private val loginSourceRepository: LoginSourceRepository ) : StoreApiRepository { override suspend fun getHomeScreenData(): Any { val homeScreenData = mutableMapOf<String, List<App>>() val homeElements = mutableMapOf( context.getString(R.string.topselling_free_apps) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topselling_free_games) to mapOf(TopChartsHelper.Chart.TOP_SELLING_FREE to TopChartsHelper.Type.GAME), context.getString(R.string.topgrossing_apps) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.APPLICATION), context.getString(R.string.topgrossing_games) to mapOf(TopChartsHelper.Chart.TOP_GROSSING to TopChartsHelper.Type.GAME), context.getString(R.string.movers_shakers_apps) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.APPLICATION), context.getString(R.string.movers_shakers_games) to mapOf(TopChartsHelper.Chart.MOVERS_SHAKERS to TopChartsHelper.Type.GAME), ) homeElements.forEach { val chart = it.value.keys.iterator().next() val type = it.value.values.iterator().next() val result = getTopApps(type, chart, loginSourceRepository.gplayAuth!!) homeScreenData[it.key] = result } return homeScreenData } override fun getSearchResult(query: String): LiveData<Pair<List<App>, Boolean>> { return liveData { withContext(Dispatchers.IO) { /* * Variable names and logic made same as that of Aurora store. * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5171 */ val searchHelper = SearchHelper(loginSourceRepository.gplayAuth!!).using(gPlayHttpClient) val searchBundle = searchHelper.searchResults(query) val initialReplacedList = mutableListOf<App>() val INITIAL_LIMIT = 4 emitReplacedList( this@liveData, initialReplacedList, INITIAL_LIMIT, searchBundle, true, ) var nextSubBundleSet: MutableSet<SearchBundle.SubBundle> do { nextSubBundleSet = searchBundle.subBundles val newSearchBundle = searchHelper.next(nextSubBundleSet) if (newSearchBundle.appList.isNotEmpty()) { searchBundle.apply { subBundles.clear() subBundles.addAll(newSearchBundle.subBundles) emitReplacedList( this@liveData, initialReplacedList, INITIAL_LIMIT, newSearchBundle, nextSubBundleSet.isNotEmpty(), ) } } } while (nextSubBundleSet.isNotEmpty()) /* * If initialReplacedList size is less than INITIAL_LIMIT, * it means the results were very less and nothing has been emitted so far. * Hence emit the list. */ if (initialReplacedList.size < INITIAL_LIMIT) { emit(Pair(initialReplacedList, false)) } } } } private suspend fun emitReplacedList( scope: LiveDataScope<Pair<List<App>, Boolean>>, accumulationList: MutableList<App>, accumulationLimit: Int, searchBundle: SearchBundle, moreToEmit: Boolean, ) { searchBundle.appList.forEach { when { accumulationList.size < accumulationLimit - 1 -> { /* * If initial limit is 4, add apps to list (without emitting) * till 2 apps. */ accumulationList.add(it) } accumulationList.size == accumulationLimit - 1 -> { /* * If initial limit is 4, and we have reached till 3 apps, * add the 4th app and emit the list. */ accumulationList.add(it) scope.emit(Pair(accumulationList, moreToEmit)) } accumulationList.size == accumulationLimit -> { /* * If initial limit is 4, and we have emitted 4 apps, * for all rest of the apps, emit each app one by one. */ scope.emit(Pair(listOf(it), moreToEmit)) } } } } private suspend fun getTopApps( type: TopChartsHelper.Type, chart: TopChartsHelper.Chart, authData: AuthData ): List<App> { val topApps = mutableListOf<App>() withContext(Dispatchers.IO) { val topChartsHelper = TopChartsHelper(authData).using(gPlayHttpClient) topApps.addAll(topChartsHelper.getCluster(type, chart).clusterAppList) } return topApps } } No newline at end of file
app/src/main/java/foundation/e/apps/di/NamedRepositoryModule.kt 0 → 100644 +29 −0 Original line number Diff line number Diff line package foundation.e.apps.di import android.content.Context import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.gplay.GplayRepository import foundation.e.apps.api.gplay.utils.GPlayHttpClient import foundation.e.apps.login.LoginSourceRepository import javax.inject.Named import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module object NamedRepositoryModule { @Singleton @Provides @Named("gplayRepository") fun getGplayRepository( @ApplicationContext context: Context, gPlayHttpClient: GPlayHttpClient, loginSourceRepository: LoginSourceRepository ): StoreApiRepository { return GplayRepository(context, gPlayHttpClient, loginSourceRepository) } } No newline at end of file
app/src/main/java/foundation/e/apps/login/LoginSourceRepository.kt +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package foundation.e.apps.login import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.utils.enums.User import javax.inject.Inject import javax.inject.Singleton Loading @@ -28,6 +29,7 @@ class LoginSourceRepository @Inject constructor( private val sources: List<LoginSourceInterface>, ) { var gplayAuth: AuthData? = null suspend fun getAuthObjects(clearAuthTypes: List<String> = listOf()): List<AuthObject> { val authObjectsLocal = ArrayList<AuthObject>() Loading @@ -37,6 +39,9 @@ class LoginSourceRepository @Inject constructor( if (source::class.java.simpleName in clearAuthTypes) { source.clearSavedAuth() } if (source is LoginSourceGPlay) { gplayAuth = source.getAuthObject().result.data } authObjectsLocal.add(source.getAuthObject()) } Loading