Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.nextcloud.client.network.ClientFactory
import com.nextcloud.client.preferences.AppPreferences
import com.nextcloud.utils.extensions.getTypedActivity
import com.nextcloud.utils.extensions.searchFilesByName
import com.nextcloud.utils.extensions.setVisibleIf
import com.nextcloud.utils.extensions.typedActivity
import com.owncloud.android.R
import com.owncloud.android.databinding.ListFragmentBinding
Expand Down Expand Up @@ -230,47 +231,41 @@ class UnifiedSearchFragment :
adapter.setData(emptyList())
adapter.setDataCurrentDirItems(listOf())

showStartYourSearch()
vm.updateScreenState(UnifiedSearchFragmentScreenState.Empty.startSearch())
showKeyboard(searchView)
}
}

private fun makeEmptyListVisible() {
binding.emptyList.run {
root.visibility = View.VISIBLE
emptyListIcon.visibility = View.VISIBLE
emptyListViewHeadline.visibility = View.VISIBLE
emptyListViewText.visibility = View.VISIBLE
emptyListIcon.visibility = View.VISIBLE
private fun handleScreenState(state: UnifiedSearchFragmentScreenState) {
when (state) {
is UnifiedSearchFragmentScreenState.ShowingContent -> {
toggleEmptyListVisible(show = false)
}
is UnifiedSearchFragmentScreenState.Empty -> {
showEmptyView(state)
}
}
}

private fun showStartYourSearch() {
makeEmptyListVisible()

private fun toggleEmptyListVisible(show: Boolean) {
binding.emptyList.run {
emptyListViewHeadline.text = getString(R.string.file_list_empty_unified_search_start_search)
emptyListViewText.text = getString(R.string.file_list_empty_unified_search_start_search_description)
emptyListIcon.setImageDrawable(
viewThemeUtils.platform.tintDrawable(
requireContext(),
R.drawable.ic_search_grey
)
)
root.setVisibleIf(show)
emptyListIcon.setVisibleIf(show)
emptyListViewHeadline.setVisibleIf(show)
emptyListViewText.setVisibleIf(show)
emptyListIcon.setVisibleIf(show)
}
}

private fun showNoResult() {
makeEmptyListVisible()
private fun showEmptyView(state: UnifiedSearchFragmentScreenState.Empty) {
toggleEmptyListVisible(show = true)

binding.emptyList.run {
emptyListViewHeadline.text =
requireContext().getString(R.string.file_list_empty_headline_server_search)
emptyListViewText.text =
requireContext().getString(R.string.file_list_empty_unified_search_no_results)
emptyListIcon.setImageDrawable(
viewThemeUtils.platform.tintDrawable(requireContext(), R.drawable.ic_search_grey)
viewThemeUtils.platform.tintDrawable(requireContext(), state.iconId)
)
emptyListViewHeadline.text = requireContext().getString(state.titleId)
emptyListViewText.text = requireContext().getString(state.descriptionId)
}
}

Expand Down Expand Up @@ -317,6 +312,9 @@ class UnifiedSearchFragment :
vm.isLoading.observe(viewLifecycleOwner) { loading ->
binding.swipeContainingList.isRefreshing = loading
}
vm.screenState.observe(viewLifecycleOwner) {
handleScreenState(it)
}

PairMediatorLiveData(vm.searchResults, vm.isLoading).observe(viewLifecycleOwner) { (searchResults, isLoading) ->
if (isLoading == true || searchResults.isNullOrEmpty()) {
Expand All @@ -329,7 +327,7 @@ class UnifiedSearchFragment :
!hasSearchResult &&
!adapter.hasLocalResults()
) {
showNoResult()
vm.updateScreenState(UnifiedSearchFragmentScreenState.Empty.noResults())
}
}

Expand Down Expand Up @@ -419,7 +417,11 @@ class UnifiedSearchFragment :
fun onSearchResultChanged(result: List<UnifiedSearchSection>) {
Log_OC.d(TAG, "result")
binding.emptyList.emptyListView.visibility = View.GONE
adapter.setData(result.filterOutHiddenFiles(listOfHiddenFiles))
val newFiles = result.filterOutHiddenFiles(listOfHiddenFiles)
if (newFiles.isNotEmpty()) {
vm.updateScreenState(UnifiedSearchFragmentScreenState.ShowingContent)
}
adapter.setData(newFiles)
}

@VisibleForTesting
Expand All @@ -446,6 +448,9 @@ class UnifiedSearchFragment :
val files = storageManager
.searchFilesByName(this, accountManager.user.accountName, query)
.filter { !it.isEncrypted }
if (files.isNotEmpty()) {
vm.updateScreenState(UnifiedSearchFragmentScreenState.ShowingContent)
}
adapter.setDataCurrentDirItems(files)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.ui.fragment

import com.owncloud.android.R

sealed class UnifiedSearchFragmentScreenState {

/**
* Content is being displayed (search results or current directory items)
*/
object ShowingContent : UnifiedSearchFragmentScreenState()

/**
* Empty state with customizable message
*/
data class Empty(val titleId: Int, val descriptionId: Int, val iconId: Int) : UnifiedSearchFragmentScreenState() {

companion object {
fun startSearch() = Empty(
titleId = R.string.file_list_empty_unified_search_start_search,
descriptionId = R.string.file_list_empty_unified_search_start_search_description,
iconId = R.drawable.ic_search_grey
)

fun noResults() = Empty(
titleId = R.string.file_list_empty_headline_server_search,
descriptionId = R.string.file_list_empty_unified_search_no_results,
iconId = R.drawable.ic_search_grey
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ package com.owncloud.android.ui.unifiedsearch

import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.SearchResultEntry
import com.owncloud.android.ui.fragment.UnifiedSearchFragmentScreenState

interface IUnifiedSearchViewModel {
val screenState: MutableLiveData<UnifiedSearchFragmentScreenState>
val browserUri: LiveData<Uri>
val error: LiveData<String>
val file: LiveData<OCFile>
Expand All @@ -25,4 +28,5 @@ interface IUnifiedSearchViewModel {
fun setQuery(query: String)
fun openFile(remotePath: String)
fun getRemoteFile(remotePath: String)
fun updateScreenState(state: UnifiedSearchFragmentScreenState)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.owncloud.android.lib.common.SearchResult
import com.owncloud.android.lib.common.SearchResultEntry
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.asynctasks.GetRemoteFileTask
import com.owncloud.android.ui.fragment.UnifiedSearchFragmentScreenState
import javax.inject.Inject

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

override val screenState: MutableLiveData<UnifiedSearchFragmentScreenState> =
MutableLiveData(UnifiedSearchFragmentScreenState.ShowingContent)
override val isLoading = MutableLiveData(false)
override val searchResults = MutableLiveData<List<UnifiedSearchSection>>(mutableListOf())
override val error = MutableLiveData("")
Expand Down Expand Up @@ -244,4 +247,8 @@ class UnifiedSearchViewModel(application: Application) :
fun setConnectivityService(connectivityService: ConnectivityService) {
this.connectivityService = connectivityService
}

override fun updateScreenState(state: UnifiedSearchFragmentScreenState) {
screenState.value = state
}
}
Loading