Skip to content

Commit aae33a3

Browse files
Merge pull request #16417 from nextcloud/fix/unified-search-fragment-screen-state
fix(unified-search): screen state
2 parents bd428d3 + 26127ae commit aae33a3

4 files changed

Lines changed: 82 additions & 28 deletions

File tree

app/src/main/java/com/owncloud/android/ui/fragment/UnifiedSearchFragment.kt

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import com.nextcloud.client.network.ClientFactory
3838
import com.nextcloud.client.preferences.AppPreferences
3939
import com.nextcloud.utils.extensions.getTypedActivity
4040
import com.nextcloud.utils.extensions.searchFilesByName
41+
import com.nextcloud.utils.extensions.setVisibleIf
4142
import com.nextcloud.utils.extensions.typedActivity
4243
import com.owncloud.android.R
4344
import com.owncloud.android.databinding.ListFragmentBinding
@@ -230,47 +231,41 @@ class UnifiedSearchFragment :
230231
adapter.setData(emptyList())
231232
adapter.setDataCurrentDirItems(listOf())
232233

233-
showStartYourSearch()
234+
vm.updateScreenState(UnifiedSearchFragmentScreenState.Empty.startSearch())
234235
showKeyboard(searchView)
235236
}
236237
}
237238

238-
private fun makeEmptyListVisible() {
239-
binding.emptyList.run {
240-
root.visibility = View.VISIBLE
241-
emptyListIcon.visibility = View.VISIBLE
242-
emptyListViewHeadline.visibility = View.VISIBLE
243-
emptyListViewText.visibility = View.VISIBLE
244-
emptyListIcon.visibility = View.VISIBLE
239+
private fun handleScreenState(state: UnifiedSearchFragmentScreenState) {
240+
when (state) {
241+
is UnifiedSearchFragmentScreenState.ShowingContent -> {
242+
toggleEmptyListVisible(show = false)
243+
}
244+
is UnifiedSearchFragmentScreenState.Empty -> {
245+
showEmptyView(state)
246+
}
245247
}
246248
}
247249

248-
private fun showStartYourSearch() {
249-
makeEmptyListVisible()
250-
250+
private fun toggleEmptyListVisible(show: Boolean) {
251251
binding.emptyList.run {
252-
emptyListViewHeadline.text = getString(R.string.file_list_empty_unified_search_start_search)
253-
emptyListViewText.text = getString(R.string.file_list_empty_unified_search_start_search_description)
254-
emptyListIcon.setImageDrawable(
255-
viewThemeUtils.platform.tintDrawable(
256-
requireContext(),
257-
R.drawable.ic_search_grey
258-
)
259-
)
252+
root.setVisibleIf(show)
253+
emptyListIcon.setVisibleIf(show)
254+
emptyListViewHeadline.setVisibleIf(show)
255+
emptyListViewText.setVisibleIf(show)
256+
emptyListIcon.setVisibleIf(show)
260257
}
261258
}
262259

263-
private fun showNoResult() {
264-
makeEmptyListVisible()
260+
private fun showEmptyView(state: UnifiedSearchFragmentScreenState.Empty) {
261+
toggleEmptyListVisible(show = true)
265262

266263
binding.emptyList.run {
267-
emptyListViewHeadline.text =
268-
requireContext().getString(R.string.file_list_empty_headline_server_search)
269-
emptyListViewText.text =
270-
requireContext().getString(R.string.file_list_empty_unified_search_no_results)
271264
emptyListIcon.setImageDrawable(
272-
viewThemeUtils.platform.tintDrawable(requireContext(), R.drawable.ic_search_grey)
265+
viewThemeUtils.platform.tintDrawable(requireContext(), state.iconId)
273266
)
267+
emptyListViewHeadline.text = requireContext().getString(state.titleId)
268+
emptyListViewText.text = requireContext().getString(state.descriptionId)
274269
}
275270
}
276271

@@ -317,6 +312,9 @@ class UnifiedSearchFragment :
317312
vm.isLoading.observe(viewLifecycleOwner) { loading ->
318313
binding.swipeContainingList.isRefreshing = loading
319314
}
315+
vm.screenState.observe(viewLifecycleOwner) {
316+
handleScreenState(it)
317+
}
320318

321319
PairMediatorLiveData(vm.searchResults, vm.isLoading).observe(viewLifecycleOwner) { (searchResults, isLoading) ->
322320
if (isLoading == true || searchResults.isNullOrEmpty()) {
@@ -329,7 +327,7 @@ class UnifiedSearchFragment :
329327
!hasSearchResult &&
330328
!adapter.hasLocalResults()
331329
) {
332-
showNoResult()
330+
vm.updateScreenState(UnifiedSearchFragmentScreenState.Empty.noResults())
333331
}
334332
}
335333

@@ -419,7 +417,11 @@ class UnifiedSearchFragment :
419417
fun onSearchResultChanged(result: List<UnifiedSearchSection>) {
420418
Log_OC.d(TAG, "result")
421419
binding.emptyList.emptyListView.visibility = View.GONE
422-
adapter.setData(result.filterOutHiddenFiles(listOfHiddenFiles))
420+
val newFiles = result.filterOutHiddenFiles(listOfHiddenFiles)
421+
if (newFiles.isNotEmpty()) {
422+
vm.updateScreenState(UnifiedSearchFragmentScreenState.ShowingContent)
423+
}
424+
adapter.setData(newFiles)
423425
}
424426

425427
@VisibleForTesting
@@ -446,6 +448,9 @@ class UnifiedSearchFragment :
446448
val files = storageManager
447449
.searchFilesByName(this, accountManager.user.accountName, query)
448450
.filter { !it.isEncrypted }
451+
if (files.isNotEmpty()) {
452+
vm.updateScreenState(UnifiedSearchFragmentScreenState.ShowingContent)
453+
}
449454
adapter.setDataCurrentDirItems(files)
450455
}
451456
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
package com.owncloud.android.ui.fragment
9+
10+
import com.owncloud.android.R
11+
12+
sealed class UnifiedSearchFragmentScreenState {
13+
14+
/**
15+
* Content is being displayed (search results or current directory items)
16+
*/
17+
object ShowingContent : UnifiedSearchFragmentScreenState()
18+
19+
/**
20+
* Empty state with customizable message
21+
*/
22+
data class Empty(val titleId: Int, val descriptionId: Int, val iconId: Int) : UnifiedSearchFragmentScreenState() {
23+
24+
companion object {
25+
fun startSearch() = Empty(
26+
titleId = R.string.file_list_empty_unified_search_start_search,
27+
descriptionId = R.string.file_list_empty_unified_search_start_search_description,
28+
iconId = R.drawable.ic_search_grey
29+
)
30+
31+
fun noResults() = Empty(
32+
titleId = R.string.file_list_empty_headline_server_search,
33+
descriptionId = R.string.file_list_empty_unified_search_no_results,
34+
iconId = R.drawable.ic_search_grey
35+
)
36+
}
37+
}
38+
}

app/src/main/java/com/owncloud/android/ui/unifiedsearch/IUnifiedSearchViewModel.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ package com.owncloud.android.ui.unifiedsearch
88

99
import android.net.Uri
1010
import androidx.lifecycle.LiveData
11+
import androidx.lifecycle.MutableLiveData
1112
import com.owncloud.android.datamodel.OCFile
1213
import com.owncloud.android.lib.common.SearchResultEntry
14+
import com.owncloud.android.ui.fragment.UnifiedSearchFragmentScreenState
1315

1416
interface IUnifiedSearchViewModel {
17+
val screenState: MutableLiveData<UnifiedSearchFragmentScreenState>
1518
val browserUri: LiveData<Uri>
1619
val error: LiveData<String>
1720
val file: LiveData<OCFile>
@@ -25,4 +28,5 @@ interface IUnifiedSearchViewModel {
2528
fun setQuery(query: String)
2629
fun openFile(remotePath: String)
2730
fun getRemoteFile(remotePath: String)
31+
fun updateScreenState(state: UnifiedSearchFragmentScreenState)
2832
}

app/src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchViewModel.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.owncloud.android.lib.common.SearchResult
2525
import com.owncloud.android.lib.common.SearchResultEntry
2626
import com.owncloud.android.lib.common.utils.Log_OC
2727
import com.owncloud.android.ui.asynctasks.GetRemoteFileTask
28+
import com.owncloud.android.ui.fragment.UnifiedSearchFragmentScreenState
2829
import javax.inject.Inject
2930

3031
@Suppress("LongParameterList")
@@ -53,6 +54,8 @@ class UnifiedSearchViewModel(application: Application) :
5354
private lateinit var repository: IUnifiedSearchRepository
5455
private var results: MutableMap<ProviderID, UnifiedSearchMetadata> = mutableMapOf()
5556

57+
override val screenState: MutableLiveData<UnifiedSearchFragmentScreenState> =
58+
MutableLiveData(UnifiedSearchFragmentScreenState.ShowingContent)
5659
override val isLoading = MutableLiveData(false)
5760
override val searchResults = MutableLiveData<List<UnifiedSearchSection>>(mutableListOf())
5861
override val error = MutableLiveData("")
@@ -244,4 +247,8 @@ class UnifiedSearchViewModel(application: Application) :
244247
fun setConnectivityService(connectivityService: ConnectivityService) {
245248
this.connectivityService = connectivityService
246249
}
250+
251+
override fun updateScreenState(state: UnifiedSearchFragmentScreenState) {
252+
screenState.value = state
253+
}
247254
}

0 commit comments

Comments
 (0)