From fac295878828df3b85acfb9e894a3e3dc2eeebdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Brey=20Vilas?= Date: Wed, 22 Sep 2021 17:39:58 +0200 Subject: [PATCH] Unified search: Show error messages, loading anim, click animations. Implement refresh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Álvaro Brey Vilas --- .../ui/fragment/UnifiedSearchFragment.kt | 38 +++++++++++++------ .../unifiedsearch/UnifiedSearchViewModel.kt | 15 ++++++-- src/main/res/layout/unified_search_footer.xml | 10 ++--- src/main/res/layout/unified_search_item.xml | 1 + 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/owncloud/android/ui/fragment/UnifiedSearchFragment.kt b/src/main/java/com/owncloud/android/ui/fragment/UnifiedSearchFragment.kt index f14350a8d1..e1a0dc9951 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/UnifiedSearchFragment.kt +++ b/src/main/java/com/owncloud/android/ui/fragment/UnifiedSearchFragment.kt @@ -36,6 +36,7 @@ import com.nextcloud.client.network.ClientFactory import com.owncloud.android.databinding.ListFragmentBinding import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.lib.common.SearchResultEntry +import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.ui.activity.FileDisplayActivity import com.owncloud.android.ui.adapter.UnifiedSearchListAdapter import com.owncloud.android.ui.asynctasks.GetRemoteFileTask @@ -43,6 +44,7 @@ import com.owncloud.android.ui.interfaces.UnifiedSearchListInterface import com.owncloud.android.ui.unifiedsearch.ProviderID import com.owncloud.android.ui.unifiedsearch.UnifiedSearchSection import com.owncloud.android.ui.unifiedsearch.UnifiedSearchViewModel +import com.owncloud.android.utils.DisplayUtils import javax.inject.Inject /** @@ -73,23 +75,36 @@ class UnifiedSearchFragment : Fragment(), Injectable, UnifiedSearchListInterface override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) vm = ViewModelProvider(this, vmFactory).get(UnifiedSearchViewModel::class.java) - vm.searchResults.observe(this, this::onSearchResultChanged) + setUpViewModel() - val query = savedInstanceState?.getString(ARG_QUERY).orEmpty() - if (query.isNotBlank()) { - vm.startLoading(query) - return + val query = savedInstanceState?.getString(ARG_QUERY) ?: arguments?.getString(ARG_QUERY) + if (!query.isNullOrEmpty()) { + vm.setQuery(query) + vm.initialQuery() } + } - val queryArgument = arguments?.getString(ARG_QUERY).orEmpty() - if (queryArgument.isNotBlank()) { - vm.startLoading(queryArgument) + private fun setUpViewModel() { + vm.searchResults.observe(this, this::onSearchResultChanged) + vm.isLoading.observe(this) { loading -> + binding.swipeContainingList.isRefreshing = loading + } + vm.error.observe(this) { error -> + if (!error.isNullOrEmpty()) { + DisplayUtils.showSnackMessage(binding.root, error) + } + } + } + + private fun setUpBinding() { + binding.swipeContainingList.setOnRefreshListener { + vm.refresh() } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { _binding = ListFragmentBinding.inflate(inflater, container, false) - + setUpBinding() return binding.root } @@ -110,7 +125,6 @@ class UnifiedSearchFragment : Fragment(), Injectable, UnifiedSearchListInterface binding.listRoot.adapter = adapter } - override fun onDestroyView() { super.onDestroyView() _binding = null @@ -148,6 +162,7 @@ class UnifiedSearchFragment : Fragment(), Injectable, UnifiedSearchListInterface @VisibleForTesting fun onSearchResultChanged(result: List) { + Log_OC.d(TAG, "result") binding.emptyList.emptyListView.visibility = View.GONE adapter.setData(result) @@ -156,10 +171,11 @@ class UnifiedSearchFragment : Fragment(), Injectable, UnifiedSearchListInterface @VisibleForTesting fun setViewModel(testViewModel: UnifiedSearchViewModel) { vm = testViewModel - vm.searchResults.observe(this, this::onSearchResultChanged) + setUpViewModel() } companion object { + private const val TAG = "UnifiedSearchFragment" const val ARG_QUERY = "ARG_QUERY" /** diff --git a/src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchViewModel.kt b/src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchViewModel.kt index dd9a31057a..e7831e2fb3 100644 --- a/src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchViewModel.kt +++ b/src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchViewModel.kt @@ -97,19 +97,23 @@ class UnifiedSearchViewModel() : ViewModel() { } open fun refresh() { + metaResults = mutableMapOf() searchResults.value = mutableListOf() - startLoading(query.value.orEmpty()) + initialQuery() } open fun startLoading(query: String) { if (!loadingStarted) { loadingStarted = true this.query.value = query - queryAll() + initialQuery() } } - fun queryAll() { + /** + * Queries all available providers + */ + fun initialQuery() { val queryTerm = query.value.orEmpty() if (isLoading.value != true && queryTerm.isNotBlank()) { @@ -161,7 +165,6 @@ class UnifiedSearchViewModel() : ViewModel() { @Synchronized fun onSearchResult(result: UnifiedSearchResult) { - isLoading.value = false if (result.success) { val providerMeta = metaResults[result.provider] ?: UnifiedSearchMetadata() @@ -220,4 +223,8 @@ class UnifiedSearchViewModel() : ViewModel() { error.value = "Error showing search result" } } + + fun setQuery(query: String) { + this.query.value = query + } } diff --git a/src/main/res/layout/unified_search_footer.xml b/src/main/res/layout/unified_search_footer.xml index e2bd556f83..299754448f 100755 --- a/src/main/res/layout/unified_search_footer.xml +++ b/src/main/res/layout/unified_search_footer.xml @@ -25,20 +25,18 @@ android:layout_width="match_parent" android:layout_height="@dimen/min_list_item_size" android:baselineAligned="false" + android:foreground="?android:attr/selectableItemBackground" android:orientation="horizontal"> - diff --git a/src/main/res/layout/unified_search_item.xml b/src/main/res/layout/unified_search_item.xml index 8575cef103..7b5bc2af95 100755 --- a/src/main/res/layout/unified_search_item.xml +++ b/src/main/res/layout/unified_search_item.xml @@ -26,6 +26,7 @@ android:layout_width="match_parent" android:layout_height="@dimen/standard_list_item_size" android:baselineAligned="false" + android:foreground="?android:attr/selectableItemBackground" android:orientation="horizontal">