Use rxjava to debounce search instead of custom debouncer

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
This commit is contained in:
Álvaro Brey 2022-05-24 14:48:55 +02:00
parent b10ea2f41f
commit d1d61e87a9
No known key found for this signature in database
GPG Key ID: 2585783189A62105
4 changed files with 67 additions and 54 deletions

View File

@ -66,7 +66,6 @@ import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
@ -521,7 +520,6 @@ public interface NcApi {
@Url String url,
@Query("reaction") String reaction);
// TODO use path params instead of passing URL
@GET
Observable<UnifiedSearchOverall> performUnifiedSearch(@Header("Authorization") String authorization,
@Url String url,

View File

@ -95,12 +95,12 @@ import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.AttendeePermissionsUtil;
import com.nextcloud.talk.utils.ClosedInterfaceImpl;
import com.nextcloud.talk.utils.ConductorRemapping;
import com.nextcloud.talk.utils.Debouncer;
import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.UriUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.utils.preferences.AppPreferences;
import com.nextcloud.talk.utils.rx.SearchViewObservable;
import com.webianks.library.PopupBubble;
import com.yarolegovich.lovelydialog.LovelySaveStateHandler;
import com.yarolegovich.lovelydialog.LovelyStandardDialog;
@ -117,6 +117,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@ -147,8 +148,7 @@ import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
@AutoInjector(NextcloudTalkApplication.class)
public class ConversationsListController extends BaseController implements SearchView.OnQueryTextListener,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener, ConversationMenuInterface {
public class ConversationsListController extends BaseController implements FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener, ConversationMenuInterface {
public static final String TAG = "ConvListController";
public static final int ID_DELETE_CONVERSATION_DIALOG = 0;
@ -236,9 +236,8 @@ public class ConversationsListController extends BaseController implements Searc
private HashMap<String, Status> userStatuses = new HashMap<>();
private Debouncer searchDebouncer = new Debouncer(SEARCH_DEBOUNCE_INTERVAL_MS);
private MessageSearchHelper searchHelper;
private Disposable searchViewDisposable;
public ConversationsListController(Bundle bundle) {
super();
@ -361,7 +360,18 @@ public class ConversationsListController extends BaseController implements Searc
if (searchManager != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
}
searchView.setOnQueryTextListener(this);
searchViewDisposable = SearchViewObservable.observeSearchView(searchView)
.debounce(query -> {
if (TextUtils.isEmpty(query)) {
return Observable.empty();
} else {
return Observable.timer(SEARCH_DEBOUNCE_INTERVAL_MS, TimeUnit.MILLISECONDS);
}
})
.distinctUntilChanged()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onQueryTextChange);
}
}
}
@ -869,21 +879,17 @@ public class ConversationsListController extends BaseController implements Searc
public void onDestroy() {
super.onDestroy();
dispose(null);
searchViewDisposable.dispose();
}
@Override
public boolean onQueryTextChange(final String newText) {
public void onQueryTextChange(final String newText) {
if (!TextUtils.isEmpty(searchQuery)) {
final String filter = searchQuery;
searchQuery = "";
performFilterAndSearch(filter);
} else if (adapter.hasNewFilter(newText)) {
new Handler();
searchDebouncer.debounce(() -> {
performFilterAndSearch(newText);
});
performFilterAndSearch(newText);
}
return true;
}
private void performFilterAndSearch(String filter) {
@ -939,11 +945,6 @@ public class ConversationsListController extends BaseController implements Searc
}
@Override
public boolean onQueryTextSubmit(String query) {
return onQueryTextChange(query);
}
@Override
protected String getTitle() {
return getResources().getString(R.string.nc_app_product_name);

View File

@ -1,34 +0,0 @@
/*
* Nextcloud Talk application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.utils
import android.os.Handler
import android.os.Looper
class Debouncer(var delay: Long) {
private val handler = Handler(Looper.getMainLooper())
fun debounce(runnable: Runnable) {
handler.removeCallbacksAndMessages(null) // clear handler
handler.postDelayed(runnable, delay)
}
}

View File

@ -0,0 +1,48 @@
/*
* Nextcloud Talk application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.utils.rx
import androidx.appcompat.widget.SearchView
import io.reactivex.Observable
import io.reactivex.subjects.PublishSubject
class SearchViewObservable {
companion object {
@JvmStatic
fun observeSearchView(searchView: SearchView): Observable<String> {
val subject: PublishSubject<String> = PublishSubject.create()
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
subject.onComplete()
return true
}
override fun onQueryTextChange(newText: String): Boolean {
subject.onNext(newText)
return true
}
})
return subject
}
}
}