Loading app/src/main/java/foundation/e/apps/api/StoreApiRepository.kt +2 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,5 @@ package foundation.e.apps.api interface StoreApiRepository { suspend fun getHomeScreenData(): Any suspend fun getSearchResult(query: String): Any suspend fun getSearchSuggestions(query: String): Any } app/src/main/java/foundation/e/apps/api/cleanapk/CleanApkAppsRepository.kt +8 −3 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package foundation.e.apps.api.cleanapk import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.cleanapk.data.home.HomeScreen import foundation.e.apps.api.cleanapk.data.search.Search import retrofit2.Response class CleanApkAppsRepository( Loading @@ -15,14 +16,18 @@ class CleanApkAppsRepository( ) } override suspend fun getSearchResult(query: String): Any { override suspend fun getSearchResult(query: String): Response<Search> { return cleanAPKInterface.searchApps( query, CleanAPKInterface.APP_TYPE_ANY, CleanAPKInterface.APP_SOURCE_FOSS, CleanAPKInterface.APP_TYPE_ANY, 20, 1, null ) } override suspend fun getSearchSuggestions(query: String): Any { TODO("Not yet implemented") } } app/src/main/java/foundation/e/apps/api/cleanapk/CleanApkPWARepository.kt +15 −2 Original line number Diff line number Diff line package foundation.e.apps.api.cleanapk import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.cleanapk.data.search.Search import retrofit2.Response class CleanApkPWARepository( private val cleanAPKInterface: CleanAPKInterface, Loading @@ -13,7 +15,18 @@ class CleanApkPWARepository( ) } override suspend fun getSearchResult(query: String): Any { override suspend fun getSearchResult(query: String): Response<Search> { return cleanAPKInterface.searchApps( query, CleanAPKInterface.APP_SOURCE_ANY, CleanAPKInterface.APP_TYPE_PWA, 20, 1, null ) } override suspend fun getSearchSuggestions(query: String): Any { TODO("Not yet implemented") } } app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +17 −19 Original line number Diff line number Diff line Loading @@ -20,7 +20,11 @@ package foundation.e.apps.api.fused import android.content.Context import android.text.format.Formatter import androidx.lifecycle.* import androidx.lifecycle.LiveData import androidx.lifecycle.LiveDataScope import androidx.lifecycle.asLiveData import androidx.lifecycle.liveData import androidx.lifecycle.map import com.aurora.gplayapi.Constants import com.aurora.gplayapi.SearchSuggestEntry import com.aurora.gplayapi.data.models.App Loading @@ -29,7 +33,6 @@ import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.Category import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.api.ResultSupreme Loading @@ -47,7 +50,6 @@ 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 @@ -63,9 +65,8 @@ import foundation.e.apps.utils.enums.isUnFiltered import foundation.e.apps.utils.modules.PWAManagerModule import foundation.e.apps.utils.modules.PreferenceManagerModule import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.withTimeout import retrofit2.Response import timber.log.Timber Loading Loading @@ -274,7 +275,7 @@ class FusedAPIImpl @Inject constructor( authData, searchResult, packageSpecificResults ) ).asLiveData() ) } } Loading @@ -288,11 +289,8 @@ class FusedAPIImpl @Inject constructor( ): ResultSupreme<Pair<List<FusedApp>, Boolean>> { val pwaApps: MutableList<FusedApp> = mutableListOf() val status = fusedAPIImpl.runCodeBlockWithTimeout({ getCleanAPKSearchResults( query, CleanAPKInterface.APP_SOURCE_ANY, CleanAPKInterface.APP_TYPE_PWA ).apply { val apps = (cleanApkPWARepository.getSearchResult(query,) as Response<Search>).body()?.apps apps?.apply { if (this.isNotEmpty()) { pwaApps.addAll(this) } Loading Loading @@ -321,7 +319,7 @@ class FusedAPIImpl @Inject constructor( authData: AuthData, searchResult: MutableList<FusedApp>, packageSpecificResults: ArrayList<FusedApp> ): LiveData<ResultSupreme<Pair<List<FusedApp>, Boolean>>> = ): Flow<ResultSupreme<Pair<List<FusedApp>, Boolean>>> = getGplaySearchResult(query, authData).map { if (it.first.isNotEmpty()) { searchResult.addAll(it.first) Loading Loading @@ -471,7 +469,7 @@ class FusedAPIImpl @Inject constructor( } suspend fun getSearchSuggestions(query: String, authData: AuthData): List<SearchSuggestEntry> { return gPlayAPIRepository.getSearchSuggestions(query, authData) return gplayRepository.getSearchSuggestions(query) as List<SearchSuggestEntry> } suspend fun getOnDemandModule( Loading Loading @@ -1175,8 +1173,8 @@ class FusedAPIImpl @Inject constructor( by: String? = null ): List<FusedApp> { val list = mutableListOf<FusedApp>() val response = cleanAPKRepository.searchApps(keyword, source, type, nres, page, by).body()?.apps val response = (cleanApkAppsRepository.getSearchResult(keyword) as Response<Search>).body()?.apps // val response = cleanAPKRepository.searchApps(keyword, source, type, nres,page, by).body()?.apps response?.forEach { it.updateStatus() Loading Loading @@ -1204,15 +1202,15 @@ class FusedAPIImpl @Inject constructor( private suspend fun getGplaySearchResult( query: String, authData: AuthData ): LiveData<Pair<List<FusedApp>, Boolean>> { val searchResults = gplayRepository.getSearchResult(query) as LiveData<Pair<List<App>, Boolean>> return searchResults.asFlow().map { ): Flow<Pair<List<FusedApp>, Boolean>> { val searchResults = gplayRepository.getSearchResult(query) as Flow<Pair<List<App>, Boolean>> return searchResults.map { val fusedAppList = it.first.map { app -> replaceWithFDroid(app) } Pair( fusedAppList, it.second ) }.asLiveData() } } /* * This function will replace a GPlay app with F-Droid app if exists, Loading app/src/main/java/foundation/e/apps/api/gplay/GplayRepository.kt +59 −42 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.SearchSuggestEntry import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.SearchBundle Loading @@ -12,11 +10,13 @@ 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.flow.Flow import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.withContext import javax.inject.Inject Loading Loading @@ -46,21 +46,21 @@ class GplayRepository @Inject constructor( return homeScreenData } override suspend fun getSearchResult(query: String): LiveData<Pair<List<App>, Boolean>> { return liveData { withContext(Dispatchers.IO) { override suspend fun getSearchResult(query: String): Flow<Pair<List<App>, Boolean>> { return flow { /* * 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 searchHelper = SearchHelper(loginSourceRepository.gplayAuth!!).using(gPlayHttpClient) val searchBundle = searchHelper.searchResults(query) val initialReplacedList = mutableListOf<App>() val INITIAL_LIMIT = 4 emitReplacedList( this@liveData, this@flow, initialReplacedList, INITIAL_LIMIT, searchBundle, Loading @@ -76,7 +76,7 @@ class GplayRepository @Inject constructor( subBundles.clear() subBundles.addAll(newSearchBundle.subBundles) emitReplacedList( this@liveData, this@flow, initialReplacedList, INITIAL_LIMIT, newSearchBundle, Loading @@ -92,14 +92,22 @@ class GplayRepository @Inject constructor( * Hence emit the list. */ if (initialReplacedList.size < INITIAL_LIMIT) { emit(Pair(initialReplacedList, false)) emitInMain(this@flow, initialReplacedList, false) } }.flowOn(Dispatchers.IO) } override suspend fun getSearchSuggestions(query: String): List<SearchSuggestEntry> { val searchData = mutableListOf<SearchSuggestEntry>() withContext(Dispatchers.IO) { val searchHelper = SearchHelper(loginSourceRepository.gplayAuth!!).using(gPlayHttpClient) searchData.addAll(searchHelper.searchSuggestions(query)) } return searchData.filter { it.suggestedQuery.isNotBlank() } } private suspend fun emitReplacedList( scope: LiveDataScope<Pair<List<App>, Boolean>>, scope: FlowCollector<Pair<List<App>, Boolean>>, accumulationList: MutableList<App>, accumulationLimit: Int, searchBundle: SearchBundle, Loading @@ -121,16 +129,25 @@ class GplayRepository @Inject constructor( */ accumulationList.add(it) scope.emit(Pair(accumulationList, moreToEmit)) emitInMain(scope, 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)) emitInMain(scope, listOf(it), moreToEmit) } } } } private suspend fun emitInMain( scope: FlowCollector<Pair<List<App>, Boolean>>, it: List<App>, moreToEmit: Boolean ) { scope.emit(Pair(it, moreToEmit)) } private suspend fun getTopApps( Loading Loading
app/src/main/java/foundation/e/apps/api/StoreApiRepository.kt +2 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,5 @@ package foundation.e.apps.api interface StoreApiRepository { suspend fun getHomeScreenData(): Any suspend fun getSearchResult(query: String): Any suspend fun getSearchSuggestions(query: String): Any }
app/src/main/java/foundation/e/apps/api/cleanapk/CleanApkAppsRepository.kt +8 −3 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package foundation.e.apps.api.cleanapk import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.cleanapk.data.home.HomeScreen import foundation.e.apps.api.cleanapk.data.search.Search import retrofit2.Response class CleanApkAppsRepository( Loading @@ -15,14 +16,18 @@ class CleanApkAppsRepository( ) } override suspend fun getSearchResult(query: String): Any { override suspend fun getSearchResult(query: String): Response<Search> { return cleanAPKInterface.searchApps( query, CleanAPKInterface.APP_TYPE_ANY, CleanAPKInterface.APP_SOURCE_FOSS, CleanAPKInterface.APP_TYPE_ANY, 20, 1, null ) } override suspend fun getSearchSuggestions(query: String): Any { TODO("Not yet implemented") } }
app/src/main/java/foundation/e/apps/api/cleanapk/CleanApkPWARepository.kt +15 −2 Original line number Diff line number Diff line package foundation.e.apps.api.cleanapk import foundation.e.apps.api.StoreApiRepository import foundation.e.apps.api.cleanapk.data.search.Search import retrofit2.Response class CleanApkPWARepository( private val cleanAPKInterface: CleanAPKInterface, Loading @@ -13,7 +15,18 @@ class CleanApkPWARepository( ) } override suspend fun getSearchResult(query: String): Any { override suspend fun getSearchResult(query: String): Response<Search> { return cleanAPKInterface.searchApps( query, CleanAPKInterface.APP_SOURCE_ANY, CleanAPKInterface.APP_TYPE_PWA, 20, 1, null ) } override suspend fun getSearchSuggestions(query: String): Any { TODO("Not yet implemented") } }
app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +17 −19 Original line number Diff line number Diff line Loading @@ -20,7 +20,11 @@ package foundation.e.apps.api.fused import android.content.Context import android.text.format.Formatter import androidx.lifecycle.* import androidx.lifecycle.LiveData import androidx.lifecycle.LiveDataScope import androidx.lifecycle.asLiveData import androidx.lifecycle.liveData import androidx.lifecycle.map import com.aurora.gplayapi.Constants import com.aurora.gplayapi.SearchSuggestEntry import com.aurora.gplayapi.data.models.App Loading @@ -29,7 +33,6 @@ import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.Category import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.helpers.TopChartsHelper import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.api.ResultSupreme Loading @@ -47,7 +50,6 @@ 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 @@ -63,9 +65,8 @@ import foundation.e.apps.utils.enums.isUnFiltered import foundation.e.apps.utils.modules.PWAManagerModule import foundation.e.apps.utils.modules.PreferenceManagerModule import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.withTimeout import retrofit2.Response import timber.log.Timber Loading Loading @@ -274,7 +275,7 @@ class FusedAPIImpl @Inject constructor( authData, searchResult, packageSpecificResults ) ).asLiveData() ) } } Loading @@ -288,11 +289,8 @@ class FusedAPIImpl @Inject constructor( ): ResultSupreme<Pair<List<FusedApp>, Boolean>> { val pwaApps: MutableList<FusedApp> = mutableListOf() val status = fusedAPIImpl.runCodeBlockWithTimeout({ getCleanAPKSearchResults( query, CleanAPKInterface.APP_SOURCE_ANY, CleanAPKInterface.APP_TYPE_PWA ).apply { val apps = (cleanApkPWARepository.getSearchResult(query,) as Response<Search>).body()?.apps apps?.apply { if (this.isNotEmpty()) { pwaApps.addAll(this) } Loading Loading @@ -321,7 +319,7 @@ class FusedAPIImpl @Inject constructor( authData: AuthData, searchResult: MutableList<FusedApp>, packageSpecificResults: ArrayList<FusedApp> ): LiveData<ResultSupreme<Pair<List<FusedApp>, Boolean>>> = ): Flow<ResultSupreme<Pair<List<FusedApp>, Boolean>>> = getGplaySearchResult(query, authData).map { if (it.first.isNotEmpty()) { searchResult.addAll(it.first) Loading Loading @@ -471,7 +469,7 @@ class FusedAPIImpl @Inject constructor( } suspend fun getSearchSuggestions(query: String, authData: AuthData): List<SearchSuggestEntry> { return gPlayAPIRepository.getSearchSuggestions(query, authData) return gplayRepository.getSearchSuggestions(query) as List<SearchSuggestEntry> } suspend fun getOnDemandModule( Loading Loading @@ -1175,8 +1173,8 @@ class FusedAPIImpl @Inject constructor( by: String? = null ): List<FusedApp> { val list = mutableListOf<FusedApp>() val response = cleanAPKRepository.searchApps(keyword, source, type, nres, page, by).body()?.apps val response = (cleanApkAppsRepository.getSearchResult(keyword) as Response<Search>).body()?.apps // val response = cleanAPKRepository.searchApps(keyword, source, type, nres,page, by).body()?.apps response?.forEach { it.updateStatus() Loading Loading @@ -1204,15 +1202,15 @@ class FusedAPIImpl @Inject constructor( private suspend fun getGplaySearchResult( query: String, authData: AuthData ): LiveData<Pair<List<FusedApp>, Boolean>> { val searchResults = gplayRepository.getSearchResult(query) as LiveData<Pair<List<App>, Boolean>> return searchResults.asFlow().map { ): Flow<Pair<List<FusedApp>, Boolean>> { val searchResults = gplayRepository.getSearchResult(query) as Flow<Pair<List<App>, Boolean>> return searchResults.map { val fusedAppList = it.first.map { app -> replaceWithFDroid(app) } Pair( fusedAppList, it.second ) }.asLiveData() } } /* * This function will replace a GPlay app with F-Droid app if exists, Loading
app/src/main/java/foundation/e/apps/api/gplay/GplayRepository.kt +59 −42 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.SearchSuggestEntry import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.SearchBundle Loading @@ -12,11 +10,13 @@ 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.flow.Flow import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.withContext import javax.inject.Inject Loading Loading @@ -46,21 +46,21 @@ class GplayRepository @Inject constructor( return homeScreenData } override suspend fun getSearchResult(query: String): LiveData<Pair<List<App>, Boolean>> { return liveData { withContext(Dispatchers.IO) { override suspend fun getSearchResult(query: String): Flow<Pair<List<App>, Boolean>> { return flow { /* * 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 searchHelper = SearchHelper(loginSourceRepository.gplayAuth!!).using(gPlayHttpClient) val searchBundle = searchHelper.searchResults(query) val initialReplacedList = mutableListOf<App>() val INITIAL_LIMIT = 4 emitReplacedList( this@liveData, this@flow, initialReplacedList, INITIAL_LIMIT, searchBundle, Loading @@ -76,7 +76,7 @@ class GplayRepository @Inject constructor( subBundles.clear() subBundles.addAll(newSearchBundle.subBundles) emitReplacedList( this@liveData, this@flow, initialReplacedList, INITIAL_LIMIT, newSearchBundle, Loading @@ -92,14 +92,22 @@ class GplayRepository @Inject constructor( * Hence emit the list. */ if (initialReplacedList.size < INITIAL_LIMIT) { emit(Pair(initialReplacedList, false)) emitInMain(this@flow, initialReplacedList, false) } }.flowOn(Dispatchers.IO) } override suspend fun getSearchSuggestions(query: String): List<SearchSuggestEntry> { val searchData = mutableListOf<SearchSuggestEntry>() withContext(Dispatchers.IO) { val searchHelper = SearchHelper(loginSourceRepository.gplayAuth!!).using(gPlayHttpClient) searchData.addAll(searchHelper.searchSuggestions(query)) } return searchData.filter { it.suggestedQuery.isNotBlank() } } private suspend fun emitReplacedList( scope: LiveDataScope<Pair<List<App>, Boolean>>, scope: FlowCollector<Pair<List<App>, Boolean>>, accumulationList: MutableList<App>, accumulationLimit: Int, searchBundle: SearchBundle, Loading @@ -121,16 +129,25 @@ class GplayRepository @Inject constructor( */ accumulationList.add(it) scope.emit(Pair(accumulationList, moreToEmit)) emitInMain(scope, 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)) emitInMain(scope, listOf(it), moreToEmit) } } } } private suspend fun emitInMain( scope: FlowCollector<Pair<List<App>, Boolean>>, it: List<App>, moreToEmit: Boolean ) { scope.emit(Pair(it, moreToEmit)) } private suspend fun getTopApps( Loading