Batch save task completions

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

@ -48,7 +48,10 @@ class TaskDao @Inject constructor(
taskDao.getRecurringTasks(remoteIds)
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()) {
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
* success.
*/
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?) {
if (taskDao.update(task, original)) {
val completionDateModified = task.completionDate != original?.completionDate ?: 0
val deletionDateModified = task.deletionDate != original?.deletionDate ?: 0
val justCompleted = completionDateModified && task.isCompleted
val justDeleted = deletionDateModified && task.isDeleted
if (justCompleted && task.isRecurring) {
workManager.scheduleRepeat(task)
} else if (!task.calendarURI.isNullOrBlank()) {
workManager.updateCalendar(task)
}
coroutineScope {
launch(Dispatchers.Default) {
if (justCompleted || justDeleted) {
notificationManager.cancel(task.id)
if (task.timerStart > 0) {
timerPlugin.stopTimer(task)
}
}
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()
afterUpdate(task, original)
}
}
private suspend fun afterUpdate(task: Task, original: Task?) {
val completionDateModified = task.completionDate != original?.completionDate ?: 0
val deletionDateModified = task.deletionDate != original?.deletionDate ?: 0
val justCompleted = completionDateModified && task.isCompleted
val justDeleted = deletionDateModified && task.isDeleted
if (justCompleted && task.isRecurring) {
workManager.scheduleRepeat(task)
} else if (!task.calendarURI.isNullOrBlank()) {
workManager.updateCalendar(task)
}
coroutineScope {
launch(Dispatchers.Default) {
if (justCompleted || justDeleted) {
notificationManager.cancel(task.id)
if (task.timerStart > 0) {
timerPlugin.stopTimer(task)
}
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 }
?: newDueDate - (computeNextDueDate(task, recurrence, repeatAfterCompletion) - newDueDate)
alarmService.rescheduleAlarms(task.id, previousDueDate, newDueDate)
taskCompleter.completeChildren(task.id, 0L)
taskCompleter.setComplete(task, false)
localBroadcastManager.broadcastRepeat(task.id, previousDueDate, newDueDate)
}

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

@ -1,7 +1,12 @@
package org.tasks.data
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 com.todoroo.andlib.sql.Criterion
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")
abstract suspend fun getRecurringTasks(remoteIds: List<String>): List<Task>
@Query("UPDATE tasks SET completed = :completionDate " + "WHERE remoteId = :remoteId")
abstract suspend fun setCompletionDate(remoteId: String, completionDate: Long)
@Query("UPDATE tasks SET completed = :completionDate, modified = :updateTime WHERE remoteId IN (:remoteIds)")
abstract suspend fun setCompletionDate(remoteIds: List<String>, completionDate: Long, updateTime: Long = now())
@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())

Loading…
Cancel
Save