From ef62a946c6b9a2fb5d2de75024e80e6ec0517be0 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Sat, 15 Jan 2022 12:00:03 -0600 Subject: [PATCH] Sort completed tasks at bottom --- .../tasks/data/TaskListQueryNonRecursive.kt | 16 ++++++---- .../org/tasks/data/TaskListQueryRecursive.kt | 8 ++--- .../java/org/tasks/tasklist/AdapterSection.kt | 5 +++- .../org/tasks/tasklist/SectionedDataSource.kt | 30 ++++++++++++++----- app/src/main/res/values/strings.xml | 1 + 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt b/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt index db532b38a..27d02376d 100644 --- a/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt +++ b/app/src/main/java/org/tasks/data/TaskListQueryNonRecursive.kt @@ -8,6 +8,7 @@ import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.PermaSql import com.todoroo.astrid.core.SortHelper import com.todoroo.astrid.data.Task +import org.tasks.filters.RecentlyModifiedFilter import org.tasks.preferences.QueryPreferences internal object TaskListQueryNonRecursive { @@ -19,17 +20,22 @@ internal object TaskListQueryNonRecursive { private val TAGS = field("group_concat(distinct(${TaskListFragment.TAGS_METADATA_JOIN}.tag_uid))") .`as`("tags") - private val FIELDS = TaskListQuery.FIELDS.plus(TAGS).toTypedArray() + private val IS_COMPLETE = field("tasks.completed > 0").`as`("is_complete") + private const val ORDER_BY = "ORDER BY is_complete ASC, tasks.completed DESC" + private val FIELDS = TaskListQuery.FIELDS.plus(TAGS).plus(IS_COMPLETE).toTypedArray() fun getNonRecursiveQuery(filter: Filter, preferences: QueryPreferences): MutableList { val joinedQuery = JOINS + filter.getSqlQuery() val sortMode = preferences.sortMode val sortGroup = field(SortHelper.getSortGroup(sortMode) ?: "NULL").`as`("sortGroup") val query = SortHelper.adjustQueryForFlagsAndSort(preferences, joinedQuery, sortMode) - val groupedQuery = if (query.contains("ORDER BY")) { - query.replace("ORDER BY", "GROUP BY ${Task.ID} ORDER BY") - } else { - "$query GROUP BY ${Task.ID}" + val groupedQuery = when { + filter is RecentlyModifiedFilter -> + query.replace("ORDER BY", "GROUP BY ${Task.ID} ORDER BY") + query.contains("ORDER BY") -> + query.replace("ORDER BY", "GROUP BY ${Task.ID} $ORDER_BY,") + else -> + "$query GROUP BY ${Task.ID} $ORDER_BY" } return mutableListOf( Query.select(*FIELDS.plus(sortGroup)) diff --git a/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt b/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt index a24b624b7..da40f7d1d 100644 --- a/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt +++ b/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt @@ -98,12 +98,12 @@ internal object TaskListQueryRecursive { val sortSelect = SortHelper.orderSelectForSortTypeRecursive(sortMode) val withClause =""" CREATE TEMPORARY TABLE `recursive_tasks` AS - WITH RECURSIVE recursive_tasks (task, parent, collapsed, hidden, indent, title, sortField, primary_sort, secondary_sort, sort_group) AS ( - SELECT tasks._id, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect, $sortField as primary_sort, NULL as secondarySort, ${SortHelper.getSortGroup(sortMode)} FROM tasks + WITH RECURSIVE recursive_tasks (task, parent_complete, subtask_complete, completion_sort, parent, collapsed, hidden, indent, title, sortField, primary_sort, secondary_sort, sort_group) AS ( + SELECT tasks._id, tasks.completed > 0 as parent_complete, 0 as subtask_complete, tasks.completed as completion_sort, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect, $sortField as primary_sort, NULL as secondarySort, ${SortHelper.getSortGroup(sortMode)} FROM tasks $parentQuery - UNION ALL SELECT tasks._id, recursive_tasks.task as parent, tasks.collapsed as collapsed, CASE WHEN recursive_tasks.collapsed > 0 OR recursive_tasks.hidden > 0 THEN 1 ELSE 0 END as hidden, recursive_tasks.indent+1 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect, recursive_tasks.primary_sort as primary_sort, $sortField as secondary_sort, recursive_tasks.sort_group FROM tasks + UNION ALL SELECT tasks._id, recursive_tasks.parent_complete, tasks.completed > 0, tasks.completed as completion_sort, recursive_tasks.task as parent, tasks.collapsed as collapsed, CASE WHEN recursive_tasks.collapsed > 0 OR recursive_tasks.hidden > 0 THEN 1 ELSE 0 END as hidden, recursive_tasks.indent+1 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect, recursive_tasks.primary_sort as primary_sort, $sortField as secondary_sort, recursive_tasks.sort_group FROM tasks $subtaskQuery - ORDER BY sort_indent DESC, ${SortHelper.orderForSortTypeRecursive(sortMode, reverseSort)} + ORDER BY parent_complete ASC, sort_indent DESC, subtask_complete ASC, completion_sort DESC, ${SortHelper.orderForSortTypeRecursive(sortMode, reverseSort)} ) SELECT * FROM recursive_tasks """.trimIndent() diff --git a/app/src/main/java/org/tasks/tasklist/AdapterSection.kt b/app/src/main/java/org/tasks/tasklist/AdapterSection.kt index a22bd02e4..7d5d0aad1 100644 --- a/app/src/main/java/org/tasks/tasklist/AdapterSection.kt +++ b/app/src/main/java/org/tasks/tasklist/AdapterSection.kt @@ -7,6 +7,8 @@ import com.todoroo.andlib.utility.DateUtilities import com.todoroo.astrid.core.SortHelper.* import org.tasks.R import org.tasks.date.DateTimeUtils.toDateTime +import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED +import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_OVERDUE import java.time.format.FormatStyle import java.util.* @@ -34,8 +36,9 @@ data class AdapterSection( compact: Boolean = false ): String = when { + value == HEADER_COMPLETED -> context.getString(R.string.completed) sortMode == SORT_IMPORTANCE -> context.getString(priorityToString()) - value == -1L -> context.getString(R.string.filter_overdue) + value == HEADER_OVERDUE -> context.getString(R.string.filter_overdue) value == 0L -> context.getString(when (sortMode) { SORT_DUE -> R.string.no_due_date SORT_START -> R.string.no_start_date diff --git a/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt b/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt index c3422b62e..b22f6def2 100644 --- a/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt +++ b/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt @@ -62,12 +62,14 @@ class SectionedDataSource constructor( for (i in tasks.indices) { val task = tasks[i] val sortGroup = task.sortGroup ?: continue - val header = if (sortMode == SortHelper.SORT_IMPORTANCE || sortGroup == 0L) { + val header = if (task.isCompleted && !task.hasParent()) { + HEADER_COMPLETED + } else if (sortMode == SortHelper.SORT_IMPORTANCE || sortGroup == 0L) { sortGroup } else if (sortMode == SortHelper.SORT_DUE) { when { sortGroup == 0L -> 0 - sortGroup < startOfToday -> -1 + sortGroup < startOfToday -> HEADER_OVERDUE else -> sortGroup.startOfDay() } } else { @@ -77,14 +79,21 @@ class SectionedDataSource constructor( if (i == 0) { sections.add(AdapterSection(i, header, 0, isCollapsed)) } else { - val previous = tasks[i - 1].sortGroup - when (sortMode) { - SortHelper.SORT_IMPORTANCE -> if (header != previous) { - sections.add(AdapterSection(i, header, 0, isCollapsed)) + val previousTask = tasks[i - 1] + val previous = previousTask.sortGroup + when { + task.isCompleted && !task.hasParent() -> { + if (!previousTask.isCompleted) { + sections.add(AdapterSection(i, header, 0, isCollapsed)) + } } - SortHelper.SORT_DUE -> { + sortMode == SortHelper.SORT_IMPORTANCE -> + if (header != previous) { + sections.add(AdapterSection(i, header, 0, isCollapsed)) + } + sortMode == SortHelper.SORT_DUE -> { val previousOverdue = previous < startOfToday - val currentOverdue = header == -1L + val currentOverdue = header == HEADER_OVERDUE if (previous > 0 && ((currentOverdue != previousOverdue) || (!currentOverdue && header != previous.startOfDay())) @@ -143,4 +152,9 @@ class SectionedDataSource constructor( sections.forEach { _, header -> values.add(header.value) } return values } + + companion object { + const val HEADER_OVERDUE = -1L + const val HEADER_COMPLETED = -2L + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d34a993e5..c95244e9a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -710,4 +710,5 @@ File %1$s contained %2$s.\n\n App bar position Top Bottom + Completed