From 808781c262260f7f3c5c139503cc4ca0bc4211ce Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Fri, 15 May 2020 16:29:46 -0500 Subject: [PATCH] Display caldav tasks in manual sort order --- .../adapter/CaldavManualSortTaskAdapter.kt | 75 +++++++++++++++++++ .../astrid/adapter/CaldavTaskAdapter.kt | 40 +--------- .../astrid/adapter/TaskAdapterProvider.java | 4 +- .../com/todoroo/astrid/api/CaldavFilter.java | 5 ++ .../com/todoroo/astrid/core/SortHelper.java | 5 ++ .../main/java/org/tasks/caldav/iCalendar.kt | 1 + .../java/org/tasks/data/TaskListQuery.java | 18 +++-- 7 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 app/src/main/java/com/todoroo/astrid/adapter/CaldavManualSortTaskAdapter.kt diff --git a/app/src/main/java/com/todoroo/astrid/adapter/CaldavManualSortTaskAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/CaldavManualSortTaskAdapter.kt new file mode 100644 index 000000000..edc7b46a5 --- /dev/null +++ b/app/src/main/java/com/todoroo/astrid/adapter/CaldavManualSortTaskAdapter.kt @@ -0,0 +1,75 @@ +package com.todoroo.astrid.adapter + +import com.todoroo.astrid.dao.TaskDao +import org.tasks.data.CaldavDao +import org.tasks.data.TaskContainer + +open class CaldavManualSortTaskAdapter internal constructor(private val taskDao: TaskDao, private val caldavDao: CaldavDao) : TaskAdapter() { + override fun canMove(source: TaskContainer, from: Int, target: TaskContainer, to: Int) = !taskIsChild(source, to) + + override fun maxIndent(previousPosition: Int, task: TaskContainer) = getTask(previousPosition).getIndent() + 1 + + override fun minIndent(nextPosition: Int, task: TaskContainer) = 0 + + override fun supportsParentingOrManualSort() = true + + override fun supportsManualSorting() = true + + override fun moved(from: Int, to: Int, indent: Int) { + val task = getTask(from) + val previous = if (to > 0) getTask(to - 1) else null + var newParent = task.parent + if (indent == 0) { + newParent = 0 + } else if (previous != null) { + when { + indent == previous.getIndent() -> newParent = previous.parent + indent > previous.getIndent() -> newParent = previous.id + indent < previous.getIndent() -> { + newParent = previous.parent + var currentIndex = to + for (i in 0 until previous.getIndent() - indent) { + var thisParent = newParent + while (newParent == thisParent) { + thisParent = getTask(--currentIndex).parent + } + newParent = thisParent + } + } + } + } + + // If nothing is changing, return + if (newParent == task.parent) { + return + } + changeParent(task, newParent) + taskDao.touch(task.id) + } + + internal fun changeParent(task: TaskContainer, newParent: Long) { + val caldavTask = task.getCaldavTask() + if (newParent == 0L) { + caldavTask.cd_remote_parent = "" + task.parent = 0 + } else { + val parentTask = caldavDao.getTask(newParent) ?: return + caldavTask.cd_remote_parent = parentTask.remoteId + task.parent = newParent + } + caldavDao.update(caldavTask) + taskDao.save(task.getTask(), null) + taskDao.touch(task.id) + } + + private fun taskIsChild(source: TaskContainer, destinationIndex: Int): Boolean { + (destinationIndex downTo 0).forEach { + when (getTask(it).parent) { + 0L -> return false + source.parent -> return false + source.id -> return true + } + } + return false + } +} \ No newline at end of file diff --git a/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt index 4563d861f..50d640c69 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt @@ -2,19 +2,9 @@ package com.todoroo.astrid.adapter import com.todoroo.astrid.dao.TaskDao import org.tasks.data.CaldavDao -import org.tasks.data.TaskContainer -class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, private val caldavDao: CaldavDao) : TaskAdapter() { - override fun canMove(source: TaskContainer, from: Int, target: TaskContainer, to: Int) = !taskIsChild(source, to) - - override fun maxIndent(previousPosition: Int, task: TaskContainer): Int { - val previous = getTask(previousPosition) - return previous.getIndent() + 1 - } - - override fun minIndent(nextPosition: Int, task: TaskContainer) = 0 - - override fun supportsParentingOrManualSort() = true +class CaldavTaskAdapter internal constructor(taskDao: TaskDao, caldavDao: CaldavDao) : CaldavManualSortTaskAdapter(taskDao, caldavDao) { + override fun supportsManualSorting() = false override fun moved(from: Int, to: Int, indent: Int) { val task = getTask(from) @@ -50,30 +40,4 @@ class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, priva } changeParent(task, newParent) } - - private fun changeParent(task: TaskContainer, newParent: Long) { - val caldavTask = task.getCaldavTask() - if (newParent == 0L) { - caldavTask.cd_remote_parent = "" - task.parent = 0 - } else { - val parentTask = caldavDao.getTask(newParent) ?: return - caldavTask.cd_remote_parent = parentTask.remoteId - task.parent = newParent - } - caldavDao.update(caldavTask) - taskDao.save(task.getTask(), null) - taskDao.touch(task.id) - } - - private fun taskIsChild(source: TaskContainer, destinationIndex: Int): Boolean { - (destinationIndex downTo 0).forEach { - when (getTask(it).parent) { - 0L -> return false - source.parent -> return false - source.id -> return true - } - } - return false - } } \ No newline at end of file diff --git a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapterProvider.java b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapterProvider.java index c88ffb297..4b0eb952d 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapterProvider.java +++ b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapterProvider.java @@ -80,7 +80,9 @@ public class TaskAdapterProvider { CaldavFilter caldavFilter = (CaldavFilter) filter; CaldavCalendar calendar = caldavDao.getCalendarByUuid(caldavFilter.getUuid()); if (calendar != null) { - return new CaldavTaskAdapter(taskDao, caldavDao); + return preferences.isManualSort() + ? new CaldavManualSortTaskAdapter(taskDao, caldavDao) + : new CaldavTaskAdapter(taskDao, caldavDao); } } else { return subtasksHelper.shouldUseSubtasksFragmentForFilter(filter) diff --git a/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java b/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java index a068171ef..a61aba78a 100644 --- a/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java +++ b/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java @@ -89,6 +89,11 @@ public class CaldavFilter extends Filter { calendar = source.readParcelable(getClass().getClassLoader()); } + @Override + public boolean supportsManualSort() { + return true; + } + @Override public int getMenu() { return R.menu.menu_caldav_list_fragment; diff --git a/app/src/main/java/com/todoroo/astrid/core/SortHelper.java b/app/src/main/java/com/todoroo/astrid/core/SortHelper.java index 719f2c08d..08a59bc21 100644 --- a/app/src/main/java/com/todoroo/astrid/core/SortHelper.java +++ b/app/src/main/java/com/todoroo/astrid/core/SortHelper.java @@ -30,6 +30,7 @@ public class SortHelper { public static final int SORT_MODIFIED = 4; public static final int SORT_CREATED = 5; public static final int SORT_GTASKS = 6; + public static final int SORT_CALDAV = 7; private static final String ADJUSTED_DUE_DATE = "(CASE WHEN (dueDate / 1000) % 60 > 0 THEN dueDate ELSE (dueDate + 43140000) END)"; @@ -139,6 +140,9 @@ public class SortHelper { case SORT_GTASKS: select = "google_tasks.gt_order AS sort_manual"; break; + case SORT_CALDAV: + select = "caldav_tasks.cd_order AS sort_manual"; + break; default: select ="(CASE WHEN (tasks.dueDate=0) " + // if no due date @@ -173,6 +177,7 @@ public class SortHelper { order = Order.desc("sort_created"); break; case SORT_GTASKS: + case SORT_CALDAV: order = Order.asc("sort_manual"); break; default: diff --git a/app/src/main/java/org/tasks/caldav/iCalendar.kt b/app/src/main/java/org/tasks/caldav/iCalendar.kt index eb01e7293..0cc2adb88 100644 --- a/app/src/main/java/org/tasks/caldav/iCalendar.kt +++ b/app/src/main/java/org/tasks/caldav/iCalendar.kt @@ -157,6 +157,7 @@ class iCalendar @Inject constructor( } CaldavConverter.apply(task, remote) caldavTask.remoteOrder = remote.order + caldavTask.order = caldavTask.remoteOrder // TODO: remove me val geo = remote.geoPosition if (geo == null) { locationDao.getActiveGeofences(task.id).forEach { diff --git a/app/src/main/java/org/tasks/data/TaskListQuery.java b/app/src/main/java/org/tasks/data/TaskListQuery.java index 0d4646312..b0e1db029 100644 --- a/app/src/main/java/org/tasks/data/TaskListQuery.java +++ b/app/src/main/java/org/tasks/data/TaskListQuery.java @@ -73,7 +73,7 @@ public class TaskListQuery { Preferences preferences, com.todoroo.astrid.api.Filter filter, SubtaskInfo subtasks) { if (filter.supportsManualSort() && preferences.isManualSort()) { - return subtasks.usesSubtasks() && filter instanceof GtasksFilter + return filter instanceof GtasksFilter || filter instanceof CaldavFilter ? getRecursiveQuery(filter, preferences, subtasks) : getNonRecursiveQuery(filter, preferences); } @@ -118,6 +118,9 @@ public class TaskListQuery { .toString(); subtaskQuery .join(Join.inner(RECURSIVE, Task.PARENT.eq(RECURSIVE_TASK))) + .join( + Join.inner(CaldavTask.TABLE, + Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0)))) .where(TaskCriteria.activeAndVisible()); } else if (filter instanceof GtasksFilter) { GoogleTaskList list = ((GtasksFilter) filter).getList(); @@ -158,11 +161,18 @@ public class TaskListQuery { boolean manualSort = preferences.isManualSort(); boolean manualGtasks = manualSort && filter instanceof GtasksFilter; + boolean manualCaldav = manualSort && filter instanceof CaldavFilter; int sortMode; + String sortField; if (manualGtasks) { sortMode = SortHelper.SORT_GTASKS; + sortField = "google_tasks.gt_order"; + } else if (manualCaldav) { + sortMode = SortHelper.SORT_CALDAV; + sortField = "caldav_tasks.cd_order"; } else { sortMode = preferences.getSortMode(); + sortField = "NULL"; } boolean reverseSort = preferences.isReverseSort() && sortMode != SortHelper.SORT_GTASKS; String sortSelect = SortHelper.orderSelectForSortTypeRecursive(sortMode); @@ -171,14 +181,12 @@ public class TaskListQuery { + "WITH RECURSIVE recursive_tasks (task, parent, collapsed, hidden, indent, title, sortField, primary_sort, secondary_sort) AS (\n" + " SELECT tasks._id, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, " + sortSelect - + (manualGtasks ? ", google_tasks.gt_order as primary_sort" : ", NULL as primary_sort") - + ", NULL as secondary_sort" + + ", " + sortField + " as primary_sort, NULL as secondarySort" + " FROM tasks\n" + parentQuery + "\nUNION 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" - + (manualGtasks ? ", google_tasks.gt_order as secondary_sort" : ", NULL as secondary_sort") + + ", recursive_tasks.primary_sort as primary_sort, " + sortField + " as secondary_sort" + " FROM tasks\n" + subtaskQuery + "\nORDER BY sort_indent DESC, "