diff --git a/app/src/main/java/foundation/e/apps/data/StoreRepository.kt b/app/src/main/java/foundation/e/apps/data/StoreRepository.kt index e1c04d98e371777d4f7278de0318ca78535a6841..f424c8112cc38070b273c68bb4136b0909cdc65e 100644 --- a/app/src/main/java/foundation/e/apps/data/StoreRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/StoreRepository.kt @@ -19,8 +19,10 @@ package foundation.e.apps.data import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.application.data.Home interface StoreRepository { - suspend fun getHomeScreenData(): Map> - suspend fun getAppDetails(packageNameOrId: String): Application + suspend fun getHomeScreenData(list: MutableList): List + suspend fun getAppDetails(packageName: String): Application + suspend fun getSearchResults(pattern: String): List } diff --git a/app/src/main/java/foundation/e/apps/data/Stores.kt b/app/src/main/java/foundation/e/apps/data/Stores.kt new file mode 100644 index 0000000000000000000000000000000000000000..ca8cf3c759b03bcd91c8a511d4547d3547d5115e --- /dev/null +++ b/app/src/main/java/foundation/e/apps/data/Stores.kt @@ -0,0 +1,39 @@ +package foundation.e.apps.data + +import foundation.e.apps.data.cleanapk.repositories.CleanApkAppsRepository +import foundation.e.apps.data.cleanapk.repositories.CleanApkPwaRepository +import foundation.e.apps.data.enums.Source +import foundation.e.apps.data.playstore.PlayStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class Stores @Inject constructor( + playStoreRepository: PlayStoreRepository, + cleanApkAppsRepository: CleanApkAppsRepository, + cleanApkPwaRepository: CleanApkPwaRepository, +) { + + private val defaultStores = mapOf( + Source.OPEN_SOURCE to cleanApkAppsRepository, + Source.PWA to cleanApkPwaRepository, + Source.PLAY_STORE to playStoreRepository + ) + + private val stores = defaultStores.toMutableMap() + + fun getStores(): Map = stores + + fun getStore(source: Source): StoreRepository? = stores[source] + + fun enableStore(source: Source) { + val repository = defaultStores[source] ?: throw IllegalStateException("store not found") + stores[source] = repository + } + + fun disableStore(source: Source) { + stores.remove(source) + } + + fun isStoreEnabled(source: Source): Boolean = stores.containsKey(source) +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt b/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt index 42541a53b975daf7963be64f5e4cba96eec9c9b0..96290fd68c36f7b33bee3a1b85e40c13a6d4e224 100644 --- a/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt +++ b/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt @@ -22,9 +22,8 @@ import com.aurora.gplayapi.Constants import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.Home import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status -import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.install.pkg.PwaManager import foundation.e.apps.install.pkg.AppLoungePackageManager import javax.inject.Inject @@ -32,15 +31,14 @@ import javax.inject.Singleton @Singleton class ApplicationDataManager @Inject constructor( - private val gPlayRepository: PlayStoreRepository, private val appLoungePackageManager: AppLoungePackageManager, private val pwaManager: PwaManager ) { - suspend fun updateFilterLevel(application: Application) { + fun updateFilterLevel(application: Application) { application.filterLevel = getAppFilterLevel(application) } - suspend fun prepareApps( + fun prepareApps( appList: List, list: MutableList, value: String @@ -55,16 +53,14 @@ class ApplicationDataManager @Inject constructor( } } - suspend fun getAppFilterLevel(application: Application): FilterLevel { + fun getAppFilterLevel(application: Application): FilterLevel { return when { application.package_name.isBlank() -> FilterLevel.UNKNOWN !application.isFree && application.price.isBlank() -> FilterLevel.UI - application.origin == Origin.CLEANAPK -> FilterLevel.NONE - application.origin == Origin.GITLAB_RELEASES -> FilterLevel.NONE + application.source == Source.PWA || application.source == Source.OPEN_SOURCE -> FilterLevel.NONE + application.source == Source.SYSTEM_APP -> FilterLevel.NONE !isRestricted(application) -> FilterLevel.NONE - !isApplicationVisible(application) -> FilterLevel.DATA application.originalSize == 0L -> FilterLevel.UI - !isDownloadable(application) -> FilterLevel.UI else -> FilterLevel.NONE } } @@ -73,28 +69,6 @@ class ApplicationDataManager @Inject constructor( return application.restriction != Constants.Restriction.NOT_RESTRICTED } - /* - * Some apps are simply not visible. - * Example: com.skype.m2 - */ - private suspend fun isApplicationVisible(application: Application): Boolean { - return kotlin.runCatching { gPlayRepository.getAppDetails(application.package_name) }.isSuccess - } - - /* - * Some apps are visible but not downloadable. - * Example: com.riotgames.league.wildrift - */ - private suspend fun isDownloadable(application: Application): Boolean { - return kotlin.runCatching { - gPlayRepository.getDownloadInfo( - application.package_name, - application.latest_version_code, - application.offer_type, - ) - }.isSuccess - } - fun updateStatus(application: Application) { if (application.status != Status.INSTALLATION_ISSUE) { application.status = getFusedAppInstallationStatus(application) diff --git a/app/src/main/java/foundation/e/apps/data/application/ApplicationRepository.kt b/app/src/main/java/foundation/e/apps/data/application/ApplicationRepository.kt index 126b589d59405d3ac8c8d26b62ed70188979b8da..44d300a1fc78f62f88cc0823c1dbffe4cd427eb2 100644 --- a/app/src/main/java/foundation/e/apps/data/application/ApplicationRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/application/ApplicationRepository.kt @@ -26,7 +26,6 @@ import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.application.apps.AppsApi import foundation.e.apps.data.application.category.CategoryApi import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status @@ -52,8 +51,8 @@ class ApplicationRepository @Inject constructor( private val downloadInfoApi: DownloadInfoApi ) { - suspend fun getHomeScreenData(authData: AuthData): LiveData>> { - return homeApi.fetchHomeScreenData(authData) + suspend fun getHomeScreenData(): LiveData>> { + return homeApi.fetchHomeScreenData() } fun getSelectedAppTypes(): List { @@ -62,9 +61,9 @@ class ApplicationRepository @Inject constructor( suspend fun getApplicationDetails( packageNameList: List, - origin: Origin + source: Source ): Pair, ResultStatus> { - return appsApi.getApplicationDetails(packageNameList, origin) + return appsApi.getApplicationDetails(packageNameList, source) } suspend fun getAppFilterLevel(application: Application): FilterLevel { @@ -74,21 +73,17 @@ class ApplicationRepository @Inject constructor( suspend fun getApplicationDetails( id: String, packageName: String, - origin: Origin + source: Source ): Pair { - return appsApi.getApplicationDetails(id, packageName, origin) - } - - suspend fun getCleanapkAppDetails(packageName: String): Pair { - return appsApi.getCleanapkAppDetails(packageName) + return appsApi.getApplicationDetails(id, packageName, source) } suspend fun updateFusedDownloadWithDownloadingInfo( - origin: Origin, + source: Source, appInstall: AppInstall ) { downloadInfoApi.updateFusedDownloadWithDownloadingInfo( - origin, + source, appInstall ) } @@ -116,17 +111,15 @@ class ApplicationRepository @Inject constructor( } suspend fun getCleanApkSearchResults( - query: String, - authData: AuthData + query: String ): SearchResult { - return searchAPIImpl.getCleanApkSearchResults(query, authData) + return searchAPIImpl.getCleanApkSearchResults(query) } suspend fun getGplaySearchResults( - query: String, - nextPageSubBundle: Set? - ): GplaySearchResult { - return searchAPIImpl.getGplaySearchResult(query, nextPageSubBundle) + query: String + ): SearchResult { + return searchAPIImpl.getGplaySearchResult(query) } suspend fun getAppsListBasedOnCategory( @@ -136,7 +129,7 @@ class ApplicationRepository @Inject constructor( source: Source ): ResultSupreme, String>> { return when (source) { - Source.OPEN -> categoryApi.getCleanApkAppsByCategory(category, Source.OPEN) + Source.OPEN_SOURCE -> categoryApi.getCleanApkAppsByCategory(category, Source.OPEN_SOURCE) Source.PWA -> categoryApi.getCleanApkAppsByCategory(category, Source.PWA) else -> categoryApi.getGplayAppsByCategory(authData, category, pageUrl) } diff --git a/app/src/main/java/foundation/e/apps/data/application/apps/AppsApi.kt b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApi.kt index 067646e8f9500f755133726b4e5fbd6b5706fab5..6505821ff317ae53e896aa5d00dac233f7dcc9ba 100644 --- a/app/src/main/java/foundation/e/apps/data/application/apps/AppsApi.kt +++ b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApi.kt @@ -18,12 +18,10 @@ package foundation.e.apps.data.application.apps -import com.aurora.gplayapi.data.models.AuthData -import com.aurora.gplayapi.data.models.ContentRating import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status interface AppsApi { @@ -36,13 +34,13 @@ interface AppsApi { suspend fun getApplicationDetails( packageNameList: List, - origin: Origin + source: Source ): Pair, ResultStatus> suspend fun getApplicationDetails( id: String, packageName: String, - origin: Origin + source: Source ): Pair /** diff --git a/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt index f98e6c1542f0b7efa1ea3ca2d754078c19bf7708..810ed55952945a5d90719bbba67b6d87bd42add2 100644 --- a/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt @@ -18,51 +18,29 @@ package foundation.e.apps.data.application.apps -import android.content.Context -import com.aurora.gplayapi.data.models.App -import com.aurora.gplayapi.data.models.AuthData -import dagger.hilt.android.qualifiers.ApplicationContext -import foundation.e.apps.data.AppSourcesContainer +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.ApplicationDataManager import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.application.utils.toApplication -import foundation.e.apps.data.cleanapk.data.search.Search import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.isUnFiltered import foundation.e.apps.data.handleNetworkResult -import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.ui.applicationlist.ApplicationDiffUtil -import retrofit2.Response import javax.inject.Inject -import foundation.e.apps.data.cleanapk.data.app.CleanApkApplication +import foundation.e.apps.data.enums.Source class AppsApiImpl @Inject constructor( - @ApplicationContext private val context: Context, - private val appLoungePreference: AppLoungePreference, - private val appSources: AppSourcesContainer, + private val stores: Stores, private val applicationDataManager: ApplicationDataManager ) : AppsApi { - companion object { - private const val KEY_SEARCH_PACKAGE_NAME = "package_name" - } - override suspend fun getCleanapkAppDetails(packageName: String): Pair { var application = Application() val result = handleNetworkResult { - val result = appSources.cleanApkAppsRepo.getSearchResult( - packageName, - KEY_SEARCH_PACKAGE_NAME - ).body() - - if (result?.hasSingleResult() == true) { - application = - appSources.cleanApkAppsRepo.getAppDetails(result.apps[0]._id) - } - + application = stores.getStore(Source.OPEN_SOURCE)?.getAppDetails(packageName) ?: Application() + application.source = Source.OPEN_SOURCE + application.updateType() application.updateFilterLevel() } @@ -72,18 +50,18 @@ class AppsApiImpl @Inject constructor( /* * Handy method to run on an instance of FusedApp to update its filter level. */ - private suspend fun Application.updateFilterLevel() { + private fun Application.updateFilterLevel() { this.filterLevel = applicationDataManager.getAppFilterLevel(this) } override suspend fun getApplicationDetails( packageNameList: List, - origin: Origin + source: Source ): Pair, ResultStatus> { val list = mutableListOf() val response: Pair, ResultStatus> = - if (origin == Origin.CLEANAPK) { + if (source == Source.OPEN_SOURCE || source == Source.PWA) { getAppDetailsListFromCleanApk(packageNameList) } else { getAppDetailsListFromGPlay(packageNameList) @@ -108,13 +86,11 @@ class AppsApiImpl @Inject constructor( private suspend fun getAppDetailsListFromCleanApk( packageNameList: List, ): Pair, ResultStatus> { - var status = ResultStatus.OK + val status = ResultStatus.OK val applicationList = mutableListOf() for (packageName in packageNameList) { - getCleanApkSearchResultByPackageName(packageName).data?.run { - handleCleanApkSearch(applicationList) - } + applicationList.add(stores.getStore(Source.OPEN_SOURCE)?.getAppDetails(packageName) ?: Application()) } return Pair(applicationList, status) @@ -125,13 +101,12 @@ class AppsApiImpl @Inject constructor( ): Pair, ResultStatus> { val applicationList = mutableListOf() - val result = handleNetworkResult { - appSources.gplayRepo.getAppsDetails(packageNameList).forEach { app -> - handleFilteredApps(app, applicationList) - } + for (packageName in packageNameList) { + val app = stores.getStore(Source.PLAY_STORE)?.getAppDetails(packageName) ?: Application() + handleFilteredApps(app, applicationList) } - return Pair(applicationList, result.getResultStatus()) + return Pair(applicationList, ResultStatus.OK) } /* @@ -140,63 +115,37 @@ class AppsApiImpl @Inject constructor( * * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5174 */ - private suspend fun handleFilteredApps( - app: App, + private fun handleFilteredApps( + app: Application, applicationList: MutableList ) { - val application = app.toApplication(context) - val filter = applicationDataManager.getAppFilterLevel(application) + val filter = applicationDataManager.getAppFilterLevel(app) if (filter.isUnFiltered()) { applicationList.add( - application.apply { + app.apply { filterLevel = filter } ) } } - private suspend fun getCleanApkSearchResultByPackageName( - packageName: String, - ) = handleNetworkResult { - appSources.cleanApkAppsRepo.getSearchResult( - packageName, - KEY_SEARCH_PACKAGE_NAME - ).body() - } - - private suspend fun Search.handleCleanApkSearch( - applicationList: MutableList - ) { - if (hasSingleResult()) { - applicationList.add( - apps[0].apply { - updateFilterLevel() - } - ) - } - } - - private fun Search.hasSingleResult() = - apps.isNotEmpty() && numberOfResults == 1 - override suspend fun getApplicationDetails( id: String, packageName: String, - origin: Origin + source: Source ): Pair { var application: Application val result = handleNetworkResult { - application = if (origin == Origin.CLEANAPK) { - appSources.cleanApkAppsRepo.getAppDetails(id) - } else { - appSources.gplayRepo.getAppDetails(packageName) - } + val store = stores.getStore(source) + ?: throw IllegalStateException("Could not get store") + + application = store.getAppDetails(packageName) application.let { applicationDataManager.updateStatus(it) + it.source = source it.updateType() - it.updateSource(context) it.updateFilterLevel() } application @@ -256,5 +205,5 @@ class AppsApiImpl @Inject constructor( return false } - override fun isOpenSourceSelected() = appLoungePreference.isOpenSourceSelected() + override fun isOpenSourceSelected() = stores.isStoreEnabled(Source.OPEN_SOURCE) } diff --git a/app/src/main/java/foundation/e/apps/data/application/category/CategoryApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/category/CategoryApiImpl.kt index cddc7f184f7b8e980da954569ea815f325ae4c0c..8bf89e8313252456ef54ca1623b30350cc61888f 100644 --- a/app/src/main/java/foundation/e/apps/data/application/category/CategoryApiImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/application/category/CategoryApiImpl.kt @@ -25,6 +25,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.data.AppSourcesContainer import foundation.e.apps.data.ResultSupreme +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.ApplicationDataManager import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.Category @@ -38,13 +39,12 @@ import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.isUnFiltered import foundation.e.apps.data.handleNetworkResult -import foundation.e.apps.data.preference.AppLoungePreference import javax.inject.Inject class CategoryApiImpl @Inject constructor( @ApplicationContext private val context: Context, - private val appLoungePreference: AppLoungePreference, private val appSources: AppSourcesContainer, + private val stores: Stores, private val applicationDataManager: ApplicationDataManager ) : CategoryApi { @@ -62,16 +62,8 @@ class CategoryApiImpl @Inject constructor( ): ResultStatus { val categoryResults: MutableList = mutableListOf() - if (appLoungePreference.isOpenSourceSelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.OPEN)) - } - - if (appLoungePreference.isPWASelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.PWA)) - } - - if (appLoungePreference.isGplaySelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.GPLAY)) + for ((source, _) in stores.getStores()) { + categoryResults.add(fetchCategoryResult(categoriesList, type, source)) } return categoryResults.find { it != ResultStatus.OK } ?: ResultStatus.OK @@ -83,8 +75,8 @@ class CategoryApiImpl @Inject constructor( source: Source ): ResultStatus { val categoryResult = when (source) { - Source.OPEN -> { - fetchCleanApkCategories(type, Source.OPEN) + Source.OPEN_SOURCE -> { + fetchCleanApkCategories(type, Source.OPEN_SOURCE) } Source.PWA -> { @@ -133,7 +125,7 @@ class CategoryApiImpl @Inject constructor( val result = handleNetworkResult { val categories = when (source) { - Source.OPEN -> { + Source.OPEN_SOURCE -> { tag = AppTag.OpenSource(context.getString(R.string.open_source)) appSources.cleanApkAppsRepo.getCategories().body() } @@ -234,6 +226,7 @@ class CategoryApiImpl @Inject constructor( response?.apps?.forEach { applicationDataManager.updateStatus(it) it.updateType() + it.source = source applicationDataManager.updateFilterLevel(it) list.add(it) } @@ -245,7 +238,7 @@ class CategoryApiImpl @Inject constructor( source: Source, category: String ) = when (source) { - Source.OPEN -> { + Source.OPEN_SOURCE -> { appSources.cleanApkAppsRepo.getAppsByCategory(category).body() } diff --git a/app/src/main/java/foundation/e/apps/data/application/data/Application.kt b/app/src/main/java/foundation/e/apps/data/application/data/Application.kt index e99278fcca8efa43dfcd23ff6c9a077664e6974b..99e603411139c41daff687a55a28af27e33f98d2 100644 --- a/app/src/main/java/foundation/e/apps/data/application/data/Application.kt +++ b/app/src/main/java/foundation/e/apps/data/application/data/Application.kt @@ -18,19 +18,16 @@ package foundation.e.apps.data.application.data -import android.content.Context import android.net.Uri import com.aurora.gplayapi.Constants.Restriction import com.aurora.gplayapi.data.models.ContentRating import com.google.gson.annotations.SerializedName -import foundation.e.apps.R import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.Type import foundation.e.apps.data.enums.Type.NATIVE import foundation.e.apps.data.enums.Type.PWA -import foundation.e.apps.di.CommonUtilsModule.LIST_OF_NULL data class Application( val _id: String = String(), @@ -51,11 +48,10 @@ data class Application( val ratings: Ratings = Ratings(), val offer_type: Int = -1, var status: Status = Status.UNAVAILABLE, - var origin: Origin = Origin.CLEANAPK, val shareUrl: String = String(), val originalSize: Long = 0, val appSize: String = String(), - var source: String = String(), + var source: Source = Source.PLAY_STORE, val price: String = String(), val isFree: Boolean = true, val is_pwa: Boolean = false, @@ -106,18 +102,6 @@ data class Application( this.type = if (this.is_pwa) PWA else NATIVE } - // TODO: Make this logic separate from data layer (https://gitlab.e.foundation/e/os/backlog/-/issues/2371) - fun updateSource(context: Context) { - this.apply { - source = when { - origin == Origin.GITLAB_RELEASES -> context.getString(R.string.system_app) - origin == Origin.GPLAY -> "" - is_pwa -> context.getString(R.string.pwa) - else -> context.getString(R.string.open_source) - } - } - } - fun hasExodusPrivacyRating(): Boolean { return this.reportId.toInt() != -1 } diff --git a/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApi.kt b/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApi.kt index acfa0a329416f775e19dd7e34487377426735949..fe8bb50b226ba5ab78a433b597e55e39ede0787a 100644 --- a/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApi.kt +++ b/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApi.kt @@ -19,7 +19,7 @@ package foundation.e.apps.data.application.downloadInfo import foundation.e.apps.data.cleanapk.data.download.Download -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.install.models.AppInstall import retrofit2.Response @@ -33,7 +33,7 @@ interface DownloadInfoApi { ): String? suspend fun updateFusedDownloadWithDownloadingInfo( - origin: Origin, + source: Source, appInstall: AppInstall ) diff --git a/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApiImpl.kt index 86b91123092891b22fbd9502b27559c075dda5d6..8e6ca6d84b71ecfa13fa96d3bad6ebac7eff973d 100644 --- a/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApiImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/application/downloadInfo/DownloadInfoApiImpl.kt @@ -20,7 +20,7 @@ package foundation.e.apps.data.application.downloadInfo import foundation.e.apps.data.AppSourcesContainer import foundation.e.apps.data.cleanapk.CleanApkDownloadInfoFetcher -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.install.models.AppInstall import foundation.e.apps.data.handleNetworkResult import javax.inject.Inject @@ -56,20 +56,24 @@ class DownloadInfoApiImpl @Inject constructor( } override suspend fun updateFusedDownloadWithDownloadingInfo( - origin: Origin, + source: Source, appInstall: AppInstall ) { val list = mutableListOf() - when (origin) { - Origin.CLEANAPK -> { + when (source) { + Source.OPEN_SOURCE -> { + updateDownloadInfoFromCleanApk(appInstall, list) + } + + Source.PWA -> { updateDownloadInfoFromCleanApk(appInstall, list) } - Origin.GPLAY -> { + Source.PLAY_STORE -> { updateDownloadInfoFromGplay(appInstall, list) } - Origin.GITLAB_RELEASES -> { + Source.SYSTEM_APP -> { return // nothing to do as downloadURLList is already set } } diff --git a/app/src/main/java/foundation/e/apps/data/application/home/HomeApi.kt b/app/src/main/java/foundation/e/apps/data/application/home/HomeApi.kt index 27508ed84bdb576a423947cc0fad8a489dad7b33..c32a1c1390e5a9a0d1a798b66a8647db29c33c14 100644 --- a/app/src/main/java/foundation/e/apps/data/application/home/HomeApi.kt +++ b/app/src/main/java/foundation/e/apps/data/application/home/HomeApi.kt @@ -24,7 +24,5 @@ import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.application.data.Home interface HomeApi { - suspend fun fetchHomeScreenData( - authData: AuthData, - ): LiveData>> + suspend fun fetchHomeScreenData(): LiveData>> } diff --git a/app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt index d81e28a7fcc72d5fb7c9055d9a9345cb297b993d..e82c70db871f22b06e065f3c2d04bd5f060932fe 100644 --- a/app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt @@ -18,79 +18,48 @@ package foundation.e.apps.data.application.home -import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.liveData -import com.aurora.gplayapi.data.models.AuthData -import dagger.hilt.android.qualifiers.ApplicationContext -import foundation.e.apps.data.AppSourcesContainer import foundation.e.apps.data.ResultSupreme -import foundation.e.apps.data.application.ApplicationDataManager +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.data.Home -import foundation.e.apps.data.application.search.FusedHomeDeferred import foundation.e.apps.data.application.search.SearchApi import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.Source import foundation.e.apps.data.handleNetworkResult -import foundation.e.apps.data.login.AuthObject -import foundation.e.apps.data.preference.AppLoungePreference -import foundation.e.apps.utils.eventBus.AppEvent -import foundation.e.apps.utils.eventBus.EventBus -import kotlinx.coroutines.MainScope import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject class HomeApiImpl @Inject constructor( - @ApplicationContext private val context: Context, - private val appLoungePreference: AppLoungePreference, - private val appSources: AppSourcesContainer, - private val applicationDataManager: ApplicationDataManager + private val stores: Stores ) : HomeApi { - companion object { - private const val THRESHOLD_LIMITED_RESULT_HOME_PAGE = 4 - } - private enum class AppSourceWeight { GPLAY, OPEN_SOURCE, PWA } - override suspend fun fetchHomeScreenData(authData: AuthData): LiveData>> { + override suspend fun fetchHomeScreenData(): LiveData>> { val list = mutableListOf() - var resultGplay: FusedHomeDeferred? = null - var resultOpenSource: FusedHomeDeferred? = null - var resultPWA: FusedHomeDeferred? = null return liveData { coroutineScope { - if (appLoungePreference.isGplaySelected()) { - resultGplay = async { loadHomeData(list, Source.GPLAY, authData) } - } - - if (appLoungePreference.isOpenSourceSelected()) { - resultOpenSource = async { loadHomeData(list, Source.OPEN, authData) } - } - - if (appLoungePreference.isPWASelected()) { - resultPWA = async { loadHomeData(list, Source.PWA, authData) } + if (Source.PLAY_STORE in stores.getStores()) { + val result = async { + loadHomeData(list, Source.PLAY_STORE) + } + emit(result.await()) } - resultGplay?.await()?.let { - emit(it) - } - - resultOpenSource?.await()?.let { - emit(it) - } - - resultPWA?.await()?.let { - emit(it) + val otherStores = stores.getStores().filter { it.key != Source.PLAY_STORE } + otherStores.forEach { (source, _) -> + val result = async { + loadHomeData(list, source) + } + emit(result.await()) } } } @@ -98,26 +67,12 @@ class HomeApiImpl @Inject constructor( private suspend fun loadHomeData( priorList: MutableList, - source: Source, - authData: AuthData, + source: Source ): ResultSupreme> { - - val result = when (source) { - Source.GPLAY -> handleNetworkResult { - fetchGPlayHome(authData, priorList) - } - - Source.OPEN -> handleNetworkResult { - handleCleanApkHomes(priorList, SearchApi.APP_TYPE_OPEN) - } - - Source.PWA -> handleNetworkResult { - handleCleanApkHomes(priorList, SearchApi.APP_TYPE_PWA) - } - - Source.GITLAB_RELEASES -> { - ResultSupreme.Error(message = "Gitlab source not allowed") - } + val result = handleNetworkResult { + val homeDataBuilder = stores.getStore(source) + homeDataBuilder?.getHomeScreenData(priorList) + ?: throw IllegalStateException("Could not find store for $source") } setHomeErrorMessage(result.getResultStatus(), source) @@ -132,75 +87,14 @@ class HomeApiImpl @Inject constructor( return ResultSupreme.create(result.getResultStatus(), priorList) } - private suspend fun handleCleanApkHomes( - priorList: MutableList, - appType: String - ): MutableList { - val homes = if (appType == SearchApi.APP_TYPE_OPEN) { - appSources.cleanApkAppsRepo.getHomeScreenData() - } else { - appSources.cleanApkPWARepo.getHomeScreenData() - } - - homes.forEach { (title, list) -> - priorList.add(Home(title, list, appType)) - } - - return priorList - } - private fun setHomeErrorMessage(apiStatus: ResultStatus, source: Source) { if (apiStatus != ResultStatus.OK) { apiStatus.message = when (source) { - Source.GPLAY -> ("GPlay home loading error\n" + apiStatus.message).trim() - Source.GITLAB_RELEASES -> ("Gitlab home not allowed\n" + apiStatus.message).trim() - Source.OPEN -> ("Open Source home loading error\n" + apiStatus.message).trim() + Source.PLAY_STORE -> ("GPlay home loading error\n" + apiStatus.message).trim() + Source.SYSTEM_APP -> ("Gitlab home not allowed\n" + apiStatus.message).trim() + Source.OPEN_SOURCE -> ("Open Source home loading error\n" + apiStatus.message).trim() Source.PWA -> ("PWA home loading error\n" + apiStatus.message).trim() } } } - - private suspend fun fetchGPlayHome( - authData: AuthData, - priorList: MutableList - ): List { - val list = mutableListOf() - val gplayHomeData = appSources.gplayRepo.getHomeScreenData() - - gplayHomeData.map { - val fusedApps = it.value.map { app -> - app.apply { - applicationDataManager.updateStatus(this) - applicationDataManager.updateFilterLevel(this) - } - } - list.add(Home(it.key, fusedApps)) - } - - handleLimitedResult(list) - Timber.d("HomePageData: $list") - - priorList.addAll(list) - return priorList - } - - private fun handleLimitedResult(homeList: List) { - val gplayHomes = homeList.filter { fusedHome -> fusedHome.source.isEmpty() } - val hasGplayLimitedResult = gplayHomes.any { fusedHome -> - fusedHome.list.size < THRESHOLD_LIMITED_RESULT_HOME_PAGE - } - - if (hasGplayLimitedResult) { - Timber.w("Limited result is found for homepage...") - refreshToken() - } - } - - private fun refreshToken() { - MainScope().launch { - EventBus.invokeEvent( - AppEvent.InvalidAuthEvent(AuthObject.GPlayAuth::class.java.simpleName) - ) - } - } } diff --git a/app/src/main/java/foundation/e/apps/data/application/search/SearchApi.kt b/app/src/main/java/foundation/e/apps/data/application/search/SearchApi.kt index 4ea26f61b2c74d0654a83cef62715404f73e3341..4dfac924fd0091703e438ed3d3be52cc425251f4 100644 --- a/app/src/main/java/foundation/e/apps/data/application/search/SearchApi.kt +++ b/app/src/main/java/foundation/e/apps/data/application/search/SearchApi.kt @@ -40,19 +40,16 @@ interface SearchApi { /** * Fetches search results from cleanAPK and GPlay servers and returns them * @param query Query - * @param authData [AuthData] * @return ResultSupreme which contains a Pair, Boolean> where List * is the app list and [Boolean] indicates more data to load or not. */ suspend fun getCleanApkSearchResults( - query: String, - authData: AuthData + query: String ): SearchResult suspend fun getGplaySearchResult( query: String, - nextPageSubBundle: Set? - ): GplaySearchResult + ): SearchResult suspend fun getSearchSuggestions(query: String): List } diff --git a/app/src/main/java/foundation/e/apps/data/application/search/SearchApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/search/SearchApiImpl.kt index ead91ecce866b15f1c78a6a6779959ca8b30a38d..d35b4476da11671828234275592157a394c96de9 100644 --- a/app/src/main/java/foundation/e/apps/data/application/search/SearchApiImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/application/search/SearchApiImpl.kt @@ -20,38 +20,31 @@ package foundation.e.apps.data.application.search import android.content.Context 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 import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.AppSourcesContainer import foundation.e.apps.data.ResultSupreme +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.ApplicationDataManager import foundation.e.apps.data.application.apps.AppsApi import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.application.data.Home import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_ANY import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_OPEN import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_PWA -import foundation.e.apps.data.application.utils.toApplication -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.handleNetworkResult import foundation.e.apps.data.login.exceptions.CleanApkIOException import foundation.e.apps.data.login.exceptions.GPlayIOException -import foundation.e.apps.data.preference.AppLoungePreference -import kotlinx.coroutines.Deferred import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton -typealias FusedHomeDeferred = Deferred>> - @Singleton class SearchApiImpl @Inject constructor( private val appsApi: AppsApi, - private val appLoungePreference: AppLoungePreference, private val appSources: AppSourcesContainer, + private val stores: Stores, private val applicationDataManager: ApplicationDataManager ) : SearchApi { @@ -61,9 +54,9 @@ class SearchApiImpl @Inject constructor( override fun getSelectedAppTypes(): List { val selectedAppTypes = mutableListOf() - if (appLoungePreference.isGplaySelected()) selectedAppTypes.add(APP_TYPE_ANY) - if (appLoungePreference.isOpenSourceSelected()) selectedAppTypes.add(APP_TYPE_OPEN) - if (appLoungePreference.isPWASelected()) selectedAppTypes.add(APP_TYPE_PWA) + if (stores.isStoreEnabled(Source.PLAY_STORE)) selectedAppTypes.add(APP_TYPE_ANY) + if (stores.isStoreEnabled(Source.OPEN_SOURCE)) selectedAppTypes.add(APP_TYPE_OPEN) + if (stores.isStoreEnabled(Source.PWA)) selectedAppTypes.add(APP_TYPE_PWA) return selectedAppTypes } @@ -71,13 +64,11 @@ class SearchApiImpl @Inject constructor( /** * Fetches search results from cleanAPK and returns them * @param query Query - * @param authData [AuthData] * @return A ResultSupreme with Pair of list of non-nullable [Application] and * a Boolean signifying if more search results are being loaded. */ override suspend fun getCleanApkSearchResults( query: String, - authData: AuthData ): SearchResult { var finalSearchResult: SearchResult = ResultSupreme.Error( message = "", @@ -85,10 +76,10 @@ class SearchApiImpl @Inject constructor( ) val packageSpecificResults = - fetchPackageSpecificResult(authData, query).data?.first ?: emptyList() + fetchPackageSpecificResult(query).data?.first ?: emptyList() val searchResult = mutableListOf() - if (appLoungePreference.isOpenSourceSelected()) { + if (stores.isStoreEnabled(Source.OPEN_SOURCE)) { finalSearchResult = fetchOpenSourceSearchResult( query, searchResult, @@ -96,7 +87,7 @@ class SearchApiImpl @Inject constructor( ) } - if (appLoungePreference.isPWASelected()) { + if (stores.isStoreEnabled(Source.PWA)) { finalSearchResult = fetchPWASearchResult( query, searchResult, @@ -104,11 +95,11 @@ class SearchApiImpl @Inject constructor( ) } - if (!appLoungePreference.isOpenSourceSelected() && !appLoungePreference.isPWASelected()) { + if (!stores.isStoreEnabled(Source.OPEN_SOURCE) && !stores.isStoreEnabled(Source.PWA)) { finalSearchResult = ResultSupreme.Success( Pair( packageSpecificResults, - appLoungePreference.isGplaySelected() + stores.isStoreEnabled(Source.PLAY_STORE) ) ) } @@ -124,11 +115,12 @@ class SearchApiImpl @Inject constructor( val pwaApps: MutableList = mutableListOf() val result = handleNetworkResult { val apps = - appSources.cleanApkPWARepo.getSearchResult(query).body()?.apps - apps?.forEach { + stores.getStore(Source.PWA)?.getSearchResults(query) ?: emptyList() + + apps.forEach { applicationDataManager.updateStatus(it) + it.source = Source.PWA it.updateType() - it.updateSource(context) pwaApps.add(it) } } @@ -145,7 +137,7 @@ class SearchApiImpl @Inject constructor( packageSpecificResults, query ), - appLoungePreference.isGplaySelected() + stores.isStoreEnabled(Source.PLAY_STORE) ), exception = result.exception ) @@ -175,14 +167,13 @@ class SearchApiImpl @Inject constructor( packageSpecificResults, query ), - appLoungePreference.isGplaySelected() || appLoungePreference.isPWASelected() + stores.isStoreEnabled(Source.PLAY_STORE) || stores.isStoreEnabled(Source.PWA) ), exception = result.exception ) } private suspend fun fetchPackageSpecificResult( - authData: AuthData, query: String, ): SearchResult { val packageSpecificResults: MutableList = mutableListOf() @@ -190,11 +181,11 @@ class SearchApiImpl @Inject constructor( var cleanapkPackageResult: Application? = null val result = handleNetworkResult { - if (appLoungePreference.isGplaySelected()) { + if (stores.isStoreEnabled(Source.PLAY_STORE)) { gplayPackageResult = getGplayPackageResult(query) } - if (appLoungePreference.isOpenSourceSelected()) { + if (stores.isStoreEnabled(Source.OPEN_SOURCE)) { cleanapkPackageResult = getCleanApkPackageResult(query) } } @@ -206,7 +197,7 @@ class SearchApiImpl @Inject constructor( gplayPackageResult?.let { packageSpecificResults.add(it) } } - if (appLoungePreference.isGplaySelected()) { + if (stores.isStoreEnabled(Source.PLAY_STORE)) { packageSpecificResults.add(Application(isPlaceHolder = true)) } @@ -238,7 +229,7 @@ class SearchApiImpl @Inject constructor( val finalList = (packageSpecificResults + filteredResults).toMutableList() finalList.removeIf { it.isPlaceHolder } - if (appLoungePreference.isGplaySelected()) { + if (stores.isStoreEnabled(Source.PLAY_STORE)) { finalList.add(Application(isPlaceHolder = true)) } @@ -260,7 +251,7 @@ class SearchApiImpl @Inject constructor( private suspend fun getGplayPackageResult( query: String, ): Application? { - appsApi.getApplicationDetails(query, query, Origin.GPLAY).let { + appsApi.getApplicationDetails(query, query, Source.PLAY_STORE).let { if (it.second == ResultStatus.OK && it.first.package_name.isNotEmpty()) { return it.first } @@ -279,13 +270,10 @@ class SearchApiImpl @Inject constructor( private suspend fun getCleanApkSearchResult(packageName: String): ResultSupreme { var application = Application() val result = handleNetworkResult { - val result = appSources.cleanApkAppsRepo.getSearchResult( - packageName, - "package_name" - ).body() + val results = stores.getStore(Source.OPEN_SOURCE)?.getSearchResults(packageName) ?: emptyList() - if (result?.apps?.isNotEmpty() == true && result.numberOfResults == 1) { - application = result.apps[0] + if (results.isNotEmpty() && results.size == 1) { + application = results[0] } } @@ -306,12 +294,11 @@ class SearchApiImpl @Inject constructor( ): List { val list = mutableListOf() val response = - appSources.cleanApkAppsRepo.getSearchResult(keyword).body()?.apps + stores.getStore(Source.OPEN_SOURCE)?.getSearchResults(keyword) ?: emptyList() - response?.forEach { + response.forEach { applicationDataManager.updateStatus(it) it.updateType() - it.updateSource(context) list.add(it) } @@ -320,29 +307,30 @@ class SearchApiImpl @Inject constructor( override suspend fun getGplaySearchResult( query: String, - nextPageSubBundle: Set? - ): GplaySearchResult { + ): SearchResult { val result = handleNetworkResult { - val searchResults = - appSources.gplayRepo.getSearchResult(query, nextPageSubBundle?.toMutableSet()) - - if (!appLoungePreference.isGplaySelected()) { + if (!stores.isStoreEnabled(Source.PLAY_STORE)) { return@handleNetworkResult Pair( listOf(), setOf() ) } - val fusedAppList = replaceWithFDroid(searchResults.first).toMutableList() + val searchResults = + stores.getStore(Source.PLAY_STORE)?.getSearchResults(query) + ?: throw IllegalStateException("Could not get store") - if (searchResults.second.isNotEmpty()) { - fusedAppList.add(Application(isPlaceHolder = true)) + val apps = replaceWithFDroid(searchResults).toMutableList() + if (searchResults.isNotEmpty()) { + apps.add(Application(isPlaceHolder = true)) } - return@handleNetworkResult Pair(fusedAppList.toList(), searchResults.second.toSet()) + return@handleNetworkResult Pair(apps.toList(), true) } - return if (result.isSuccess()) result else ResultSupreme.Error( + return if (result.isSuccess()) { + ResultSupreme.Success(result.data as Pair, Boolean>) + } else ResultSupreme.Error( message = "", exception = GPlayIOException("Unable to reach Google Play API") ) @@ -352,24 +340,24 @@ class SearchApiImpl @Inject constructor( * This function will replace a GPlay app with F-Droid app if exists, * else will show the GPlay app itself. */ - private suspend fun replaceWithFDroid(gPlayApps: List): List { + private suspend fun replaceWithFDroid(gPlayApps: List): List { try { if (gPlayApps.isEmpty()) return emptyList() - val packageNames = gPlayApps.map { it.packageName } + val packageNames = gPlayApps.map { it.package_name } val response = appSources.cleanApkAppsRepo.checkAvailablePackages(packageNames) val availableApps = response.body()?.apps ?: emptyList() return gPlayApps.map { gPlayApp -> - availableApps.find { it.package_name == gPlayApp.packageName }?.apply { + availableApps.find { it.package_name == gPlayApp.package_name }?.apply { isGplayReplaced = true - updateSource(context) - } ?: gPlayApp.toApplication(context) + source = Source.PLAY_STORE + } ?: gPlayApp } } catch (e: Exception) { Timber.w(e, "Failed to replace Google apps with their F-Droid counterparts.") - return gPlayApps.map { it.toApplication(context) } + return gPlayApps } } } diff --git a/app/src/main/java/foundation/e/apps/data/application/utils/GplayApiExtensions.kt b/app/src/main/java/foundation/e/apps/data/application/utils/GplayApiExtensions.kt index d43e9fc48c224dfd2f5d3b1bc275ce0b1a31b12f..0ddc34c77cffa5e1d96e8f7422e843b687be6a58 100644 --- a/app/src/main/java/foundation/e/apps/data/application/utils/GplayApiExtensions.kt +++ b/app/src/main/java/foundation/e/apps/data/application/utils/GplayApiExtensions.kt @@ -26,7 +26,6 @@ import com.aurora.gplayapi.data.models.Category import foundation.e.apps.data.application.data.Category as AppLoungeCategory import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.Ratings -import foundation.e.apps.data.enums.Origin fun App.toApplication(context: Context): Application { val app = Application( @@ -50,7 +49,6 @@ fun App.toApplication(context: Context): Application { } ), offer_type = this.offerType, - origin = Origin.GPLAY, shareUrl = this.shareUrl, originalSize = this.size, appSize = Formatter.formatFileSize(context, this.size), diff --git a/app/src/main/java/foundation/e/apps/data/cleanapk/data/home/CleanApkHome.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/data/home/CleanApkHome.kt index 7118307bed1fb092e5a35f0e7c272d0949e5cd88..de40e01f5af76c34487454c6cc73d636037818ae 100644 --- a/app/src/main/java/foundation/e/apps/data/cleanapk/data/home/CleanApkHome.kt +++ b/app/src/main/java/foundation/e/apps/data/cleanapk/data/home/CleanApkHome.kt @@ -18,7 +18,6 @@ package foundation.e.apps.data.cleanapk.data.home -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.application.data.Application data class CleanApkHome( @@ -27,5 +26,4 @@ data class CleanApkHome( val popular_apps: List = emptyList(), val popular_games: List = emptyList(), val discover: List = emptyList(), - var origin: Origin = Origin.CLEANAPK // Origin ) diff --git a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkAppsRepository.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkAppsRepository.kt index b97b3ce301573483c072b9021990feda76ab1cdd..9c96bbf0ae076a0658d583533fdc1be8ac67dc32 100644 --- a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkAppsRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkAppsRepository.kt @@ -18,15 +18,15 @@ package foundation.e.apps.data.cleanapk.repositories -import android.content.Context -import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.application.data.Home +import foundation.e.apps.data.application.search.SearchApi import foundation.e.apps.data.cleanapk.CleanApkDownloadInfoFetcher import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.cleanapk.data.app.CleanApkApplication import foundation.e.apps.data.cleanapk.data.categories.Categories import foundation.e.apps.data.cleanapk.data.download.Download import foundation.e.apps.data.cleanapk.data.search.Search +import foundation.e.apps.data.enums.Source import retrofit2.Response import javax.inject.Inject @@ -35,7 +35,7 @@ class CleanApkAppsRepository @Inject constructor( private val homeConverter: HomeConverter ) : CleanApkRepository, CleanApkDownloadInfoFetcher { - override suspend fun getHomeScreenData(): Map> { + override suspend fun getHomeScreenData(list: MutableList): List { val response = cleanApkRetrofit.getHomeScreenData( CleanApkRetrofit.APP_TYPE_ANY, @@ -43,24 +43,18 @@ class CleanApkAppsRepository @Inject constructor( ) val home = response.body()?.home ?: throw IllegalStateException("No home data found") - val listHome = homeConverter.toGenericHome(home, CleanApkRetrofit.APP_TYPE_ANY) + val listHome = homeConverter.toGenericHome(home, CleanApkRetrofit.APP_SOURCE_FOSS) val map = mutableMapOf>() listHome.forEach { map[it.title] = it.list } - return map - } + listHome.forEach { (title, apps) -> + apps.forEach { app -> app.source = Source.OPEN_SOURCE } + list.add(Home(title, apps, SearchApi.APP_TYPE_OPEN)) + } - override suspend fun getSearchResult(query: String, searchBy: String?): Response { - return cleanApkRetrofit.searchApps( - query, - CleanApkRetrofit.APP_SOURCE_FOSS, - CleanApkRetrofit.APP_TYPE_ANY, - NUMBER_OF_ITEMS, - NUMBER_OF_PAGES, - searchBy - ) + return list } override suspend fun getAppsByCategory( @@ -87,9 +81,32 @@ class CleanApkAppsRepository @Inject constructor( return cleanApkRetrofit.checkAvailablePackages(packageNames) } - override suspend fun getAppDetails(packageNameOrId: String): Application { - val response = cleanApkRetrofit.getAppOrPWADetailsByID(packageNameOrId, null, null) - return response.body()?.app ?: throw IllegalStateException("No app data found") + override suspend fun getAppDetails(packageName: String): Application { + val apps = cleanApkRetrofit.checkAvailablePackages(listOf(packageName)) + val app = apps.body()?.apps?.firstOrNull() ?: return Application() + val response = cleanApkRetrofit.getAppOrPWADetailsByID(app._id, null, null) + return response.body()?.app ?: return Application() + } + + override suspend fun getSearchResults(pattern: String): List { + val searchResult = cleanApkRetrofit.searchApps( + pattern, + CleanApkRetrofit.APP_SOURCE_FOSS, + CleanApkRetrofit.APP_TYPE_NATIVE, + NUMBER_OF_ITEMS, + NUMBER_OF_PAGES + ) + + val apps = searchResult.body()?.apps + apps?.forEach { app -> + app.source = if (app.is_pwa) { + Source.PWA + } else { + Source.OPEN_SOURCE + } + } + + return apps ?: emptyList() } override suspend fun getDownloadInfo(idOrPackageName: String, versionCode: Any?): Response { diff --git a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkPwaRepository.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkPwaRepository.kt index edf52f91e318cf10b35949471dc3d199e1600ec5..d6bb3b1f02d8401412e53b083b178d63b8bf1f0f 100644 --- a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkPwaRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkPwaRepository.kt @@ -21,9 +21,12 @@ package foundation.e.apps.data.cleanapk.repositories import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.application.data.Home +import foundation.e.apps.data.application.search.SearchApi import foundation.e.apps.data.cleanapk.CleanApkRetrofit import foundation.e.apps.data.cleanapk.data.categories.Categories import foundation.e.apps.data.cleanapk.data.search.Search +import foundation.e.apps.data.enums.Source import retrofit2.Response import javax.inject.Inject @@ -33,7 +36,7 @@ class CleanApkPwaRepository @Inject constructor( @ApplicationContext val context: Context ) : CleanApkRepository { - override suspend fun getHomeScreenData(): Map> { + override suspend fun getHomeScreenData(list: MutableList): List { val response = cleanApkRetrofit.getHomeScreenData( CleanApkRetrofit.APP_TYPE_PWA, CleanApkRetrofit.APP_SOURCE_ANY @@ -47,18 +50,12 @@ class CleanApkPwaRepository @Inject constructor( map[it.title] = it.list } - return map - } + listHome.forEach { (title, apps) -> + apps.forEach { app -> app.source = Source.PWA } + list.add(Home(title, apps, SearchApi.APP_TYPE_PWA)) + } - override suspend fun getSearchResult(query: String, searchBy: String?): Response { - return cleanApkRetrofit.searchApps( - query, - CleanApkRetrofit.APP_SOURCE_ANY, - CleanApkRetrofit.APP_TYPE_PWA, - 20, - 1, - searchBy - ) + return list } override suspend fun getAppsByCategory(category: String, paginationParameter: Any?): Response { @@ -82,8 +79,31 @@ class CleanApkPwaRepository @Inject constructor( return cleanApkRetrofit.checkAvailablePackages(packageNames) } - override suspend fun getAppDetails(packageNameOrId: String): Application { - val response = cleanApkRetrofit.getAppOrPWADetailsByID(packageNameOrId, null, null) - return response.body()?.app ?: throw IllegalStateException("No app data found") + override suspend fun getAppDetails(packageName: String): Application { + val apps = cleanApkRetrofit.checkAvailablePackages(listOf(packageName), CleanApkRetrofit.APP_TYPE_PWA) + val app = apps.body()?.apps?.firstOrNull() ?: return Application() + val response = cleanApkRetrofit.getAppOrPWADetailsByID(app._id, null, null) + return response.body()?.app ?: return Application() + } + + override suspend fun getSearchResults(pattern: String): List { + val searchResult = cleanApkRetrofit.searchApps( + pattern, + CleanApkRetrofit.APP_SOURCE_ANY, + CleanApkRetrofit.APP_TYPE_PWA, + NUMBER_OF_ITEMS, + NUMBER_OF_PAGES + ) + + val apps = searchResult.body()?.apps + apps?.forEach { app -> + app.source = if (app.is_pwa) { + Source.PWA + } else { + Source.OPEN_SOURCE + } + } + + return apps ?: emptyList() } } diff --git a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkRepository.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkRepository.kt index 2a9388f0240dcec8c8923ab72db9c7466a3942ec..3d0c19e213353397d0bf621dbc02107723eca497 100644 --- a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkRepository.kt @@ -27,7 +27,6 @@ const val NUMBER_OF_ITEMS = 20 const val NUMBER_OF_PAGES = 1 interface CleanApkRepository : StoreRepository { - suspend fun getSearchResult(query: String, searchBy: String? = null): Response suspend fun getAppsByCategory(category: String, paginationParameter: Any? = null): Response suspend fun getCategories(): Response suspend fun checkAvailablePackages(packageNames: List): Response diff --git a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/HomeConverter.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/HomeConverter.kt index a5ecafbfcbb06d7218a633e577c48883202406e2..b6e45dce2b75a94db9f05ecb42a7689c5d86f32d 100644 --- a/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/HomeConverter.kt +++ b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/HomeConverter.kt @@ -13,7 +13,7 @@ class HomeConverter @Inject constructor( private val applicationDataManager: ApplicationDataManager ) { - suspend fun toGenericHome(cleanApkHome: CleanApkHome, appType: String): List { + fun toGenericHome(cleanApkHome: CleanApkHome, appType: String): List { val list = mutableListOf() openSourceCategories.forEach { (key, value) -> diff --git a/app/src/main/java/foundation/e/apps/data/database/install/AppInstallDatabase.kt b/app/src/main/java/foundation/e/apps/data/database/install/AppInstallDatabase.kt index 424e01798ef86238d62b960696141c1a4dc7e72d..4928227462824e73374e7d12ca6342b6bf6a9e59 100644 --- a/app/src/main/java/foundation/e/apps/data/database/install/AppInstallDatabase.kt +++ b/app/src/main/java/foundation/e/apps/data/database/install/AppInstallDatabase.kt @@ -9,7 +9,7 @@ import foundation.e.apps.data.database.AppDatabase import foundation.e.apps.data.install.AppInstallDAO import foundation.e.apps.data.install.models.AppInstall -@Database(entities = [AppInstall::class], version = 5, exportSchema = false) +@Database(entities = [AppInstall::class], version = 6, exportSchema = false) @TypeConverters(AppInstallConverter::class) abstract class AppInstallDatabase : RoomDatabase() { abstract fun fusedDownloadDao(): AppInstallDAO diff --git a/app/src/main/java/foundation/e/apps/data/enums/Origin.kt b/app/src/main/java/foundation/e/apps/data/enums/Origin.kt deleted file mode 100644 index d5305b23de0f1ff6debf045272a22a9a3c6e8ab3..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/apps/data/enums/Origin.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Apps Quickly and easily install Android apps onto your device! - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package foundation.e.apps.data.enums - -enum class Origin { - CLEANAPK, - GPLAY, - GITLAB_RELEASES, -} diff --git a/app/src/main/java/foundation/e/apps/data/enums/Source.kt b/app/src/main/java/foundation/e/apps/data/enums/Source.kt index fdecbc5ee2b5b4d073dc1edd29ff82e1b4a1849a..bb10fcdbe132e18f17c140a64739a08299719cc2 100644 --- a/app/src/main/java/foundation/e/apps/data/enums/Source.kt +++ b/app/src/main/java/foundation/e/apps/data/enums/Source.kt @@ -18,18 +18,24 @@ package foundation.e.apps.data.enums enum class Source { - GPLAY, - GITLAB_RELEASES, - OPEN, + PLAY_STORE, + SYSTEM_APP, + OPEN_SOURCE, PWA; + override fun toString(): String { + return name.lowercase() + .split("_") + .joinToString(" ") { it.replaceFirstChar(Char::uppercase) } + } + companion object { fun fromString(source: String): Source { return when (source) { - "Open Source" -> OPEN + "Open Source" -> OPEN_SOURCE "PWA" -> PWA - "GITLAB_RELEASES" -> GITLAB_RELEASES - else -> GPLAY + "SYSTEM_APP" -> SYSTEM_APP + else -> PLAY_STORE } } } diff --git a/app/src/main/java/foundation/e/apps/data/fdroid/FDroidRepository.kt b/app/src/main/java/foundation/e/apps/data/fdroid/FDroidRepository.kt index 34fd7c4dd4a821015482a4f7c1a1bee71d472e1c..dbb9397affaa29657140e7d36aa42f8c88f2c9b8 100644 --- a/app/src/main/java/foundation/e/apps/data/fdroid/FDroidRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/fdroid/FDroidRepository.kt @@ -2,10 +2,10 @@ package foundation.e.apps.data.fdroid import android.content.Context import foundation.e.apps.data.cleanapk.ApkSignatureManager -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.fdroid.models.BuildInfo import foundation.e.apps.data.fdroid.models.FdroidEntity import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.enums.Source import javax.inject.Inject import javax.inject.Singleton @@ -41,7 +41,7 @@ class FDroidRepository @Inject constructor( } override suspend fun getAuthorName(application: Application): String { - if (application.author != UNKNOWN || application.origin != Origin.CLEANAPK) { + if (application.author != UNKNOWN || (application.source != Source.OPEN_SOURCE && application.source != Source.PWA)) { return application.author.ifEmpty { UNKNOWN } } diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt b/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt index bdce73bf50d072cf2d49018b1ac10ffe2c8fbf22..e6f9e290ac50d619492af63f26d530ed27715ab3 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt @@ -22,6 +22,7 @@ import android.os.Build import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.application.ApplicationDataManager import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.gitlab.UpdatableSystemAppsApi.* import foundation.e.apps.data.gitlab.models.OsReleaseType @@ -254,8 +255,8 @@ class SystemAppsUpdatesRepository @Inject constructor( app.run { applicationDataManager.updateStatus(this) + source = Source.SYSTEM_APP updateList.add(this) - updateSource(context) } } diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt b/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt index 7361cfb644a958c53aa04fd32bd80da9ed037e0b..a80aad3125fda9019e511a055de38a02d1dae78a 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt @@ -23,7 +23,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.squareup.moshi.Json import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin import java.util.UUID @JsonIgnoreProperties(ignoreUnknown = true) @@ -53,7 +52,6 @@ fun SystemAppInfo.toApplication(context: Context): Application { latest_version_number = versionName, name = name, package_name = packageName, - origin = Origin.GITLAB_RELEASES, originalSize = apkSize, appSize = Formatter.formatFileSize(context, apkSize), url = downloadUrl, diff --git a/app/src/main/java/foundation/e/apps/data/install/AppManagerWrapper.kt b/app/src/main/java/foundation/e/apps/data/install/AppManagerWrapper.kt index 119b5653a84f76adbce3e4232f5f7ec2ffd5dc68..3a54630e064e3fcf4bdb127733318c583c39e59d 100644 --- a/app/src/main/java/foundation/e/apps/data/install/AppManagerWrapper.kt +++ b/app/src/main/java/foundation/e/apps/data/install/AppManagerWrapper.kt @@ -176,7 +176,7 @@ class AppManagerWrapper @Inject constructor( fun getDownloadingItemStatus(application: Application?, downloadList: List): Status? { application?.let { app -> val downloadingItem = - downloadList.find { it.origin == app.origin && (it.packageName == app.package_name || it.id == app.package_name) } + downloadList.find { it.packageName == app.package_name || it.id == app.package_name } return downloadingItem?.status } return null diff --git a/app/src/main/java/foundation/e/apps/data/install/models/AppInstall.kt b/app/src/main/java/foundation/e/apps/data/install/models/AppInstall.kt index 13477a2f42bedf5e0661220c786758a3c4025a8b..af28c92a894705bd619cb10a3db32003f9808f4f 100644 --- a/app/src/main/java/foundation/e/apps/data/install/models/AppInstall.kt +++ b/app/src/main/java/foundation/e/apps/data/install/models/AppInstall.kt @@ -3,19 +3,17 @@ package foundation.e.apps.data.install.models import androidx.room.Entity import androidx.room.Ignore import androidx.room.PrimaryKey -import androidx.room.TypeConverter import com.aurora.gplayapi.data.models.ContentRating import com.aurora.gplayapi.data.models.File -import com.google.gson.Gson import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.Type @Entity(tableName = "FusedDownload") data class AppInstall( @PrimaryKey val id: String = String(), - val origin: Origin = Origin.CLEANAPK, + val source: Source = Source.PLAY_STORE, var status: Status = Status.UNAVAILABLE, val name: String = String(), val packageName: String = String(), @@ -47,7 +45,7 @@ data class AppInstall( fun areFilesDownloaded() = downloadIdMap.isNotEmpty() && !downloadIdMap.values.contains(false) fun getAppIconUrl(): String { - if (this.origin == Origin.CLEANAPK) { + if (this.source == Source.PLAY_STORE || this.source == Source.PWA) { return "${CleanApkRetrofit.ASSET_URL}${this.iconImageUrl}" } return this.iconImageUrl diff --git a/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt b/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt index 9977924a97e165fb4e867fe5c73fd2f760b3bf1d..c84e5845f329736575f749ad7e1920ec3d1e0213 100644 --- a/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt @@ -24,7 +24,6 @@ import com.aurora.gplayapi.data.models.App as GplayApp import com.aurora.gplayapi.data.models.Category import com.aurora.gplayapi.data.models.ContentRating import com.aurora.gplayapi.data.models.File -import com.aurora.gplayapi.data.models.SearchBundle import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.helpers.AppDetailsHelper import com.aurora.gplayapi.helpers.ContentRatingHelper @@ -38,9 +37,12 @@ import com.aurora.gplayapi.helpers.web.WebTopChartsHelper 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.data.Application +import foundation.e.apps.data.application.data.Home import foundation.e.apps.data.application.utils.CategoryType import foundation.e.apps.data.application.utils.toApplication +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.login.AuthenticatorRepository import foundation.e.apps.data.playstore.utils.GPlayHttpClient import kotlinx.coroutines.Dispatchers @@ -51,10 +53,10 @@ import javax.inject.Inject class PlayStoreRepository @Inject constructor( @ApplicationContext private val context: Context, private val gPlayHttpClient: GPlayHttpClient, - private val authenticatorRepository: AuthenticatorRepository + private val authenticatorRepository: AuthenticatorRepository, + private val applicationDataManager: ApplicationDataManager ) : StoreRepository { - - override suspend fun getHomeScreenData(): Map> { + override suspend fun getHomeScreenData(list: MutableList): List { val homeScreenData = mutableMapOf>() val homeElements = createTopChartElements() @@ -67,7 +69,18 @@ class PlayStoreRepository @Inject constructor( homeScreenData[it.key] = result } - return homeScreenData + homeScreenData.map { + val fusedApps = it.value.map { app -> + app.apply { + applicationDataManager.updateStatus(this) + applicationDataManager.updateFilterLevel(this) + source = Source.PLAY_STORE + } + } + list.add(Home(it.key, fusedApps)) + } + + return list } private fun createTopChartElements() = mutableMapOf( @@ -79,31 +92,11 @@ class PlayStoreRepository @Inject constructor( context.getString(R.string.movers_shakers_games) to mapOf(Chart.MOVERS_SHAKERS to Type.GAME), ) - fun getSearchResult( - query: String, - subBundle: MutableSet? - ): Pair, MutableSet> { - val searchHelper = WebSearchHelper().using(gPlayHttpClient) - - Timber.d("Fetching search result for $query, subBundle: $subBundle") - - val searchResult = if (subBundle != null) { - Timber.d("fetching next page search data...") - searchHelper.next(subBundle) - } else { - searchHelper.searchResults(query) + override suspend fun getSearchResults(pattern: String): List { + val searchResult = WebSearchHelper().using(gPlayHttpClient).searchResults(pattern) + return searchResult.appList.map { + it.toApplication(context) } - - return getSearchResultPair(searchResult, query) - } - - private fun getSearchResultPair( - searchBundle: SearchBundle, - query: String - ): Pair, MutableSet> { - val apps = searchBundle.appList - Timber.d("Found ${apps.size} apps for query, $query") - return Pair(apps, searchBundle.subBundles) } suspend fun getSearchSuggestions(query: String): List { @@ -145,14 +138,14 @@ class PlayStoreRepository @Inject constructor( return categoryList } - override suspend fun getAppDetails(packageNameOrId: String): Application { + override suspend fun getAppDetails(packageName: String): Application { var appDetails: GplayApp? val appDetailsHelper = AppDetailsHelper(authenticatorRepository.getGPlayAuthOrThrow()).using(gPlayHttpClient) withContext(Dispatchers.IO) { - appDetails = appDetailsHelper.getAppByPackageName(packageNameOrId) + appDetails = appDetailsHelper.getAppByPackageName(packageName) } if (appDetails?.versionCode == 0) { @@ -162,23 +155,6 @@ class PlayStoreRepository @Inject constructor( return appDetails?.toApplication(context) ?: Application() } - suspend fun getAppsDetails(packageNamesOrIds: List): List { - val appDetailsList = mutableListOf() - - val appDetailsHelper = - AppDetailsHelper(authenticatorRepository.getGPlayAuthOrThrow()).using(gPlayHttpClient) - - withContext(Dispatchers.IO) { - appDetailsList.addAll(appDetailsHelper.getAppByPackageName(packageNamesOrIds)) - } - - if (appDetailsList.first().versionCode == 0) { - throw IllegalStateException("App version code cannot be 0") - } - - return appDetailsList - } - private fun getCategoryType(type: CategoryType): Category.Type { return if (type == CategoryType.APPLICATION) Category.Type.APPLICATION else Category.Type.GAME @@ -191,7 +167,12 @@ class PlayStoreRepository @Inject constructor( val topApps = mutableListOf() withContext(Dispatchers.IO) { val topChartsHelper = WebTopChartsHelper().using(gPlayHttpClient) - topApps.addAll(topChartsHelper.getCluster(type.value, chart.value).clusterAppList) + try { + topApps.addAll(topChartsHelper.getCluster(type.value, chart.value).clusterAppList) + } catch (exception: Exception) { + Timber.w("Could not get top apps: $exception") + topApps.addAll(emptyList()) + } } return topApps.map { diff --git a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt index d6cd28ffa5f728e6df0dfd494756aabbc7b5854a..068efbb3f7ee149f01bc986ca8dd2e7f9dbc90ad 100644 --- a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt @@ -20,11 +20,9 @@ package foundation.e.apps.data.updates import android.content.Context import android.content.pm.ApplicationInfo -import com.aurora.gplayapi.data.models.AuthData import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.blockedApps.BlockedAppRepository import foundation.e.apps.data.cleanapk.ApkSignatureManager -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.isUnFiltered @@ -33,13 +31,11 @@ import foundation.e.apps.data.fdroid.FDroidRepository import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_ANY import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.gitlab.SystemAppsUpdatesRepository import foundation.e.apps.data.handleNetworkResult -import foundation.e.apps.data.login.AuthObject import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.install.pkg.AppLoungePackageManager -import foundation.e.apps.utils.eventBus.AppEvent -import foundation.e.apps.utils.eventBus.EventBus import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -68,7 +64,7 @@ class UpdatesManagerImpl @Inject constructor( private val userApplications: List get() = appLoungePackageManager.getAllUserApps() - suspend fun getUpdates(authData: AuthData): Pair, ResultStatus> { + suspend fun getUpdates(): Pair, ResultStatus> { val updateList = mutableListOf() var status = ResultStatus.OK @@ -103,7 +99,7 @@ class UpdatesManagerImpl @Inject constructor( status = getUpdatesFromApi({ applicationRepository.getApplicationDetails( openSourceInstalledApps, - Origin.CLEANAPK + Source.OPEN_SOURCE ) }, updateList) } @@ -115,8 +111,7 @@ class UpdatesManagerImpl @Inject constructor( val gplayStatus = getUpdatesFromApi({ getGPlayUpdates( - gPlayInstalledApps, - authData + gPlayInstalledApps ) }, updateList) @@ -158,7 +153,7 @@ class UpdatesManagerImpl @Inject constructor( status = getUpdatesFromApi({ applicationRepository.getApplicationDetails( openSourceInstalledApps, - Origin.CLEANAPK + Source.OPEN_SOURCE ) }, updateList) } @@ -278,7 +273,6 @@ class UpdatesManagerImpl @Inject constructor( */ private suspend fun getGPlayUpdates( packageNames: List, - authData: AuthData ): Pair, ResultStatus> { val appsResults = coroutineScope { @@ -287,7 +281,7 @@ class UpdatesManagerImpl @Inject constructor( applicationRepository.getApplicationDetails( "", packageName, - Origin.GPLAY + Source.PLAY_STORE ) } } @@ -327,11 +321,15 @@ class UpdatesManagerImpl @Inject constructor( packageName: String, appsAndSignatures: HashMap ) { - val cleanApkFusedApp = applicationRepository.getCleanapkAppDetails(packageName).first - if (cleanApkFusedApp.package_name.isBlank()) { + val apps = applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).first + if (apps.isEmpty()) { return } - appsAndSignatures[packageName] = getPgpSignature(cleanApkFusedApp) + + if (apps[0].package_name.isBlank()) { + return + } + appsAndSignatures[packageName] = getPgpSignature(apps[0]) } private suspend fun getPgpSignature(cleanApkApplication: Application): String { diff --git a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerRepository.kt b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerRepository.kt index 7e030148cba5bad60bbad84259e3330673416214..581ce4fa9f9db61bc893690f9d22ab019a568448 100644 --- a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerRepository.kt @@ -32,7 +32,7 @@ class UpdatesManagerRepository @Inject constructor( if (UpdatesDao.hasAnyAppsForUpdate()) { return Pair(UpdatesDao.appsAwaitingForUpdate, ResultStatus.OK) } - return updatesManagerImpl.getUpdates(authData).run { + return updatesManagerImpl.getUpdates().run { val filteredApps = first.filter { !(!it.isFree && authData.isAnonymous) } UpdatesDao.addItemsForUpdate(filteredApps) Pair(filteredApps, this.second) diff --git a/app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt b/app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt index 4da0219edc6d25c01ee84d14194fc8b603f0a7ea..00b9f17765103ba7ba1e4b1317af7963b29403da 100644 --- a/app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt +++ b/app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt @@ -22,7 +22,7 @@ import com.aurora.gplayapi.data.models.ContentRating import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.application.apps.AppsApi import foundation.e.apps.data.blockedApps.BlockedAppRepository -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Type import foundation.e.apps.data.install.models.AppInstall import foundation.e.apps.data.parentalcontrol.Age @@ -84,17 +84,17 @@ class ValidateAppAgeLimitUseCase @Inject constructor( } private fun isGitlabApp(app: AppInstall): Boolean { - return app.origin == Origin.GITLAB_RELEASES + return app.source == Source.SYSTEM_APP } private fun isCleanApkApp(app: AppInstall): Boolean { return app.id.isNotBlank() - && app.origin == Origin.CLEANAPK + && (app.source == Source.PWA || app.source == Source.OPEN_SOURCE) && app.type == Type.NATIVE } private fun isWhiteListedCleanApkApp(app: AppInstall): Boolean { - return app.origin == Origin.CLEANAPK + return app.source == Source.OPEN_SOURCE || app.source == Source.PWA } private suspend fun isNsfwAppByCleanApkApi(app: AppInstall): Boolean { @@ -133,7 +133,7 @@ class ValidateAppAgeLimitUseCase @Inject constructor( } private suspend fun hasNoContentRatingOnGPlay(app: AppInstall): Boolean { - return app.origin == Origin.GPLAY && !verifyContentRatingExists(app) + return app.source == Source.PLAY_STORE && !verifyContentRatingExists(app) } private fun isValidAppAgeRating( diff --git a/app/src/main/java/foundation/e/apps/install/download/DownloadManagerUtils.kt b/app/src/main/java/foundation/e/apps/install/download/DownloadManagerUtils.kt index 689f70343f4e535527464c51090b1e34d94fcaef..4f0086cdf91dadf9f6e17bd5112232e7d6e4358c 100644 --- a/app/src/main/java/foundation/e/apps/install/download/DownloadManagerUtils.kt +++ b/app/src/main/java/foundation/e/apps/install/download/DownloadManagerUtils.kt @@ -22,7 +22,7 @@ import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.R import foundation.e.apps.data.DownloadManager -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.install.AppManagerWrapper import foundation.e.apps.data.install.models.AppInstall @@ -164,7 +164,7 @@ class DownloadManagerUtils @Inject constructor( } private suspend fun checkCleanApkSignatureOK(appInstall: AppInstall): Boolean { - if (appInstall.origin != Origin.CLEANAPK || appManagerWrapper.isFDroidApplicationSigned( + if ((appInstall.source != Source.PWA && appInstall.source != Source.OPEN_SOURCE) || appManagerWrapper.isFDroidApplicationSigned( context, appInstall ) ) { diff --git a/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt b/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt index 43e97d19865fe702bd1a407aea39d13090cacf7e..e61c84164f294a0a8cf637a4205f100e1c2dd793 100644 --- a/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt +++ b/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt @@ -33,7 +33,7 @@ import androidx.core.content.pm.PackageInfoCompat import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.OpenForTesting import foundation.e.apps.data.application.search.SearchApi -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.Type import foundation.e.apps.data.install.models.AppInstall @@ -124,7 +124,7 @@ class AppLoungePackageManager @Inject constructor( if (appInstall == null || appInstall.packageName.isBlank()) { return } - if (appInstall.origin == Origin.GPLAY) { + if (appInstall.source == Source.PLAY_STORE) { if (appInstall.type == Type.NATIVE && isInstalled(FAKE_STORE_PACKAGE_NAME)) { val targetPackage = appInstall.packageName try { diff --git a/app/src/main/java/foundation/e/apps/install/workmanager/AppInstallProcessor.kt b/app/src/main/java/foundation/e/apps/install/workmanager/AppInstallProcessor.kt index e96a9b5ac75fe22b7bfb3597738dc2fd983cb95e..58cc4ca8196a592b58b406374a3504d1ec6e89fb 100644 --- a/app/src/main/java/foundation/e/apps/install/workmanager/AppInstallProcessor.kt +++ b/app/src/main/java/foundation/e/apps/install/workmanager/AppInstallProcessor.kt @@ -29,7 +29,7 @@ import foundation.e.apps.data.enums.Type import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.UpdatesDao import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.User import foundation.e.apps.data.install.models.AppInstall import foundation.e.apps.data.login.AuthObject @@ -83,7 +83,7 @@ class AppInstallProcessor @Inject constructor( ) { val appInstall = AppInstall( application._id, - application.origin, + application.source, application.status, application.name, application.package_name, @@ -100,7 +100,7 @@ class AppInstallProcessor @Inject constructor( it.contentRating = application.contentRating } - if (appInstall.type == Type.PWA || application.origin == Origin.GITLAB_RELEASES) { + if (appInstall.type == Type.PWA || application.source == Source.SYSTEM_APP) { appInstall.downloadURLList = mutableListOf(application.url) } @@ -221,7 +221,7 @@ class AppInstallProcessor @Inject constructor( appInstall: AppInstall ) { applicationRepository.updateFusedDownloadWithDownloadingInfo( - appInstall.origin, appInstall + appInstall.source, appInstall ) } diff --git a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt index 1b262b85f0f6d28e447c22bbb81b590f8767e89b..1cd4991b512b474bfad5af2e3aafcabc887a6b38 100644 --- a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt +++ b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt @@ -38,7 +38,7 @@ import foundation.e.apps.contract.ParentalControlContract.PATH_BLOCKLIST import foundation.e.apps.contract.ParentalControlContract.PATH_LOGIN_TYPE import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.blockedApps.BlockedAppRepository -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.install.models.AppInstall import foundation.e.apps.data.login.AuthenticatorRepository import foundation.e.apps.data.login.exceptions.GPlayLoginException @@ -204,7 +204,7 @@ class AgeRatingProvider : ContentProvider() { private suspend fun isAppValidRegardingAge(packageName: String): Boolean? { val fakeAppInstall = AppInstall( packageName = packageName, - origin = Origin.GPLAY + source = Source.PLAY_STORE ) val validateResult = validateAppAgeLimitUseCase.invoke(fakeAppInstall) saveContentRatingIfInvalid(validateResult, packageName) @@ -230,7 +230,7 @@ class AgeRatingProvider : ContentProvider() { private suspend fun isAppValidRegardingNSFW(packageName: String): Boolean { val fakeAppInstall = AppInstall( packageName = packageName, - origin = Origin.CLEANAPK, + source = Source.OPEN_SOURCE, ) val validateResult = validateAppAgeLimitUseCase.invoke(fakeAppInstall) return validateResult.data?.isValid ?: false diff --git a/app/src/main/java/foundation/e/apps/ui/LoginViewModel.kt b/app/src/main/java/foundation/e/apps/ui/LoginViewModel.kt index 3c8c363877677cc24bcc668d4d65577cc872b1eb..16cb8c28313d9533d8bcef30449270fcc280e7e4 100644 --- a/app/src/main/java/foundation/e/apps/ui/LoginViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/LoginViewModel.kt @@ -21,6 +21,8 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import foundation.e.apps.data.Stores +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.User import foundation.e.apps.data.login.AuthObject import foundation.e.apps.data.login.AuthenticatorRepository @@ -37,6 +39,7 @@ import javax.inject.Inject class LoginViewModel @Inject constructor( private val authenticatorRepository: AuthenticatorRepository, private val cache: Cache, + private val stores: Stores ) : ViewModel() { /** @@ -68,6 +71,7 @@ class LoginViewModel @Inject constructor( */ fun initialAnonymousLogin(onUserSaved: () -> Unit) { viewModelScope.launch { + stores.enableStore(Source.PLAY_STORE) authenticatorRepository.saveUserType(User.ANONYMOUS) onUserSaved() startLoginFlow() @@ -82,6 +86,7 @@ class LoginViewModel @Inject constructor( */ fun initialGoogleLogin(email: String, oauthToken: String, onUserSaved: () -> Unit) { viewModelScope.launch { + stores.enableStore(Source.PLAY_STORE) authenticatorRepository.saveGoogleLogin(email, oauthToken) authenticatorRepository.saveUserType(User.GOOGLE) onUserSaved() @@ -98,6 +103,7 @@ class LoginViewModel @Inject constructor( */ fun initialNoGoogleLogin(onUserSaved: () -> Unit) { viewModelScope.launch { + stores.disableStore(Source.PLAY_STORE) authenticatorRepository.setNoGoogleMode() onUserSaved() startLoginFlow() diff --git a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt index 91848af3e71c6be16d559704afc5f9be385c1e57..59d88fcd0cc98d4519cf7f770caf62a627742250 100644 --- a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt @@ -130,6 +130,7 @@ class MainActivity : AppCompatActivity() { override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) checkGPlayLoginRequest(intent) + findNavController(R.id.fragment).handleDeepLink(intent) } private fun checkGPlayLoginRequest(intent: Intent?) { diff --git a/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt index a91df34c0a14aa75496fabec647149c8157d8f99..2649b66cf4de16021e99eb83774f4724277edb0f 100644 --- a/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt @@ -34,6 +34,7 @@ import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.blockedApps.BlockedAppRepository import foundation.e.apps.data.ecloud.EcloudRepository +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.User import foundation.e.apps.data.enums.isInitialized import foundation.e.apps.data.enums.isUnFiltered @@ -232,7 +233,7 @@ class MainActivityViewModel @Inject constructor( ) { applicationList.forEach { val downloadingItem = appInstallList.find { fusedDownload -> - fusedDownload.origin == it.origin && (fusedDownload.packageName == it.package_name || fusedDownload.id == it._id) + fusedDownload.source == it.source && (fusedDownload.packageName == it.package_name || fusedDownload.id == it._id) } it.status = downloadingItem?.status ?: applicationRepository.getFusedAppInstallationStatus(it) diff --git a/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt index 9722b8c254e902ec954c506691f6ad11c5d3663c..f5ee3f4763ad4d444dd603d384fbe40f0a20849b 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt @@ -22,7 +22,6 @@ import android.annotation.SuppressLint import android.content.Intent import android.graphics.Color import android.graphics.drawable.Drawable -import android.net.Uri import android.os.Bundle import android.text.Html import android.text.format.Formatter @@ -56,8 +55,8 @@ import foundation.e.apps.R import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.shareUri import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.User import foundation.e.apps.data.enums.isInitialized @@ -109,19 +108,6 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { activity?.intent?.data?.host?.equals("f-droid.org") ?: false } - /* - * We will use this variable in all cases instead of directly calling args.origin. - * - * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 - */ - private val origin by lazy { - if (isFdroidDeepLink) { - Origin.CLEANAPK - } else { - args.origin - } - } - private var isDetailsLoaded = false private lateinit var screenshotsRVAdapter: ApplicationScreenshotsRVAdapter @@ -330,7 +316,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { binding.infoInclude.apply { appUpdatedOn.text = getString( R.string.updated_on, - if (origin == Origin.CLEANAPK) it.updatedOn else it.last_modified + if (it.source == Source.PWA || it.source == Source.OPEN_SOURCE) it.updatedOn else it.last_modified ) val notAvailable = getString(R.string.not_available) appRequires.text = getString(R.string.min_android_version, notAvailable) @@ -437,12 +423,10 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } updateCategoryTitle(it) - - if (it.origin == Origin.CLEANAPK) { + val source = if (isFdroidDeepLink) Source.OPEN_SOURCE else args.source + if (source == Source.OPEN_SOURCE || source == Source.PWA) { sourceTag.visibility = View.VISIBLE - sourceTag.text = it.source - } - if (origin == Origin.CLEANAPK) { + sourceTag.text = it.source.toString() appIcon.load(CleanApkRetrofit.ASSET_URL + it.icon_image_path) } else { appIcon.load(it.icon_image_path) @@ -491,7 +475,8 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } private fun setupScreenshotRVAdapter() { - screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(origin) + val source = if (isFdroidDeepLink) Source.OPEN_SOURCE else args.source + screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(source) binding.recyclerView.apply { adapter = screenshotsRVAdapter layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) @@ -602,14 +587,16 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { /* Remove trailing slash (if present) that can become part of the packageName */ val packageName = args.packageName.run { if (endsWith('/')) dropLast(1) else this } + val source = if (isFdroidDeepLink) Source.OPEN_SOURCE else args.source val applicationLoadingParams = ApplicationLoadingParams( args.id, packageName, - origin, + source, isFdroidDeepLink, authObjectList, args.isPurchased ) + applicationViewModel.loadData(applicationLoadingParams) { clearAndRestartGPlayLogin() true diff --git a/app/src/main/java/foundation/e/apps/ui/application/ApplicationViewModel.kt b/app/src/main/java/foundation/e/apps/ui/application/ApplicationViewModel.kt index 15c1ce8c1a64a46c50e5384f1382959728a89863..dcfe7432e4e682ff5397af1b1b75ccaadc7cd4e6 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/ApplicationViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/ApplicationViewModel.kt @@ -28,8 +28,8 @@ import foundation.e.apps.R import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.shareUri -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.Status import foundation.e.apps.data.install.AppManagerWrapper import foundation.e.apps.data.install.models.AppInstall @@ -87,7 +87,7 @@ class ApplicationViewModel @Inject constructor( * If user is viewing only open source apps, auth object list will not have * GPlayAuth, it will only have CleanApkAuth. */ - if (gPlayObj == null && params.origin == Origin.GPLAY) { + if (gPlayObj == null && (params.source == Source.OPEN_SOURCE || params.source == Source.PWA)) { _errorMessageLiveData.postValue(R.string.gplay_data_for_oss) return } @@ -106,7 +106,7 @@ class ApplicationViewModel @Inject constructor( params.appId, params.packageName, params.isPurchased, - params.origin + params.source ) return@onLoadData } @@ -116,7 +116,7 @@ class ApplicationViewModel @Inject constructor( params.appId, params.packageName, params.isPurchased, - params.origin + params.source ) return@onLoadData } @@ -127,7 +127,7 @@ class ApplicationViewModel @Inject constructor( id: String, packageName: String, isPurchased: Boolean, - origin: Origin + source: Source ) { viewModelScope.launch(Dispatchers.IO) { try { @@ -135,7 +135,7 @@ class ApplicationViewModel @Inject constructor( applicationRepository.getApplicationDetails( id, packageName, - origin + source ) val app = result.first @@ -193,12 +193,12 @@ class ApplicationViewModel @Inject constructor( fun getCleanapkAppDetails(packageName: String) { viewModelScope.launch { try { - applicationRepository.getCleanapkAppDetails(packageName).run { - if (this.first.package_name.isBlank()) { + applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).run { + if (this.first[0].package_name.isBlank()) { _errorMessageLiveData.postValue(R.string.app_not_found) } else { - applicationLiveData.postValue(this) - updateShareVisibilityState(first.shareUri.toString()) + applicationLiveData.postValue(Pair(this.first[0], this.second)) + updateShareVisibilityState(first[0].shareUri.toString()) } } } catch (e: Exception) { @@ -244,7 +244,7 @@ sealed class ShareButtonVisibilityState { data class ApplicationLoadingParams( val appId: String, val packageName: String, - val origin: Origin, + val source: Source, val isFdroidDeepLink: Boolean, val authObjectList: List, val isPurchased: Boolean diff --git a/app/src/main/java/foundation/e/apps/ui/application/model/ApplicationScreenshotsRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/application/model/ApplicationScreenshotsRVAdapter.kt index 7fa122efba5dbda14212c3740f97415e30ba9967..6119dfb12a89d9748a9b8087b3fdedf38199730b 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/model/ApplicationScreenshotsRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/model/ApplicationScreenshotsRVAdapter.kt @@ -25,12 +25,12 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import coil.load import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.databinding.ApplicationScreenshotsListItemBinding import foundation.e.apps.ui.application.ApplicationFragmentDirections class ApplicationScreenshotsRVAdapter( - private val origin: Origin + private val source: Source ) : RecyclerView.Adapter() { @@ -51,14 +51,17 @@ class ApplicationScreenshotsRVAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val imageView = holder.binding.imageView - when (origin) { - Origin.CLEANAPK -> { + when (source) { + Source.PWA -> { imageView.load(CleanApkRetrofit.ASSET_URL + oldList[position]) } - Origin.GPLAY -> { + Source.OPEN_SOURCE -> { + imageView.load(CleanApkRetrofit.ASSET_URL + oldList[position]) + } + Source.PLAY_STORE -> { imageView.load(oldList[position]) } - Origin.GITLAB_RELEASES -> { + Source.SYSTEM_APP -> { // no operation } } @@ -67,7 +70,7 @@ class ApplicationScreenshotsRVAdapter( ApplicationFragmentDirections.actionApplicationFragmentToScreenshotFragment( oldList.toTypedArray(), position, - origin + source ) it.findNavController().navigate(action) } diff --git a/app/src/main/java/foundation/e/apps/ui/application/model/ScreenshotRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/application/model/ScreenshotRVAdapter.kt index 01fe6c50bb700126ca7252f5748512f530a7eb57..c065af546076e1335cee3cfe1a3c31e620a3a02e 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/model/ScreenshotRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/model/ScreenshotRVAdapter.kt @@ -27,10 +27,10 @@ import androidx.swiperefreshlayout.widget.CircularProgressDrawable import coil.load import foundation.e.apps.R import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.databinding.ScreenshotListItemBinding -class ScreenshotRVAdapter(private val list: List, private val origin: Origin) : +class ScreenshotRVAdapter(private val list: List, private val source: Source) : RecyclerView.Adapter() { private lateinit var circularProgressDrawable: CircularProgressDrawable @@ -55,13 +55,18 @@ class ScreenshotRVAdapter(private val list: List, private val origin: Or override fun onBindViewHolder(holder: ViewHolder, position: Int) { val imageView = holder.binding.imageView - when (origin) { - Origin.CLEANAPK -> { + when (source) { + Source.PWA -> { imageView.load(CleanApkRetrofit.ASSET_URL + list[position]) { placeholder(circularProgressDrawable) } } - Origin.GPLAY -> { + Source.OPEN_SOURCE -> { + imageView.load(CleanApkRetrofit.ASSET_URL + list[position]) { + placeholder(circularProgressDrawable) + } + } + Source.PLAY_STORE -> { imageView.load(list[position]) { placeholder(circularProgressDrawable) } diff --git a/app/src/main/java/foundation/e/apps/ui/application/subFrags/ScreenshotFragment.kt b/app/src/main/java/foundation/e/apps/ui/application/subFrags/ScreenshotFragment.kt index eb65823eeacb013f5ab823934087a3c03dc60cc7..2b5e4bddae138cd40c1af2aeba4629edafa84f9c 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/subFrags/ScreenshotFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/subFrags/ScreenshotFragment.kt @@ -45,7 +45,7 @@ class ScreenshotFragment : Fragment(R.layout.fragment_screenshot) { view.findNavController().navigateUp() } - val screenshotRVAdapter = ScreenshotRVAdapter(args.list.toList(), args.origin) + val screenshotRVAdapter = ScreenshotRVAdapter(args.list.toList(), args.source) binding.viewPager.apply { adapter = screenshotRVAdapter currentItem = args.position diff --git a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt index ef7aa73a697017cbc49b84990e62dbb39f3277f1..3c5fc507d65654fade934894f4cae6a87e219ae5 100644 --- a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt @@ -165,6 +165,7 @@ class ApplicationListFragment : if (it != null && it.isSuccess()) { observeDownloadList(listAdapter, it) } + listAdapter.setData(it?.data ?: emptyList(), args.translation) } } diff --git a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt index 66cc24c811a8a2d708dbbced255990bd933267e0..d8855538c6f7f85318650a69bb25f77989b7867d 100644 --- a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt @@ -41,11 +41,11 @@ import com.google.android.material.button.MaterialButton import com.google.android.material.snackbar.Snackbar import foundation.e.apps.R import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.User import foundation.e.apps.data.application.ApplicationInstaller import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.enums.Source import foundation.e.apps.databinding.ApplicationListItemBinding import foundation.e.apps.install.pkg.InstallerService import foundation.e.apps.ui.AppInfoFetchViewModel @@ -169,23 +169,27 @@ class ApplicationListRVAdapter( searchApp: Application, shimmerDrawable: ShimmerDrawable ) { - when (searchApp.origin) { - Origin.GPLAY -> { + when (searchApp.source) { + Source.PLAY_STORE -> { appIcon.load(searchApp.icon_image_path) { placeholder(shimmerDrawable) } } - Origin.CLEANAPK -> { + Source.PWA -> { appIcon.load(CleanApkRetrofit.ASSET_URL + searchApp.icon_image_path) { placeholder(shimmerDrawable) } } - Origin.GITLAB_RELEASES -> { + Source.OPEN_SOURCE -> { + appIcon.load(CleanApkRetrofit.ASSET_URL + searchApp.icon_image_path) { + placeholder(shimmerDrawable) + } + } + Source.SYSTEM_APP -> { appIcon.load(getAppIcon(appIcon.context, searchApp.package_name)) { placeholder(shimmerDrawable) } } - else -> Timber.wtf("${searchApp.package_name} is from an unknown origin") } } @@ -235,12 +239,7 @@ class ApplicationListRVAdapter( } private fun ApplicationListItemBinding.updateSourceTag(searchApp: Application) { - if (searchApp.source.isEmpty()) { - sourceTag.visibility = View.INVISIBLE - } else { - sourceTag.visibility = View.VISIBLE - } - sourceTag.text = searchApp.source + sourceTag.text = searchApp.source.toString() } private fun handleAppItemClick( @@ -256,7 +255,7 @@ class ApplicationListRVAdapter( ApplicationListFragmentDirections.actionApplicationListFragmentToApplicationFragment( searchApp.package_name, searchApp._id, - searchApp.origin, + searchApp.source, catText, searchApp.isGplayReplaced, searchApp.isPurchased @@ -266,7 +265,7 @@ class ApplicationListRVAdapter( SearchFragmentDirections.actionSearchFragmentToApplicationFragment( searchApp.package_name, searchApp._id, - searchApp.origin, + searchApp.source, catText, searchApp.isGplayReplaced, searchApp.isPurchased @@ -276,7 +275,7 @@ class ApplicationListRVAdapter( UpdatesFragmentDirections.actionUpdatesFragmentToApplicationFragment( searchApp.package_name, searchApp._id, - searchApp.origin, + searchApp.source, catText, searchApp.isGplayReplaced, searchApp.isPurchased diff --git a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListViewModel.kt b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListViewModel.kt index bf4272a17563055deaa5833684382af66772ddc6..a89dd1291dd33fd7e1d16d3ae3d23b8015f2e07e 100644 --- a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListViewModel.kt @@ -155,7 +155,7 @@ class ApplicationListViewModel @Inject constructor( authData, category, nextPageUrl, - Source.GPLAY + Source.PLAY_STORE ) isLoading = false diff --git a/app/src/main/java/foundation/e/apps/ui/home/HomeViewModel.kt b/app/src/main/java/foundation/e/apps/ui/home/HomeViewModel.kt index 455a9e30445000d21b5996617ea5380e0c2c75d0..3e57bace086fe8450a271e32bb9a12d9f1601c3a 100644 --- a/app/src/main/java/foundation/e/apps/ui/home/HomeViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/home/HomeViewModel.kt @@ -22,24 +22,24 @@ import androidx.annotation.VisibleForTesting import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope -import com.aurora.gplayapi.data.models.AuthData import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.data.ResultSupreme +import foundation.e.apps.data.StoreRepository +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.data.Home +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.login.AuthObject -import foundation.e.apps.data.login.exceptions.CleanApkException -import foundation.e.apps.data.login.exceptions.GPlayException import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.ui.applicationlist.ApplicationDiffUtil import foundation.e.apps.ui.parentFragment.LoadingViewModel import kotlinx.coroutines.launch -import java.util.UUID import javax.inject.Inject @HiltViewModel class HomeViewModel @Inject constructor( private val applicationRepository: ApplicationRepository, + private val stores: Stores ) : LoadingViewModel() { @Inject @@ -55,11 +55,11 @@ class HomeViewModel @Inject constructor( var currentHomes: List? = null - private var previousSources = emptyList() + private var previousStores = mapOf() - fun hasData(): Boolean { - return homeScreenData.value?.data?.isNotEmpty() ?: false - } + fun hasData(): Boolean { + return homeScreenData.value?.data?.isNotEmpty() ?: false + } fun loadData( authObjectList: List, @@ -69,57 +69,37 @@ class HomeViewModel @Inject constructor( super.onLoadData(authObjectList, { successAuthList, _ -> successAuthList.find { it is AuthObject.GPlayAuth }?.run { - getHomeScreenData(result.data!! as AuthData, lifecycleOwner) + getHomeScreenData(lifecycleOwner) return@onLoadData } successAuthList.find { it is AuthObject.CleanApk }?.run { - getHomeScreenData(AuthData("", ""), lifecycleOwner) + getHomeScreenData(lifecycleOwner) return@onLoadData } }, retryBlock) } fun haveSourcesChanged(): Boolean { - val sources = listOf( - appLoungePreference.isGplaySelected(), - appLoungePreference.isOpenSourceSelected(), - appLoungePreference.isPWASelected() - ) - - if (sources == previousSources) { + val newStores = stores.getStores() + if (newStores == previousStores) { return false } - previousSources = sources + previousStores = newStores.toMutableMap() return true } - fun getHomeScreenData( - authData: AuthData, + private fun getHomeScreenData( lifecycleOwner: LifecycleOwner, ) { viewModelScope.launch { - applicationRepository.getHomeScreenData(authData).observe(lifecycleOwner) { + applicationRepository.getHomeScreenData().observe(lifecycleOwner) { postHomeResult(it) if (it.isSuccess()) { return@observe } - - val exception = - if (authData.aasToken.isNotBlank() || authData.authToken.isNotBlank()) - GPlayException( - it.isTimeout(), - it.message.ifBlank { "Data load error" } - ) - else CleanApkException( - it.isTimeout(), - it.message.ifBlank { "Data load error" } - ) - - exceptionsList.add(exception) - exceptionsLiveData.postValue(exceptionsList) } } } diff --git a/app/src/main/java/foundation/e/apps/ui/home/model/HomeChildRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/home/model/HomeChildRVAdapter.kt index 62886ab2d6194c2c9c0efa93ef8ba124a8373dcf..a98aaca4154c8a8f2c5e72e5abd76ad4f3dda54b 100644 --- a/app/src/main/java/foundation/e/apps/ui/home/model/HomeChildRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/ui/home/model/HomeChildRVAdapter.kt @@ -33,11 +33,11 @@ import com.google.android.material.button.MaterialButton import com.google.android.material.snackbar.Snackbar import foundation.e.apps.R import foundation.e.apps.data.cleanapk.CleanApkRetrofit -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.User import foundation.e.apps.data.application.ApplicationInstaller import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.enums.Source import foundation.e.apps.databinding.HomeChildListItemBinding import foundation.e.apps.ui.AppInfoFetchViewModel import foundation.e.apps.ui.MainActivityViewModel @@ -81,7 +81,7 @@ class HomeChildRVAdapter( val shimmerDrawable = ShimmerDrawable().apply { setShimmer(shimmer) } holder.binding.apply { - if (homeApp.origin == Origin.CLEANAPK) { + if (homeApp.source == Source.PWA || homeApp.source == Source.OPEN_SOURCE) { appIcon.load(CleanApkRetrofit.ASSET_URL + homeApp.icon_image_path) { placeholder(shimmerDrawable) } @@ -95,7 +95,7 @@ class HomeChildRVAdapter( val action = HomeFragmentDirections.actionHomeFragmentToApplicationFragment( homeApp.package_name, homeApp._id, - homeApp.origin, + homeApp.source, homeApp.category, homeApp.isGplayReplaced, homeApp.isPurchased diff --git a/app/src/main/java/foundation/e/apps/ui/parentFragment/LoadingViewModel.kt b/app/src/main/java/foundation/e/apps/ui/parentFragment/LoadingViewModel.kt index a59e502ca0bc1aa937f4afe847ac73102c5ae07f..7e7d2d3cd547341002549bf340e1c508173fdb57 100644 --- a/app/src/main/java/foundation/e/apps/ui/parentFragment/LoadingViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/parentFragment/LoadingViewModel.kt @@ -35,22 +35,22 @@ abstract class LoadingViewModel : ViewModel() { /** * Call this method from ViewModel. * - * @param authObjectList List obtained from login process. + * @param authObjects List obtained from login process. * @param loadingBlock Define how to load data in this method. * @param retryBlock Define retry mechanism for failed AuthObject. * Return `true` to signify the failure event is consumed by the block and no further * processing on failed AuthObject is needed. */ fun onLoadData( - authObjectList: List, + authObjects: List, loadingBlock: (successObjects: List, failedObjects: List) -> Unit, retryBlock: (failedObjects: List) -> Boolean, ) { exceptionsList.clear() - val successAuthList = authObjectList.filter { it.result.isSuccess() } - val failedAuthList = authObjectList.filter { !it.result.isSuccess() } + val successAuthList = authObjects.filter { it.result.isSuccess() } + val failedAuthList = authObjects.filter { !it.result.isSuccess() } failedAuthList.forEach { exceptionsList.add(it.result.exception ?: UnknownSourceException()) diff --git a/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt index f9017ec0618176c23ced6cb11941c71ceda27012..8ba57a29a08eaaa94b5cbbe80e775c96f75e6d1b 100644 --- a/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt @@ -65,6 +65,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject @AndroidEntryPoint @@ -187,6 +188,7 @@ class SearchFragment : observeDownloadList(adapter) } } + updateSearchResult(listAdapter, it.data?.first ?: emptyList()) observeScrollOfSearchResult(listAdapter) } } @@ -366,7 +368,7 @@ class SearchFragment : override fun loadData(authObjectList: List) { showLoadingUI() - searchViewModel.loadData(searchText, viewLifecycleOwner, authObjectList) { + searchViewModel.loadData(searchText, authObjectList) { clearAndRestartGPlayLogin() true } diff --git a/app/src/main/java/foundation/e/apps/ui/search/SearchViewModel.kt b/app/src/main/java/foundation/e/apps/ui/search/SearchViewModel.kt index 19820b0d9906082d5b5242f5c0e5d02ec0f03d57..2aaa106f0df3142859e9dac759a4eb6a4eab8476 100644 --- a/app/src/main/java/foundation/e/apps/ui/search/SearchViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/search/SearchViewModel.kt @@ -18,26 +18,20 @@ package foundation.e.apps.ui.search -import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.aurora.gplayapi.SearchSuggestEntry -import com.aurora.gplayapi.data.models.AuthData -import com.aurora.gplayapi.data.models.SearchBundle import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.application.search.GplaySearchResult import foundation.e.apps.data.application.search.SearchResult -import foundation.e.apps.data.enums.Origin +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.exodus.repositories.IAppPrivacyInfoRepository import foundation.e.apps.data.exodus.repositories.PrivacyScoreRepository import foundation.e.apps.data.login.AuthObject -import foundation.e.apps.di.CommonUtilsModule.LIST_OF_NULL import foundation.e.apps.ui.parentFragment.LoadingViewModel -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -64,7 +58,6 @@ class SearchViewModel @Inject constructor( private var lastAuthObjects: List? = null - private var nextSubBundle: Set? = null private var isLoading: Boolean = false private var hasGPlayBeenFetched = false @@ -105,25 +98,22 @@ class SearchViewModel @Inject constructor( fun loadData( query: String, - lifecycleOwner: LifecycleOwner, - authObjectList: List, + authObjects: List, retryBlock: (failedObjects: List) -> Boolean ) { if (query.isBlank()) return - this.lastAuthObjects = authObjectList - super.onLoadData(authObjectList, { successAuthList, failedAuthList -> - successAuthList.find { it is AuthObject.CleanApk }?.run { - fetchCleanApkData(query, null) + this.lastAuthObjects = authObjects + super.onLoadData(authObjects, { successObjects, failedObjects -> + successObjects.find { it is AuthObject.CleanApk }?.run { + fetchCleanApkData(query) } - successAuthList.find { it is AuthObject.GPlayAuth }?.run { - nextSubBundle = null + successObjects.find { it is AuthObject.GPlayAuth }?.run { fetchGplayData(query) } - failedAuthList.find { it is AuthObject.GPlayAuth }?.run { - nextSubBundle = null + failedObjects.find { it is AuthObject.GPlayAuth }?.run { fetchGplayData(query) } @@ -137,14 +127,10 @@ class SearchViewModel @Inject constructor( * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5171 */ private fun fetchCleanApkData( - query: String, - authData: AuthData? + query: String ) { viewModelScope.launch(IO) { - val searchResultSupreme = applicationRepository.getCleanApkSearchResults( - query, - authData ?: AuthData("", "") - ) + val searchResultSupreme = applicationRepository.getCleanApkSearchResults(query) hasGPlayBeenFetched = false emitFilteredResults(searchResultSupreme) @@ -173,7 +159,7 @@ class SearchViewModel @Inject constructor( viewModelScope.launch(IO) { isLoading = true val gplaySearchResult = - applicationRepository.getGplaySearchResults(query, nextSubBundle) + applicationRepository.getGplaySearchResults(query) if (!gplaySearchResult.isSuccess()) { gplaySearchResult.exception?.let { @@ -181,11 +167,9 @@ class SearchViewModel @Inject constructor( } } - nextSubBundle = gplaySearchResult.data?.second - val currentAppList = updateCurrentAppList(gplaySearchResult) val finalResult = ResultSupreme.Success( - Pair(currentAppList.toList(), nextSubBundle?.isNotEmpty() ?: false) + Pair(currentAppList.toList(), false) ) hasGPlayBeenFetched = true @@ -195,10 +179,10 @@ class SearchViewModel @Inject constructor( } } - private fun updateCurrentAppList(gplaySearchResult: GplaySearchResult): List { + private fun updateCurrentAppList(searchResult: SearchResult): List { val currentAppList = accumulatedList currentAppList.removeIf { item -> item.isPlaceHolder } - currentAppList.addAll(gplaySearchResult.data?.first ?: emptyList()) + currentAppList.addAll(searchResult.data?.first ?: emptyList()) return currentAppList.distinctBy { it.package_name } } @@ -250,7 +234,7 @@ class SearchViewModel @Inject constructor( accumulatedList.filter { if (!flagNoTrackers && !flagOpenSource && !flagPWA) return@filter true if (flagNoTrackers && !hasTrackers(it)) return@filter true - if (flagOpenSource && !it.is_pwa && it.origin == Origin.CLEANAPK) return@filter true + if (flagOpenSource && !it.is_pwa && it.source == Source.OPEN_SOURCE) return@filter true if (flagPWA && it.is_pwa) return@filter true false } diff --git a/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt b/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt index 29f8f7f858d9444fce28bef98dcbb5d1418ddaf6..0fd753a7a697d0c97b4c5dda03bad834893ebb11 100644 --- a/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt @@ -41,7 +41,10 @@ import com.google.gson.Gson import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.BuildConfig import foundation.e.apps.R +import foundation.e.apps.data.Constants +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.UpdatesDao +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.enums.User import foundation.e.apps.databinding.CustomPreferenceBinding import foundation.e.apps.install.updates.UpdatesWorkManager @@ -63,12 +66,15 @@ class SettingsFragment : PreferenceFragmentCompat() { private var showPWAApplications: CheckBoxPreference? = null private var troubleShootPreference: Preference? = null - val loginViewModel: LoginViewModel by lazy { + private val loginViewModel: LoginViewModel by lazy { ViewModelProvider(requireActivity())[LoginViewModel::class.java] } private var sourcesChangedFlag = false + @Inject + lateinit var stores: Stores + @Inject lateinit var gson: Gson @@ -87,9 +93,9 @@ class SettingsFragment : PreferenceFragmentCompat() { setPreferencesFromResource(R.xml.settings_preferences, rootKey) // Show applications preferences - showAllApplications = findPreference("showAllApplications") - showFOSSApplications = findPreference("showFOSSApplications") - showPWAApplications = findPreference("showPWAApplications") + showAllApplications = findPreference("showAllApplications") + showFOSSApplications = findPreference("showFOSSApplications") + showPWAApplications = findPreference("showPWAApplications") troubleShootPreference = findPreference(getString(R.string.having_troubles)) val updateCheckInterval = @@ -141,7 +147,13 @@ class SettingsFragment : PreferenceFragmentCompat() { * Checkbox listener to prevent all checkboxes from getting unchecked. */ private val sourceCheckboxListener = - Preference.OnPreferenceChangeListener { preference: Preference, newValue: Any? -> + OnPreferenceChangeListener { preference: Preference, newValue: Any? -> + + when (preference.key) { + Constants.PREFERENCE_SHOW_GPLAY -> updateStore(Source.PLAY_STORE, newValue == true) + Constants.PREFERENCE_SHOW_FOSS -> updateStore(Source.OPEN_SOURCE, newValue == true) + Constants.PREFERENCE_SHOW_PWA -> updateStore(Source.PWA, newValue == true) + } sourcesChangedFlag = true loginViewModel.authObjects.value = null @@ -298,4 +310,12 @@ class SettingsFragment : PreferenceFragmentCompat() { super.onDestroyView() _binding = null } + + private fun updateStore(source: Source, isEnabled: Boolean) { + if (isEnabled) { + stores.enableStore(source) + } else { + stores.disableStore(source) + } + } } diff --git a/app/src/main/res/navigation/navigation_resource.xml b/app/src/main/res/navigation/navigation_resource.xml index 90fae739dc1d077e5a0e8c4b0b1b53384e30aced..330939045d13972458066dea4f88074e383219af 100644 --- a/app/src/main/res/navigation/navigation_resource.xml +++ b/app/src/main/res/navigation/navigation_resource.xml @@ -103,9 +103,9 @@ android:name="packageName" app:argType="string" /> + android:name="source" + android:defaultValue="PLAY_STORE" + app:argType="foundation.e.apps.data.enums.Source"/> + app:uri="play.google.com/store/apps/details?id={packageName}&arguments={arguments}" /> + app:uri="f-droid.org/packages/{packageName}/" /> + app:uri="f-droid.org/{locale}/packages/{packageName}/" /> @@ -184,8 +184,8 @@ android:name="position" app:argType="integer" /> + android:name="source" + app:argType="foundation.e.apps.data.enums.Source" /> Abrufen der Inhaltsbewertungen für alle Ihre installierten Apps. Wenn Sie auf \"%1$s\" klicken, öffnet sich ein Tab in Ihrem Browser, in dem der Paketname der App schon vorausgefüllt ist. <br /><br />Klicken Sie auf „Perform analysis“, um die Analyse durch Exodus zu starten.<br /><br />Wenn die Schaltfläche „See the report“ angezeigt wird (dies kann je nach App eine Weile dauern), können Sie den Tab schließen und zur App-Beschreibung in %2$s zurückkehren, wo die Datenschutz-Bewertung angezeigt werden sollte. Manchmal kann es vorkommen, dass Exodus eine App nicht analysieren kann.<br /><br />Hinweis: Es kann bis zu 10 Min dauern, bis der Wert in der App-Beschreibung aktualisiert wird. Diese App kann Nacktheit, obszöne Ausdrücke, Verleumdungen, Sexualität, politische Inkorrektheit oder andere möglicherweise verstörende Inhalte anzeigen. Das kann fraglich sein für bestimmte Umgebungen wie Arbeitsplätze, Schulen, religiöse oder familiäre Situationen. - System-App Achtung – Aktualisierung! App Lounge wird vom System beendet, um eine Aktualisierung durchzuführen. Bitte führen Sie keine anderen Aktionen aus, bis App Lounge aktualisert und beendet ist. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 53be90f04660c482a5e14eb6970bc278c1cf6565..cd8a604121533e9dc16617c1cfbf4d1633268007 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -192,7 +192,6 @@ [%1$s] Aplicación restringida Eres demasiado joven para instalar %1$s. Por favor, comprueba con tus padres que tu grupo de edad es correcto o desactiva el control parental para poder instalar. Esta aplicación puede tener contenido inapropiado. - Aplicación del sistema Recopilando la clasificación de contenido de todas las aplicaciones que has instalado. Advertencia del contenido La aplicación puede contener desnudos, blasfemias, insultos, violencia, sexualidad intensa, incorrección política u otros temas potencialmente perturbadores. Esto es especialmente importante en entornos como lugares de trabajo, escuelas, entornos religiosos y familiares. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2a8105dbbc0d0247604f410fed9c161689cb062a..ae1667f1ea913a33decf750ef4976e1ddbb60884 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -195,7 +195,6 @@ Demander le rapport Exodus Cliquer sur \"%1$s\" ouvrira un onglet dans votre navigateur avec le nom du paquet de l\'application pré-rempli.<br /><br /> Cliquez sur \"Perform analysis\" pour lancer l\'analyse par Exodus.<br /><br /> Quand le bouton \"See the report\" apparaît (cela peut prendre un moment selon l\'application) vous pouvez fermer l\'onglet et retourner sur la description de l\'application dans %2$s où vous devriez voir la note de Confidentialité. Parfois Exodus peut échouer à analyser l\'application.<br /><br />NB : cela peut prendre jusqu\'à 10 min pour que le score apparaisse dans la description de l\'application. RENOUVELER LA SESSION - Application système Applications communes indisponibles diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 4383050edae9ad403956359505d76adcd52461ee..10db1ac7bccfb7eaf3e5225533caae65663987e8 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -194,11 +194,10 @@ Sæki umsagnir um efni fyrir öll þau forrit sem þú hefur sett upp. Þú hefur ekki aldur til að setja upp %1$s. Hafðu samráð við foreldra þína hvort aldurshópurinn þinn sé réttur eða hvort gera eigi barnalæsingu óvirka til að geta sett það upp. Forritið gæti innihaldið nekt, blótsyrði, aðdróttanir, ofbeldi, kynferðislegt efni, pólitískar rangfærslur eða annað efni sem gæti misboðið. Þetta getur valdið óþægindum á vinnustöðum, skólum, trúartengum athöfnum eða hjá fjölskyldum. - Kerfisforrit Aðvörun vegna uppfærslu! App Lounge verður lokað af kerfinu á meðan það uppfærir sjálft sig. Vertu helst ekki að gera neitt annað þangað til uppfærslu App Lounge er lokið. Forrit með opnum grunnkóða og PWA óaðgengileg Villa kom upp við að hlaða inn forritum með opnum grunnkóða og PWA. Aðeins algeng forrit eru tiltæk í augnablikinu. Algeng forrit óaðgengileg Villa kom upp við að hlaða inn algengum forritum. Aðeins forrit með opnum grunnkóða og PWA eru tiltæk í augnablikinu. - \ No newline at end of file + diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index b2dcd0b666769de486533747a0c88d84e1905e2b..95b5f2a670e27e89527e3ef85f1056fd8b8ca726 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -189,7 +189,6 @@ Account non disponibile Condividere Nessun tracciamento - App di sistema [%1$s] app con restrizioni Sei troppo giovane per poter installare %1$s. Per favore controlla con i tuoi genitori se la fascia d\'età è corretta o disabilita il controllo parentale per poter effettuare l\'installazione. Questa app potrebbe avere contenuti inappropriati. diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 5b584b7e13b324cfcb6f066136debee875e7b68e..ebfc8bc3fd5eb82c6808b0ee4a53acca3a2273a9 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -192,7 +192,6 @@ Du er for ung til å kunne installere %1$s. Vennligst sjekk med foreldrene dine om aldersgruppen din er riktig, eller deaktiver foreldrekontroll for å kunne installere det. Denne applikasjonen kan inneholde upassende innhold. Applikasjonen kan inneholde nakenhet, banning, skjellsord, vold, intens seksualitet, politisk ukorrekthet eller andre potensielt forstyrrende emner. Dette er spesielt relevant i miljøer som arbeidsplasser, skoler, religiøse miljøer og familiemiljøer. - Systemapplikasjon Innholdsvarsel Samler innholdsvurdering for alle applikasjonene du har installert. Vanlige applikasjoner er ikke tilgjengelige @@ -201,4 +200,4 @@ Det oppstod en feil under innlasting av PWA- og åpen kildekode-applikasjoner. Bare vanlige applikasjoner er tilgjengelige for øyeblikket. Advarsel om oppdatering! Systemet vil slå av App Lounge mens det installerer sin egen oppdatering. Vennligst avstå fra å utføre andre oppgaver inntil App Lounge er oppdatert. - \ No newline at end of file + diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 287ce641bf561cdaa6935e281db717d1ec5d9d88..8c3978acf0bf912f4af17a04bdaf9ae88e0109cf 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -188,7 +188,6 @@ \n\t• Impact te beperken wanneer Google dit account ingeperkt wordt Split-installatiekanaal Wanneer je klikt op \"%1$s\" zal er een tab in jouw browser geopend worden met de pakket naam van de app ingevuld.<br /><br />Klik op \"Perform analysis\" om een analyse door Exodus te starten.<br /><br />Wanneer de knop \"See the report\" wordt weergegeven (dit kan even duren afhankelijk van de app) kan je de browser tab sluiten en terugkeren naar de app beschrijving in %2$s waar je de Privacy Score kan zien. Het kan voorvallen dat de analyse door Exodus niet lukt.<br /><br />Ook kan het tot 10 min duren voor de score wordt weergegeven bij de app beschrijving. - Systeem app [%1$s] Gelimiteerde App Je bent te jong om %1$s te installeren. Bekijk met je ouders of jouw leeftijdsgroep correct is ingesteld of schakel ouderlijk toezicht uit om het te kunnen installeren. Deze app bevat mogelijk ongepaste inhoud. @@ -201,4 +200,4 @@ Open source apps en PWA niet beschikbaar Er is een fout opgetreden tijdens het laden van de algemene apps. Enkel opensource apps en PWA\'s zijn beschikbaar. Er is een fout opgetreden tijdens het laden van PWA en opensource apps. Enkel algemene apps zijn beschikbaar. - \ No newline at end of file + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 36e577c074d36f6e83129ba6d2f8c72a43d8fc57..969ca3f66444f8d24d55bfe32cdf1cd6b827345d 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -175,7 +175,6 @@ Освободите %1$s на своем телефоне, чтобы получить последние обновления. Пожалуйста, освободите немного места на вашем телефоне, чтобы App Lounge мог работать должным образом. Игнорировать - Системное приложение Перейдите к входу в систему Google Предупреждение относительно %s %s хочет установить дополнительные модули. Вам необходимо снова войти в AppLounge, чтобы иметь возможность установить их. diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 1274e94172e44eba5e22c498dc6525592ab0fead..76ababc92c9cd56a98a4498954cebe30cbb3a868 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -194,7 +194,6 @@ Du är för ung för att kunna installera %1$s. Kontrollera med din förälder om din åldersgrupp är korrekt eller inaktivera föräldrakontroll för att kunna installera den. Denna app kan innehålla nakenhet, svordomar, kränkningar, intensiv sexualitet, politisk inkorrekthet eller andra potentiellt stötande ämnen. Detta är extra relevant i miljöer som till exempel arbetsplatser, skolor, religiösa och familjesammanhang. [%1$s] Begränsad app - Systemapp Varning för uppdatering! Systemet kommer stänga App Lounge medan uppdatering installeras för App Lounge. Undvik att något annat tills App Lounge är uppdaterat och har stängts. Ett fel uppstod vid inläsning av PWA-appar och appar med öppen källkod. Endast vanliga appar är tillgängliga just nu. diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d18b67c49e54b0c1e25ce71237b7441892799e53..d9e2b5536f519cd961decce39a6910e2b2fecdfe 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -133,7 +133,6 @@ [%1$s] Kısıtlandırılmış Uygulama %1$s yükleyebilmek için çok küçüksünüz. Lütfen yaş grubunuzun doğru olup olmadığını ebeveyninizle kontrol edin veya yükleyebilmek için ebeveyn kontrolünü devre dışı bırakın. Bu uygulama uygunsuz içerik içerebilir. - Sistem uygulaması Ücretli uygulamalar anonim modda yüklenemez. Ücretli uygulamaları yüklemek için lütfen Google hesabınıza giriş yapın. Bağlantı kurulamıyor! Lütfen internet bağlantınızı kontrol edin ve tekrar deneyin Uygulamaları getirirken zaman aşımı! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 84a84cd38c6fc603f9dc4ae05c2853350830ce18..c6c3b2155c5d95701a37bb71b11985b8e387e200 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -120,7 +120,6 @@ Open Source apps Some proprietary apps may also have an Open Source version. Whenever this happens App Lounge shows the Open Source version only, in order to avoid duplicates. Downloading… - System app Additional file for %s Having troubles? https://e.foundation/%1$s/get-e-os/#applounge diff --git a/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt b/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt index 06ad1b1a48aa9b240c3f336bff576cdd341351fc..8a73e01848bee7b194fe1232f1c97cc165e14d20 100644 --- a/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt +++ b/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt @@ -22,7 +22,6 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.data.blockedApps.BlockedAppRepository import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.Status import foundation.e.apps.data.faultyApps.FaultyAppRepository @@ -30,6 +29,7 @@ import foundation.e.apps.data.fdroid.FDroidRepository import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.search.SearchApi import foundation.e.apps.data.application.data.Application +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.gitlab.SystemAppsUpdatesRepository import foundation.e.apps.data.updates.UpdatesManagerImpl import foundation.e.apps.util.MainCoroutineRule @@ -107,7 +107,7 @@ class UpdateManagerImptTest { status = status, name = "Demo Four", package_name = "foundation.e.demofour", - origin = Origin.GITLAB_RELEASES, + source = Source.SYSTEM_APP, filterLevel = FilterLevel.NONE ) ) @@ -127,7 +127,7 @@ class UpdateManagerImptTest { systemAppUpdates ) - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() System.out.println("===> updates: ${updateResult.first.map { it.package_name }}") assertEquals("fetchUpdate", 3, updateResult.first.size) @@ -139,7 +139,7 @@ class UpdateManagerImptTest { status = status, name = "Demo One", package_name = "foundation.e.demoone", - origin = Origin.GPLAY, + source = Source.PLAY_STORE, filterLevel = FilterLevel.NONE ), Application( @@ -147,7 +147,7 @@ class UpdateManagerImptTest { status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo", - origin = Origin.GPLAY, + source = Source.PLAY_STORE, filterLevel = FilterLevel.NONE ), ) @@ -159,7 +159,7 @@ class UpdateManagerImptTest { setupMockingSystemApps() - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() System.out.println("===> updates: ${updateResult.first.map { it.package_name }}") assertEquals("fetchUpdate", 0, updateResult.first.size) @@ -180,7 +180,7 @@ class UpdateManagerImptTest { systemAppUpdates, ) - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() System.out.println("===> updates: ${updateResult.first.map { it.package_name }}") assertEquals("fetchUpdate", 0, updateResult.first.size) @@ -201,10 +201,10 @@ class UpdateManagerImptTest { systemAppUpdates, ) - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() System.out.println("===> updates: ${updateResult.first.map { it.package_name }}") - assertFalse("fetchupdate", updateResult.first.any { it.origin != Origin.CLEANAPK }) + assertFalse("fetchupdate", updateResult.first.any { it.source != Source.OPEN_SOURCE && it.source != Source.PWA }) } @Test @@ -222,8 +222,8 @@ class UpdateManagerImptTest { systemAppUpdates, ) - val updateResult = updatesManagerImpl.getUpdates(authData) - assertFalse("fetchupdate", updateResult.first.any { it.origin != Origin.GPLAY }) + val updateResult = updatesManagerImpl.getUpdates() + assertFalse("fetchupdate", updateResult.first.any { it.source != Source.PLAY_STORE }) } @Test @@ -241,8 +241,8 @@ class UpdateManagerImptTest { systemAppUpdates, ) - val updateResult = updatesManagerImpl.getUpdates(authData) - assertFalse("fetchupdate", updateResult.first.any { it.origin != Origin.GITLAB_RELEASES }) + val updateResult = updatesManagerImpl.getUpdates() + assertFalse("fetchupdate", updateResult.first.any { it.source != Source.SYSTEM_APP }) } @Test @@ -258,7 +258,7 @@ class UpdateManagerImptTest { gplayUpdates ) - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() assertEquals("fetchupdate", 1, updateResult.first.size) assertEquals("fetchupdate", ResultStatus.OK, updateResult.second) } @@ -276,7 +276,7 @@ class UpdateManagerImptTest { gplayUpdates ) - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() System.out.println("===> updates: ${updateResult.first.map { it.package_name }}") assertEquals("fetchupdate", 1, updateResult.first.size) @@ -296,7 +296,7 @@ class UpdateManagerImptTest { gplayUpdates ) - val updateResult = updatesManagerImpl.getUpdates(authData) + val updateResult = updatesManagerImpl.getUpdates() System.out.println("===> updates: ${updateResult.first.map { it.package_name }}") assertEquals("fetchupdate", 1, updateResult.first.size) @@ -309,7 +309,7 @@ class UpdateManagerImptTest { status = status, name = "Demo Three", package_name = "foundation.e.demothree", - origin = Origin.CLEANAPK, + source = Source.OPEN_SOURCE, filterLevel = FilterLevel.NONE ) ) @@ -327,8 +327,8 @@ class UpdateManagerImptTest { val updateResult = updatesManagerImpl.getUpdatesOSS() assertEquals("UpdateOSS", 2, updateResult.first.size) - assertEquals("UpdateOSS", Origin.CLEANAPK, updateResult.first[1].origin) - assertEquals("UpdateOSS", Origin.GITLAB_RELEASES, updateResult.first[0].origin) + assertEquals("UpdateOSS", Source.OPEN_SOURCE, updateResult.first[1].source) + assertEquals("UpdateOSS", Source.SYSTEM_APP, updateResult.first[0].source) } @Test @@ -373,7 +373,7 @@ class UpdateManagerImptTest { Mockito.`when`( applicationRepository.getApplicationDetails( any(), - eq(Origin.CLEANAPK) + eq(Source.OPEN_SOURCE) ) ).thenReturn(openSourceUpdates) @@ -387,7 +387,7 @@ class UpdateManagerImptTest { applicationRepository.getApplicationDetails( any(), any(), - eq(Origin.GPLAY) + eq(Source.PLAY_STORE) ) ).thenReturn( Pair(gplayUpdates.first.first(), ResultStatus.OK), @@ -398,7 +398,7 @@ class UpdateManagerImptTest { applicationRepository.getApplicationDetails( any(), any(), - eq(Origin.GPLAY) + eq(Source.PLAY_STORE) ) ).thenReturn(Pair(Application(), ResultStatus.TIMEOUT)) } diff --git a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt index 66206c2bd8f182eea1f1f155f00ce2eca4e04e99..812e3c54126f60d7f8a0edeca5b71c7cc59b68db 100644 --- a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt +++ b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt @@ -22,18 +22,15 @@ import android.content.Context import android.text.format.Formatter import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.aurora.gplayapi.Constants -import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.FakeAppLoungePreference -import foundation.e.apps.data.AppSourcesContainer +import foundation.e.apps.data.Stores import foundation.e.apps.data.enums.FilterLevel -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.Status import foundation.e.apps.data.application.ApplicationDataManager import foundation.e.apps.data.application.apps.AppsApi import foundation.e.apps.data.application.apps.AppsApiImpl import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.cleanapk.repositories.CleanApkAppsRepository -import foundation.e.apps.data.cleanapk.repositories.CleanApkPwaRepository +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.install.pkg.PwaManager import foundation.e.apps.install.pkg.AppLoungePackageManager @@ -76,13 +73,10 @@ class AppsApiTest { private lateinit var context: Context @Mock - private lateinit var cleanApkAppsRepository: CleanApkAppsRepository - - @Mock - private lateinit var cleanApkPWARepository: CleanApkPwaRepository + private lateinit var gPlayAPIRepository: PlayStoreRepository @Mock - private lateinit var gPlayAPIRepository: PlayStoreRepository + private lateinit var stores: Stores private lateinit var appsApi: AppsApi @@ -98,13 +92,9 @@ class AppsApiTest { formatterMocked = Mockito.mockStatic(Formatter::class.java) preferenceManagerModule = FakeAppLoungePreference(context) applicationDataManager = - ApplicationDataManager(gPlayAPIRepository, appLoungePackageManager, pwaManager) - val appSourcesContainer = - AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) + ApplicationDataManager(appLoungePackageManager, pwaManager) appsApi = AppsApiImpl( - context, - preferenceManagerModule, - appSourcesContainer, + stores, applicationDataManager ) } @@ -433,7 +423,7 @@ class AppsApiTest { name = "Demo Three", package_name = "foundation.e.demothree", latest_version_code = 123, - origin = Origin.CLEANAPK, + source = Source.OPEN_SOURCE, originalSize = -1, isFree = isFree, price = "" @@ -450,7 +440,7 @@ class AppsApiTest { @Test fun `getAppFilterLevel when app is restricted and paid and no price`() = runTest { val fusedApp = getFusedAppForFilterLevelTest(false).apply { - this.origin = Origin.GPLAY + this.source = Source.PLAY_STORE this.restriction = Constants.Restriction.UNKNOWN } @@ -461,7 +451,7 @@ class AppsApiTest { @Test fun `getAppFilterLevel when app is not_restricted and paid and no price`() = runTest { val fusedApp = getFusedAppForFilterLevelTest(false).apply { - this.origin = Origin.GPLAY + this.source = Source.PLAY_STORE this.restriction = Constants.Restriction.NOT_RESTRICTED } @@ -473,7 +463,7 @@ class AppsApiTest { fun `getAppFilterLevel when app is restricted and getAppDetails and getDownloadDetails returns success`() = runTest { val fusedApp = getFusedAppForFilterLevelTest().apply { - this.origin = Origin.GPLAY + this.source = Source.PLAY_STORE this.restriction = Constants.Restriction.UNKNOWN } @@ -491,44 +481,4 @@ class AppsApiTest { val filterLevel = appsApi.getAppFilterLevel(fusedApp) assertEquals("getAppFilterLevel", FilterLevel.NONE, filterLevel) } - - @Test - fun `getAppFilterLevel when app is restricted and getAppDetails throws exception`() = runTest { - val fusedApp = getFusedAppForFilterLevelTest().apply { - this.origin = Origin.GPLAY - this.restriction = Constants.Restriction.UNKNOWN - } - - Mockito.`when`(gPlayAPIRepository.getAppDetails(fusedApp.package_name)) - .thenThrow(RuntimeException()) - - Mockito.`when`( - gPlayAPIRepository.getDownloadInfo( - fusedApp.package_name, fusedApp.latest_version_code, fusedApp.offer_type - ) - ).thenReturn(listOf()) - - val filterLevel = appsApi.getAppFilterLevel(fusedApp) - assertEquals("getAppFilterLevel", FilterLevel.DATA, filterLevel) - } - - @Test - fun `getAppFilterLevel when app is restricted and getDownoadInfo throws exception`() = runTest { - val fusedApp = getFusedAppForFilterLevelTest().apply { - this.origin = Origin.GPLAY - this.restriction = Constants.Restriction.UNKNOWN - } - - Mockito.`when`(gPlayAPIRepository.getAppDetails(fusedApp.package_name)) - .thenReturn(Application(fusedApp.package_name)) - - Mockito.`when`( - gPlayAPIRepository.getDownloadInfo( - fusedApp.package_name, fusedApp.latest_version_code, fusedApp.offer_type - ) - ).thenThrow(RuntimeException()) - - val filterLevel = appsApi.getAppFilterLevel(fusedApp) - assertEquals("getAppFilterLevel", FilterLevel.UI, filterLevel) - } } diff --git a/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt b/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt index ddf7a556a94b044727107c361de55c8b308179bc..b7e4a767334a889b6b1223ee069c20953dd80c62 100644 --- a/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt +++ b/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt @@ -24,6 +24,7 @@ import com.aurora.gplayapi.data.models.Category import foundation.e.apps.FakeAppLoungePreference import foundation.e.apps.R import foundation.e.apps.data.AppSourcesContainer +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.ApplicationDataManager import foundation.e.apps.data.application.category.CategoryApi import foundation.e.apps.data.application.category.CategoryApiImpl @@ -32,6 +33,7 @@ import foundation.e.apps.data.cleanapk.data.categories.Categories import foundation.e.apps.data.cleanapk.repositories.CleanApkAppsRepository import foundation.e.apps.data.cleanapk.repositories.CleanApkPwaRepository import foundation.e.apps.data.enums.ResultStatus +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.install.pkg.PwaManager import foundation.e.apps.install.pkg.AppLoungePackageManager @@ -79,22 +81,24 @@ class CategoryApiTest { @Mock private lateinit var gPlayAPIRepository: PlayStoreRepository - private lateinit var preferenceManagerModule: FakeAppLoungePreference + private lateinit var fakeStores: Stores private lateinit var categoryApi: CategoryApi @Before fun setup() { MockitoAnnotations.openMocks(this) - preferenceManagerModule = FakeAppLoungePreference(context) val applicationDataManager = - ApplicationDataManager(gPlayAPIRepository, appLoungePackageManager, pwaManager) + ApplicationDataManager(appLoungePackageManager, pwaManager) + + fakeStores = Stores(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) + val appSourcesContainer = AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) categoryApi = CategoryApiImpl( context, - preferenceManagerModule, appSourcesContainer, + fakeStores, applicationDataManager ) } @@ -104,14 +108,14 @@ class CategoryApiTest { val categories = Categories(listOf("app one", "app two", "app three"), listOf("game 1", "game 2"), true) val response = Response.success(categories) - preferenceManagerModule.isPWASelectedFake = true - preferenceManagerModule.isOpenSourceelectedFake = false - preferenceManagerModule.isGplaySelectedFake = false Mockito.`when`( cleanApkPWARepository.getCategories() ).thenReturn(response) + fakeStores.disableStore(Source.OPEN_SOURCE) + fakeStores.disableStore(Source.PLAY_STORE) + Mockito.`when`(context.getString(eq(R.string.pwa))).thenReturn("PWA") val categoryListResponse = @@ -126,15 +130,14 @@ class CategoryApiTest { Categories(listOf("app one", "app two", "app three"), listOf("game 1", "game 2"), true) val response = Response.success(categories) - preferenceManagerModule.isPWASelectedFake = false - preferenceManagerModule.isOpenSourceelectedFake = true - preferenceManagerModule.isGplaySelectedFake = false - Mockito.`when`( cleanApkAppsRepository.getCategories() ).thenReturn(response) Mockito.`when`(context.getString(eq(R.string.open_source))).thenReturn("Open source") + fakeStores.disableStore(Source.PWA) + fakeStores.disableStore(Source.PLAY_STORE) + val categoryListResponse = categoryApi.getCategoriesList(CategoryType.APPLICATION) @@ -145,14 +148,13 @@ class CategoryApiTest { fun `getCategory when gplay source is selected`() = runTest { val categories = listOf(Category(), Category(), Category(), Category()) - preferenceManagerModule.isPWASelectedFake = false - preferenceManagerModule.isOpenSourceelectedFake = false - preferenceManagerModule.isGplaySelectedFake = true - Mockito.`when`( gPlayAPIRepository.getCategories(CategoryType.APPLICATION) ).thenReturn(categories) + fakeStores.disableStore(Source.PWA) + fakeStores.disableStore(Source.OPEN_SOURCE) + val categoryListResponse = categoryApi.getCategoriesList(CategoryType.APPLICATION) @@ -161,13 +163,13 @@ class CategoryApiTest { @Test fun `getCategory when gplay source is selected return error`() = runTest { - preferenceManagerModule.isPWASelectedFake = false - preferenceManagerModule.isOpenSourceelectedFake = false - preferenceManagerModule.isGplaySelectedFake = true Mockito.`when`( gPlayAPIRepository.getCategories(CategoryType.APPLICATION) ).thenThrow() + + fakeStores.disableStore(Source.PWA) + fakeStores.disableStore(Source.OPEN_SOURCE) val categoryListResponse = categoryApi.getCategoriesList(CategoryType.APPLICATION) @@ -202,9 +204,6 @@ class CategoryApiTest { Mockito.`when`(context.getString(eq(R.string.open_source))).thenReturn("Open source") Mockito.`when`(context.getString(eq(R.string.pwa))).thenReturn("pwa") - preferenceManagerModule.isPWASelectedFake = true - preferenceManagerModule.isOpenSourceelectedFake = true - preferenceManagerModule.isGplaySelectedFake = true val categoryListResponse = categoryApi.getCategoriesList(CategoryType.APPLICATION) diff --git a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt index 320a96c21b31701a22f7635f72a2d85aaa47f66b..3bf8dac88886a480113cc2b35067010503f26f3e 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -21,12 +21,11 @@ import android.content.Context import android.text.format.Formatter import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.aurora.gplayapi.data.models.App -import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.SearchBundle import foundation.e.apps.FakeAppLoungePreference import foundation.e.apps.data.AppSourcesContainer +import foundation.e.apps.data.Stores import foundation.e.apps.data.cleanapk.data.search.Search -import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.Status import foundation.e.apps.data.application.search.SearchApiImpl import foundation.e.apps.data.application.ApplicationDataManager @@ -35,23 +34,19 @@ import foundation.e.apps.data.application.apps.AppsApiImpl import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.cleanapk.repositories.CleanApkAppsRepository import foundation.e.apps.data.cleanapk.repositories.CleanApkPwaRepository +import foundation.e.apps.data.enums.Source import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.install.pkg.PwaManager import foundation.e.apps.install.pkg.AppLoungePackageManager import foundation.e.apps.util.MainCoroutineRule -import foundation.e.apps.utils.eventBus.EventBus import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest -import okhttp3.ResponseBody.Companion.toResponseBody import org.junit.After import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test -import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.MockedStatic import org.mockito.Mockito @@ -93,6 +88,9 @@ class SearchApiImplTest { @Mock private lateinit var gPlayAPIRepository: PlayStoreRepository + @Mock + private lateinit var stores: Stores + private lateinit var appsApi: AppsApi private lateinit var applicationDataManager: ApplicationDataManager @@ -101,30 +99,24 @@ class SearchApiImplTest { private lateinit var formatterMocked: MockedStatic - companion object { - private val AUTH_DATA = AuthData("e@e.email", "AtadyMsIAtadyM") - } - @Before fun setup() { MockitoAnnotations.openMocks(this) formatterMocked = Mockito.mockStatic(Formatter::class.java) preferenceManagerModule = FakeAppLoungePreference(context) applicationDataManager = - ApplicationDataManager(gPlayAPIRepository, appLoungePackageManager, pwaManager) + ApplicationDataManager(appLoungePackageManager, pwaManager) val appSourcesContainer = AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) appsApi = AppsApiImpl( - context, - preferenceManagerModule, - appSourcesContainer, + stores, applicationDataManager, ) fusedAPIImpl = SearchApiImpl( appsApi, - preferenceManagerModule, appSourcesContainer, + stores, applicationDataManager ) } @@ -139,7 +131,7 @@ class SearchApiImplTest { name = "Demo Three", package_name = "foundation.e.demothree", latest_version_code = 123, - origin = Origin.CLEANAPK, + source = Source.OPEN_SOURCE, originalSize = -1, isFree = isFree, price = "" @@ -183,31 +175,32 @@ class SearchApiImplTest { listOf(App("a.b.c"), App("c.d.e"), App("d.e.f"), App("d.e.g")), mutableSetOf() ) - setupMockingSearchApp( - packageNameSearchResponse, gplayPackageResult, gplayFlow - ) + val playStoreApps = listOf( + Application(package_name = "a.b.c"), + Application(package_name = "c.d.e"), + Application(package_name = "d.e.f"), + Application(package_name = "d.e.g")) + + setupMockingSearchApp(playStoreApps, gplayPackageResult) val searchResultLiveData = - fusedAPIImpl.getCleanApkSearchResults("com.search.package", AUTH_DATA) + fusedAPIImpl.getCleanApkSearchResults("com.search.package") val size = searchResultLiveData.data?.first?.size ?: -2 assertEquals("getSearchResult", 8, size) } private suspend fun setupMockingSearchApp( - packageNameSearchResponse: Response?, + apps: List, gplayPackageResult: Application, - gplayLivedata: Pair, MutableSet>, willThrowException: Boolean = false ) { Mockito.`when`(pwaManager.getPwaStatus(any())).thenReturn(Status.UNAVAILABLE) Mockito.`when`(appLoungePackageManager.getPackageStatus(any(), any())) .thenReturn(Status.UNAVAILABLE) Mockito.`when`( - cleanApkAppsRepository.getSearchResult( - query = "com.search.package", searchBy = "package_name" - ) - ).thenReturn(packageNameSearchResponse) + cleanApkAppsRepository.getSearchResults("com.search.package") + ).thenReturn(apps) formatterMocked.`when` { Formatter.formatFileSize(any(), any()) }.thenReturn("15MB") if (willThrowException) { @@ -218,23 +211,21 @@ class SearchApiImplTest { .thenReturn(gplayPackageResult) } - Mockito.`when`(cleanApkAppsRepository.getSearchResult(query = "com.search.package")) - .thenReturn(packageNameSearchResponse) + Mockito.`when`(cleanApkAppsRepository.getSearchResults("com.search.package")) + .thenReturn(apps) - Mockito.`when`(cleanApkPWARepository.getSearchResult(query = "com.search.package")) - .thenReturn(packageNameSearchResponse) + Mockito.`when`(cleanApkPWARepository.getSearchResults("com.search.package")) + .thenReturn(apps) Mockito.`when`( - cleanApkAppsRepository.getSearchResult( - query = "com.search.package" - ) - ).thenReturn(packageNameSearchResponse) + cleanApkAppsRepository.getSearchResults("com.search.package") + ).thenReturn(apps) Mockito.`when`(cleanApkAppsRepository.getAppDetails(any())) .thenReturn(Application()) - Mockito.`when`(gPlayAPIRepository.getSearchResult(eq("com.search.package"), null)) - .thenReturn(gplayLivedata) + Mockito.`when`(gPlayAPIRepository.getSearchResults(eq("com.search.package"))) + .thenReturn(apps) } @Ignore("Dependencies are not mockable") @@ -264,16 +255,16 @@ class SearchApiImplTest { ) ) - val searchResult = Search(apps = appList, numberOfResults = 1, success = true) - val packageNameSearchResponse = Response.success(searchResult) val gplayPackageResult = Application("com.search.package") - val gplayFlow: Pair, MutableSet> = Pair( - listOf(App("a.b.c"), App("c.d.e"), App("d.e.f"), App("d.e.g")), mutableSetOf() - ) + val playStoreApps = listOf( + Application(package_name = "a.b.c"), + Application(package_name = "c.d.e"), + Application(package_name = "d.e.f"), + Application(package_name = "d.e.g")) setupMockingSearchApp( - packageNameSearchResponse, gplayPackageResult, gplayFlow, true + playStoreApps, gplayPackageResult, true ) preferenceManagerModule.isPWASelectedFake = false @@ -281,7 +272,7 @@ class SearchApiImplTest { preferenceManagerModule.isGplaySelectedFake = true val searchResultLiveData = - fusedAPIImpl.getCleanApkSearchResults("com.search.package", AUTH_DATA) + fusedAPIImpl.getCleanApkSearchResults("com.search.package") val size = searchResultLiveData.data?.first?.size ?: -2 assertEquals("getSearchResult", 4, size) diff --git a/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt b/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt deleted file mode 100644 index c284213ebf6474b3cf3244ce76298abed94926e2..0000000000000000000000000000000000000000 --- a/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright MURENA SAS 2023 - * Apps Quickly and easily install Android apps onto your device! - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package foundation.e.apps.home - -import android.content.Context -import android.text.format.Formatter -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import com.aurora.gplayapi.data.models.AuthData -import foundation.e.apps.FakeAppLoungePreference -import foundation.e.apps.data.AppSourcesContainer -import foundation.e.apps.data.application.ApplicationDataManager -import foundation.e.apps.data.application.data.Application -import foundation.e.apps.data.application.home.HomeApi -import foundation.e.apps.data.application.home.HomeApiImpl -import foundation.e.apps.data.cleanapk.repositories.CleanApkAppsRepository -import foundation.e.apps.data.cleanapk.repositories.CleanApkPwaRepository -import foundation.e.apps.data.enums.Status -import foundation.e.apps.data.playstore.PlayStoreRepository -import foundation.e.apps.install.pkg.PwaManager -import foundation.e.apps.install.pkg.AppLoungePackageManager -import foundation.e.apps.util.MainCoroutineRule -import foundation.e.apps.util.getOrAwaitValue -import foundation.e.apps.utils.eventBus.EventBus -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.mockito.ArgumentMatchers -import org.mockito.Mock -import org.mockito.MockedStatic -import org.mockito.Mockito -import org.mockito.MockitoAnnotations -import org.mockito.kotlin.any - -class HomeApiTest { - - // Run tasks synchronously - @Rule - @JvmField - val instantExecutorRule = InstantTaskExecutorRule() - - // Sets the main coroutines dispatcher to a TestCoroutineScope for unit testing. - @ExperimentalCoroutinesApi - @get:Rule - var mainCoroutineRule = MainCoroutineRule() - - private lateinit var homeApi: HomeApi - - private lateinit var applicationDataManager: ApplicationDataManager - - @Mock - private lateinit var pwaManager: PwaManager - - @Mock - private lateinit var appLoungePackageManager: AppLoungePackageManager - - @Mock - private lateinit var context: Context - - @Mock - private lateinit var cleanApkAppsRepository: CleanApkAppsRepository - - @Mock - private lateinit var cleanApkPWARepository: CleanApkPwaRepository - - @Mock - private lateinit var gPlayAPIRepository: PlayStoreRepository - - private lateinit var preferenceManagerModule: FakeAppLoungePreference - - private lateinit var formatterMocked: MockedStatic - - companion object { - private val AUTH_DATA = AuthData("e@e.email", "AtadyMsIAtadyM") - } - - @Before - fun setup() { - MockitoAnnotations.openMocks(this) - formatterMocked = Mockito.mockStatic(Formatter::class.java) - preferenceManagerModule = FakeAppLoungePreference(context) - applicationDataManager = - ApplicationDataManager(gPlayAPIRepository, appLoungePackageManager, pwaManager) - val appSourcesContainer = - AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) - homeApi = HomeApiImpl( - context, - preferenceManagerModule, - appSourcesContainer, - applicationDataManager - ) - } - - @Test - fun testHomeScreenDataWhenDataIsLimited() = runTest { - val newAppList = mutableListOf( - Application("foundation.e.demoone"), - Application("foundation.e.demotwo"), - Application("foundation.e.demothree"), - ) - - val newHomeData = mapOf>(Pair("Top Free Apps", newAppList)) - preferenceManagerModule.isGplaySelectedFake = true - - formatterMocked.`when` { Formatter.formatFileSize(any(), any()) }.thenReturn("15MB") - Mockito.`when`(gPlayAPIRepository.getHomeScreenData()).thenReturn(newHomeData) - Mockito.`when`(gPlayAPIRepository.getAppDetails(ArgumentMatchers.anyString())).thenReturn( - Application("foundation.e.demothree") - ) - Mockito.`when`( - gPlayAPIRepository.getDownloadInfo( - ArgumentMatchers.anyString(), - any(), - any() - ) - ).thenReturn(listOf()) - Mockito.`when`(appLoungePackageManager.getPackageStatus(any(), any())) - .thenReturn(Status.UNAVAILABLE) - - var hasLimitedDataFound = false - val job = launch { - EventBus.events.collect { - hasLimitedDataFound = true - } - } - - homeApi.fetchHomeScreenData(AUTH_DATA).getOrAwaitValue() - delay(500) - job.cancel() - - assert(hasLimitedDataFound) - } -} diff --git a/app/src/test/java/foundation/e/apps/home/HomeViewModelTest.kt b/app/src/test/java/foundation/e/apps/home/HomeViewModelTest.kt index 7930a3b4841a427b614b5d372b0bd14a27140580..db4a4e28fb18ac8c12ffa7471c66019f8d71707b 100644 --- a/app/src/test/java/foundation/e/apps/home/HomeViewModelTest.kt +++ b/app/src/test/java/foundation/e/apps/home/HomeViewModelTest.kt @@ -18,6 +18,7 @@ package foundation.e.apps.home +import foundation.e.apps.data.Stores import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.Home @@ -34,12 +35,15 @@ class HomeViewModelTest { @Mock private lateinit var applicationRepository: ApplicationRepository + @Mock + private lateinit var stores: Stores + private lateinit var homeViewModel: HomeViewModel @Before fun setup() { MockitoAnnotations.openMocks(this) - homeViewModel = HomeViewModel(applicationRepository) + homeViewModel = HomeViewModel(applicationRepository, stores) } @Test @@ -49,7 +53,7 @@ class HomeViewModelTest { val oldHomeData = listOf(Home("Top Free Apps", oldAppList, id = "123"), Home("Top Free Games", oldAppList, id = "124")) - var newHomeData = + val newHomeData = listOf(Home("Top Free Apps", newAppList, id = "123"), Home("Top Free Games", newAppList, id = "124")) homeViewModel.currentHomes = oldHomeData @@ -65,7 +69,7 @@ class HomeViewModelTest { val oldHomeData = listOf(Home("Top Free Apps", oldAppList, id = "123"), Home("Top Free Games", oldAppList, id = "124")) - var newHomeData = + val newHomeData = listOf(Home("Top Free Apps", newAppList, id = "123"), Home("Top Free Games", newAppList, id = "124")) homeViewModel.currentHomes = oldHomeData @@ -81,7 +85,7 @@ class HomeViewModelTest { val oldHomeData = listOf(Home("Top Free Apps", oldAppList, id = "123"), Home("Top Free Games", oldAppList, id = "124")) - var newHomeData = + val newHomeData = listOf(Home("Top Free Apps", newAppList, id = "123"), Home("Top Free Games", newAppList, id = "124")) homeViewModel.currentHomes = oldHomeData diff --git a/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt index 38fdebfe9d7b2c2dd0ab9dc381ed45eb282dedc5..c3f13a29c5e057cde103f78271125dc64f4471d7 100644 --- a/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt +++ b/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt @@ -21,6 +21,7 @@ package foundation.e.apps.login import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.data.ResultSupreme +import foundation.e.apps.data.Stores import foundation.e.apps.data.enums.User import foundation.e.apps.data.login.AuthObject import foundation.e.apps.data.login.AuthenticatorRepository @@ -38,6 +39,8 @@ class LoginViewModelTest { private lateinit var authenticatorRepository: AuthenticatorRepository @Mock private lateinit var cache: Cache + @Mock + private lateinit var stores: Stores private lateinit var loginViewModel: LoginViewModel @@ -48,7 +51,7 @@ class LoginViewModelTest { @Before fun setup() { MockitoAnnotations.openMocks(this) - loginViewModel = LoginViewModel(authenticatorRepository, cache) + loginViewModel = LoginViewModel(authenticatorRepository, cache, stores) } @Test