From 5082a733022767e4b7e04682616d2907ba44cab6 Mon Sep 17 00:00:00 2001 From: konradkluz Date: Thu, 15 Nov 2018 15:23:57 +0100 Subject: [PATCH] Search works in a reactive way --- .../astrid/activity/TaskListFragment.java | 82 +++++++++++++------ .../java/org/tasks/ui/TaskListViewModel.java | 9 +- .../main/res/menu/menu_task_list_fragment.xml | 4 +- 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java index 576330de5..e5fcc6604 100644 --- a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java +++ b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.java @@ -46,6 +46,9 @@ import com.todoroo.astrid.service.TaskCreator; import com.todoroo.astrid.service.TaskDeleter; import com.todoroo.astrid.service.TaskMover; import com.todoroo.astrid.timers.TimerPlugin; +import io.reactivex.disposables.Disposable; +import io.reactivex.subjects.PublishSubject; +import java.util.concurrent.TimeUnit; import java.util.List; import javax.inject.Inject; import org.tasks.LocalBroadcastManager; @@ -88,6 +91,7 @@ public class TaskListFragment extends InjectingFragment private static final String FRAG_TAG_SORT_DIALOG = "frag_tag_sort_dialog"; // --- instance variables private static final int REQUEST_EDIT_FILTER = 11544; + private static final int SEARCH_DEBOUNCE_TIMEOUT = 300; private final RefreshReceiver refreshReceiver = new RefreshReceiver(); @Inject protected Tracker tracker; protected Filter filter; @@ -124,7 +128,10 @@ public class TaskListFragment extends InjectingFragment private TaskAdapter taskAdapter = null; private TaskListRecyclerAdapter recyclerAdapter; - /* + private PublishSubject searchSubject; + private Disposable searchDisposable; + + /* * ====================================================================== * ======================================================= initialization * ====================================================================== @@ -247,34 +254,53 @@ public class TaskListFragment extends InjectingFragment } menu.findItem(R.id.menu_voice_add).setVisible(device.voiceInputAvailable()); + setupSearchView(menu); + } + + private void setupSearchView(Menu menu) { final MenuItem item = menu.findItem(R.id.menu_search); final SearchView actionView = (SearchView) MenuItemCompat.getActionView(item); + searchSubject = PublishSubject.create(); + searchDisposable = searchSubject + .debounce(SEARCH_DEBOUNCE_TIMEOUT, TimeUnit.MILLISECONDS) + .subscribe(query -> searchByQuery(query)); + actionView.setOnQueryTextListener( - new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - query = query.trim(); - String title = getString(R.string.FLA_search_filter, query); - Filter savedFilter = - new Filter( - title, - new QueryTemplate() - .where( - Criterion.and( - Task.DELETION_DATE.eq(0), - Criterion.or( + new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + return false; + } + + @Override + public boolean onQueryTextChange(String query) { + searchSubject.onNext(query); + return true; + } + }); + } + + private void searchByQuery(String query) { + query = query.trim(); + if (!query.isEmpty()) { + Filter savedFilter = createSearchFilter(query); + taskListViewModel.searchByFilter(savedFilter); + } else { + MainActivity activity = (MainActivity) getActivity(); + taskListViewModel.searchByFilter(activity.defaultFilterProvider.getDefaultFilter()); + } + } + + private Filter createSearchFilter(String query){ + String title = getString(R.string.FLA_search_filter, query); + return new Filter( + title, new QueryTemplate() + .where( + Criterion.and( + Task.DELETION_DATE.eq(0), + Criterion.or( Task.NOTES.like("%" + query + "%"), Task.TITLE.like("%" + query + "%"))))); - ((MainActivity) getActivity()).onFilterItemClicked(savedFilter); - MenuItemCompat.collapseActionView(item); - return true; - } - - @Override - public boolean onQueryTextChange(String query) { - return false; - } - }); } @Override @@ -405,7 +431,13 @@ public class TaskListFragment extends InjectingFragment localBroadcastManager.unregisterReceiver(refreshReceiver); } - /** + @Override + public void onDestroyView() { + super.onDestroyView(); + searchDisposable.dispose(); + } + + /** * Called by the RefreshReceiver when the task list receives a refresh broadcast. Subclasses * should override this. */ diff --git a/app/src/main/java/org/tasks/ui/TaskListViewModel.java b/app/src/main/java/org/tasks/ui/TaskListViewModel.java index 6063e3c02..f7e941ad7 100644 --- a/app/src/main/java/org/tasks/ui/TaskListViewModel.java +++ b/app/src/main/java/org/tasks/ui/TaskListViewModel.java @@ -49,12 +49,12 @@ public class TaskListViewModel extends ViewModel { public LiveData> getTasks(Filter filter, Property[] properties) { if (tasks == null || !filter.equals(this.filter)) { this.filter = filter; - tasks = getLiveData(filter, properties); + tasks = getLiveData(properties); } return tasks; } - private LiveData> getLiveData(Filter filter, Property[] properties) { + private LiveData> getLiveData(Property[] properties) { return new LivePagedListBuilder<>( new Factory() { @Override @@ -131,6 +131,11 @@ public class TaskListViewModel extends ViewModel { return new LimitOffsetDataSource(database, query); } + public void searchByFilter(Filter filter){ + this.filter = filter; + invalidate(); + } + public void invalidate() { if (latest != null) { latest.invalidate(); diff --git a/app/src/main/res/menu/menu_task_list_fragment.xml b/app/src/main/res/menu/menu_task_list_fragment.xml index a6d0ed539..9c9199d35 100644 --- a/app/src/main/res/menu/menu_task_list_fragment.xml +++ b/app/src/main/res/menu/menu_task_list_fragment.xml @@ -7,13 +7,13 @@ android:id="@+id/menu_voice_add" android:icon="@drawable/ic_outline_mic_none_24px" android:title="@string/EPr_voiceInputEnabled_title" - app:showAsAction="ifRoom"/> + app:showAsAction="always"/> + app:showAsAction="always|collapseActionView"/>