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

Commit 2bd04e44 authored by Jonathan Klee's avatar Jonathan Klee
Browse files

feat: improve Home loading performances

parent 47712e61
Loading
Loading
Loading
Loading
+46 −20
Original line number Diff line number Diff line
@@ -41,40 +41,54 @@ class HomeApiImpl @Inject constructor(
    }

    override suspend fun fetchHomeScreenData(): LiveData<ResultSupreme<List<Home>>> {
        val list = mutableListOf<Home>()

        return liveData {
            coroutineScope {
                if (Source.PLAY_STORE in stores.getStores()) {
                    val result = async {
                        loadHomeData(list, Source.PLAY_STORE)
            suspend fun emitResult(
                result: ResultSupreme<List<Home>>,
                resultsBySource: Map<Source, ResultSupreme<List<Home>>>
            ) {
                val merged = mergeResults(resultsBySource.values)
                emit(
                    ResultSupreme.create(
                        result.getResultStatus(),
                        merged,
                        result.message,
                        result.exception,
                    )
                )
            }
                    emit(result.await())

            coroutineScope {
                val resultsBySource = mutableMapOf<Source, ResultSupreme<List<Home>>>()
                val sources = stores.getStores().keys
                val deferredResults = sources.associateWith { source ->
                    async { loadHomeData(source) }
                }

                val otherStores = stores.getStores().filter { it.key != Source.PLAY_STORE }
                otherStores.forEach { (source, _) ->
                    val result = async {
                        loadHomeData(list, source)
                val playStoreResult = deferredResults[Source.PLAY_STORE]?.await()
                playStoreResult?.let {
                    resultsBySource[Source.PLAY_STORE] = it
                    emitResult(it, resultsBySource)
                }
                    emit(result.await())

                sources.filter { it != Source.PLAY_STORE }.forEach { source ->
                    val result = deferredResults.getValue(source).await()
                    resultsBySource[source] = result
                    emitResult(result, resultsBySource)
                }
            }
        }
    }

    private suspend fun loadHomeData(
        priorList: MutableList<Home>,
        source: Source
    ): ResultSupreme<List<Home>> {
    private suspend fun loadHomeData(source: Source): ResultSupreme<List<Home>> {
        val list = mutableListOf<Home>()
        val result = handleNetworkResult {
            val homeDataBuilder = stores.getStore(source)
            homeDataBuilder?.getHomeScreenData(priorList)
            homeDataBuilder?.getHomeScreenData(list)
                ?: throw IllegalStateException("Could not find store for $source")
        }

        setHomeErrorMessage(result.getResultStatus(), source)
        priorList.sortBy {
        list.sortBy {
            when (it.source) {
                ApplicationRepository.APP_TYPE_OPEN -> AppSourceWeight.OPEN_SOURCE.ordinal
                ApplicationRepository.APP_TYPE_PWA -> AppSourceWeight.PWA.ordinal
@@ -82,7 +96,7 @@ class HomeApiImpl @Inject constructor(
            }
        }

        return ResultSupreme.create(result.getResultStatus(), priorList)
        return ResultSupreme.create(result.getResultStatus(), list)
    }

    private fun setHomeErrorMessage(apiStatus: ResultStatus, source: Source) {
@@ -95,4 +109,16 @@ class HomeApiImpl @Inject constructor(
            }
        }
    }

    private fun mergeResults(results: Collection<ResultSupreme<List<Home>>>): List<Home> {
        val merged = results.flatMap { it.data.orEmpty() }.toMutableList()
        merged.sortBy {
            when (it.source) {
                ApplicationRepository.APP_TYPE_OPEN -> AppSourceWeight.OPEN_SOURCE.ordinal
                ApplicationRepository.APP_TYPE_PWA -> AppSourceWeight.PWA.ordinal
                else -> AppSourceWeight.GPLAY.ordinal
            }
        }
        return merged
    }
}
+22 −13
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.apps.R
import foundation.e.apps.data.StoreRepository
import foundation.e.apps.data.application.ApplicationDataManager
import foundation.e.apps.data.application.ApplicationRepository
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.application.data.Home
import foundation.e.apps.data.application.search.SearchSuggestion
@@ -51,6 +52,9 @@ import foundation.e.apps.data.playstore.utils.GplayHttpRequestException
import foundation.e.apps.utils.SystemInfoProvider
import kotlinx.coroutines.CancellationException
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 java.net.HttpURLConnection
@@ -66,31 +70,36 @@ class PlayStoreRepository @Inject constructor(
    private val playStoreSearchHelper: PlayStoreSearchHelper
) : StoreRepository {

    override suspend fun getHomeScreenData(list: MutableList<Home>): List<Home> {
        val homeScreenData = mutableMapOf<String, List<Application>>()
    override suspend fun getHomeScreenData(list: MutableList<Home>) = coroutineScope {
        val homeElements = createTopChartElements()

        homeElements.forEach {
            if (it.value.isEmpty()) return@forEach
        val results = homeElements.map { (title, chartMap) ->
            async {
                if (chartMap.isEmpty()) {
                    return@async null
                }
                val chart = chartMap.keys.iterator().next()
                val type = chartMap.values.iterator().next()
                title to getTopApps(type, chart)
            }
        }.awaitAll().filterNotNull()

            val chart = it.value.keys.iterator().next()
            val type = it.value.values.iterator().next()
            val result = getTopApps(type, chart)
            homeScreenData[it.key] = result
        results.forEach { (title, apps) ->
            if (apps.isEmpty()) {
                return@forEach
            }

        homeScreenData.map {
            val fusedApps = it.value.map { app ->
            val fusedApps = apps.map { app ->
                app.apply {
                    applicationDataManager.updateStatus(this)
                    applicationDataManager.updateFilterLevel(this)
                    source = Source.PLAY_STORE
                }
            }
            list.add(Home(it.key, fusedApps))
            list.add(Home(title, fusedApps, ApplicationRepository.APP_TYPE_ANY))
        }

        return list
        list
    }

    private fun createTopChartElements() = mutableMapOf(