diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt index 5fac54cdf2a0555bf69293e199c624f805ff87ac..bd4414dd6c298cfaabb7bc66ed0d6b910559dd40 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -208,12 +208,18 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { if (appInfoFetchViewModel.isAppInBlockedList(it)) { binding.snackbarLayout.visibility = View.VISIBLE } + fetchAppTracker(it) + observeDownloadList() + observeDownloadStatus(binding.root) + stopLoadingUI() + } + private fun observeDownloadList() { + mainActivityViewModel.downloadList.removeObservers(viewLifecycleOwner) mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> applicationViewModel.updateApplicationStatus(list) } - stopLoadingUI() } private fun updateAppDescriptionText(it: FusedApp) { @@ -483,11 +489,6 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } } - override fun onResume() { - super.onResume() - observeDownloadStatus(binding.root) - } - private fun handleInstallingIssue( installButton: MaterialButton, fusedApp: FusedApp, @@ -709,7 +710,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { downloadProgress: DownloadProgress, ) { val progressResult = applicationViewModel.calculateProgress(downloadProgress) - if (progressResult.first < 1) { + if (view == null || progressResult.first < 1) { return } val downloadedSize = "${ @@ -783,6 +784,11 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { binding.ratingsInclude.appPrivacyScore.visibility = visibility } + override fun onResume() { + super.onResume() + observeDownloadList() + } + override fun onDestroyView() { super.onDestroyView() _binding?.recyclerView?.adapter = null @@ -790,11 +796,6 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { applicationIcon = null } - override fun onPause() { - super.onPause() - mainActivityViewModel.downloadList.removeObservers(viewLifecycleOwner) - } - private fun shareApp(name: String, shareUrl: String): Intent { val shareIntent = Intent().apply { action = Intent.ACTION_SEND diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt index 34108be7a249de0f8820af45725d00fec6d14670..aa1bb75d10a2cccd99c8903fb5ebfdc49f8ad48f 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -116,12 +116,19 @@ class ApplicationListFragment : } } - private fun observeDownloadList(adapter: ApplicationListRVAdapter) { + private fun observeDownloadList( + adapter: ApplicationListRVAdapter, + fusedAppResult: ResultSupreme> + ) { + mainActivityViewModel.downloadList.removeObservers(viewLifecycleOwner) mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> val appList = viewModel.appListLiveData.value?.data?.toMutableList() ?: emptyList() + appList.let { mainActivityViewModel.updateStatusOfFusedApps(it, list) - adapter.setData(it) + if (isFusedAppsUpdated(fusedAppResult, listAdapter.currentList)) { + adapter.setData(it, args.translation) + } } } } @@ -134,26 +141,28 @@ class ApplicationListFragment : override fun onResume() { super.onResume() + addDownloadProgressObserver() - if (listAdapter.currentList.isNotEmpty() && viewModel.hasAnyAppInstallStatusChanged(listAdapter.currentList)) { - /*mainActivityViewModel.authData.value?.let { - refreshData(it) - }*/ + if (listAdapter.currentList.isNotEmpty() && viewModel.hasAnyAppInstallStatusChanged( + listAdapter.currentList + ) + ) { repostAuthObjects() } } + private fun addDownloadProgressObserver() { + appProgressViewModel.downloadProgress.removeObservers(viewLifecycleOwner) + appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { + updateProgressOfDownloadingItems(binding.recyclerView, it) + } + } + private fun observeAppListLiveData() { viewModel.appListLiveData.observe(viewLifecycleOwner) { stopLoadingUI() if (it.isSuccess()) { - if (!isFusedAppsUpdated(it)) { - return@observe - } - updateAppListRecyclerView(listAdapter, it) - appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { - updateProgressOfDownloadingItems(binding.recyclerView, it) - } + observeDownloadList(listAdapter, it) } } } @@ -203,21 +212,6 @@ class ApplicationListFragment : return recyclerView } - private fun updateAppListRecyclerView( - listAdapter: ApplicationListRVAdapter?, - fusedAppResult: ResultSupreme> - ) { - val currentList = listAdapter?.currentList - if (!isFusedAppsUpdated(fusedAppResult, currentList) - ) { - return - } - listAdapter?.setData(fusedAppResult.data!!, args.translation) - listAdapter?.let { adapter -> - observeDownloadList(adapter) - } - } - private fun isFusedAppsUpdated( fusedAppResult: ResultSupreme>, currentList: MutableList? @@ -340,7 +334,6 @@ class ApplicationListFragment : override fun onPause() { binding.shimmerLayout.stopShimmer() - mainActivityViewModel.downloadList.removeObservers(viewLifecycleOwner) super.onPause() } diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index 58aa1075a4804f8063a6424070d0be8c5f25bb26..176c6ea36f6f609e1ae91b02755b82e72c0333d2 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -53,6 +53,7 @@ import foundation.e.apps.application.subFrags.ApplicationDialogFragment import foundation.e.apps.applicationlist.ApplicationListRVAdapter import foundation.e.apps.databinding.FragmentSearchBinding import foundation.e.apps.login.AuthObject +import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status @@ -120,7 +121,8 @@ class SearchFragment : setupListening() authObjects.observe(viewLifecycleOwner) { - if (it == null) return@observe + val currentQuery = searchView?.query?.toString() ?: "" + if (it == null || (currentQuery.isNotEmpty() && lastSearch == currentQuery)) return@observe loadData(it) } @@ -134,13 +136,10 @@ class SearchFragment : if (it.data?.first.isNullOrEmpty() && it.data?.second == false) { noAppsFoundLayout?.visibility = View.VISIBLE } else { - if (!updateSearchResult(listAdapter, it)) return@observe - } - - listAdapter?.let { adapter -> - observeDownloadList(adapter) + listAdapter?.let { adapter -> + observeDownloadList(adapter) + } } - observeScrollOfSearchResult(listAdapter) } } @@ -172,19 +171,20 @@ class SearchFragment : listAdapter: ApplicationListRVAdapter?, it: ResultSupreme, Boolean>> ): Boolean { - val currentList = listAdapter?.currentList - if (it.data?.first != null && !currentList.isNullOrEmpty() && !searchViewModel.isAnyAppUpdated( + val currentList = listAdapter?.currentList ?: listOf() + if (it.data?.first != null && !searchViewModel.isAnyAppUpdated( it.data?.first!!, currentList ) ) { return false } - listAdapter?.setData(it.data!!.first) + binding.loadingProgressBar.isVisible = it.data!!.second stopLoadingUI() noAppsFoundLayout?.visibility = View.GONE searchHintLayout?.visibility = View.GONE + listAdapter?.setData(it.data?.first!!) return true } @@ -249,16 +249,24 @@ class SearchFragment : } private fun observeDownloadList(applicationListRVAdapter: ApplicationListRVAdapter) { - mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> - val searchList = - searchViewModel.searchResult.value?.data?.first?.toMutableList() ?: emptyList() - searchList.let { - mainActivityViewModel.updateStatusOfFusedApps(searchList, list) - applicationListRVAdapter.setData(it) - } + mainActivityViewModel.downloadList.removeObservers(viewLifecycleOwner) + mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { fusedDownloadList -> + refreshUI(fusedDownloadList, applicationListRVAdapter) } } + private fun refreshUI( + fusedDownloadList: List, + applicationListRVAdapter: ApplicationListRVAdapter + ) { + val searchList = + searchViewModel.searchResult.value?.data?.first?.toMutableList() ?: emptyList() + + val hasMoreDataToLoad = searchViewModel.searchResult.value?.data?.second == true + mainActivityViewModel.updateStatusOfFusedApps(searchList, fusedDownloadList) + updateSearchResult(applicationListRVAdapter, ResultSupreme.Success(Pair(searchList, hasMoreDataToLoad))) + } + override fun onTimeout( exception: Exception, predefinedDialog: AlertDialog.Builder @@ -325,12 +333,13 @@ class SearchFragment : override fun onResume() { super.onResume() binding.shimmerLayout.startShimmer() - appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { - updateProgressOfInstallingApps(it) - } + addDownloadProgressObservers() if (shouldRefreshData()) { - repostAuthObjects() + if (binding.recyclerView.adapter is ApplicationListRVAdapter) { + val searchAdapter = binding.recyclerView.adapter as ApplicationListRVAdapter + observeDownloadList(searchAdapter) + } } if (searchText.isEmpty() && (recyclerView?.adapter as ApplicationListRVAdapter).currentList.isEmpty()) { @@ -339,10 +348,15 @@ class SearchFragment : } } + private fun addDownloadProgressObservers() { + appProgressViewModel.downloadProgress.removeObservers(viewLifecycleOwner) + appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { + updateProgressOfInstallingApps(it) + } + } + private fun shouldRefreshData() = - searchText.isNotEmpty() && recyclerView?.adapter != null && searchViewModel.hasAnyAppInstallStatusChanged( - (recyclerView?.adapter as ApplicationListRVAdapter).currentList - ) + searchText.isNotEmpty() && recyclerView?.adapter != null override fun onPause() { binding.shimmerLayout.stopShimmer() diff --git a/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt b/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt index 2ced7456ac689a062238894348e22aefde06f4d8..ac6c7281d654b2bdc23352173ccf01a72020bed6 100644 --- a/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt @@ -124,12 +124,14 @@ class FusedApiImplTest { status = Status.UNAVAILABLE, name = "Demo One", package_name = "foundation.e.demoone" - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo" - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -156,12 +158,14 @@ class FusedApiImplTest { status = Status.UNAVAILABLE, name = "Demo One", package_name = "foundation.e.demoone" - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo" - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -175,12 +179,14 @@ class FusedApiImplTest { status = Status.UNAVAILABLE, name = "Demo One", package_name = "foundation.e.demoone" - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.UNAVAILABLE, name = "Demo Two", package_name = "foundation.e.demotwo" - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -201,13 +207,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -242,13 +250,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -283,13 +293,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -324,13 +336,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.INSTALLED, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -346,13 +360,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.UNAVAILABLE, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -608,7 +624,7 @@ class FusedApiImplTest { val categoryListResponse = fusedAPIImpl.getCategoriesList(Category.Type.APPLICATION, AUTH_DATA) - + assertEquals("getCategory", 3, categoryListResponse.first.size) } @@ -719,13 +735,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.UNAVAILABLE, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three", @@ -806,13 +824,15 @@ class FusedApiImplTest { name = "Demo One", package_name = "foundation.e.demoone", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "112", status = Status.UNAVAILABLE, name = "Demo Two", package_name = "foundation.e.demotwo", latest_version_code = 123 - ), FusedApp( + ), + FusedApp( _id = "113", status = Status.UNAVAILABLE, name = "Demo Three",