From df2ac320b0c8b96495d10a4f91fb5a616243bd77 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Thu, 31 Oct 2024 11:38:13 +0100 Subject: [PATCH 01/12] Introduce Stores class --- .../foundation/e/apps/data/StoreRepository.kt | 3 +- .../java/foundation/e/apps/data/Stores.kt | 27 ++++ .../application/ApplicationDataManager.kt | 31 +--- .../data/application/ApplicationRepository.kt | 4 +- .../e/apps/data/application/home/HomeApi.kt | 4 +- .../apps/data/application/home/HomeApiImpl.kt | 112 ++----------- .../repositories/CleanApkAppsRepository.kt | 13 +- .../repositories/CleanApkPwaRepository.kt | 10 +- .../cleanapk/repositories/HomeConverter.kt | 2 +- .../data/playstore/PlayStoreRepository.kt | 26 ++- .../e/apps/ui/home/HomeViewModel.kt | 26 +-- .../foundation/e/apps/apps/AppsApiTest.kt | 43 +---- .../e/apps/category/CategoryApiTest.kt | 2 +- .../e/apps/fused/SearchApiImplTest.kt | 7 +- .../foundation/e/apps/home/HomeApiTest.kt | 152 ------------------ 15 files changed, 95 insertions(+), 367 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/data/Stores.kt delete mode 100644 app/src/test/java/foundation/e/apps/home/HomeApiTest.kt 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 e1c04d98e..f2249925d 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,9 @@ 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 getHomeScreenData(list: MutableList): List suspend fun getAppDetails(packageNameOrId: String): Application } 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 000000000..0e62cbd7b --- /dev/null +++ b/app/src/main/java/foundation/e/apps/data/Stores.kt @@ -0,0 +1,27 @@ +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 stores = mutableMapOf() + + fun getStores(): Map { + return stores + } + + init { + stores[Source.OPEN] = cleanApkAppsRepository + stores[Source.PWA] = cleanApkPwaRepository + stores[Source.GPLAY] = playStoreRepository + } +} \ 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 42541a53b..3c514586d 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 @@ -32,15 +32,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 +54,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 !isRestricted(application) -> FilterLevel.NONE - !isApplicationVisible(application) -> FilterLevel.DATA application.originalSize == 0L -> FilterLevel.UI - !isDownloadable(application) -> FilterLevel.UI else -> FilterLevel.NONE } } @@ -73,28 +70,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 126b589d5..bc8ce28f0 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 @@ -52,8 +52,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 { 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 27508ed84..c32a1c139 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 d81e28a7f..1aa161696 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 @@ -21,46 +21,37 @@ 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.Stores import foundation.e.apps.data.application.ApplicationDataManager 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.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.handleNetworkResult -import foundation.e.apps.data.login.AuthObject +import foundation.e.apps.data.playstore.PlayStoreRepository 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 @@ -70,15 +61,15 @@ class HomeApiImpl @Inject constructor( coroutineScope { if (appLoungePreference.isGplaySelected()) { - resultGplay = async { loadHomeData(list, Source.GPLAY, authData) } + resultGplay = async { loadHomeData(list, Source.GPLAY) } } if (appLoungePreference.isOpenSourceSelected()) { - resultOpenSource = async { loadHomeData(list, Source.OPEN, authData) } + resultOpenSource = async { loadHomeData(list, Source.OPEN) } } if (appLoungePreference.isPWASelected()) { - resultPWA = async { loadHomeData(list, Source.PWA, authData) } + resultPWA = async { loadHomeData(list, Source.PWA) } } resultGplay?.await()?.let { @@ -98,26 +89,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.getStores()[source] + homeDataBuilder?.getHomeScreenData(priorList) + ?: throw IllegalStateException("Could not find store for $source") } setHomeErrorMessage(result.getResultStatus(), source) @@ -132,23 +109,6 @@ 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) { @@ -159,48 +119,4 @@ class HomeApiImpl @Inject constructor( } } } - - 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/cleanapk/repositories/CleanApkAppsRepository.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkAppsRepository.kt index b97b3ce30..74923e8c7 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,12 +18,11 @@ 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 @@ -35,7 +34,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, @@ -49,7 +48,11 @@ class CleanApkAppsRepository @Inject constructor( map[it.title] = it.list } - return map + listHome.forEach { (title, apps) -> + list.add(Home(title, apps, SearchApi.APP_TYPE_OPEN)) + } + + return list } override suspend fun getSearchResult(query: String, searchBy: String?): 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 edf52f91e..0d569d3d4 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,6 +21,8 @@ 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 @@ -33,7 +35,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,7 +49,11 @@ class CleanApkPwaRepository @Inject constructor( map[it.title] = it.list } - return map + listHome.forEach { (title, apps) -> + list.add(Home(title, apps, SearchApi.APP_TYPE_PWA)) + } + + return list } override suspend fun getSearchResult(query: String, searchBy: String?): 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 a5ecafbfc..b6e45dce2 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/playstore/PlayStoreRepository.kt b/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt index 9977924a9..760ce8d09 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 @@ -38,7 +38,9 @@ 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.login.AuthenticatorRepository @@ -51,10 +53,11 @@ 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 +70,17 @@ 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) + } + } + list.add(Home(it.key, fusedApps)) + } + + return list } private fun createTopChartElements() = mutableMapOf( @@ -191,7 +204,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/ui/home/HomeViewModel.kt b/app/src/main/java/foundation/e/apps/ui/home/HomeViewModel.kt index 455a9e304..666f81acd 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,14 +22,11 @@ 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.application.ApplicationRepository import foundation.e.apps.data.application.data.Home 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 @@ -69,12 +66,12 @@ 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) @@ -95,31 +92,16 @@ class HomeViewModel @Inject constructor( 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/test/java/foundation/e/apps/apps/AppsApiTest.kt b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt index 66206c2bd..9dbf39776 100644 --- a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt +++ b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt @@ -22,7 +22,6 @@ 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.enums.FilterLevel @@ -98,7 +97,7 @@ class AppsApiTest { 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( @@ -491,44 +490,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 ddf7a556a..349e143fc 100644 --- a/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt +++ b/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt @@ -88,7 +88,7 @@ class CategoryApiTest { MockitoAnnotations.openMocks(this) preferenceManagerModule = FakeAppLoungePreference(context) val applicationDataManager = - ApplicationDataManager(gPlayAPIRepository, appLoungePackageManager, pwaManager) + ApplicationDataManager(appLoungePackageManager, pwaManager) val appSourcesContainer = AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) categoryApi = CategoryApiImpl( 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 320a96c21..18bd3e121 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -39,19 +39,14 @@ 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 @@ -111,7 +106,7 @@ class SearchApiImplTest { 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( 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 c284213eb..000000000 --- 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) - } -} -- GitLab From 6132760151c8e14fc5979410afd70c4fe6af4b8c Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Tue, 31 Dec 2024 13:53:37 +0100 Subject: [PATCH 02/12] Small improvement --- .../foundation/e/apps/data/StoreRepository.kt | 1 + .../apps/data/application/apps/AppsApiImpl.kt | 24 ++++++++++--------- .../foundation/e/apps/data/enums/Source.kt | 8 +++++++ 3 files changed, 22 insertions(+), 11 deletions(-) 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 f2249925d..a28a08440 100644 --- a/app/src/main/java/foundation/e/apps/data/StoreRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/StoreRepository.kt @@ -24,4 +24,5 @@ import foundation.e.apps.data.application.data.Home interface StoreRepository { suspend fun getHomeScreenData(list: MutableList): List suspend fun getAppDetails(packageNameOrId: String): Application + } 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 f98e6c154..0162fcb8a 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 @@ -20,9 +20,9 @@ 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 @@ -35,14 +35,15 @@ 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 +import foundation.e.apps.data.playstore.PlayStoreRepository 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 { @@ -72,7 +73,7 @@ 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) } @@ -140,7 +141,7 @@ class AppsApiImpl @Inject constructor( * * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5174 */ - private suspend fun handleFilteredApps( + private fun handleFilteredApps( app: App, applicationList: MutableList ) { @@ -164,7 +165,7 @@ class AppsApiImpl @Inject constructor( ).body() } - private suspend fun Search.handleCleanApkSearch( + private fun Search.handleCleanApkSearch( applicationList: MutableList ) { if (hasSingleResult()) { @@ -187,11 +188,12 @@ class AppsApiImpl @Inject constructor( var application: Application val result = handleNetworkResult { - application = if (origin == Origin.CLEANAPK) { - appSources.cleanApkAppsRepo.getAppDetails(id) - } else { - appSources.gplayRepo.getAppDetails(packageName) - } + + val store = stores.getStores()[Source.fromOrigin(origin)] + ?: throw IllegalStateException("Could not get store") + + val idOrPackageName = if (store is PlayStoreRepository) packageName else id + application = store.getAppDetails(idOrPackageName) application.let { applicationDataManager.updateStatus(it) 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 fdecbc5ee..cf6769c3f 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 @@ -32,5 +32,13 @@ enum class Source { else -> GPLAY } } + + fun fromOrigin(origin: Origin): Source { + return when (origin) { + Origin.GPLAY -> GPLAY + Origin.CLEANAPK -> OPEN + Origin.GITLAB_RELEASES -> GITLAB_RELEASES + } + } } } -- GitLab From 8e5e0aada395262ca5ac8c1a171c202723238308 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Thu, 2 Jan 2025 14:07:33 +0100 Subject: [PATCH 03/12] Get rid off Origin class since it is kind of redundant with the Source class --- .../foundation/e/apps/data/StoreRepository.kt | 3 +- .../java/foundation/e/apps/data/Stores.kt | 4 +- .../application/ApplicationDataManager.kt | 7 ++- .../data/application/ApplicationRepository.kt | 20 ++++----- .../e/apps/data/application/apps/AppsApi.kt | 8 ++-- .../apps/data/application/apps/AppsApiImpl.kt | 15 +++---- .../application/category/CategoryApiImpl.kt | 13 +++--- .../apps/data/application/data/Application.kt | 20 +-------- .../downloadInfo/DownloadInfoApi.kt | 4 +- .../downloadInfo/DownloadInfoApiImpl.kt | 16 ++++--- .../apps/data/application/home/HomeApiImpl.kt | 12 ++--- .../apps/data/application/search/SearchApi.kt | 4 +- .../data/application/search/SearchApiImpl.kt | 16 +++---- .../application/utils/GplayApiExtensions.kt | 2 - .../data/cleanapk/data/home/CleanApkHome.kt | 2 - .../repositories/CleanApkAppsRepository.kt | 12 +++-- .../repositories/CleanApkPwaRepository.kt | 10 +++-- .../database/install/AppInstallDatabase.kt | 2 +- .../foundation/e/apps/data/enums/Origin.kt | 25 ----------- .../foundation/e/apps/data/enums/Source.kt | 22 +++++----- .../e/apps/data/fdroid/FDroidRepository.kt | 4 +- .../gitlab/SystemAppsUpdatesRepository.kt | 3 +- .../apps/data/gitlab/models/SystemAppInfo.kt | 2 - .../e/apps/data/install/AppManagerWrapper.kt | 2 +- .../e/apps/data/install/models/AppInstall.kt | 8 ++-- .../data/playstore/PlayStoreRepository.kt | 6 ++- .../e/apps/data/updates/UpdatesManagerImpl.kt | 18 +++----- .../data/updates/UpdatesManagerRepository.kt | 2 +- .../apps/domain/ValidateAppAgeLimitUseCase.kt | 10 ++--- .../install/download/DownloadManagerUtils.kt | 4 +- .../install/pkg/AppLoungePackageManager.kt | 4 +- .../workmanager/AppInstallProcessor.kt | 8 ++-- .../e/apps/provider/AgeRatingProvider.kt | 6 +-- .../e/apps/ui/MainActivityViewModel.kt | 3 +- .../ui/application/ApplicationFragment.kt | 28 +++--------- .../ui/application/ApplicationViewModel.kt | 14 +++--- .../model/ApplicationScreenshotsRVAdapter.kt | 17 ++++--- .../application/model/ScreenshotRVAdapter.kt | 15 ++++--- .../subFrags/ScreenshotFragment.kt | 2 +- .../ApplicationListFragment.kt | 1 + .../ApplicationListRVAdapter.kt | 29 ++++++------ .../ApplicationListViewModel.kt | 2 +- .../apps/ui/home/model/HomeChildRVAdapter.kt | 6 +-- .../e/apps/ui/search/SearchFragment.kt | 4 +- .../e/apps/ui/search/SearchViewModel.kt | 17 +++---- .../res/navigation/navigation_resource.xml | 10 ++--- .../e/apps/UpdateManagerImptTest.kt | 44 +++++++++---------- .../foundation/e/apps/apps/AppsApiTest.kt | 15 ++++--- .../e/apps/fused/SearchApiImplTest.kt | 13 ++++-- 49 files changed, 227 insertions(+), 287 deletions(-) delete mode 100644 app/src/main/java/foundation/e/apps/data/enums/Origin.kt 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 a28a08440..fa37e4edc 100644 --- a/app/src/main/java/foundation/e/apps/data/StoreRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/StoreRepository.kt @@ -23,6 +23,5 @@ import foundation.e.apps.data.application.data.Home interface StoreRepository { suspend fun getHomeScreenData(list: MutableList): List - suspend fun getAppDetails(packageNameOrId: String): Application - + suspend fun getAppDetails(packageName: String): Application } diff --git a/app/src/main/java/foundation/e/apps/data/Stores.kt b/app/src/main/java/foundation/e/apps/data/Stores.kt index 0e62cbd7b..2152b4878 100644 --- a/app/src/main/java/foundation/e/apps/data/Stores.kt +++ b/app/src/main/java/foundation/e/apps/data/Stores.kt @@ -20,8 +20,8 @@ class Stores @Inject constructor( } init { - stores[Source.OPEN] = cleanApkAppsRepository + stores[Source.OPEN_SOURCE] = cleanApkAppsRepository stores[Source.PWA] = cleanApkPwaRepository - stores[Source.GPLAY] = playStoreRepository + stores[Source.PLAY_STORE] = playStoreRepository } } \ 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 3c514586d..d6c78793b 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 @@ -58,8 +57,8 @@ class ApplicationDataManager @Inject constructor( 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.GITLAB_RELEASES -> FilterLevel.NONE !isRestricted(application) -> FilterLevel.NONE application.originalSize == 0L -> FilterLevel.UI else -> FilterLevel.NONE 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 bc8ce28f0..400fa25aa 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 @@ -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,9 +73,9 @@ class ApplicationRepository @Inject constructor( suspend fun getApplicationDetails( id: String, packageName: String, - origin: Origin + source: Source ): Pair { - return appsApi.getApplicationDetails(id, packageName, origin) + return appsApi.getApplicationDetails(id, packageName, source) } suspend fun getCleanapkAppDetails(packageName: String): Pair { @@ -84,11 +83,11 @@ class ApplicationRepository @Inject constructor( } suspend fun updateFusedDownloadWithDownloadingInfo( - origin: Origin, + source: Source, appInstall: AppInstall ) { downloadInfoApi.updateFusedDownloadWithDownloadingInfo( - origin, + source, appInstall ) } @@ -116,10 +115,9 @@ 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( @@ -136,7 +134,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 067646e8f..6505821ff 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 0162fcb8a..25ccb03bc 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 @@ -28,7 +28,6 @@ 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 @@ -37,7 +36,6 @@ import foundation.e.apps.data.preference.AppLoungePreference import foundation.e.apps.ui.applicationlist.ApplicationDiffUtil import javax.inject.Inject import foundation.e.apps.data.enums.Source -import foundation.e.apps.data.playstore.PlayStoreRepository class AppsApiImpl @Inject constructor( @ApplicationContext private val context: Context, @@ -79,12 +77,12 @@ class AppsApiImpl @Inject constructor( 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) @@ -183,22 +181,21 @@ class AppsApiImpl @Inject constructor( override suspend fun getApplicationDetails( id: String, packageName: String, - origin: Origin + source: Source ): Pair { var application: Application val result = handleNetworkResult { - val store = stores.getStores()[Source.fromOrigin(origin)] + val store = stores.getStores()[source] ?: throw IllegalStateException("Could not get store") - val idOrPackageName = if (store is PlayStoreRepository) packageName else id - application = store.getAppDetails(idOrPackageName) + application = store.getAppDetails(packageName) application.let { applicationDataManager.updateStatus(it) + it.source = source it.updateType() - it.updateSource(context) it.updateFilterLevel() } application 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 cddc7f184..13335b467 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 @@ -63,7 +63,7 @@ class CategoryApiImpl @Inject constructor( val categoryResults: MutableList = mutableListOf() if (appLoungePreference.isOpenSourceSelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.OPEN)) + categoryResults.add(fetchCategoryResult(categoriesList, type, Source.OPEN_SOURCE)) } if (appLoungePreference.isPWASelected()) { @@ -71,7 +71,7 @@ class CategoryApiImpl @Inject constructor( } if (appLoungePreference.isGplaySelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.GPLAY)) + categoryResults.add(fetchCategoryResult(categoriesList, type, Source.PLAY_STORE)) } return categoryResults.find { it != ResultStatus.OK } ?: ResultStatus.OK @@ -83,8 +83,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 +133,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 +234,7 @@ class CategoryApiImpl @Inject constructor( response?.apps?.forEach { applicationDataManager.updateStatus(it) it.updateType() + it.source = source applicationDataManager.updateFilterLevel(it) list.add(it) } @@ -245,7 +246,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 e99278fcc..99e603411 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 acfa0a329..fe8bb50b2 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 86b911230..0b6fed0d5 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.GITLAB_RELEASES -> { return // nothing to do as downloadURLList is already set } } 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 1aa161696..063c052cc 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 @@ -24,16 +24,12 @@ import androidx.lifecycle.liveData import dagger.hilt.android.qualifiers.ApplicationContext 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.Home import foundation.e.apps.data.application.search.FusedHomeDeferred import foundation.e.apps.data.application.search.SearchApi -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.handleNetworkResult -import foundation.e.apps.data.playstore.PlayStoreRepository import foundation.e.apps.data.preference.AppLoungePreference import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope @@ -61,11 +57,11 @@ class HomeApiImpl @Inject constructor( coroutineScope { if (appLoungePreference.isGplaySelected()) { - resultGplay = async { loadHomeData(list, Source.GPLAY) } + resultGplay = async { loadHomeData(list, Source.PLAY_STORE) } } if (appLoungePreference.isOpenSourceSelected()) { - resultOpenSource = async { loadHomeData(list, Source.OPEN) } + resultOpenSource = async { loadHomeData(list, Source.OPEN_SOURCE) } } if (appLoungePreference.isPWASelected()) { @@ -112,9 +108,9 @@ class HomeApiImpl @Inject constructor( 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.PLAY_STORE -> ("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.OPEN_SOURCE -> ("Open Source home loading error\n" + apiStatus.message).trim() Source.PWA -> ("PWA home loading error\n" + apiStatus.message).trim() } } 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 4ea26f61b..6279b5c71 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,13 +40,11 @@ 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( 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 ead91ecce..a9ada7447 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 @@ -21,7 +21,6 @@ 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 @@ -34,8 +33,8 @@ import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_AN 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 @@ -71,13 +70,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,7 +82,7 @@ class SearchApiImpl @Inject constructor( ) val packageSpecificResults = - fetchPackageSpecificResult(authData, query).data?.first ?: emptyList() + fetchPackageSpecificResult(query).data?.first ?: emptyList() val searchResult = mutableListOf() if (appLoungePreference.isOpenSourceSelected()) { @@ -127,8 +124,8 @@ class SearchApiImpl @Inject constructor( appSources.cleanApkPWARepo.getSearchResult(query).body()?.apps apps?.forEach { applicationDataManager.updateStatus(it) + it.source = Source.PWA it.updateType() - it.updateSource(context) pwaApps.add(it) } } @@ -182,7 +179,6 @@ class SearchApiImpl @Inject constructor( } private suspend fun fetchPackageSpecificResult( - authData: AuthData, query: String, ): SearchResult { val packageSpecificResults: MutableList = mutableListOf() @@ -260,7 +256,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 } @@ -310,8 +306,8 @@ class SearchApiImpl @Inject constructor( response?.forEach { applicationDataManager.updateStatus(it) + it.source = if (it.is_pwa) Source.PWA else Source.OPEN_SOURCE it.updateType() - it.updateSource(context) list.add(it) } @@ -364,7 +360,7 @@ class SearchApiImpl @Inject constructor( return gPlayApps.map { gPlayApp -> availableApps.find { it.package_name == gPlayApp.packageName }?.apply { isGplayReplaced = true - updateSource(context) + source = Source.PLAY_STORE } ?: gPlayApp.toApplication(context) } } catch (e: Exception) { 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 d43e9fc48..0ddc34c77 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 7118307be..de40e01f5 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 74923e8c7..c18be19d0 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 @@ -26,6 +26,7 @@ import foundation.e.apps.data.cleanapk.CleanApkRetrofit 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 @@ -42,13 +43,14 @@ 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 } listHome.forEach { (title, apps) -> + apps.forEach { app -> app.source = Source.OPEN_SOURCE } list.add(Home(title, apps, SearchApi.APP_TYPE_OPEN)) } @@ -90,9 +92,11 @@ 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 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 0d569d3d4..2c65b0c02 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 @@ -26,6 +26,7 @@ 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 @@ -50,6 +51,7 @@ class CleanApkPwaRepository @Inject constructor( } listHome.forEach { (title, apps) -> + apps.forEach { app -> app.source = Source.PWA } list.add(Home(title, apps, SearchApi.APP_TYPE_PWA)) } @@ -88,8 +90,10 @@ 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() } } 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 424e01798..492822746 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 d5305b23d..000000000 --- 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 cf6769c3f..1f471c7b6 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,26 +18,24 @@ package foundation.e.apps.data.enums enum class Source { - GPLAY, + PLAY_STORE, GITLAB_RELEASES, - OPEN, + 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 - } - } - - fun fromOrigin(origin: Origin): Source { - return when (origin) { - Origin.GPLAY -> GPLAY - Origin.CLEANAPK -> OPEN - Origin.GITLAB_RELEASES -> GITLAB_RELEASES + 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 34fd7c4dd..dbb9397af 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 bdce73bf5..9e31d88b0 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.GITLAB_RELEASES 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 7361cfb64..a80aad312 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 119b5653a..3a54630e0 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 13477a2f4..af28c92a8 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 760ce8d09..d3908ae24 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 @@ -43,6 +43,7 @@ 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 @@ -75,6 +76,7 @@ class PlayStoreRepository @Inject constructor( app.apply { applicationDataManager.updateStatus(this) applicationDataManager.updateFilterLevel(this) + source = Source.PLAY_STORE } } list.add(Home(it.key, fusedApps)) @@ -158,14 +160,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) { 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 d6cd28ffa..a79f0cbbe 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 ) } } 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 7e030148c..581ce4fa9 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 4da0219ed..3345357f9 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.GITLAB_RELEASES } 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 689f70343..4f0086cdf 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 43e97d198..e61c84164 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 e96a9b5ac..121461fa6 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.GITLAB_RELEASES) { 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 1b262b85f..1cd4991b5 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/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt index a91df34c0..2649b66cf 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 9722b8c25..dd66c0873 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) @@ -438,11 +424,11 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { updateCategoryTitle(it) - if (it.origin == Origin.CLEANAPK) { + if (it.source == Source.OPEN_SOURCE || it.source == Source.PWA) { sourceTag.visibility = View.VISIBLE - sourceTag.text = it.source + sourceTag.text = it.source.toString() } - if (origin == Origin.CLEANAPK) { + if (it.source == Source.PWA || it.source == Source.OPEN_SOURCE) { appIcon.load(CleanApkRetrofit.ASSET_URL + it.icon_image_path) } else { appIcon.load(it.icon_image_path) @@ -491,7 +477,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } private fun setupScreenshotRVAdapter() { - screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(origin) + screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(args.source) binding.recyclerView.apply { adapter = screenshotsRVAdapter layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) @@ -605,7 +591,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { val applicationLoadingParams = ApplicationLoadingParams( args.id, packageName, - origin, + args.source, isFdroidDeepLink, authObjectList, args.isPurchased 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 15c1ce8c1..de033ec6f 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 @@ -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 7fa122efb..ceb025eb0 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.GITLAB_RELEASES -> { // 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 01fe6c50b..c065af546 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 eb65823ee..2b5e4bdda 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 ef7aa73a6..3c5fc507d 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 66cc24c81..cb6826f94 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.GITLAB_RELEASES -> { 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 bf4272a17..a89dd1291 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/model/HomeChildRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/home/model/HomeChildRVAdapter.kt index 62886ab2d..a98aaca41 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/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt index f9017ec06..8ba57a29a 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 19820b0d9..0a81cc638 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 @@ -31,13 +31,11 @@ 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 @@ -105,7 +103,6 @@ class SearchViewModel @Inject constructor( fun loadData( query: String, - lifecycleOwner: LifecycleOwner, authObjectList: List, retryBlock: (failedObjects: List) -> Boolean ) { @@ -114,7 +111,7 @@ class SearchViewModel @Inject constructor( this.lastAuthObjects = authObjectList super.onLoadData(authObjectList, { successAuthList, failedAuthList -> successAuthList.find { it is AuthObject.CleanApk }?.run { - fetchCleanApkData(query, null) + fetchCleanApkData(query) } successAuthList.find { it is AuthObject.GPlayAuth }?.run { @@ -137,14 +134,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) @@ -250,7 +243,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/res/navigation/navigation_resource.xml b/app/src/main/res/navigation/navigation_resource.xml index 90fae739d..59362730e 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"/> + android:name="source" + app:argType="foundation.e.apps.data.enums.Source" /> 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.GITLAB_RELEASES }) } @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.GITLAB_RELEASES, 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 9dbf39776..c0a884b9d 100644 --- a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt +++ b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt @@ -24,8 +24,8 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.aurora.gplayapi.Constants 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 @@ -33,6 +33,7 @@ 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 @@ -83,6 +84,9 @@ class AppsApiTest { @Mock private lateinit var gPlayAPIRepository: PlayStoreRepository + @Mock + private lateinit var stores: Stores + private lateinit var appsApi: AppsApi private lateinit var applicationDataManager: ApplicationDataManager @@ -104,6 +108,7 @@ class AppsApiTest { context, preferenceManagerModule, appSourcesContainer, + stores, applicationDataManager ) } @@ -432,7 +437,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 = "" @@ -449,7 +454,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 } @@ -460,7 +465,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 } @@ -472,7 +477,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 } 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 18bd3e121..0d2314ac9 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -25,8 +25,8 @@ 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,6 +35,7 @@ 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 @@ -88,6 +89,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 @@ -113,6 +117,7 @@ class SearchApiImplTest { context, preferenceManagerModule, appSourcesContainer, + stores, applicationDataManager, ) @@ -134,7 +139,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,7 +188,7 @@ class SearchApiImplTest { ) 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) @@ -276,7 +281,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) -- GitLab From b43ad639e59375c38a853f1fd528fdd1d2e60fc6 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Tue, 7 Jan 2025 11:59:19 +0100 Subject: [PATCH 04/12] Sanitize search --- .../foundation/e/apps/data/StoreRepository.kt | 1 + .../data/application/ApplicationRepository.kt | 7 ++- .../apps/data/application/search/SearchApi.kt | 3 +- .../data/application/search/SearchApiImpl.kt | 54 +++++++++---------- .../repositories/CleanApkAppsRepository.kt | 21 ++++++++ .../repositories/CleanApkPwaRepository.kt | 21 ++++++++ .../data/playstore/PlayStoreRepository.kt | 8 ++- .../ui/parentFragment/LoadingViewModel.kt | 8 +-- .../e/apps/ui/search/SearchViewModel.kt | 29 ++++------ .../e/apps/fused/SearchApiImplTest.kt | 1 + 10 files changed, 95 insertions(+), 58 deletions(-) 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 fa37e4edc..f424c8112 100644 --- a/app/src/main/java/foundation/e/apps/data/StoreRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/StoreRepository.kt @@ -24,4 +24,5 @@ import foundation.e.apps.data.application.data.Home interface StoreRepository { 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/application/ApplicationRepository.kt b/app/src/main/java/foundation/e/apps/data/application/ApplicationRepository.kt index 400fa25aa..d6252d018 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 @@ -121,10 +121,9 @@ class ApplicationRepository @Inject constructor( } suspend fun getGplaySearchResults( - query: String, - nextPageSubBundle: Set? - ): GplaySearchResult { - return searchAPIImpl.getGplaySearchResult(query, nextPageSubBundle) + query: String + ): SearchResult { + return searchAPIImpl.getGplaySearchResult(query) } suspend fun getAppsListBasedOnCategory( 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 6279b5c71..4dfac924f 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 @@ -49,8 +49,7 @@ interface SearchApi { 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 a9ada7447..46bb79a86 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,11 +20,11 @@ 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.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 @@ -32,7 +32,6 @@ 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.ResultStatus import foundation.e.apps.data.enums.Source import foundation.e.apps.data.handleNetworkResult @@ -51,6 +50,7 @@ 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 { @@ -121,8 +121,9 @@ class SearchApiImpl @Inject constructor( val pwaApps: MutableList = mutableListOf() val result = handleNetworkResult { val apps = - appSources.cleanApkPWARepo.getSearchResult(query).body()?.apps - apps?.forEach { + stores.getStores()[Source.PWA]?.getSearchResults(query) ?: emptyList() + + apps.forEach { applicationDataManager.updateStatus(it) it.source = Source.PWA it.updateType() @@ -275,13 +276,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.getStores()[Source.PWA]?.getSearchResults(packageName) ?: emptyList() - if (result?.apps?.isNotEmpty() == true && result.numberOfResults == 1) { - application = result.apps[0] + if (results.isNotEmpty() && results.size == 1) { + application = results[0] } } @@ -302,11 +300,10 @@ class SearchApiImpl @Inject constructor( ): List { val list = mutableListOf() val response = - appSources.cleanApkAppsRepo.getSearchResult(keyword).body()?.apps + stores.getStores()[Source.OPEN_SOURCE]?.getSearchResults(keyword) ?: emptyList() - response?.forEach { + response.forEach { applicationDataManager.updateStatus(it) - it.source = if (it.is_pwa) Source.PWA else Source.OPEN_SOURCE it.updateType() list.add(it) } @@ -316,12 +313,8 @@ 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()) { return@handleNetworkResult Pair( listOf(), @@ -329,16 +322,21 @@ class SearchApiImpl @Inject constructor( ) } - val fusedAppList = replaceWithFDroid(searchResults.first).toMutableList() + val searchResults = + stores.getStores()[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") ) @@ -348,24 +346,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 source = Source.PLAY_STORE - } ?: gPlayApp.toApplication(context) + } ?: 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/cleanapk/repositories/CleanApkAppsRepository.kt b/app/src/main/java/foundation/e/apps/data/cleanapk/repositories/CleanApkAppsRepository.kt index c18be19d0..f6bac7107 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 @@ -99,6 +99,27 @@ class CleanApkAppsRepository @Inject constructor( 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 { val version = versionCode?.let { it as String } return cleanApkRetrofit.getDownloadInfo(idOrPackageName, version, null) 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 2c65b0c02..c65e8bc7d 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 @@ -96,4 +96,25 @@ class CleanApkPwaRepository @Inject constructor( 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/playstore/PlayStoreRepository.kt b/app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt index d3908ae24..c5c6d30f0 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 @@ -57,7 +57,6 @@ class PlayStoreRepository @Inject constructor( private val authenticatorRepository: AuthenticatorRepository, private val applicationDataManager: ApplicationDataManager ) : StoreRepository { - override suspend fun getHomeScreenData(list: MutableList): List { val homeScreenData = mutableMapOf>() val homeElements = createTopChartElements() @@ -94,6 +93,13 @@ class PlayStoreRepository @Inject constructor( context.getString(R.string.movers_shakers_games) to mapOf(Chart.MOVERS_SHAKERS to Type.GAME), ) + override suspend fun getSearchResults(pattern: String): List { + val searchResult = WebSearchHelper().using(gPlayHttpClient).searchResults(pattern) + return searchResult.appList.map { + it.toApplication(context) + } + } + fun getSearchResult( query: String, subBundle: MutableSet? 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 a59e502ca..7e7d2d3cd 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/SearchViewModel.kt b/app/src/main/java/foundation/e/apps/ui/search/SearchViewModel.kt index 0a81cc638..2aaa106f0 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,18 +18,14 @@ 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.Source import foundation.e.apps.data.exodus.repositories.IAppPrivacyInfoRepository @@ -62,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 @@ -103,24 +98,22 @@ class SearchViewModel @Inject constructor( fun loadData( query: String, - 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 { + 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) } @@ -166,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 { @@ -174,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 @@ -188,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 } } 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 0d2314ac9..09cbd0438 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -125,6 +125,7 @@ class SearchApiImplTest { appsApi, preferenceManagerModule, appSourcesContainer, + stores, applicationDataManager ) } -- GitLab From a76999e40594402339b4fbf23255a89347732655 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Thu, 9 Jan 2025 08:58:39 +0100 Subject: [PATCH 05/12] Fix System app label --- .../e/apps/data/application/ApplicationDataManager.kt | 2 +- .../data/application/downloadInfo/DownloadInfoApiImpl.kt | 2 +- .../foundation/e/apps/data/application/home/HomeApiImpl.kt | 2 +- app/src/main/java/foundation/e/apps/data/enums/Source.kt | 4 ++-- .../e/apps/data/gitlab/SystemAppsUpdatesRepository.kt | 2 +- .../foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt | 2 +- .../e/apps/install/workmanager/AppInstallProcessor.kt | 2 +- .../ui/application/model/ApplicationScreenshotsRVAdapter.kt | 2 +- .../e/apps/ui/applicationlist/ApplicationListRVAdapter.kt | 2 +- app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-is/strings.xml | 3 +-- app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-nb-rNO/strings.xml | 3 +-- app/src/main/res/values-nl/strings.xml | 3 +-- app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values/strings.xml | 1 - .../test/java/foundation/e/apps/UpdateManagerImptTest.kt | 6 +++--- 21 files changed, 16 insertions(+), 27 deletions(-) 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 d6c78793b..96290fd68 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 @@ -58,7 +58,7 @@ class ApplicationDataManager @Inject constructor( application.package_name.isBlank() -> FilterLevel.UNKNOWN !application.isFree && application.price.isBlank() -> FilterLevel.UI application.source == Source.PWA || application.source == Source.OPEN_SOURCE -> FilterLevel.NONE - application.source == Source.GITLAB_RELEASES -> FilterLevel.NONE + application.source == Source.SYSTEM_APP -> FilterLevel.NONE !isRestricted(application) -> FilterLevel.NONE application.originalSize == 0L -> FilterLevel.UI else -> FilterLevel.NONE 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 0b6fed0d5..8e6ca6d84 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 @@ -73,7 +73,7 @@ class DownloadInfoApiImpl @Inject constructor( updateDownloadInfoFromGplay(appInstall, list) } - Source.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/HomeApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/home/HomeApiImpl.kt index 063c052cc..039bb6892 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 @@ -109,7 +109,7 @@ class HomeApiImpl @Inject constructor( if (apiStatus != ResultStatus.OK) { apiStatus.message = when (source) { Source.PLAY_STORE -> ("GPlay home loading error\n" + apiStatus.message).trim() - Source.GITLAB_RELEASES -> ("Gitlab home not allowed\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() } 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 1f471c7b6..bb10fcdbe 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 @@ -19,7 +19,7 @@ package foundation.e.apps.data.enums enum class Source { PLAY_STORE, - GITLAB_RELEASES, + SYSTEM_APP, OPEN_SOURCE, PWA; @@ -34,7 +34,7 @@ enum class Source { return when (source) { "Open Source" -> OPEN_SOURCE "PWA" -> PWA - "GITLAB_RELEASES" -> GITLAB_RELEASES + "SYSTEM_APP" -> SYSTEM_APP else -> PLAY_STORE } } 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 9e31d88b0..e6f9e290a 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 @@ -255,7 +255,7 @@ class SystemAppsUpdatesRepository @Inject constructor( app.run { applicationDataManager.updateStatus(this) - source = Source.GITLAB_RELEASES + source = Source.SYSTEM_APP updateList.add(this) } } 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 3345357f9..00b9f1776 100644 --- a/app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt +++ b/app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt @@ -84,7 +84,7 @@ class ValidateAppAgeLimitUseCase @Inject constructor( } private fun isGitlabApp(app: AppInstall): Boolean { - return app.source == Source.GITLAB_RELEASES + return app.source == Source.SYSTEM_APP } private fun isCleanApkApp(app: AppInstall): Boolean { 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 121461fa6..58cc4ca81 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 @@ -100,7 +100,7 @@ class AppInstallProcessor @Inject constructor( it.contentRating = application.contentRating } - if (appInstall.type == Type.PWA || application.source == Source.GITLAB_RELEASES) { + if (appInstall.type == Type.PWA || application.source == Source.SYSTEM_APP) { appInstall.downloadURLList = mutableListOf(application.url) } 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 ceb025eb0..6119dfb12 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 @@ -61,7 +61,7 @@ class ApplicationScreenshotsRVAdapter( Source.PLAY_STORE -> { imageView.load(oldList[position]) } - Source.GITLAB_RELEASES -> { + Source.SYSTEM_APP -> { // no operation } } 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 cb6826f94..d8855538c 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 @@ -185,7 +185,7 @@ class ApplicationListRVAdapter( placeholder(shimmerDrawable) } } - Source.GITLAB_RELEASES -> { + Source.SYSTEM_APP -> { appIcon.load(getAppIcon(appIcon.context, searchApp.package_name)) { placeholder(shimmerDrawable) } diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 8ff4f10be..1daaf6179 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -195,7 +195,6 @@ 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 53be90f04..cd8a60412 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 2a8105dbb..ae1667f1e 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 4383050ed..10db1ac7b 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 b2dcd0b66..95b5f2a67 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 5b584b7e1..ebfc8bc3f 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 287ce641b..8c3978acf 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 36e577c07..969ca3f66 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 1274e9417..76ababc92 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 d18b67c49..d9e2b5536 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 84a84cd38..c6c3b2155 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 45acbd34a..8a73e0184 100644 --- a/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt +++ b/app/src/test/java/foundation/e/apps/UpdateManagerImptTest.kt @@ -107,7 +107,7 @@ class UpdateManagerImptTest { status = status, name = "Demo Four", package_name = "foundation.e.demofour", - source = Source.GITLAB_RELEASES, + source = Source.SYSTEM_APP, filterLevel = FilterLevel.NONE ) ) @@ -242,7 +242,7 @@ class UpdateManagerImptTest { ) val updateResult = updatesManagerImpl.getUpdates() - assertFalse("fetchupdate", updateResult.first.any { it.source != Source.GITLAB_RELEASES }) + assertFalse("fetchupdate", updateResult.first.any { it.source != Source.SYSTEM_APP }) } @Test @@ -328,7 +328,7 @@ class UpdateManagerImptTest { val updateResult = updatesManagerImpl.getUpdatesOSS() assertEquals("UpdateOSS", 2, updateResult.first.size) assertEquals("UpdateOSS", Source.OPEN_SOURCE, updateResult.first[1].source) - assertEquals("UpdateOSS", Source.GITLAB_RELEASES, updateResult.first[0].source) + assertEquals("UpdateOSS", Source.SYSTEM_APP, updateResult.first[0].source) } @Test -- GitLab From 0fb723261af5d02e8c7f95121416abd944c840b5 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Fri, 10 Jan 2025 08:45:21 +0100 Subject: [PATCH 06/12] Fix deep links --- .../data/application/ApplicationRepository.kt | 4 -- .../apps/data/application/apps/AppsApiImpl.kt | 72 ++++--------------- .../repositories/CleanApkAppsRepository.kt | 11 --- .../repositories/CleanApkPwaRepository.kt | 11 --- .../repositories/CleanApkRepository.kt | 1 - .../e/apps/data/updates/UpdatesManagerImpl.kt | 6 +- .../java/foundation/e/apps/ui/MainActivity.kt | 1 + .../ui/application/ApplicationFragment.kt | 13 ++-- .../ui/application/ApplicationViewModel.kt | 8 +-- .../res/navigation/navigation_resource.xml | 6 +- 10 files changed, 30 insertions(+), 103 deletions(-) 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 d6252d018..44d300a1f 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 @@ -78,10 +78,6 @@ class ApplicationRepository @Inject constructor( return appsApi.getApplicationDetails(id, packageName, source) } - suspend fun getCleanapkAppDetails(packageName: String): Pair { - return appsApi.getCleanapkAppDetails(packageName) - } - suspend fun updateFusedDownloadWithDownloadingInfo( source: Source, appInstall: AppInstall 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 25ccb03bc..213469c72 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,15 +18,9 @@ package foundation.e.apps.data.application.apps -import android.content.Context -import com.aurora.gplayapi.data.models.App -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.ResultStatus import foundation.e.apps.data.enums.Status @@ -38,30 +32,17 @@ import javax.inject.Inject 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.getStores()[Source.OPEN_SOURCE]?.getAppDetails(packageName) ?: Application() + application.source = Source.OPEN_SOURCE + application.updateType() application.updateFilterLevel() } @@ -107,13 +88,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.getStores()[Source.OPEN_SOURCE]?.getAppDetails(packageName) ?: Application()) } return Pair(applicationList, status) @@ -124,13 +103,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.getStores()[Source.PLAY_STORE]?.getAppDetails(packageName) ?: Application() + handleFilteredApps(app, applicationList) } - return Pair(applicationList, result.getResultStatus()) + return Pair(applicationList, ResultStatus.OK) } /* @@ -140,44 +118,19 @@ class AppsApiImpl @Inject constructor( * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5174 */ private fun handleFilteredApps( - app: App, + 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 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, @@ -191,7 +144,6 @@ class AppsApiImpl @Inject constructor( ?: throw IllegalStateException("Could not get store") application = store.getAppDetails(packageName) - application.let { applicationDataManager.updateStatus(it) it.source = source 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 f6bac7107..9c96bbf0a 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 @@ -57,17 +57,6 @@ class CleanApkAppsRepository @Inject constructor( return list } - 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 - ) - } - override suspend fun getAppsByCategory( category: String, paginationParameter: Any? 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 c65e8bc7d..d6bb3b1f0 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 @@ -58,17 +58,6 @@ class CleanApkPwaRepository @Inject constructor( return list } - override suspend fun getSearchResult(query: String, searchBy: String?): Response { - return cleanApkRetrofit.searchApps( - query, - CleanApkRetrofit.APP_SOURCE_ANY, - CleanApkRetrofit.APP_TYPE_PWA, - 20, - 1, - searchBy - ) - } - override suspend fun getAppsByCategory(category: String, paginationParameter: Any?): Response { return cleanApkRetrofit.listApps( category, 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 2a9388f02..3d0c19e21 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/updates/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt index a79f0cbbe..eb6015505 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 @@ -321,11 +321,11 @@ class UpdatesManagerImpl @Inject constructor( packageName: String, appsAndSignatures: HashMap ) { - val cleanApkFusedApp = applicationRepository.getCleanapkAppDetails(packageName).first - if (cleanApkFusedApp.package_name.isBlank()) { + val app = applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).first + if (app[0].package_name.isBlank()) { return } - appsAndSignatures[packageName] = getPgpSignature(cleanApkFusedApp) + appsAndSignatures[packageName] = getPgpSignature(app[0]) } private suspend fun getPgpSignature(cleanApkApplication: Application): String { 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 91848af3e..59d88fcd0 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/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt index dd66c0873..f5ee3f476 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 @@ -423,12 +423,10 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } updateCategoryTitle(it) - - if (it.source == Source.OPEN_SOURCE || it.source == Source.PWA) { + 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.toString() - } - if (it.source == Source.PWA || it.source == Source.OPEN_SOURCE) { appIcon.load(CleanApkRetrofit.ASSET_URL + it.icon_image_path) } else { appIcon.load(it.icon_image_path) @@ -477,7 +475,8 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } private fun setupScreenshotRVAdapter() { - screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(args.source) + val source = if (isFdroidDeepLink) Source.OPEN_SOURCE else args.source + screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(source) binding.recyclerView.apply { adapter = screenshotsRVAdapter layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) @@ -588,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, - args.source, + 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 de033ec6f..dcfe7432e 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 @@ -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) { diff --git a/app/src/main/res/navigation/navigation_resource.xml b/app/src/main/res/navigation/navigation_resource.xml index 59362730e..330939045 100644 --- a/app/src/main/res/navigation/navigation_resource.xml +++ b/app/src/main/res/navigation/navigation_resource.xml @@ -120,17 +120,17 @@ android:defaultValue="false"/> + 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}/" /> -- GitLab From 7043435a19b3da3d649598723a6ec87a134869a7 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Mon, 13 Jan 2025 13:39:07 +0100 Subject: [PATCH 07/12] Fix unit tests --- .../foundation/e/apps/apps/AppsApiTest.kt | 13 ----- .../e/apps/fused/SearchApiImplTest.kt | 56 ++++++++----------- 2 files changed, 24 insertions(+), 45 deletions(-) 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 c0a884b9d..d9b680dc8 100644 --- a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt +++ b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt @@ -23,7 +23,6 @@ import android.text.format.Formatter import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.aurora.gplayapi.Constants 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.Status @@ -31,8 +30,6 @@ 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 @@ -75,12 +72,6 @@ class AppsApiTest { @Mock private lateinit var context: Context - @Mock - private lateinit var cleanApkAppsRepository: CleanApkAppsRepository - - @Mock - private lateinit var cleanApkPWARepository: CleanApkPwaRepository - @Mock private lateinit var gPlayAPIRepository: PlayStoreRepository @@ -102,12 +93,8 @@ class AppsApiTest { preferenceManagerModule = FakeAppLoungePreference(context) applicationDataManager = ApplicationDataManager(appLoungePackageManager, pwaManager) - val appSourcesContainer = - AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) appsApi = AppsApiImpl( - context, preferenceManagerModule, - appSourcesContainer, stores, applicationDataManager ) 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 09cbd0438..2efe135d3 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -21,7 +21,6 @@ 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 @@ -100,10 +99,6 @@ class SearchApiImplTest { private lateinit var formatterMocked: MockedStatic - companion object { - private val AUTH_DATA = AuthData("e@e.email", "AtadyMsIAtadyM") - } - @Before fun setup() { MockitoAnnotations.openMocks(this) @@ -114,9 +109,7 @@ class SearchApiImplTest { val appSourcesContainer = AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) appsApi = AppsApiImpl( - context, preferenceManagerModule, - appSourcesContainer, stores, applicationDataManager, ) @@ -184,9 +177,13 @@ 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") @@ -196,19 +193,16 @@ class SearchApiImplTest { } 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) { @@ -219,23 +213,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") @@ -265,16 +257,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 -- GitLab From d865d151ce7fe239718eeb0d2b3ba0f63f798f2d Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Mon, 13 Jan 2025 14:54:37 +0100 Subject: [PATCH 08/12] Remove deadcode --- .../data/playstore/PlayStoreRepository.kt | 45 ------------------- 1 file changed, 45 deletions(-) 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 c5c6d30f0..c84e5845f 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 @@ -100,33 +99,6 @@ class PlayStoreRepository @Inject constructor( } } - 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) - } - - 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 { val searchData = mutableListOf() withContext(Dispatchers.IO) { @@ -183,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 -- GitLab From 115eb2fbd53c1ba00c33226048400c6014a84def Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Tue, 14 Jan 2025 13:43:18 +0100 Subject: [PATCH 09/12] Improve Stores class --- .../java/foundation/e/apps/data/Stores.kt | 26 ++++++++---- .../apps/data/application/apps/AppsApiImpl.kt | 12 +++--- .../application/category/CategoryApiImpl.kt | 16 ++----- .../apps/data/application/home/HomeApiImpl.kt | 41 +++++------------- .../data/application/search/SearchApiImpl.kt | 42 ++++++++----------- .../e/apps/ui/home/HomeViewModel.kt | 24 +++++------ .../e/apps/ui/settings/SettingsFragment.kt | 30 ++++++++++--- .../foundation/e/apps/apps/AppsApiTest.kt | 1 - .../e/apps/category/CategoryApiTest.kt | 39 +++++++++-------- .../e/apps/fused/SearchApiImplTest.kt | 2 - .../e/apps/home/HomeViewModelTest.kt | 12 ++++-- 11 files changed, 120 insertions(+), 125 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/data/Stores.kt b/app/src/main/java/foundation/e/apps/data/Stores.kt index 2152b4878..ca8cf3c75 100644 --- a/app/src/main/java/foundation/e/apps/data/Stores.kt +++ b/app/src/main/java/foundation/e/apps/data/Stores.kt @@ -13,15 +13,27 @@ class Stores @Inject constructor( cleanApkAppsRepository: CleanApkAppsRepository, cleanApkPwaRepository: CleanApkPwaRepository, ) { - private val stores = mutableMapOf() - fun getStores(): Map { - return stores + 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 } - init { - stores[Source.OPEN_SOURCE] = cleanApkAppsRepository - stores[Source.PWA] = cleanApkPwaRepository - stores[Source.PLAY_STORE] = playStoreRepository + 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/apps/AppsApiImpl.kt b/app/src/main/java/foundation/e/apps/data/application/apps/AppsApiImpl.kt index 213469c72..810ed5595 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 @@ -26,13 +26,11 @@ 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 javax.inject.Inject import foundation.e.apps.data.enums.Source class AppsApiImpl @Inject constructor( - private val appLoungePreference: AppLoungePreference, private val stores: Stores, private val applicationDataManager: ApplicationDataManager ) : AppsApi { @@ -40,7 +38,7 @@ class AppsApiImpl @Inject constructor( override suspend fun getCleanapkAppDetails(packageName: String): Pair { var application = Application() val result = handleNetworkResult { - application = stores.getStores()[Source.OPEN_SOURCE]?.getAppDetails(packageName) ?: Application() + application = stores.getStore(Source.OPEN_SOURCE)?.getAppDetails(packageName) ?: Application() application.source = Source.OPEN_SOURCE application.updateType() application.updateFilterLevel() @@ -92,7 +90,7 @@ class AppsApiImpl @Inject constructor( val applicationList = mutableListOf() for (packageName in packageNameList) { - applicationList.add(stores.getStores()[Source.OPEN_SOURCE]?.getAppDetails(packageName) ?: Application()) + applicationList.add(stores.getStore(Source.OPEN_SOURCE)?.getAppDetails(packageName) ?: Application()) } return Pair(applicationList, status) @@ -104,7 +102,7 @@ class AppsApiImpl @Inject constructor( val applicationList = mutableListOf() for (packageName in packageNameList) { - val app = stores.getStores()[Source.PLAY_STORE]?.getAppDetails(packageName) ?: Application() + val app = stores.getStore(Source.PLAY_STORE)?.getAppDetails(packageName) ?: Application() handleFilteredApps(app, applicationList) } @@ -140,7 +138,7 @@ class AppsApiImpl @Inject constructor( val result = handleNetworkResult { - val store = stores.getStores()[source] + val store = stores.getStore(source) ?: throw IllegalStateException("Could not get store") application = store.getAppDetails(packageName) @@ -207,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 13335b467..8bf89e831 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_SOURCE)) - } - - if (appLoungePreference.isPWASelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.PWA)) - } - - if (appLoungePreference.isGplaySelected()) { - categoryResults.add(fetchCategoryResult(categoriesList, type, Source.PLAY_STORE)) + for ((source, _) in stores.getStores()) { + categoryResults.add(fetchCategoryResult(categoriesList, type, source)) } return categoryResults.find { it != ResultStatus.OK } ?: ResultStatus.OK 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 039bb6892..1ac730bca 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,26 +18,20 @@ package foundation.e.apps.data.application.home -import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.liveData -import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.ResultSupreme 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.preference.AppLoungePreference import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope import javax.inject.Inject class HomeApiImpl @Inject constructor( - @ApplicationContext private val context: Context, - private val appLoungePreference: AppLoungePreference, private val stores: Stores ) : HomeApi { @@ -49,35 +43,22 @@ class HomeApiImpl @Inject constructor( 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.PLAY_STORE) } + if (Source.PLAY_STORE in stores.getStores()) { + val result = async { + loadHomeData(list, Source.PLAY_STORE) + } + emit(result.await()) } - if (appLoungePreference.isOpenSourceSelected()) { - resultOpenSource = async { loadHomeData(list, Source.OPEN_SOURCE) } - } - - if (appLoungePreference.isPWASelected()) { - resultPWA = async { loadHomeData(list, Source.PWA) } - } - - resultGplay?.await()?.let { - emit(it) - } - - resultOpenSource?.await()?.let { - emit(it) - } - - resultPWA?.await()?.let { - emit(it) + stores.getStores().forEach { (source, _) -> + val result = async { + loadHomeData(list, source) + } + emit(result.await()) } } } @@ -88,7 +69,7 @@ class HomeApiImpl @Inject constructor( source: Source ): ResultSupreme> { val result = handleNetworkResult { - val homeDataBuilder = stores.getStores()[source] + val homeDataBuilder = stores.getStore(source) homeDataBuilder?.getHomeScreenData(priorList) ?: throw IllegalStateException("Could not find store for $source") } 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 46bb79a86..d35b4476d 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 @@ -28,7 +28,6 @@ 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 @@ -37,18 +36,13 @@ 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 @@ -60,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 } @@ -85,7 +79,7 @@ class SearchApiImpl @Inject constructor( fetchPackageSpecificResult(query).data?.first ?: emptyList() val searchResult = mutableListOf() - if (appLoungePreference.isOpenSourceSelected()) { + if (stores.isStoreEnabled(Source.OPEN_SOURCE)) { finalSearchResult = fetchOpenSourceSearchResult( query, searchResult, @@ -93,7 +87,7 @@ class SearchApiImpl @Inject constructor( ) } - if (appLoungePreference.isPWASelected()) { + if (stores.isStoreEnabled(Source.PWA)) { finalSearchResult = fetchPWASearchResult( query, searchResult, @@ -101,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) ) ) } @@ -121,7 +115,7 @@ class SearchApiImpl @Inject constructor( val pwaApps: MutableList = mutableListOf() val result = handleNetworkResult { val apps = - stores.getStores()[Source.PWA]?.getSearchResults(query) ?: emptyList() + stores.getStore(Source.PWA)?.getSearchResults(query) ?: emptyList() apps.forEach { applicationDataManager.updateStatus(it) @@ -143,7 +137,7 @@ class SearchApiImpl @Inject constructor( packageSpecificResults, query ), - appLoungePreference.isGplaySelected() + stores.isStoreEnabled(Source.PLAY_STORE) ), exception = result.exception ) @@ -173,7 +167,7 @@ class SearchApiImpl @Inject constructor( packageSpecificResults, query ), - appLoungePreference.isGplaySelected() || appLoungePreference.isPWASelected() + stores.isStoreEnabled(Source.PLAY_STORE) || stores.isStoreEnabled(Source.PWA) ), exception = result.exception ) @@ -187,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) } } @@ -203,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)) } @@ -235,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)) } @@ -276,7 +270,7 @@ class SearchApiImpl @Inject constructor( private suspend fun getCleanApkSearchResult(packageName: String): ResultSupreme { var application = Application() val result = handleNetworkResult { - val results = stores.getStores()[Source.PWA]?.getSearchResults(packageName) ?: emptyList() + val results = stores.getStore(Source.OPEN_SOURCE)?.getSearchResults(packageName) ?: emptyList() if (results.isNotEmpty() && results.size == 1) { application = results[0] @@ -300,7 +294,7 @@ class SearchApiImpl @Inject constructor( ): List { val list = mutableListOf() val response = - stores.getStores()[Source.OPEN_SOURCE]?.getSearchResults(keyword) ?: emptyList() + stores.getStore(Source.OPEN_SOURCE)?.getSearchResults(keyword) ?: emptyList() response.forEach { applicationDataManager.updateStatus(it) @@ -315,7 +309,7 @@ class SearchApiImpl @Inject constructor( query: String, ): SearchResult { val result = handleNetworkResult { - if (!appLoungePreference.isGplaySelected()) { + if (!stores.isStoreEnabled(Source.PLAY_STORE)) { return@handleNetworkResult Pair( listOf(), setOf() @@ -323,7 +317,7 @@ class SearchApiImpl @Inject constructor( } val searchResults = - stores.getStores()[Source.PLAY_STORE]?.getSearchResults(query) + stores.getStore(Source.PLAY_STORE)?.getSearchResults(query) ?: throw IllegalStateException("Could not get store") val apps = replaceWithFDroid(searchResults).toMutableList() 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 666f81acd..3e57bace0 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 @@ -24,19 +24,22 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope 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.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 @@ -52,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, @@ -78,17 +81,12 @@ class HomeViewModel @Inject constructor( } 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 } 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 29f8f7f85..0fd753a7a 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/test/java/foundation/e/apps/apps/AppsApiTest.kt b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt index d9b680dc8..812e3c541 100644 --- a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt +++ b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt @@ -94,7 +94,6 @@ class AppsApiTest { applicationDataManager = ApplicationDataManager(appLoungePackageManager, pwaManager) appsApi = AppsApiImpl( - preferenceManagerModule, stores, applicationDataManager ) 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 349e143fc..b7e4a7673 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(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 2efe135d3..3bf8dac88 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -109,14 +109,12 @@ class SearchApiImplTest { val appSourcesContainer = AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) appsApi = AppsApiImpl( - preferenceManagerModule, stores, applicationDataManager, ) fusedAPIImpl = SearchApiImpl( appsApi, - preferenceManagerModule, appSourcesContainer, stores, applicationDataManager 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 7930a3b48..db4a4e28f 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 -- GitLab From b4df302430f84f6b5d466edaa33a1760bb8eb9a4 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Wed, 15 Jan 2025 08:14:38 +0100 Subject: [PATCH 10/12] Enable Play Store according to user mode. --- app/src/main/java/foundation/e/apps/ui/LoginViewModel.kt | 6 ++++++ .../test/java/foundation/e/apps/login/LoginViewModelTest.kt | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) 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 3c8c36387..16cb8c283 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/test/java/foundation/e/apps/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt index 38fdebfe9..c3f13a29c 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 -- GitLab From a6ef2ee99d6c0c5f3580ab8d3cd6144a502c6df3 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Fri, 17 Jan 2025 15:12:12 +0100 Subject: [PATCH 11/12] Fix issue loading Play Store twice. --- .../foundation/e/apps/data/application/home/HomeApiImpl.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 1ac730bca..e82c70db8 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 @@ -54,7 +54,8 @@ class HomeApiImpl @Inject constructor( emit(result.await()) } - stores.getStores().forEach { (source, _) -> + val otherStores = stores.getStores().filter { it.key != Source.PLAY_STORE } + otherStores.forEach { (source, _) -> val result = async { loadHomeData(list, source) } -- GitLab From ed7d49b6d59a7129ae929a89730128671f7e9b9a Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Fri, 17 Jan 2025 16:30:37 +0100 Subject: [PATCH 12/12] Fix IndexOutOfBoundsException --- .../e/apps/data/updates/UpdatesManagerImpl.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 eb6015505..068efbb3f 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 @@ -321,11 +321,15 @@ class UpdatesManagerImpl @Inject constructor( packageName: String, appsAndSignatures: HashMap ) { - val app = applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).first - if (app[0].package_name.isBlank()) { + val apps = applicationRepository.getApplicationDetails(listOf(packageName), Source.OPEN_SOURCE).first + if (apps.isEmpty()) { return } - appsAndSignatures[packageName] = getPgpSignature(app[0]) + + if (apps[0].package_name.isBlank()) { + return + } + appsAndSignatures[packageName] = getPgpSignature(apps[0]) } private suspend fun getPgpSignature(cleanApkApplication: Application): String { -- GitLab