Skip to content

Commit bbf8db6

Browse files
committed
chore: resolve merge conflict
Signed-off-by: alperozturk <[email protected]>
1 parent 19183f3 commit bbf8db6

File tree

3 files changed

+124
-49
lines changed

3 files changed

+124
-49
lines changed

app/src/main/java/com/nextcloud/client/database/dao/FileDao.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,16 @@ interface FileDao {
108108
dirType: String = MimeType.DIRECTORY,
109109
webdavType: String = MimeType.WEBDAV_FOLDER
110110
): List<FileEntity>
111+
112+
@Query(
113+
"""
114+
SELECT *
115+
FROM filelist
116+
WHERE file_owner = :fileOwner
117+
AND parent = :parentId
118+
AND ${ProviderTableMeta.FILE_NAME} LIKE '%' || :query || '%'
119+
ORDER BY ${ProviderTableMeta.FILE_DEFAULT_SORT_ORDER}
120+
"""
121+
)
122+
fun searchFilesInFolder(parentId: Long, fileOwner: String, query: String): List<FileEntity>
111123
}

app/src/main/java/com/nextcloud/utils/extensions/FileDataStorageManagerExtensions.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ package com.nextcloud.utils.extensions
1010
import com.owncloud.android.datamodel.FileDataStorageManager
1111
import com.owncloud.android.datamodel.OCFile
1212

13+
fun FileDataStorageManager.searchFilesByName(file: OCFile, accountName: String, query: String): List<OCFile> =
14+
fileDao.searchFilesInFolder(file.fileId, accountName, query).map {
15+
createFileInstance(it)
16+
}
17+
1318
fun FileDataStorageManager.getParentIdsOfSubfiles(paths: List<String>): List<Long> =
1419
fileDao.getParentIdsOfSubfiles(paths)
1520

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

Lines changed: 107 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
77
*/
88
package com.owncloud.android.ui.fragment
9-
109
import android.Manifest
1110
import android.content.Context
1211
import android.content.Intent
@@ -27,25 +26,33 @@ import androidx.appcompat.widget.SearchView
2726
import androidx.core.view.updatePadding
2827
import androidx.fragment.app.Fragment
2928
import androidx.lifecycle.ViewModelProvider
29+
import androidx.lifecycle.lifecycleScope
3030
import androidx.recyclerview.widget.GridLayoutManager
3131
import com.nextcloud.client.account.CurrentAccountProvider
3232
import com.nextcloud.client.account.UserAccountManager
3333
import com.nextcloud.client.core.AsyncRunner
34+
import com.nextcloud.client.core.Clock
3435
import com.nextcloud.client.di.Injectable
3536
import com.nextcloud.client.di.ViewModelFactory
3637
import com.nextcloud.client.network.ClientFactory
38+
import com.nextcloud.client.preferences.AppPreferences
39+
import com.nextcloud.utils.extensions.getTypedActivity
40+
import com.nextcloud.utils.extensions.searchFilesByName
3741
import com.nextcloud.utils.extensions.typedActivity
3842
import com.owncloud.android.R
3943
import com.owncloud.android.databinding.ListFragmentBinding
4044
import com.owncloud.android.datamodel.FileDataStorageManager
4145
import com.owncloud.android.datamodel.OCFile
46+
import com.owncloud.android.datamodel.SyncedFolderProvider
4247
import com.owncloud.android.lib.common.SearchResultEntry
4348
import com.owncloud.android.lib.common.utils.Log_OC
4449
import com.owncloud.android.lib.resources.status.NextcloudVersion
50+
import com.owncloud.android.ui.activity.FileActivity
4551
import com.owncloud.android.ui.activity.FileDisplayActivity
4652
import com.owncloud.android.ui.adapter.UnifiedSearchItemViewHolder
4753
import com.owncloud.android.ui.adapter.UnifiedSearchListAdapter
4854
import com.owncloud.android.ui.fragment.util.PairMediatorLiveData
55+
import com.owncloud.android.ui.interfaces.UnifiedSearchCurrentDirItemAction
4956
import com.owncloud.android.ui.interfaces.UnifiedSearchListInterface
5057
import com.owncloud.android.ui.unifiedsearch.IUnifiedSearchViewModel
5158
import com.owncloud.android.ui.unifiedsearch.ProviderID
@@ -55,6 +62,9 @@ import com.owncloud.android.ui.unifiedsearch.filterOutHiddenFiles
5562
import com.owncloud.android.utils.DisplayUtils
5663
import com.owncloud.android.utils.PermissionUtil
5764
import com.owncloud.android.utils.theme.ViewThemeUtils
65+
import kotlinx.coroutines.Dispatchers
66+
import kotlinx.coroutines.launch
67+
import kotlinx.coroutines.withContext
5868
import javax.inject.Inject
5969

