diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index c58ac69901da8def56450a9e580484d1cf82fed6..4c023ae44405be51e48e09c37c9d8104eb92ee7c 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -29,11 +29,14 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavController import androidx.navigation.NavOptions import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.NavigationUI import androidx.navigation.ui.setupWithNavController import com.aurora.gplayapi.exceptions.ApiException +import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.application.subFrags.ApplicationDialogFragment @@ -41,6 +44,7 @@ import foundation.e.apps.databinding.ActivityMainBinding import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.workmanager.InstallWorkManager import foundation.e.apps.purchase.AppPurchaseFragmentDirections +import foundation.e.apps.settings.SettingsFragment import foundation.e.apps.setup.signin.SignInViewModel import foundation.e.apps.updates.UpdatesNotifier import foundation.e.apps.utils.enums.Status @@ -73,6 +77,7 @@ class MainActivity : AppCompatActivity() { supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment val navController = navHostFragment.navController bottomNavigationView.setupWithNavController(navController) + setupBottomNavItemSelectedListener(bottomNavigationView, navHostFragment, navController) var hasInternet = true @@ -135,7 +140,6 @@ class MainActivity : AppCompatActivity() { if (!hasInternet) { showNoInternet() } - when (destination.id) { R.id.applicationFragment, R.id.applicationListFragment, @@ -223,6 +227,30 @@ class MainActivity : AppCompatActivity() { } } + private fun setupBottomNavItemSelectedListener( + bottomNavigationView: BottomNavigationView, + navHostFragment: NavHostFragment, + navController: NavController + ) { + bottomNavigationView.setOnItemSelectedListener { + val fragment = + navHostFragment.childFragmentManager.fragments.find { fragment -> fragment is SettingsFragment } + if (bottomNavigationView.selectedItemId == R.id.settingsFragment && fragment is SettingsFragment && !fragment.isAnyAppSourceSelected()) { + ApplicationDialogFragment( + title = "", + message = getString(R.string.select_one_source_of_applications), + positiveButtonText = getString(R.string.ok) + ).show(supportFragmentManager, TAG) + return@setOnItemSelectedListener false + } + + return@setOnItemSelectedListener NavigationUI.onNavDestinationSelected( + it, + navController + ) + } + } + private fun handleFusedDownloadQueued( it: FusedDownload, viewModel: MainActivityViewModel diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 0736a4af3874679a0cab560fa3707a670cdceea4..5f6d9c0926aa659e996f19d570c375554b541833 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -1224,7 +1224,7 @@ class FusedAPIImpl @Inject constructor( mapOf( "popular_apps" to context.getString(R.string.popular_apps), "popular_games" to context.getString(R.string.popular_games), - "discover" to context.getString(R.string.discover) + "discover" to context.getString(R.string.discover_pwa) ) } headings.forEach { (key, value) -> diff --git a/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt b/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt index 6dd0bf0016060f4b52ecc20ea31547dd9cb2d964..76b4638dd4f8c8e1513bf9f99112417b74512e5f 100644 --- a/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt @@ -19,7 +19,6 @@ package foundation.e.apps.home.model import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.LinearLayoutManager @@ -27,8 +26,6 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import foundation.e.apps.AppInfoFetchViewModel import foundation.e.apps.MainActivityViewModel -import foundation.e.apps.R -import foundation.e.apps.api.fused.FusedAPIImpl import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.api.fused.data.FusedHome @@ -74,19 +71,6 @@ class HomeParentRVAdapter( holder.binding.titleTV.text = fusedHome.title - when (fusedHome.source) { - FusedAPIImpl.APP_TYPE_OPEN -> { - holder.binding.categoryTag.visibility = View.VISIBLE - holder.binding.categoryTag.text = holder.binding.root.context.getString(R.string.open_source) - } - FusedAPIImpl.APP_TYPE_PWA -> { - holder.binding.categoryTag.visibility = View.VISIBLE - holder.binding.categoryTag.text = holder.binding.root.context.getString(R.string.pwa) - } - else -> { - holder.binding.categoryTag.visibility = View.GONE - } - } holder.binding.childRV.apply { recycledViewPool.setMaxRecycledViews(0, 0) adapter = homeChildRVAdapter diff --git a/app/src/main/java/foundation/e/apps/settings/SettingsFragment.kt b/app/src/main/java/foundation/e/apps/settings/SettingsFragment.kt index 07d9281616b36f17f6fa3795da34785a814575fe..18cbb4164307a63681eefae720f9c6d83ab311db 100644 --- a/app/src/main/java/foundation/e/apps/settings/SettingsFragment.kt +++ b/app/src/main/java/foundation/e/apps/settings/SettingsFragment.kt @@ -55,6 +55,9 @@ class SettingsFragment : PreferenceFragmentCompat() { private val binding get() = _binding!! private val viewModel: SignInViewModel by viewModels() private val mainActivityViewModel: MainActivityViewModel by viewModels() + private var showAllApplications: CheckBoxPreference? = null + private var showFOSSApplications: CheckBoxPreference? = null + private var showPWAApplications: CheckBoxPreference? = null @Inject lateinit var gson: Gson @@ -70,10 +73,9 @@ class SettingsFragment : PreferenceFragmentCompat() { setPreferencesFromResource(R.xml.settings_preferences, rootKey) // Show applications preferences - val showAllApplications = findPreference("showAllApplications") - val showFOSSApplications = findPreference("showFOSSApplications") - val showPWAApplications = findPreference("showPWAApplications") - + showAllApplications = findPreference("showAllApplications") + showFOSSApplications = findPreference("showFOSSApplications") + showPWAApplications = findPreference("showPWAApplications") val updateCheckInterval = preferenceManager.findPreference(getString(R.string.update_check_intervals)) updateCheckInterval?.setOnPreferenceChangeListener { _, newValue -> @@ -149,6 +151,9 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + fun isAnyAppSourceSelected() = + showAllApplications?.isChecked == true || showFOSSApplications?.isChecked == true || showPWAApplications?.isChecked == true + private fun backToMainActivity() { Intent(context, MainActivity::class.java).also { activity?.finish() diff --git a/app/src/main/res/layout/home_parent_list_item.xml b/app/src/main/res/layout/home_parent_list_item.xml index 5ecf01ecc9cea49f2b363753e5f1d717d8631556..bcb362ac8723995e9c0f4003753173add99825d0 100644 --- a/app/src/main/res/layout/home_parent_list_item.xml +++ b/app/src/main/res/layout/home_parent_list_item.xml @@ -36,27 +36,7 @@ android:paddingEnd="10dp" android:textColor="?android:textColorPrimary" android:textSize="18sp" - android:textStyle="bold" - android:ellipsize="end" - android:lines="1" - android:layout_toStartOf="@id/categoryTag"/> - - + android:textStyle="bold" /> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 01ca821bc6da171bde68c54de788565797734da8..01884f499bb099b62d2c34418a71d78fc89b18d0 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -24,7 +24,7 @@ Benachrichtige, wenn App-Aktualisierungen verfügbar sind Zeige Anwendungen: Zeige nur quelloffene Apps an - Zeige alle Apps an + Zeige alle Apps an Zeige nur PWAs an Konto Nutzungsbedingungen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 56deca22e1bb409dfb0e238e3801ae463f87b2d8..e3322571c7e9f4131f1ac50e2abbbec8c761ac2f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -36,7 +36,7 @@ Descargar e instalar actualizaciones de aplicaciones en segundo plano Mostrar aplicaciones disponibles Mostrar aplicaciones: - Mostrar todas las aplicaciones + Mostrar todas las aplicaciones Mostrar solo aplicaciones de código abierto Mostrar solo las PWA Cuenta diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index eadc7654ce29218b95f3f365ce1fb2fb4cca1df1..bbfff2eeec7806e0868ec77b18a4ab38fff75cb7 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -43,7 +43,7 @@ Tili Näytä vain PWAt Näytä vain avoimen lähdekoodin sovellukset - Näytä kaikki sovellukset + Näytä kaikki sovellukset Näytä sovellukset: Näytä ilmoitus kun sovelluspäivityksiä on saatavilla Näytä saatavilla olevat päivitykset diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 76ae8d20fc75c188f5d8e960a84b8a37d82b4997..488796282632c33065b932c34851d2ea2ae3d1c7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -17,7 +17,7 @@ Afficher les mises à jour disponibles Afficher une notification lorsque des mises à jour d\'applications sont disponibles Afficher les applications : - Afficher toutes les applications + Afficher toutes les applications Afficher les PWA uniquement Compte Conditions de Service diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 84af82df75148876f1f5800ca98b2befc8e9816a..73b2157e6d97d5118e1fd02074fe5eaf755367ea 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -36,7 +36,7 @@ Scarica ed installa gli aggiornamenti App in background Mostra gli aggiornamenti disponibili Mostra App: - Mostra tutte le App + Mostra tutte le App Mostra solo le App open-source Mostra solo le PWA Account diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ae79a32265e8ba44fd1cf8e368a65c425a12af7a..0c4f999c3902efdcea03d6bb519d19d20c2a42e3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -61,9 +61,9 @@ Show available updates Show a notification when app updates are available Show applications: - Show all apps - Show only open-source apps - Show only PWAs + Show commercial apps + Show open source apps + Show PWAs About App Lounge version /e/ OS version @@ -127,12 +127,13 @@ Discover - Top Updated Apps - Top Updated Games - Popular Apps In Last 24 Hours - Popular Games In Last 24 Hours - Popular Apps - Popular Games + Discover PWA + Open Source Top Updated Apps + Open Source Top Updated Games + Open Source Popular Apps In Last 24 Hours + Open Source Popular Games In Last 24 Hours + PWA Popular Apps + PWA Popular Games Top Free Apps Top Free Games @@ -191,5 +192,6 @@ Install anyway This app may not work properly! Forcing installation will allow you to download and install it, but it won\'t guarantee that it will work.<br /><br />Attempting to install unsupported apps may cause crashes or slow down the system.<br /><br />We\'re working on improving compatiblity with this application in a near future. + Please select at least one source of applications. diff --git a/app/src/main/res/xml/settings_preferences.xml b/app/src/main/res/xml/settings_preferences.xml index 28d6968b59ab5fbac6b1f76178f0c6671b7ed85d..ecb81054020901e4f504f144d634b845d3e3440f 100644 --- a/app/src/main/res/xml/settings_preferences.xml +++ b/app/src/main/res/xml/settings_preferences.xml @@ -56,7 +56,7 @@ + android:title="@string/Show_commercial_apps" /> , Boolean>>> { - size = it.data?.first?.size ?: -2 - println("search result: $size") - } - searchResultLiveData.observeForever(observer) - delay(3000) - searchResultLiveData.removeObserver(observer) - assertEquals("getSearchResult", 1, size) + val searchResultLiveData = fusedAPIImpl.getSearchResults("com.search.package", authData).getOrAwaitValue() + val size = searchResultLiveData.data?.first?.size ?: -2 + assertEquals("getSearchResult", 8, size) } private suspend fun setupMockingSearchApp( packageNameSearchResponse: Response?, authData: AuthData, - packageResult: App, + gplayPackageResult: App, gplayLivedata: MutableLiveData, Boolean>> ) { Mockito.`when`(pwaManagerModule.getPwaStatus(any())).thenReturn(Status.UNAVAILABLE) @@ -784,7 +775,7 @@ class FusedApiImplTest { formatterMocked.`when` { Formatter.formatFileSize(any(), any()) }.thenReturn("15MB") Mockito.`when`(gPlayAPIRepository.getAppDetails(eq("com.search.package"), eq(authData))) - .thenReturn(packageResult) + .thenReturn(gplayPackageResult) Mockito.`when`(cleanApkRepository.searchApps(keyword = "com.search.package")) .thenReturn(packageNameSearchResponse) diff --git a/app/src/test/java/foundation/e/apps/util/LiveDataTestUtil.kt b/app/src/test/java/foundation/e/apps/util/LiveDataTestUtil.kt index a28ada765d8778e4a37defd14f82670324642b1d..679cc04e20a3f9ee6028459e0d239150f0cf790a 100644 --- a/app/src/test/java/foundation/e/apps/util/LiveDataTestUtil.kt +++ b/app/src/test/java/foundation/e/apps/util/LiveDataTestUtil.kt @@ -19,9 +19,9 @@ package foundation.e.apps.util import androidx.lifecycle.LiveData import androidx.lifecycle.Observer +import kotlinx.coroutines.delay import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException /** * Gets the value of a [LiveData] or waits for it to have one, with a timeout. @@ -29,30 +29,19 @@ import java.util.concurrent.TimeoutException * Use this extension from host-side (JVM) tests. It's recommended to use it alongside * `InstantTaskExecutorRule` or a similar mechanism to execute tasks synchronously. */ -fun LiveData.getOrAwaitValue( +suspend fun LiveData.getOrAwaitValue( time: Long = 5, - timeUnit: TimeUnit = TimeUnit.SECONDS, afterObserve: () -> Unit = {} ): T { var data: T? = null - val latch = CountDownLatch(1) - val observer = object : Observer { - override fun onChanged(o: T?) { - data = o - latch.countDown() - this@getOrAwaitValue.removeObserver(this) - } + val observer = Observer { o -> + data = o + print("onChanged: $o") } this.observeForever(observer) - afterObserve.invoke() - - // Don't wait indefinitely if the LiveData is not set. - if (!latch.await(time, timeUnit)) { - this.removeObserver(observer) - throw TimeoutException("LiveData value was never set.") - } - + delay(time * 1000) + this.removeObserver(observer) @Suppress("UNCHECKED_CAST") return data as T }