Loading app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt +46 −20 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) { Loading @@ -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 } } app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +22 −13 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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( Loading Loading
app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt +46 −20 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) { Loading @@ -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 } }
app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +22 −13 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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( Loading