Sfoglia il codice sorgente

Unified search: get search to fetch and show multiple providers

Signed-off-by: Álvaro Brey Vilas <alvaro.brey@nextcloud.com>
Álvaro Brey Vilas 3 anni fa
parent
commit
b0b9d3a3e3

+ 20 - 10
src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -2527,16 +2527,26 @@ public class FileDisplayActivity extends FileActivity
     public void showFile(String message) {
         dismissLoadingDialog();
 
-        OCFileListFragment listOfFiles = getListOfFilesFragment();
-        if (listOfFiles != null) {
-            if (TextUtils.isEmpty(message)) {
-                OCFile temp = getFile();
-                setFile(getCurrentDir());
-                listOfFiles.listDirectory(getCurrentDir(), temp, MainApp.isOnlyOnDevice(), false);
-                updateActionBarTitleAndHomeButton(null);
-            } else {
-                DisplayUtils.showSnackMessage(listOfFiles.getView(), message);
-            }
+        final Fragment leftFragment = getLeftFragment();
+        OCFileListFragment listOfFiles = null;
+        if (leftFragment instanceof OCFileListFragment) {
+            listOfFiles = (OCFileListFragment) leftFragment;
+        } else {
+            listOfFiles = new OCFileListFragment();
+            Bundle args = new Bundle();
+            args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
+            listOfFiles.setArguments(args);
+            setLeftFragment(listOfFiles);
+            getSupportFragmentManager().executePendingTransactions();
+        }
+
+        if (TextUtils.isEmpty(message)) {
+            OCFile temp = getFile();
+            setFile(getCurrentDir());
+            listOfFiles.listDirectory(getCurrentDir(), temp, MainApp.isOnlyOnDevice(), false);
+            updateActionBarTitleAndHomeButton(null);
+        } else {
+            DisplayUtils.showSnackMessage(listOfFiles.getView(), message);
         }
     }
 }

+ 1 - 0
src/main/java/com/owncloud/android/ui/adapter/UnifiedSearchListAdapter.java