6070
/**
@@ -67,7 +77,8 @@ class UnifiedSearchFragment :
6777
Injectable,
6878
UnifiedSearchListInterface,
6979
SearchView.OnQueryTextListener,
70-
UnifiedSearchItemViewHolder.FilesAction {
80+
UnifiedSearchItemViewHolder.FilesAction,
81+
UnifiedSearchCurrentDirItemAction {
7182
private lateinit var adapter: UnifiedSearchListAdapter
7283
private var _binding: ListFragmentBinding? = null
7384
val binding get() = _binding!!
@@ -77,16 +88,20 @@ class UnifiedSearchFragment :
7788
companion object {
7889
private const val TAG = "UnifiedSearchFragment"
7990

80-
const val ARG_QUERY = "ARG_QUERY"
81-
const val ARG_HIDDEN_FILES = "ARG_HIDDEN_FILES"
82-
83-
fun newInstance(query: String?, listOfHiddenFiles: ArrayList<String>?): UnifiedSearchFragment {
84-
val fragment = UnifiedSearchFragment()
85-
val args = Bundle()
86-
args.putString(ARG_QUERY, query)
87-
args.putStringArrayList(ARG_HIDDEN_FILES, listOfHiddenFiles)
88-
fragment.arguments = args
89-
return fragment
91+
private const val ARG_QUERY = "ARG_QUERY"
92+
private const val ARG_HIDDEN_FILES = "ARG_HIDDEN_FILES"
93+
private const val CURRENT_DIR_PATH = "CURRENT_DIR"
94+
95+
fun newInstance(
96+
query: String?,
97+
listOfHiddenFiles: ArrayList<String>?,
98+
currentDirPath: String
99+
): UnifiedSearchFragment = UnifiedSearchFragment().apply {
100+
arguments = Bundle().apply {
101+
putString(ARG_QUERY, query)
102+
putString(CURRENT_DIR_PATH, currentDirPath)
103+
putStringArrayList(ARG_HIDDEN_FILES, listOfHiddenFiles)
104+
}
90105
}
91106
}
92107

@@ -111,23 +126,26 @@ class UnifiedSearchFragment :
111126
@Inject
112127
lateinit var accountManager: UserAccountManager
113128

129+
@Inject
130+
lateinit var appPreferences: AppPreferences
131+
132+
@Inject
133+
lateinit var clock: Clock
134+
114135
private var listOfHiddenFiles = ArrayList<String>()
115136
private var showMoreActions = false
137+
private var currentDir: OCFile? = null
138+
private var initialQuery: String? = null
116139

117140
override fun onCreate(savedInstanceState: Bundle?) {
118141
super.onCreate(savedInstanceState)
119142
vm = ViewModelProvider(this, vmFactory)[UnifiedSearchViewModel::class.java]
120-
setUpViewModel()
121-
122-
val query = savedInstanceState?.getString(ARG_QUERY) ?: arguments?.getString(ARG_QUERY)
143+
initialQuery = savedInstanceState?.getString(ARG_QUERY) ?: arguments?.getString(ARG_QUERY)
144+
val currentDirPath = savedInstanceState?.getString(CURRENT_DIR_PATH) ?: arguments?.getString(CURRENT_DIR_PATH)
145+
currentDir = storageManager.getFileByDecryptedRemotePath(currentDirPath)
123146
listOfHiddenFiles =
124147
savedInstanceState?.getStringArrayList(ARG_HIDDEN_FILES) ?: arguments?.getStringArrayList(ARG_HIDDEN_FILES)
125148
?: ArrayList()
126-
127-
if (!query.isNullOrEmpty()) {
128-
vm.setQuery(query)
129-
vm.initialQuery()
130-
}
131149
}
132150

133151
@Suppress("DEPRECATION")
@@ -149,6 +167,15 @@ class UnifiedSearchFragment :
149167
}
150168
}
151169

170+
override fun onResume() {
171+
super.onResume()
172+
typedActivity<FileDisplayActivity>()?.run {
173+
setupToolbar()
174+
setMainFabVisible(false)
175+
updateActionBarTitleAndHomeButtonByString(null)
176+
}
177+
}
178+
152179
private fun supportsOpeningCalendarContactsLocally(): Boolean = storageManager
153180
.getCapability(accountManager.user)
154181
.version
@@ -200,6 +227,7 @@ class UnifiedSearchFragment :
200227

201228
vm.setQuery("")
202229
adapter.setData(emptyList())
230+
adapter.setDataCurrentDirItems(listOf())
203231

204232
showStartYourSearch()
205233
showKeyboard(searchView)
@@ -282,36 +310,41 @@ class UnifiedSearchFragment :
282310
}
283311
}
284312

313+
@Suppress("ComplexCondition")
285314
private fun setUpViewModel() {
286-
vm.searchResults.observe(this, this::onSearchResultChanged)
287-
vm.isLoading.observe(this) { loading ->
315+
vm.searchResults.observe(viewLifecycleOwner, this::onSearchResultChanged)
316+
vm.isLoading.observe(viewLifecycleOwner) { loading ->
288317
binding.swipeContainingList.isRefreshing = loading
289318
}
290319

291-
PairMediatorLiveData(vm.searchResults, vm.isLoading).observe(this) { pair ->
320+
PairMediatorLiveData(vm.searchResults, vm.isLoading).observe(viewLifecycleOwner) { pair ->
292321
if (pair.second == false) {
293322
var count = 0
294323

295324
pair.first?.forEach {
296325
count += it.entries.size
297326
}
298327

299-
if (count == 0 && pair.first?.isNotEmpty() == true && context != null && !adapter.isCurrentDirItemsEmpty()) {
328+
if (count == 0 &&
329+
pair.first?.isNotEmpty() == true &&
330+
context != null &&
331+
!adapter.isCurrentDirItemsEmpty()
332+
) {
300333
showNoResult()
301334
}
302335
}
303336
}
304337

305-
vm.error.observe(this) { error ->
338+
vm.error.observe(viewLifecycleOwner) { error ->
306339
if (!error.isNullOrEmpty()) {
307340
DisplayUtils.showSnackMessage(binding.root, error)
308341
}
309342
}
310-
vm.browserUri.observe(this) { uri ->
343+
vm.browserUri.observe(viewLifecycleOwner) { uri ->
311344
val browserIntent = Intent(Intent.ACTION_VIEW, uri)
312345
startActivity(browserIntent)
313346
}
314-
vm.file.observe(this) {
347+
vm.file.observe(viewLifecycleOwner) {
315348
showFile(it, showMoreActions)
316349
}
317350
}
@@ -337,30 +370,42 @@ class UnifiedSearchFragment :
337370
}
338371
}
339372

340-
override fun onResume() {
341-
super.onResume()
342-
typedActivity<FileDisplayActivity>()?.run {
343-
setupToolbar()
344-
setMainFabVisible(false)
345-
updateActionBarTitleAndHomeButtonByString(null)
346-
}
347-
}
348-
349373
private fun setupAdapter() {
374+
val syncedFolderProvider = SyncedFolderProvider(requireContext().contentResolver, appPreferences, clock)
350375
val gridLayoutManager = GridLayoutManager(requireContext(), 1)
351-
adapter = UnifiedSearchListAdapter(
352-
supportsOpeningCalendarContactsLocally(),
353-
storageManager,
354-
this,
355-
this,
356-
currentAccountProvider.user,
357-
requireContext(),
358-
viewThemeUtils
359-
)
360-
adapter.shouldShowFooters(true)
361-
adapter.setLayoutManager(gridLayoutManager)
362-
binding.listRoot.layoutManager = gridLayoutManager
363-
binding.listRoot.adapter = adapter
376+
377+
lifecycleScope.launch(Dispatchers.IO) {
378+
val client =
379+
getTypedActivity(FileActivity::class.java)?.clientRepository?.getNextcloudClient() ?: return@launch
380+
381+
withContext(Dispatchers.Main) {
382+
adapter = UnifiedSearchListAdapter(
383+
supportsOpeningCalendarContactsLocally(),
384+
storageManager,
385+
this@UnifiedSearchFragment,
386+
this@UnifiedSearchFragment,
387+
currentAccountProvider.user,
388+
requireContext(),
389+
viewThemeUtils,
390+
appPreferences,
391+
syncedFolderProvider,
392+
client,
393+
this@UnifiedSearchFragment
394+
)
395+
396+
adapter.shouldShowFooters(true)
397+
adapter.setLayoutManager(gridLayoutManager)
398+
binding.listRoot.layoutManager = gridLayoutManager
399+
binding.listRoot.adapter = adapter
400+
searchInCurrentDirectory(initialQuery ?: "")
401+
402+
setUpViewModel()
403+
if (!initialQuery.isNullOrEmpty()) {
404+
vm.setQuery(initialQuery!!)
405+
vm.initialQuery()
406+
}
407+
}
408+
}
364409
}
365410

366411
override fun onSearchResultClicked(searchResultEntry: SearchResultEntry) {
@@ -394,9 +439,17 @@ class UnifiedSearchFragment :
394439
override fun onQueryTextChange(newText: String?): Boolean {
395440
val closeButton = searchView?.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn)
396441
closeButton?.visibility = if (newText?.isEmpty() == true) View.INVISIBLE else View.VISIBLE
442+
searchInCurrentDirectory(newText ?: "")
397443
return true
398444
}
399445

446+
private fun searchInCurrentDirectory(query: String) {
447+
currentDir?.run {
448+
val files = storageManager.searchFilesByName(this, accountManager.user.accountName, query)
449+
adapter.setDataCurrentDirItems(files)
450+
}
451+
}
452+
400453
override fun onDestroyView() {
401454
super.onDestroyView()
402455
_binding = null
@@ -406,4 +459,9 @@ class UnifiedSearchFragment :
406459
showMoreActions = true
407460
vm.openResult(searchResultEntry)
408461
}
462+
463+
override fun openFile(remotePath: String, showMoreActions: Boolean) {
464+
this.showMoreActions = showMoreActions
465+
vm.openFile(remotePath)
466+
}
409467
}

0 commit comments

Comments
 (0)