From 881627065363d2b4ddb598053a2544c200311571 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Thu, 28 May 2020 07:45:10 -0500 Subject: [PATCH] Move canMove/min/max logic into TaskAdapter --- .../astrid/adapter/CaldavTaskAdapter.kt | 51 +------------ .../astrid/adapter/GoogleTaskAdapter.kt | 46 ++---------- .../adapter/GoogleTaskManualSortAdapter.kt | 4 +- .../com/todoroo/astrid/adapter/TaskAdapter.kt | 74 ++++++++++++++++++- .../tasklist/DragAndDropRecyclerAdapter.kt | 19 +++-- 5 files changed, 94 insertions(+), 100 deletions(-) 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 1d6b3c935..bacee6e5b 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt @@ -6,22 +6,6 @@ import org.tasks.data.TaskContainer import org.tasks.date.DateTimeUtils.toAppleEpoch open class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, private val caldavDao: CaldavDao, private val newTasksOnTop: Boolean = false) : 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): Int { - (nextPosition until count).forEach { - if (isHeader(it)) { - return 0 - } - if (!taskIsChild(task, it)) { - return getTask(it).indent - } - } - return 0 - } - override fun supportsParentingOrManualSort() = true override fun moved(from: Int, to: Int, indent: Int) { @@ -42,25 +26,8 @@ open class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, } internal fun changeParent(task: TaskContainer, indent: Int, to: Int): Long { - val previous = if (to > 0) getTask(to - 1) else null - val newParent = when { - indent == 0 || previous == null -> 0 - indent == previous.getIndent() -> previous.parent - indent > previous.getIndent() -> previous.id - else -> { - var 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 - } - newParent - } - } - if (newParent != task.parent) { + val newParent = findParent(indent, to)?.id ?: 0 + if (task.parent != newParent) { changeParent(task, newParent) } return newParent @@ -79,18 +46,4 @@ open class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, caldavDao.update(caldavTask.cd_id, caldavTask.cd_remote_parent) taskDao.save(task.getTask(), null) } - - private fun taskIsChild(source: TaskContainer, destinationIndex: Int): Boolean { - (destinationIndex downTo 0).forEach { - if (isHeader(it)) { - return false - } - 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/GoogleTaskAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskAdapter.kt index 0b891c244..b86b5e283 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskAdapter.kt @@ -3,54 +3,22 @@ package com.todoroo.astrid.adapter import com.todoroo.astrid.dao.TaskDao import org.tasks.BuildConfig import org.tasks.data.GoogleTaskDao -import org.tasks.data.TaskContainer open class GoogleTaskAdapter internal constructor(private val taskDao: TaskDao, private val googleTaskDao: GoogleTaskDao, private val newTasksOnTop: Boolean) : TaskAdapter() { - override fun canMove(source: TaskContainer, from: Int, target: TaskContainer, to: Int): Boolean { - return if (!source.hasChildren() || to <= 0 || to >= count - 1) { - true - } else if (from < to) { - when { - target.hasChildren() -> false - target.hasParent() -> !getTask(to + 1).hasParent() - else -> true - } - } else { - when { - target.hasChildren() -> true - target.hasParent() -> target.parent == source.id && target.secondarySort == 0L - else -> true - } - } - } - - override fun maxIndent(previousPosition: Int, task: TaskContainer) = if (task.hasChildren()) 0 else 1 - - override fun minIndent(nextPosition: Int, task: TaskContainer) = if (task.hasChildren() || !getTask(nextPosition).hasParent()) 0 else 1 - override fun supportsParentingOrManualSort() = true override fun moved(from: Int, to: Int, indent: Int) { val task = getTask(from) val googleTask = task.googleTask - if (indent == 0) { - if (googleTask.indent == 0) { - return - } - googleTaskDao.move( - googleTask, 0, if (newTasksOnTop) 0 else googleTaskDao.getBottom(googleTask.listId, 0)) - } else { - val previous = if (to > 0) getTask(to - 1) else null - val newParent = if (previous!!.hasParent()) previous.parent else previous.id - if (googleTask.parent == newParent) { - return - } - googleTaskDao.move( - googleTask, - newParent, - if (newTasksOnTop) 0 else googleTaskDao.getBottom(googleTask.listId, newParent)) + val newParent = findParent(indent, to)?.id ?: 0 + if (googleTask.parent == newParent) { + return } + googleTaskDao.move( + googleTask, + newParent, + if (newTasksOnTop) 0 else googleTaskDao.getBottom(googleTask.listId, newParent)) taskDao.touch(task.id) if (BuildConfig.DEBUG) { googleTaskDao.validateSorting(task.googleTaskList!!) diff --git a/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskManualSortAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskManualSortAdapter.kt index 302518674..493dc095a 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskManualSortAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/GoogleTaskManualSortAdapter.kt @@ -4,7 +4,9 @@ import com.todoroo.astrid.dao.TaskDao import org.tasks.BuildConfig import org.tasks.data.GoogleTaskDao -class GoogleTaskManualSortAdapter internal constructor(val taskDao: TaskDao, val googleTaskDao: GoogleTaskDao) : GoogleTaskAdapter(taskDao, googleTaskDao, false) { +class GoogleTaskManualSortAdapter internal constructor(val taskDao: TaskDao, val googleTaskDao: GoogleTaskDao) : TaskAdapter() { + + override fun supportsParentingOrManualSort() = true override fun supportsManualSorting() = true diff --git a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt index d2cf4a4f2..b15278858 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.kt @@ -45,11 +45,52 @@ open class TaskAdapter { open fun getIndent(task: TaskContainer): Int = task.getIndent() - open fun canMove(source: TaskContainer, from: Int, target: TaskContainer, to: Int): Boolean = false + open fun canMove(source: TaskContainer, from: Int, target: TaskContainer, to: Int): Boolean { + if (target.isGoogleTask) { + return if (!source.hasChildren() || to <= 0 || to >= count - 1) { + true + } else if (from < to) { + when { + target.hasChildren() -> false + target.hasParent() -> !getTask(to + 1).hasParent() + else -> true + } + } else { + when { + target.hasChildren() -> true + target.hasParent() -> target.parent == source.id && target.secondarySort == 0L + else -> true + } + } + } else { + return !taskIsChild(source, to) + } + } - open fun maxIndent(previousPosition: Int, task: TaskContainer): Int = 0 + open fun maxIndent(previousPosition: Int, task: TaskContainer): Int { + val previous = getTask(previousPosition) + return if (previous.isGoogleTask) { + if (task.hasChildren()) 0 else 1 + } else { + previous.indent + 1 + } + } - open fun minIndent(nextPosition: Int, task: TaskContainer): Int = 0 + fun minIndent(nextPosition: Int, task: TaskContainer): Int { + (nextPosition until count).forEach { + if (isHeader(it)) { + return 0 + } + val next = getTask(it) + if (next.isGoogleTask) { + return if (task.hasChildren() || !next.hasParent()) 0 else 1 + } + if (!taskIsChild(task, it)) { + return next.indent + } + } + return 0 + } fun isSelected(task: TaskContainer): Boolean = selected.contains(task.id) @@ -89,4 +130,31 @@ open class TaskAdapter { open fun onTaskDeleted(task: Task) {} open fun supportsHiddenTasks(): Boolean = true + + private fun taskIsChild(source: TaskContainer, destinationIndex: Int): Boolean { + (destinationIndex downTo 0).forEach { + if (isHeader(it)) { + return false + } + when (getTask(it).parent) { + 0L -> return false + source.parent -> return false + source.id -> return true + } + } + return false + } + + internal fun findParent(indent: Int, to: Int): TaskContainer? { + if (indent == 0 || to == 0) { + return null + } + for (i in to - 1 downTo 0) { + val previous = getTask(i) + if (indent > previous.getIndent()) { + return previous + } + } + return null + } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt b/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt index ba7157a2c..dadf2a56d 100644 --- a/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt +++ b/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt @@ -5,6 +5,8 @@ import android.view.ViewGroup import androidx.core.util.Pair import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.ItemTouchHelper.* +import androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.RecyclerView import com.todoroo.andlib.utility.AndroidUtilities @@ -113,7 +115,7 @@ class DragAndDropRecyclerAdapter( private var to = -1 override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { super.onSelectedChanged(viewHolder, actionState) - if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { + if (actionState == ACTION_STATE_DRAG) { taskList.startActionMode() (viewHolder as TaskViewHolder?)!!.isMoving = true dragging = true @@ -123,12 +125,11 @@ class DragAndDropRecyclerAdapter( } override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int { - return if (adapter.isHeader(viewHolder.adapterPosition)) { - makeMovementFlags(0, 0) - } else if (adapter.supportsParentingOrManualSort() && adapter.numSelected == 0) { - makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT, 0) - } else { - makeMovementFlags(0, 0) + return when { + !dragAndDropEnabled() -> NO_MOVEMENT + adapter.isHeader(viewHolder.adapterPosition) -> NO_MOVEMENT + adapter.numSelected > 0 -> NO_MOVEMENT + else -> ALLOW_DRAGGING } } @@ -177,7 +178,7 @@ class DragAndDropRecyclerAdapter( val vh = viewHolder as TaskViewHolder val task = vh.task val shiftSize = vh.shiftSize - if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { + if (actionState == ACTION_STATE_DRAG) { val currentIndent = viewHolder.indent val maxIndent = vh.maxIndent val minIndent = vh.minIndent @@ -255,6 +256,8 @@ class DragAndDropRecyclerAdapter( companion object { private const val LONG_LIST_SIZE = 500 + private val NO_MOVEMENT = makeMovementFlags(0, 0) + private val ALLOW_DRAGGING = makeMovementFlags(UP or DOWN or LEFT or RIGHT, 0) } init {