@@ -125,6 +125,7 @@ public class UnifiedSearchListAdapter extends SectionedRecyclerViewAdapter<Secti
 
     @Override
     public void onBindViewHolder(SectionedViewHolder holder, int section, int relativePosition, int absolutePosition) {
+        // TODO different binding (and also maybe diff UI) for non-file results
         UnifiedSearchItemViewHolder itemViewHolder = (UnifiedSearchItemViewHolder) holder;
         SearchResultEntry entry = list.get(section).getEntries().get(relativePosition);
 

+ 52 - 0
src/main/java/com/owncloud/android/ui/unifiedsearch/GetSearchProvidersTask.kt

@@ -0,0 +1,52 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Chris Narkiewicz
+ * Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.unifiedsearch
+
+import com.nextcloud.android.lib.resources.search.UnifiedSearchProvidersRemoteOperation
+import com.nextcloud.common.NextcloudClient
+import com.owncloud.android.lib.common.SearchProviders
+import com.owncloud.android.lib.common.utils.Log_OC
+
+class GetSearchProvidersTask(
+    private val client: NextcloudClient
+) : () -> GetSearchProvidersTask.Result {
+
+    companion object {
+        const val TAG = "GetSearchProviders"
+    }
+
+    data class Result(val success: Boolean = false, val providers: SearchProviders = SearchProviders())
+
+    override fun invoke(): Result {
+        Log_OC.d(TAG, "Getting search providers")
+        val result = UnifiedSearchProvidersRemoteOperation().execute(client)
+
+        Log_OC.d(TAG, "Task finished: " + result.isSuccess)
+        return when {
+            result.isSuccess && result.resultData != null -> {
+                Result(
+                    success = true,
+                    providers = result.resultData
+                )
+            }
+            else -> Result()
+        }
+    }
+}

+ 5 - 1
src/main/java/com/owncloud/android/ui/unifiedsearch/IUnifiedSearchRepository.kt

@@ -22,8 +22,12 @@
 
 package com.owncloud.android.ui.unifiedsearch
 
+import com.owncloud.android.lib.common.SearchResult
+
+data class UnifiedSearchResults(val success: Boolean, val results: List<SearchResult>)
+
 interface IUnifiedSearchRepository {
     fun refresh()
     fun startLoading()
-    fun loadMore(query: String, vm: UnifiedSearchViewModel)
+    fun loadMore(query: String, onResult: (UnifiedSearchResults) -> Unit, onError: (Throwable) -> Unit)
 }

+ 2 - 2
src/main/java/com/owncloud/android/ui/unifiedsearch/SearchOnProviderTask.kt

@@ -37,10 +37,10 @@ class SearchOnProviderTask(
         val result = UnifiedSearchRemoteOperation(provider, query).execute(client)
 
         Log_OC.d("Unified Search", "Task finished: " + result.isSuccess)
-        return if (result.isSuccess && result.singleData != null) {
+        return if (result.isSuccess && result.resultData != null) {
             Result(
                 success = true,
-                searchResult = result.singleData as SearchResult
+                searchResult = result.resultData as SearchResult
             )
         } else {
             Result()

+ 59 - 0
src/main/java/com/owncloud/android/ui/unifiedsearch/SearchOnProvidersTask.kt

@@ -0,0 +1,59 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Chris Narkiewicz
+ * Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.unifiedsearch
+
+import com.nextcloud.android.lib.resources.search.UnifiedSearchRemoteOperation
+import com.nextcloud.common.NextcloudClient
+import com.owncloud.android.lib.common.SearchResult
+import com.owncloud.android.lib.common.utils.Log_OC
+
+class SearchOnProvidersTask(
+    private val query: String,
+    private val providers: List<String>,
+    private val client: NextcloudClient
+) : () -> SearchOnProvidersTask.Result {
+
+    companion object {
+        const val TAG = "SearchOnProvidersTask"
+    }
+
+    data class Result(val success: Boolean = false, val searchResults: List<SearchResult> = emptyList())
+
+    override fun invoke(): Result {
+
+        Log_OC.d(TAG, "Run task")
+        val results = providers
+            .map { UnifiedSearchRemoteOperation(it, query) }
+            .map { it.execute(client) }
+
+        val success = results.isNotEmpty() && results.any { it.isSuccess }
+        Log_OC.d(TAG, "Task finished, success: $success")
+        Log_OC.d(TAG, "Providers successful: ${results.count { it.isSuccess }}")
+        Log_OC.d(TAG, "Providers successful: ${results.count { !it.isSuccess }}")
+
+        return when {
+            success -> Result(
+                success = true,
+                searchResults = results.filter { it.isSuccess }.map { it.resultData }
+            )
+            else -> Result()
+        }
+    }
+}

+ 39 - 4
src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchRemoteRepository.kt

@@ -24,6 +24,7 @@ package com.owncloud.android.ui.unifiedsearch
 import com.nextcloud.client.account.CurrentAccountProvider
 import com.nextcloud.client.core.AsyncRunner
 import com.nextcloud.client.network.ClientFactory
+import com.owncloud.android.lib.common.SearchProviders
 import com.owncloud.android.lib.common.utils.Log_OC
 
 class UnifiedSearchRemoteRepository(
@@ -31,6 +32,9 @@ class UnifiedSearchRemoteRepository(
     private val currentAccountProvider: CurrentAccountProvider,
     private val asyncRunner: AsyncRunner
 ) : IUnifiedSearchRepository {
+
+    private var providers: SearchProviders? = null
+
     override fun refresh() {
         TODO("Not yet implemented")
     }
@@ -39,10 +43,41 @@ class UnifiedSearchRemoteRepository(
         TODO("Not yet implemented")
     }
 
-    override fun loadMore(query: String, vm: UnifiedSearchViewModel) {
+    override fun loadMore(
+        query: String,
+        onResult: (UnifiedSearchResults) -> Unit,
+        onError: (Throwable) -> Unit
+    ) {
         Log_OC.d(this, "loadMore")
-        val client = clientFactory.createNextcloudClient(currentAccountProvider.user)
-        val task = SearchOnProviderTask(query, "files", client)
-        asyncRunner.postQuickTask(task, onResult = vm::onSearchResult, onError = vm::onError)
+        fetchProviders(
+            onResult = { result ->
+                val providerIds = result.providers.map { it.id }
+                val client = clientFactory.createNextcloudClient(currentAccountProvider.user)
+                val task = SearchOnProvidersTask(query, providerIds, client)
+                asyncRunner.postQuickTask(
+                    task = task,
+                    onResult = {
+                        onResult(UnifiedSearchResults(it.success, it.searchResults))
+                    },
+                    onError = onError
+                )
+            },
+            onError = onError
+        )
+    }
+
+    private fun fetchProviders(onResult: (SearchProviders) -> Unit, onError: (Throwable) -> Unit) {
+        Log_OC.d(this, "fetchProviders")
+        if (this.providers != null) {
+            onResult(this.providers!!)
+        } else {
+            val client = clientFactory.createNextcloudClient(currentAccountProvider.user)
+            val task = GetSearchProvidersTask(client)
+            asyncRunner.postQuickTask(
+                task,
+                onResult = { onResult(it.providers) },
+                onError = onError
+            )
+        }
     }
 }

+ 7 - 5
src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchViewModel.kt

@@ -35,7 +35,6 @@ import com.owncloud.android.ui.asynctasks.GetRemoteFileTask
 import javax.inject.Inject
 
 @Suppress("LongParameterList")
-open // legacy code had large dependencies
 class UnifiedSearchViewModel() : ViewModel() {
     lateinit var currentAccountProvider: CurrentAccountProvider
     lateinit var runner: AsyncRunner
@@ -92,7 +91,7 @@ class UnifiedSearchViewModel() : ViewModel() {
 
         if (isLoading.value != true && queryTerm.isNotBlank()) {
             isLoading.value = true
-            repository.loadMore(queryTerm, this)
+            repository.loadMore(queryTerm, this::onSearchResult, this::onError)
         }
     }
 
@@ -119,18 +118,21 @@ class UnifiedSearchViewModel() : ViewModel() {
         Log_OC.d("Unified Search", "Error: " + error.stackTrace)
     }
 
-    fun onSearchResult(result: SearchOnProviderTask.Result) {
+    fun onSearchResult(result: UnifiedSearchResults) {
         isLoading.value = false
 
         if (result.success) {
             // TODO append if already exists
-            searchResults.value = mutableListOf(result.searchResult)
+            searchResults.value = result.results.toMutableList()
         } else {
             error.value = resources.getString(R.string.search_error)
         }
 
         Log_OC.d("Unified Search", "Success: " + result.success)
-        Log_OC.d("Unified Search", "Size: " + result.searchResult.entries.size)
+        if (result.success) {
+            Log_OC.d("Unified Search", "Got results from ${result.results.size} providers")
+            Log_OC.d("Unified Search", "Total results: " + result.results.sumOf { it.entries.size })
+        }
     }
 
     @VisibleForTesting