From 8c5c6c8d76abef61bd316472cc6c4c55ac2145b5 Mon Sep 17 00:00:00 2001 From: Fahim Masud Choudhury Date: Thu, 7 Aug 2025 20:02:00 +0600 Subject: [PATCH] refactor: remove authentication from Search fragment As search suggestions and search results are now using WebSearchHelper from GPlayAPI, these requests don't need to tie with authentication. Search Fragment now extends from Android Fragment instead of TimeoutFragment to exclude authentication functionalities. --- .../e/apps/ui/search/SearchFragment.kt | 77 +++---------------- .../e/apps/ui/search/SearchViewModel.kt | 45 ++++++----- 2 files changed, 36 insertions(+), 86 deletions(-) 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 4c0df8b7d..db775616c 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 @@ -29,10 +29,10 @@ import android.widget.CompoundButton.OnCheckedChangeListener import android.widget.EditText import android.widget.ImageView import android.widget.LinearLayout -import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.SearchView import androidx.cursoradapter.widget.CursorAdapter import androidx.cursoradapter.widget.SimpleCursorAdapter +import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope @@ -48,8 +48,6 @@ import foundation.e.apps.data.application.ApplicationInstaller import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.enums.Status import foundation.e.apps.data.install.models.AppInstall -import foundation.e.apps.data.login.AuthObject -import foundation.e.apps.data.login.exceptions.GPlayLoginException import foundation.e.apps.databinding.FragmentSearchBinding import foundation.e.apps.install.download.data.DownloadProgress import foundation.e.apps.install.pkg.PwaManager @@ -59,7 +57,6 @@ import foundation.e.apps.ui.MainActivityViewModel import foundation.e.apps.ui.PrivacyInfoViewModel import foundation.e.apps.ui.application.subFrags.ApplicationDialogFragment import foundation.e.apps.ui.applicationlist.ApplicationListRVAdapter -import foundation.e.apps.ui.parentFragment.TimeoutFragment import foundation.e.apps.utils.isNetworkAvailable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -68,9 +65,10 @@ import kotlinx.coroutines.launch import java.util.Locale import javax.inject.Inject +@Suppress("TooManyFunctions") // TODO: Remove after refactoring is complete @AndroidEntryPoint class SearchFragment : - TimeoutFragment(R.layout.fragment_search), + Fragment(R.layout.fragment_search), SearchView.OnQueryTextListener, SearchView.OnSuggestionListener, ApplicationInstaller { @@ -84,7 +82,7 @@ class SearchFragment : protected val searchViewModel: SearchViewModel by viewModels() private val privacyInfoViewModel: PrivacyInfoViewModel by viewModels() private val appInfoFetchViewModel: AppInfoFetchViewModel by viewModels() - override val mainActivityViewModel: MainActivityViewModel by activityViewModels() + val mainActivityViewModel: MainActivityViewModel by activityViewModels() private val appProgressViewModel: AppProgressViewModel by viewModels() private val SUGGESTION_KEY = "suggestion" @@ -130,25 +128,7 @@ class SearchFragment : setupSearchFilters() - setupListening() - - authObjects.observe(viewLifecycleOwner) { - val currentQuery = searchView?.query?.toString() ?: "" - if (it == null || shouldIgnore(it, currentQuery)) { - return@observe - } - - if (currentQuery.isNotEmpty()) searchText = currentQuery - - val applicationListRVAdapter = recyclerView?.adapter as ApplicationListRVAdapter - applicationListRVAdapter.setData(mutableListOf()) - - loadDataWhenNetworkAvailable(it) - } - - searchViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { - handleExceptionsCommon(it) - } + initiateSearch() binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { @@ -157,23 +137,12 @@ class SearchFragment : if (!requireContext().isNetworkAvailable()) { return } - - if (authObjects.value?.none { it is AuthObject.GPlayAuth } == true) { - return - } - searchViewModel.loadMore(searchText) } } }) } - private fun shouldIgnore( - authObjectList: List?, - currentQuery: String - ) = currentQuery.isNotEmpty() && searchViewModel.isAuthObjectListSame(authObjectList) && - lastSearch == currentQuery - private fun observeSearchResult(listAdapter: ApplicationListRVAdapter?) { searchViewModel.searchResult.observe(viewLifecycleOwner) { result -> val apps = result.data?.first @@ -342,41 +311,19 @@ class SearchFragment : updateSearchResult(applicationListRVAdapter, searchList) } - override fun onTimeout( - exception: Exception, - predefinedDialog: AlertDialog.Builder - ): AlertDialog.Builder? { - return predefinedDialog - } - - override fun onDataLoadError( - exception: Exception, - predefinedDialog: AlertDialog.Builder - ): AlertDialog.Builder? { - return predefinedDialog - } - - override fun onSignInError( - exception: GPlayLoginException, - predefinedDialog: AlertDialog.Builder - ): AlertDialog.Builder? { - return predefinedDialog - } - - override fun loadData(authObjectList: List) { + private fun initiateSearch() { showLoadingUI() - searchViewModel.loadData(searchText, authObjectList) { - clearAndRestartGPlayLogin() + searchViewModel.loadData(searchText) { true } } - override fun showLoadingUI() { + private fun showLoadingUI() { shimmerLayout?.visibility = View.VISIBLE shimmerLayout?.startShimmer() } - override fun stopLoadingUI() { + private fun stopLoadingUI() { shimmerLayout?.stopShimmer() shimmerLayout?.visibility = View.GONE } @@ -449,7 +396,7 @@ class SearchFragment : * Set the search text and call for network result. */ searchText = text - repostAuthObjects() + initiateSearch() } return false } @@ -463,9 +410,7 @@ class SearchFragment : searchJob?.cancel() searchJob = lifecycleScope.launch(Dispatchers.Main.immediate) { delay(SEARCH_DEBOUNCE_DELAY_MILLIS) - authObjects.value?.find { it is AuthObject.GPlayAuth }?.run { - searchViewModel.getSearchSuggestions(text) - } + searchViewModel.getSearchSuggestions(text) } } 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 492d57cd1..b4b04c8ae 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 @@ -32,6 +32,7 @@ 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.data.login.AuthenticatorRepository import foundation.e.apps.ui.parentFragment.LoadingViewModel import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main @@ -49,7 +50,8 @@ import javax.inject.Inject class SearchViewModel @Inject constructor( private val applicationRepository: ApplicationRepository, private val privacyScoreRepository: PrivacyScoreRepository, - private val appPrivacyInfoRepository: IAppPrivacyInfoRepository + private val appPrivacyInfoRepository: IAppPrivacyInfoRepository, + private val authenticatorRepository: AuthenticatorRepository ) : LoadingViewModel() { val searchSuggest: MutableLiveData?> = MutableLiveData() @@ -98,32 +100,35 @@ class SearchViewModel @Inject constructor( fun loadData( query: String, - authObjects: List, retryBlock: (failedObjects: List) -> Boolean ) { - if (query.isBlank()) return + viewModelScope.launch { + if (query.isBlank()) return@launch - this.lastAuthObjects = authObjects - super.onLoadData(authObjects, { successObjects, failedObjects -> - viewModelScope.launch { - mutex.withLock { - accumulatedList.clear() - } - } + val authObjects = authenticatorRepository.getAuthObjects() - successObjects.find { it is AuthObject.CleanApk }?.run { - fetchCleanApkData(query) - } + lastAuthObjects = authObjects - successObjects.find { it is AuthObject.GPlayAuth }?.run { - fetchGplayData(query) - } + super.onLoadData(authObjects, { successObjects, failedObjects -> + viewModelScope.launch { + mutex.withLock { + accumulatedList.clear() + } + } - failedObjects.find { it is AuthObject.GPlayAuth }?.run { - fetchGplayData(query) - } + successObjects.find { it is AuthObject.CleanApk }?.run { + fetchCleanApkData(query) + } + + successObjects.find { it is AuthObject.GPlayAuth }?.run { + fetchGplayData(query) + } - }, retryBlock) + failedObjects.find { it is AuthObject.GPlayAuth }?.run { + fetchGplayData(query) + } + }, retryBlock) + } } /* -- GitLab