Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfffabc1 authored by Hasib Prince's avatar Hasib Prince
Browse files

paritally done

parent c820e9c7
Loading
Loading
Loading
Loading
+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
+9 −13
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
@@ -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
) {

@@ -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
    }

+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
+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
+5 −0
Original line number Diff line number Diff line
@@ -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
@@ -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>()
@@ -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())
        }