mirror of https://github.com/tasks/tasks
Begin refactoring FilterSettingsActivity
parent
e3edd4797a
commit
be5a4dfc01
@ -0,0 +1,157 @@
|
|||||||
|
package org.tasks.activities
|
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.todoroo.astrid.api.PermaSql
|
||||||
|
import com.todoroo.astrid.core.CriterionInstance
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.tasks.activities.FilterSettingsActivity.Companion.EXTRA_CRITERIA
|
||||||
|
import org.tasks.activities.FilterSettingsActivity.Companion.TOKEN_FILTER
|
||||||
|
import org.tasks.data.dao.TaskDao.TaskCriteria.activeAndVisible
|
||||||
|
import org.tasks.data.db.Database
|
||||||
|
import org.tasks.data.entity.Task
|
||||||
|
import org.tasks.data.rawQuery
|
||||||
|
import org.tasks.data.sql.Field
|
||||||
|
import org.tasks.data.sql.Query
|
||||||
|
import org.tasks.data.sql.UnaryCriterion
|
||||||
|
import org.tasks.db.QueryUtils
|
||||||
|
import org.tasks.filters.CustomFilter
|
||||||
|
import org.tasks.filters.FilterCriteriaProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class FilterSettingsViewModel @Inject constructor(
|
||||||
|
savedStateHandle: SavedStateHandle,
|
||||||
|
private val filterCriteriaProvider: FilterCriteriaProvider,
|
||||||
|
private val database: Database
|
||||||
|
) : ViewModel() {
|
||||||
|
data class ViewState(
|
||||||
|
val filter: CustomFilter? = null,
|
||||||
|
val fabExtended: Boolean = false,
|
||||||
|
val criteria: ImmutableList<CriterionInstance> = persistentListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private val _viewState = MutableStateFlow(
|
||||||
|
ViewState(
|
||||||
|
filter = savedStateHandle.get<CustomFilter>(TOKEN_FILTER),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val viewState: StateFlow<ViewState> = _viewState
|
||||||
|
|
||||||
|
init {
|
||||||
|
_viewState.value.filter
|
||||||
|
?.let { filter ->
|
||||||
|
viewModelScope.launch {
|
||||||
|
setCriteria(filterCriteriaProvider.fromString(filter.criterion))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?: savedStateHandle.get<String>(EXTRA_CRITERIA)?.let { criteria ->
|
||||||
|
viewModelScope.launch {
|
||||||
|
setCriteria(filterCriteriaProvider.fromString(criteria))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?: setCriteria(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFabExtended(extended: Boolean) {
|
||||||
|
_viewState.update { it.copy(fabExtended = extended) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setCriteria(criteria: List<CriterionInstance>) {
|
||||||
|
_viewState.update {
|
||||||
|
it.copy(
|
||||||
|
criteria = criteria.ifEmpty { universe() }.toImmutableList(),
|
||||||
|
fabExtended = it.filter == null || criteria.size <= 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
_viewState.update {
|
||||||
|
it.copy(criteria = updateCounts(it.criteria).toImmutableList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeAt(index: Int) {
|
||||||
|
setCriteria(_viewState.value.criteria.toMutableList().apply { removeAt(index) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun move(from: Int, to: Int) {
|
||||||
|
setCriteria(
|
||||||
|
_viewState.value.criteria
|
||||||
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
|
val criterion = removeAt(from)
|
||||||
|
add(to, criterion)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addCriteria(instance: CriterionInstance) {
|
||||||
|
setCriteria(_viewState.value.criteria.toMutableList().apply { add(instance) })
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun updateCounts(criteria: List<CriterionInstance>): List<CriterionInstance> {
|
||||||
|
val newList = mutableListOf<CriterionInstance>()
|
||||||
|
var max = 0
|
||||||
|
var last = -1
|
||||||
|
val sql = StringBuilder(Query.select(Field.COUNT).from(Task.TABLE).toString())
|
||||||
|
.append(" WHERE ")
|
||||||
|
|
||||||
|
for (instance in criteria.map { CriterionInstance(it) }) {
|
||||||
|
when (instance.type) {
|
||||||
|
CriterionInstance.TYPE_ADD -> sql.append("OR ")
|
||||||
|
CriterionInstance.TYPE_SUBTRACT -> sql.append("AND NOT ")
|
||||||
|
CriterionInstance.TYPE_INTERSECT -> sql.append("AND ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// special code for all tasks universe
|
||||||
|
if (instance.type == CriterionInstance.TYPE_UNIVERSE || instance.criterion.sql == null) {
|
||||||
|
sql.append(activeAndVisible()).append(' ')
|
||||||
|
} else {
|
||||||
|
var subSql: String = instance.criterion.sql.replace(
|
||||||
|
"?",
|
||||||
|
UnaryCriterion.sanitize(instance.valueFromCriterion!!)
|
||||||
|
)
|
||||||
|
subSql = PermaSql.replacePlaceholdersForQuery(subSql)
|
||||||
|
sql.append(Task.ID).append(" IN (").append(subSql).append(")")
|
||||||
|
}
|
||||||
|
val sqlString = QueryUtils.showHiddenAndCompleted(sql.toString())
|
||||||
|
database.rawQuery(sqlString) { cursor ->
|
||||||
|
cursor.step()
|
||||||
|
instance.start = if (last == -1) cursor.getInt(0) else last
|
||||||
|
instance.end = cursor.getInt(0)
|
||||||
|
last = instance.end
|
||||||
|
max = max(max, last)
|
||||||
|
}
|
||||||
|
newList.add(instance)
|
||||||
|
}
|
||||||
|
for (instance in newList) {
|
||||||
|
instance.max = max
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun universe() = listOf(
|
||||||
|
CriterionInstance().apply {
|
||||||
|
criterion = filterCriteriaProvider.startingUniverse
|
||||||
|
type = CriterionInstance.TYPE_UNIVERSE
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
fun setCriterion(index: Int, criterionInstance: CriterionInstance) {
|
||||||
|
setCriteria(
|
||||||
|
_viewState.value.criteria.toMutableList().apply {
|
||||||
|
set(index, criterionInstance)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue