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 ca8cf3c759b03bcd91c8a511d4547d3547d5115e..2437dbc87b4c7b7858f2b6018fb4a0c4b23046ba 100644 --- a/app/src/main/java/foundation/e/apps/data/Stores.kt +++ b/app/src/main/java/foundation/e/apps/data/Stores.kt @@ -1,39 +1,82 @@ +/* + * Copyright (C) 2025 e Foundation + * Copyright (C) 2024 MURENA SAS + * + * 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 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.enums.Source.OPEN_SOURCE +import foundation.e.apps.data.enums.Source.PLAY_STORE +import foundation.e.apps.data.enums.Source.PWA import foundation.e.apps.data.playstore.PlayStoreRepository +import foundation.e.apps.data.preference.AppLoungePreference import javax.inject.Inject import javax.inject.Singleton @Singleton class Stores @Inject constructor( - playStoreRepository: PlayStoreRepository, - cleanApkAppsRepository: CleanApkAppsRepository, - cleanApkPwaRepository: CleanApkPwaRepository, + private val playStoreRepository: PlayStoreRepository, + private val cleanApkAppsRepository: CleanApkAppsRepository, + private val cleanApkPwaRepository: CleanApkPwaRepository, + private val appLoungePreference: AppLoungePreference ) { - private val defaultStores = mapOf( - Source.OPEN_SOURCE to cleanApkAppsRepository, - Source.PWA to cleanApkPwaRepository, - Source.PLAY_STORE to playStoreRepository - ) - - private val stores = defaultStores.toMutableMap() + /** + * Retrieves a map of enabled store repositories based on user preferences. + * + * @return A map where the keys are the selected [Source] types and + * the values are their corresponding [StoreRepository] instances. + */ + fun getStores(): Map { + val showOpenSourceApps = appLoungePreference.isOpenSourceSelected() + val showPwaApps = appLoungePreference.isPWASelected() + val showPlayStoreApps = appLoungePreference.isPlayStoreSelected() - fun getStores(): Map = stores + return buildMap { + if (showPlayStoreApps) { + put(PLAY_STORE, playStoreRepository) + } + if (showOpenSourceApps) { + put(OPEN_SOURCE, cleanApkAppsRepository) + } + if (showPwaApps) { + put(PWA, cleanApkPwaRepository) + } + } + } - fun getStore(source: Source): StoreRepository? = stores[source] + fun getStore(source: Source): StoreRepository? = getStores()[source] - fun enableStore(source: Source) { - val repository = defaultStores[source] ?: throw IllegalStateException("store not found") - stores[source] = repository + fun enableStore(source: Source) = when (source) { + OPEN_SOURCE -> appLoungePreference.enableOpenSource() + PWA -> appLoungePreference.enablePwa() + PLAY_STORE -> appLoungePreference.enablePlayStore() + else -> error("No matching Store found for $source.") } - fun disableStore(source: Source) { - stores.remove(source) + fun disableStore(source: Source) = when (source) { + OPEN_SOURCE -> appLoungePreference.disableOpenSource() + PWA -> appLoungePreference.disablePwa() + PLAY_STORE -> appLoungePreference.disablePlayStore() + else -> error("No matching Store found for $source.") } - fun isStoreEnabled(source: Source): Boolean = stores.containsKey(source) -} \ No newline at end of file + fun isStoreEnabled(source: Source): Boolean = getStores().containsKey(source) +} diff --git a/app/src/main/java/foundation/e/apps/data/login/LoginCommon.kt b/app/src/main/java/foundation/e/apps/data/login/LoginCommon.kt index 137ecf433bf569d719fa90ff639ff8003a0be3c8..8ba19f5ed0b4d0e0a857e31da4fbdd1c43b7c44f 100644 --- a/app/src/main/java/foundation/e/apps/data/login/LoginCommon.kt +++ b/app/src/main/java/foundation/e/apps/data/login/LoginCommon.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 E FOUNDATION + * Copyright (C) 2019-2025 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 @@ -13,11 +13,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * */ package foundation.e.apps.data.login -import foundation.e.apps.data.Constants import foundation.e.apps.data.enums.User import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.data.preference.AppLoungePreference @@ -48,9 +48,11 @@ class LoginCommon @Inject constructor( } suspend fun setNoGoogleMode() { - appLoungePreference.setSource(Constants.PREFERENCE_SHOW_FOSS, true) - appLoungePreference.setSource(Constants.PREFERENCE_SHOW_PWA, true) - appLoungePreference.setSource(Constants.PREFERENCE_SHOW_GPLAY, false) + appLoungePreference.run { + disablePlayStore() + enableOpenSource() + enablePwa() + } appLoungeDataStore.saveUserType(User.NO_GOOGLE) } @@ -58,8 +60,10 @@ class LoginCommon @Inject constructor( appLoungeDataStore.destroyCredentials() appLoungeDataStore.saveUserType(null) // reset app source preferences on logout. - appLoungePreference.setSource(Constants.PREFERENCE_SHOW_FOSS, true) - appLoungePreference.setSource(Constants.PREFERENCE_SHOW_PWA, true) - appLoungePreference.setSource(Constants.PREFERENCE_SHOW_GPLAY, true) + appLoungePreference.run { + enableOpenSource() + enablePwa() + enablePlayStore() + } } } diff --git a/app/src/main/java/foundation/e/apps/data/login/PlayStoreAuthenticator.kt b/app/src/main/java/foundation/e/apps/data/login/PlayStoreAuthenticator.kt index 823c84f63ae8851ba754c39ae5911f4f7f118247..bb93cc826fa27ffb34153df342c769755c305d9c 100644 --- a/app/src/main/java/foundation/e/apps/data/login/PlayStoreAuthenticator.kt +++ b/app/src/main/java/foundation/e/apps/data/login/PlayStoreAuthenticator.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 E FOUNDATION + * Copyright (C) 2019-2025 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 @@ -13,6 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * */ package foundation.e.apps.data.login @@ -24,14 +25,14 @@ import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.enums.ResultStatus import foundation.e.apps.data.enums.User -import foundation.e.apps.data.login.api.PlayStoreLoginManagerFactory -import foundation.e.apps.data.login.api.PlayStoreLoginManager import foundation.e.apps.data.login.api.GoogleLoginManager +import foundation.e.apps.data.login.api.PlayStoreLoginManager +import foundation.e.apps.data.login.api.PlayStoreLoginManagerFactory import foundation.e.apps.data.login.api.PlayStoreLoginWrapper import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.data.preference.AppLoungePreference -import foundation.e.apps.data.retryWithBackoff import foundation.e.apps.data.preference.getSync +import foundation.e.apps.data.retryWithBackoff import timber.log.Timber import java.util.Locale import javax.inject.Inject @@ -73,7 +74,7 @@ class PlayStoreAuthenticator @Inject constructor( */ return false } - return appLoungePreference.isGplaySelected() + return appLoungePreference.isPlayStoreSelected() } /** diff --git a/app/src/main/java/foundation/e/apps/data/preference/AppLoungePreference.kt b/app/src/main/java/foundation/e/apps/data/preference/AppLoungePreference.kt index aca4e21888e16459e4153c0404cb68611271326b..1a67ad7eaf478ee76d49922d862f4fd84df550f6 100644 --- a/app/src/main/java/foundation/e/apps/data/preference/AppLoungePreference.kt +++ b/app/src/main/java/foundation/e/apps/data/preference/AppLoungePreference.kt @@ -1,4 +1,5 @@ /* + * Copyright (C) 2025 e Foundation * Copyright (C) 2021-2024 MURENA SAS * * This program is free software: you can redistribute it and/or modify @@ -19,6 +20,7 @@ package foundation.e.apps.data.preference import android.content.Context +import androidx.core.content.edit import androidx.preference.PreferenceManager import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.OpenForTesting @@ -29,6 +31,7 @@ import foundation.e.apps.data.Constants.PREFERENCE_SHOW_PWA import javax.inject.Inject import javax.inject.Singleton +@Suppress("TooManyFunctions") @Singleton @OpenForTesting class AppLoungePreference @Inject constructor( @@ -50,13 +53,15 @@ class AppLoungePreference @Inject constructor( fun isOpenSourceSelected() = preferenceManager.getBoolean(PREFERENCE_SHOW_FOSS, true) fun isPWASelected() = preferenceManager.getBoolean(PREFERENCE_SHOW_PWA, true) - fun isGplaySelected() = preferenceManager.getBoolean(PREFERENCE_SHOW_GPLAY, true) + fun isPlayStoreSelected() = preferenceManager.getBoolean(PREFERENCE_SHOW_GPLAY, true) - fun disableGplay() = preferenceManager.edit().putBoolean(PREFERENCE_SHOW_GPLAY, false).apply() + fun disablePlayStore() = preferenceManager.edit { putBoolean(PREFERENCE_SHOW_GPLAY, false) } + fun disableOpenSource() = preferenceManager.edit { putBoolean(PREFERENCE_SHOW_FOSS, false) } + fun disablePwa() = preferenceManager.edit { putBoolean(PREFERENCE_SHOW_PWA, false) } - fun autoUpdatePreferred(): Boolean { - return preferenceManager.getBoolean("updateInstallAuto", false) - } + fun enablePlayStore() = preferenceManager.edit { putBoolean(PREFERENCE_SHOW_GPLAY, true) } + fun enableOpenSource() = preferenceManager.edit { putBoolean(PREFERENCE_SHOW_FOSS, true) } + fun enablePwa() = preferenceManager.edit { putBoolean(PREFERENCE_SHOW_PWA, true) } fun getUpdateInterval() = preferenceManager.getString( context.getString(R.string.update_check_intervals), @@ -67,12 +72,4 @@ class AppLoungePreference @Inject constructor( context.getString(R.string.update_apps_from_other_stores), true ) - - fun setSource(source: String, value: Boolean) { - val editor = preferenceManager.edit() - editor.run { - this.putBoolean(source, value) - } - editor.apply() - } } diff --git a/app/src/test/java/foundation/e/apps/FakeAppLoungePreference.kt b/app/src/test/java/foundation/e/apps/FakeAppLoungePreference.kt index 7fca0e5ba3c54f0a95fc53dcbff95d7b505f9d91..00e3c57b37f814f64a8be90595523cee72b3be6f 100644 --- a/app/src/test/java/foundation/e/apps/FakeAppLoungePreference.kt +++ b/app/src/test/java/foundation/e/apps/FakeAppLoungePreference.kt @@ -1,5 +1,6 @@ /* - * Copyright (C) 2022 ECORP + * Copyright (C) 2025 e Foundation + * Copyright (C) 2022 ECORP * * 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 @@ -34,7 +35,7 @@ class FakeAppLoungePreference(context: Context) : AppLoungePreference(context) { return isOpenSourceelectedFake } - override fun isGplaySelected(): Boolean { + override fun isPlayStoreSelected(): Boolean { return isGplaySelectedFake } 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 b7e4a767334a889b6b1223ee069c20953dd80c62..e0718f55f31c015af7b0be09e7d97631545b086e 100644 --- a/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt +++ b/app/src/test/java/foundation/e/apps/category/CategoryApiTest.kt @@ -1,4 +1,5 @@ /* + * Copyright (C) 2025 e Foundation * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * @@ -21,7 +22,6 @@ package foundation.e.apps.category import android.content.Context import androidx.arch.core.executor.testing.InstantTaskExecutorRule 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 @@ -35,8 +35,9 @@ 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.data.preference.AppLoungePreference import foundation.e.apps.install.pkg.AppLoungePackageManager +import foundation.e.apps.install.pkg.PwaManager import foundation.e.apps.util.MainCoroutineRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -81,6 +82,9 @@ class CategoryApiTest { @Mock private lateinit var gPlayAPIRepository: PlayStoreRepository + @Mock + private lateinit var appLoungePreference: AppLoungePreference + private lateinit var fakeStores: Stores private lateinit var categoryApi: CategoryApi @@ -91,7 +95,7 @@ class CategoryApiTest { val applicationDataManager = ApplicationDataManager(appLoungePackageManager, pwaManager) - fakeStores = Stores(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) + fakeStores = Stores(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository, appLoungePreference) val appSourcesContainer = AppSourcesContainer(gPlayAPIRepository, cleanApkAppsRepository, cleanApkPWARepository) @@ -118,6 +122,8 @@ class CategoryApiTest { Mockito.`when`(context.getString(eq(R.string.pwa))).thenReturn("PWA") + Mockito.`when`(appLoungePreference.isPWASelected()).thenReturn(true) + val categoryListResponse = categoryApi.getCategoriesList(CategoryType.APPLICATION) @@ -133,8 +139,11 @@ class CategoryApiTest { Mockito.`when`( cleanApkAppsRepository.getCategories() ).thenReturn(response) + Mockito.`when`(context.getString(eq(R.string.open_source))).thenReturn("Open source") + Mockito.`when`(appLoungePreference.isOpenSourceSelected()).thenReturn(true) + fakeStores.disableStore(Source.PWA) fakeStores.disableStore(Source.PLAY_STORE) @@ -152,6 +161,8 @@ class CategoryApiTest { gPlayAPIRepository.getCategories(CategoryType.APPLICATION) ).thenReturn(categories) + Mockito.`when`(appLoungePreference.isPlayStoreSelected()).thenReturn(true) + fakeStores.disableStore(Source.PWA) fakeStores.disableStore(Source.OPEN_SOURCE) @@ -163,11 +174,12 @@ class CategoryApiTest { @Test fun `getCategory when gplay source is selected return error`() = runTest { - Mockito.`when`( gPlayAPIRepository.getCategories(CategoryType.APPLICATION) - ).thenThrow() - + ).thenThrow(RuntimeException()) + + Mockito.`when`(appLoungePreference.isPlayStoreSelected()).thenReturn(true) + fakeStores.disableStore(Source.PWA) fakeStores.disableStore(Source.OPEN_SOURCE) @@ -204,6 +216,9 @@ class CategoryApiTest { Mockito.`when`(context.getString(eq(R.string.open_source))).thenReturn("Open source") Mockito.`when`(context.getString(eq(R.string.pwa))).thenReturn("pwa") + Mockito.`when`(appLoungePreference.isPlayStoreSelected()).thenReturn(true) + Mockito.`when`(appLoungePreference.isOpenSourceSelected()).thenReturn(true) + Mockito.`when`(appLoungePreference.isPWASelected()).thenReturn(true) val categoryListResponse = categoryApi.getCategoriesList(CategoryType.APPLICATION)