Unified search: Show error messages, loading anim, click animations. Implement refresh.

Signed-off-by: Álvaro Brey Vilas <alvaro.brey@nextcloud.com>
This commit is contained in:
Álvaro Brey Vilas 2021-09-22 17:39:58 +02:00
parent e898965dc1
commit fac2958788
No known key found for this signature in database
GPG key ID: 2585783189A62105
4 changed files with 43 additions and 21 deletions

View file

@ -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<UnifiedSearchSection>) {
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"
/**

View file

@ -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
}
}

View file

@ -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">
<View
android:layout_width="@dimen/standard_list_item_size"
android:layout_height="@dimen/standard_list_item_size"
android:layout_marginStart="@dimen/zero"
android:layout_marginEnd="@dimen/standard_quarter_padding" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_height="@dimen/standard_list_item_size"
android:layout_marginStart="@dimen/standard_list_item_size"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingStart="@dimen/standard_quarter_padding"
android:text="@string/load_more_results"
android:textColor="@color/secondary_text_color"
tools:text="Load more results">

View file

@ -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">
<androidx.constraintlayout.widget.ConstraintLayout