Batch save task completions

pull/1718/head
Alex Baker 4 years ago
parent 21db56c4e9
commit 4ea948e3f3

@ -48,7 +48,10 @@ class TaskDao @Inject constructor(
taskDao.getRecurringTasks(remoteIds) taskDao.getRecurringTasks(remoteIds)
suspend fun setCompletionDate(remoteId: String, completionDate: Long) = suspend fun setCompletionDate(remoteId: String, completionDate: Long) =
taskDao.setCompletionDate(remoteId, completionDate) setCompletionDate(listOf(remoteId), completionDate)
suspend fun setCompletionDate(remoteIds: List<String>, completionDate: Long) =
taskDao.setCompletionDate(remoteIds, completionDate)
suspend fun snooze(taskIds: List<Long>, snoozeTime: Long, updateTime: Long = now()) { suspend fun snooze(taskIds: List<Long>, snoozeTime: Long, updateTime: Long = now()) {
taskDao.snooze(taskIds, snoozeTime, updateTime) taskDao.snooze(taskIds, snoozeTime, updateTime)
@ -93,44 +96,55 @@ class TaskDao @Inject constructor(
* Saves the given task to the database.getDatabase(). Task must already exist. Returns true on * Saves the given task to the database.getDatabase(). Task must already exist. Returns true on
* success. * success.
*/ */
suspend fun save(task: Task) = save(task, fetch(task.id)) suspend fun save(task: Task) = save(task, fetch(task.id))
suspend fun saved(original: Task, suppressRefresh: Boolean) =
fetch(original.id)?.let {
afterUpdate(
it.apply { if (suppressRefresh) suppressRefresh() },
original
)
}
suspend fun save(task: Task, original: Task?) { suspend fun save(task: Task, original: Task?) {
if (taskDao.update(task, original)) { if (taskDao.update(task, original)) {
val completionDateModified = task.completionDate != original?.completionDate ?: 0 afterUpdate(task, original)
val deletionDateModified = task.deletionDate != original?.deletionDate ?: 0 }
val justCompleted = completionDateModified && task.isCompleted }
val justDeleted = deletionDateModified && task.isDeleted
if (justCompleted && task.isRecurring) { private suspend fun afterUpdate(task: Task, original: Task?) {
workManager.scheduleRepeat(task) val completionDateModified = task.completionDate != original?.completionDate ?: 0
} else if (!task.calendarURI.isNullOrBlank()) { val deletionDateModified = task.deletionDate != original?.deletionDate ?: 0
workManager.updateCalendar(task) val justCompleted = completionDateModified && task.isCompleted
} val justDeleted = deletionDateModified && task.isDeleted
coroutineScope { if (justCompleted && task.isRecurring) {
launch(Dispatchers.Default) { workManager.scheduleRepeat(task)
if (justCompleted || justDeleted) { } else if (!task.calendarURI.isNullOrBlank()) {
notificationManager.cancel(task.id) workManager.updateCalendar(task)
if (task.timerStart > 0) { }
timerPlugin.stopTimer(task) coroutineScope {
} launch(Dispatchers.Default) {
} if (justCompleted || justDeleted) {
if (task.reminderSnooze.isAfterNow()) { notificationManager.cancel(task.id)
notificationManager.cancel(task.id) if (task.timerStart > 0) {
} timerPlugin.stopTimer(task)
if (task.dueDate != original?.dueDate && task.dueDate.isAfterNow()) {
notificationManager.cancel(task.id)
}
if (completionDateModified || deletionDateModified) {
geofenceApi.update(task.id)
}
reminderService.scheduleAlarm(task)
refreshScheduler.scheduleRefresh(task)
if (!task.checkTransitory(Task.TRANS_SUPPRESS_REFRESH)) {
localBroadcastManager.broadcastRefresh()
} }
syncAdapters.sync(task, original)
} }
if (task.reminderSnooze.isAfterNow()) {
notificationManager.cancel(task.id)
}
if (task.dueDate != original?.dueDate && task.dueDate.isAfterNow()) {
notificationManager.cancel(task.id)
}
if (completionDateModified || deletionDateModified) {
geofenceApi.update(task.id)
}
reminderService.scheduleAlarm(task)
refreshScheduler.scheduleRefresh(task)
if (!task.checkTransitory(Task.TRANS_SUPPRESS_REFRESH)) {
localBroadcastManager.broadcastRefresh()
}
syncAdapters.sync(task, original)
} }
} }
} }

@ -73,7 +73,7 @@ class RepeatTaskHelper @Inject constructor(
.takeIf { it > 0 } .takeIf { it > 0 }
?: newDueDate - (computeNextDueDate(task, recurrence, repeatAfterCompletion) - newDueDate) ?: newDueDate - (computeNextDueDate(task, recurrence, repeatAfterCompletion) - newDueDate)
alarmService.rescheduleAlarms(task.id, previousDueDate, newDueDate) alarmService.rescheduleAlarms(task.id, previousDueDate, newDueDate)
taskCompleter.completeChildren(task.id, 0L) taskCompleter.setComplete(task, false)
localBroadcastManager.broadcastRepeat(task.id, previousDueDate, newDueDate) localBroadcastManager.broadcastRepeat(task.id, previousDueDate, newDueDate)
} }

@ -28,32 +28,25 @@ class TaskCompleter @Inject internal constructor(
suspend fun setComplete(item: Task, completed: Boolean) { suspend fun setComplete(item: Task, completed: Boolean) {
val completionDate = if (completed) DateUtilities.now() else 0L val completionDate = if (completed) DateUtilities.now() else 0L
completeChildren(item.id, completionDate)
setComplete(listOf(item), completionDate)
}
suspend fun completeChildren(id: Long, completionDate: Long) {
googleTaskDao googleTaskDao
.getChildTasks(id) .getChildTasks(item.id)
.plus(taskDao.getChildren(id) .plus(taskDao.getChildren(item.id)
.takeIf { it.isNotEmpty() } .takeIf { it.isNotEmpty() }
?.let { taskDao.fetch(it) } ?.let { taskDao.fetch(it) }
?: emptyList() ?: emptyList()
) )
.filter { it.isCompleted != completionDate > 0 } .plus(listOf(item))
.let { setComplete(it, completionDate)} .filter { it.isCompleted != completionDate > 0 }
.let { setComplete(it, completionDate) }
} }
private suspend fun setComplete(tasks: List<Task>, completionDate: Long) { private suspend fun setComplete(tasks: List<Task>, completionDate: Long) {
taskDao.setCompletionDate(tasks.mapNotNull { it.remoteId }, completionDate)
tasks.forEachIndexed { i, task -> tasks.forEachIndexed { i, task ->
task.completionDate = completionDate taskDao.saved(task, i < tasks.size - 1)
if (i < tasks.size - 1) {
task.suppressRefresh()
}
taskDao.save(task)
} }
if ( if (
tasks.size == 1 && tasks.isNotEmpty() &&
completionDate > 0 && completionDate > 0 &&
notificationManager.currentInterruptionFilter == INTERRUPTION_FILTER_ALL notificationManager.currentInterruptionFilter == INTERRUPTION_FILTER_ALL
) { ) {

@ -1,7 +1,12 @@
package org.tasks.data package org.tasks.data
import androidx.paging.DataSource import androidx.paging.DataSource
import androidx.room.* import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Update
import androidx.room.withTransaction
import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SimpleSQLiteQuery
import com.todoroo.andlib.sql.Criterion import com.todoroo.andlib.sql.Criterion
import com.todoroo.andlib.sql.Field import com.todoroo.andlib.sql.Field
@ -50,8 +55,8 @@ abstract class TaskDao(private val database: Database) {
+ "AND recurrence IS NOT NULL AND LENGTH(recurrence) > 0") + "AND recurrence IS NOT NULL AND LENGTH(recurrence) > 0")
abstract suspend fun getRecurringTasks(remoteIds: List<String>): List<Task> abstract suspend fun getRecurringTasks(remoteIds: List<String>): List<Task>
@Query("UPDATE tasks SET completed = :completionDate " + "WHERE remoteId = :remoteId") @Query("UPDATE tasks SET completed = :completionDate, modified = :updateTime WHERE remoteId IN (:remoteIds)")
abstract suspend fun setCompletionDate(remoteId: String, completionDate: Long) abstract suspend fun setCompletionDate(remoteIds: List<String>, completionDate: Long, updateTime: Long = now())
@Query("UPDATE tasks SET snoozeTime = :snoozeTime, modified = :updateTime WHERE _id in (:taskIds)") @Query("UPDATE tasks SET snoozeTime = :snoozeTime, modified = :updateTime WHERE _id in (:taskIds)")
internal abstract suspend fun snooze(taskIds: List<Long>, snoozeTime: Long, updateTime: Long = now()) internal abstract suspend fun snooze(taskIds: List<Long>, snoozeTime: Long, updateTime: Long = now())

Loading…
Cancel
Save