Move search to viewmodel

pull/2546/head
Alex Baker 9 months ago
parent e70f5f3b24
commit 94b6d7569b

@ -55,7 +55,6 @@ import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.IdListFilter
import com.todoroo.astrid.api.SearchFilter
import com.todoroo.astrid.api.TagFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao
@ -69,9 +68,7 @@ import com.todoroo.astrid.service.TaskMover
import com.todoroo.astrid.timers.TimerPlugin
import com.todoroo.astrid.utility.Flags
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -119,6 +116,7 @@ import org.tasks.ui.TaskEditEventBus
import org.tasks.ui.TaskListEvent
import org.tasks.ui.TaskListEventBus
import org.tasks.ui.TaskListViewModel
import org.tasks.ui.TaskListViewModel.Companion.createSearchQuery
import java.time.format.FormatStyle
import java.util.Locale
import javax.inject.Inject
@ -159,9 +157,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
private lateinit var taskAdapter: TaskAdapter
private var recyclerAdapter: DragAndDropRecyclerAdapter? = null
private lateinit var filter: Filter
private var searchJob: Job? = null
private lateinit var search: MenuItem
private var searchQuery: String? = null
private var mode: ActionMode? = null
lateinit var themeColor: ThemeColor
private lateinit var callbacks: TaskListFragmentCallbackHandler
@ -219,7 +215,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
super.onSaveInstanceState(outState)
val selectedTaskIds: List<Long> = taskAdapter.getSelected()
outState.putLongArray(EXTRA_SELECTED_TASK_IDS, selectedTaskIds.toLongArray())
outState.putString(EXTRA_SEARCH, searchQuery)
outState.putLongArray(EXTRA_COLLAPSED, taskAdapter.getCollapsed().toLongArray())
}
@ -258,10 +253,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
// set up list adapters
taskAdapter = taskAdapterProvider.createTaskAdapter(filter)
taskAdapter.setCollapsed(savedInstanceState?.getLongArray(EXTRA_COLLAPSED))
if (savedInstanceState != null) {
searchQuery = savedInstanceState.getString(EXTRA_SEARCH)
}
listViewModel.setFilter((if (searchQuery == null) filter else createSearchFilter(searchQuery!!)))
listViewModel.setFilter(filter)
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
recyclerView.layoutManager = LinearLayoutManager(context)
lifecycleScope.launch {
@ -394,25 +386,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
}
private fun searchByQuery(query: String?) {
searchJob?.cancel()
searchJob = lifecycleScope.launch {
delay(SEARCH_DEBOUNCE_TIMEOUT)
searchQuery = query?.trim { it <= ' ' } ?: ""
if (searchQuery?.isEmpty() == true) {
listViewModel.setFilter(
BuiltInFilterExposer.getMyTasksFilter(requireContext().resources))
} else {
val savedFilter = createSearchFilter(searchQuery!!)
listViewModel.setFilter(savedFilter)
}
}
}
private fun createSearchFilter(query: String): Filter {
return SearchFilter(getString(R.string.FLA_search_filter, query), query)
}
override fun onMenuItemClick(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_voice_add -> {
@ -657,9 +630,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
onBackPressed.isEnabled = true
search.setOnQueryTextListener(this)
if (searchQuery == null) {
searchByQuery("")
}
listViewModel.setSearchQuery("")
if (preferences.isTopAppBar) {
binding.toolbar.menu.forEach { it.isVisible = false }
}
@ -670,8 +641,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
onBackPressed.isEnabled = false
search.setOnQueryTextListener(null)
listViewModel.setFilter(filter)
searchJob?.cancel()
searchQuery = null
listViewModel.setSearchQuery(null)
if (preferences.isTopAppBar) {
setupMenu(binding.toolbar)
}
@ -679,13 +649,13 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
override fun onQueryTextSubmit(query: String): Boolean {
openFilter(createSearchFilter(query.trim { it <= ' ' }))
openFilter(requireContext().createSearchQuery(query.trim()))
search.collapseActionView()
return true
}
override fun onQueryTextChange(query: String): Boolean {
searchByQuery(query)
listViewModel.setSearchQuery(query)
return true
}
@ -988,7 +958,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
const val ACTION_RELOAD = "action_reload"
const val ACTION_DELETED = "action_deleted"
private const val EXTRA_SELECTED_TASK_IDS = "extra_selected_task_ids"
private const val EXTRA_SEARCH = "extra_search"
private const val EXTRA_COLLAPSED = "extra_collapsed"
private const val VOICE_RECOGNITION_REQUEST_CODE = 1234
private const val EXTRA_FILTER = "extra_filter"
@ -997,7 +966,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
private const val FRAG_TAG_PRIORITY_PICKER = "frag_tag_priority_picker"
private const val REQUEST_LIST_SETTINGS = 10101
private const val REQUEST_TAG_TASKS = 10106
private const val SEARCH_DEBOUNCE_TIMEOUT = 300L
fun newTaskListFragment(context: Context, filter: Filter?): TaskListFragment {
val fragment = TaskListFragment()
val bundle = Bundle()

@ -8,6 +8,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.SearchFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
@ -48,6 +50,7 @@ class TaskListViewModel @Inject constructor(
data class State(
val filter: Filter? = null,
val now: Long = DateUtilities.now(),
val searchQuery: String? = null,
val tasks: List<TaskContainer> = emptyList(),
val begForSubscription: Boolean = false,
val syncOngoing: Boolean = false,
@ -68,6 +71,10 @@ class TaskListViewModel @Inject constructor(
}
}
fun setSearchQuery(query: String?) {
_state.update { it.copy(searchQuery = query?.trim()) }
}
fun invalidate() {
_state.update {
it.copy(
@ -99,7 +106,14 @@ class TaskListViewModel @Inject constructor(
_state
.filter { it.filter != null }
.throttleLatest(333)
.map { taskDao.fetchTasks { getQuery(preferences, it.filter!!) } }
.map {
val filter = when {
it.searchQuery == null -> it.filter!!
it.searchQuery.isBlank() -> BuiltInFilterExposer.getMyTasksFilter(context.resources)
else -> context.createSearchQuery(it.searchQuery)
}
taskDao.fetchTasks { getQuery(preferences, filter) }
}
.onEach { tasks ->
_state.update {
it.copy(tasks = tasks)
@ -120,4 +134,9 @@ class TaskListViewModel @Inject constructor(
override fun onCleared() {
localBroadcastManager.unregisterReceiver(refreshReceiver)
}
companion object {
fun Context.createSearchQuery(query: String): Filter =
SearchFilter(getString(R.string.FLA_search_filter, query), query)
}
}

Loading…
Cancel
Save