Use coroutines in task completer

pull/1051/head
Alex Baker 4 years ago
parent 1fa17583c0
commit f4ad55b42d

@ -20,7 +20,6 @@ import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -41,10 +40,7 @@ import com.todoroo.astrid.api.*
import com.todoroo.astrid.core.BuiltInFilterExposer import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskCreator import com.todoroo.astrid.service.*
import com.todoroo.astrid.service.TaskDeleter
import com.todoroo.astrid.service.TaskDuplicator
import com.todoroo.astrid.service.TaskMover
import com.todoroo.astrid.timers.TimerPlugin import com.todoroo.astrid.timers.TimerPlugin
import com.todoroo.astrid.utility.Flags import com.todoroo.astrid.utility.Flags
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -111,6 +107,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
@Inject lateinit var colorProvider: ColorProvider @Inject lateinit var colorProvider: ColorProvider
@Inject lateinit var notificationManager: NotificationManager @Inject lateinit var notificationManager: NotificationManager
@Inject lateinit var shortcutManager: ShortcutManager @Inject lateinit var shortcutManager: ShortcutManager
@Inject lateinit var taskCompleter: TaskCompleter
@BindView(R.id.swipe_layout) @BindView(R.id.swipe_layout)
lateinit var swipeRefreshLayout: SwipeRefreshLayout lateinit var swipeRefreshLayout: SwipeRefreshLayout
@ -753,8 +750,11 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
fun clearCollapsed() = taskAdapter.clearCollapsed() fun clearCollapsed() = taskAdapter.clearCollapsed()
override fun onCompletedTask(task: TaskContainer, newState: Boolean) { override fun onCompletedTask(task: TaskContainer, newState: Boolean) {
taskAdapter.onCompletedTask(task, newState) lifecycleScope.launch {
loadTaskListContent() taskCompleter.setComplete(task.getTask(), newState)
taskAdapter.onCompletedTask(task, newState)
loadTaskListContent()
}
} }
override fun onClick(taskViewHolder: TaskViewHolder) { override fun onClick(taskViewHolder: TaskViewHolder) {

@ -11,14 +11,12 @@ 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
import com.todoroo.andlib.sql.Functions import com.todoroo.andlib.sql.Functions
import com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.PermaSql import com.todoroo.astrid.api.PermaSql
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.NO_ID import com.todoroo.astrid.data.Task.Companion.NO_ID
import com.todoroo.astrid.helper.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import kotlinx.coroutines.runBlocking
import org.tasks.BuildConfig import org.tasks.BuildConfig
import org.tasks.data.Place import org.tasks.data.Place
import org.tasks.data.SubtaskInfo import org.tasks.data.SubtaskInfo
@ -42,10 +40,6 @@ abstract class TaskDao(private val database: Database) {
@Query("SELECT * FROM tasks WHERE completed = 0 AND deleted = 0 AND (hideUntil > :now OR dueDate > :now)") @Query("SELECT * FROM tasks WHERE completed = 0 AND deleted = 0 AND (hideUntil > :now OR dueDate > :now)")
internal abstract suspend fun needsRefresh(now: Long = DateUtilities.now()): List<Task> internal abstract suspend fun needsRefresh(now: Long = DateUtilities.now()): List<Task>
suspend fun fetchBlocking(id: Long) = runBlocking {
fetch(id)
}
@Query("SELECT * FROM tasks WHERE _id = :id LIMIT 1") @Query("SELECT * FROM tasks WHERE _id = :id LIMIT 1")
abstract suspend fun fetch(id: Long): Task? abstract suspend fun fetch(id: Long): Task?
@ -218,7 +212,7 @@ SELECT EXISTS(SELECT 1 FROM tasks WHERE parent > 0 AND deleted = 0) AS hasSubtas
* success. * success.
*/ */
suspend fun save(task: Task) = save(task, fetchBlocking(task.id)) suspend fun save(task: Task) = save(task, fetch(task.id))
suspend fun save(task: Task, original: Task?) { suspend fun save(task: Task, original: Task?) {
if (!task.insignificantChange(original)) { if (!task.insignificantChange(original)) {

@ -22,7 +22,7 @@ class TaskDaoBlocking @Inject constructor(private val dao: TaskDao) {
} }
fun fetchBlocking(id: Long) = runBlocking { fun fetchBlocking(id: Long) = runBlocking {
dao.fetchBlocking(id) dao.fetch(id)
} }
fun fetch(id: Long): Task? = runBlocking { fun fetch(id: Long): Task? = runBlocking {

@ -1,31 +1,35 @@
package com.todoroo.astrid.service package com.todoroo.astrid.service
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.dao.TaskDaoBlocking import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import org.tasks.data.GoogleTaskDaoBlocking import kotlinx.coroutines.runBlocking
import org.tasks.data.GoogleTaskDao
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class TaskCompleter @Inject internal constructor( class TaskCompleter @Inject internal constructor(
private val taskDao: TaskDaoBlocking, private val taskDao: TaskDao,
private val googleTaskDao: GoogleTaskDaoBlocking) { private val googleTaskDao: GoogleTaskDao) {
fun setComplete(taskId: Long) = fun setCompleteBlocking(taskId: Long) = runBlocking {
taskDao.fetchBlocking(taskId)?.let { setComplete(it, true) } taskDao.fetch(taskId)?.let { setComplete(it, true) }
?: Timber.e("Could not find task $taskId") ?: Timber.e("Could not find task $taskId")
}
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
setComplete(listOf(item), completionDate) setComplete(listOf(item), completionDate)
val tasks = googleTaskDao.getChildTasks(item.id) val tasks = googleTaskDao.getChildTasks(item.id)
.plus(taskDao.getChildren(item.id).takeIf { it.isNotEmpty() }?.let(taskDao::fetch) .plus(taskDao.getChildren(item.id)
.takeIf { it.isNotEmpty() }
?.let { taskDao.fetch(it) }
?: emptyList()) ?: emptyList())
.filter { it.isCompleted != completed } .filter { it.isCompleted != completed }
setComplete(tasks, completionDate) setComplete(tasks, completionDate)
} }
private fun setComplete(tasks: List<Task>, completionDate: Long) { private suspend fun setComplete(tasks: List<Task>, completionDate: Long) {
tasks.forEachIndexed { i, task -> tasks.forEachIndexed { i, task ->
task.completionDate = completionDate task.completionDate = completionDate
if (i < tasks.size - 1) { if (i < tasks.size - 1) {

@ -23,7 +23,7 @@ public class CompleteTaskReceiver extends InjectingBroadcastReceiver {
long taskId = intent.getLongExtra(TASK_ID, 0); long taskId = intent.getLongExtra(TASK_ID, 0);
Timber.i("Completing %s", taskId); Timber.i("Completing %s", taskId);
Completable.fromAction(() -> taskCompleter.setComplete(taskId)) Completable.fromAction(() -> taskCompleter.setCompleteBlocking(taskId))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe(); .subscribe();
} }

@ -16,7 +16,6 @@ import com.google.android.material.chip.ChipGroup
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.core.SortHelper import com.todoroo.astrid.core.SortHelper
import com.todoroo.astrid.service.TaskCompleter
import com.todoroo.astrid.ui.CheckableImageView import com.todoroo.astrid.ui.CheckableImageView
import org.tasks.R import org.tasks.R
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
@ -39,7 +38,6 @@ class TaskViewHolder internal constructor(
private val checkBoxProvider: CheckBoxProvider, private val checkBoxProvider: CheckBoxProvider,
private val textColorOverdue: Int, private val textColorOverdue: Int,
private val textColorSecondary: Int, private val textColorSecondary: Int,
private val taskCompleter: TaskCompleter,
private val callback: ViewHolderCallbacks, private val callback: ViewHolderCallbacks,
private val metrics: DisplayMetrics, private val metrics: DisplayMetrics,
private val background: Int, private val background: Int,
@ -240,7 +238,6 @@ class TaskViewHolder internal constructor(
fun onCompleteBoxClick() { fun onCompleteBoxClick() {
val newState = completeBox.isChecked val newState = completeBox.isChecked
if (newState != task.isCompleted) { if (newState != task.isCompleted) {
taskCompleter.setComplete(task.getTask(), newState)
callback.onCompletedTask(task, newState) callback.onCompletedTask(task, newState)
} }

@ -6,7 +6,6 @@ import android.util.DisplayMetrics
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.astrid.service.TaskCompleter
import dagger.hilt.android.qualifiers.ActivityContext import dagger.hilt.android.qualifiers.ActivityContext
import org.tasks.R import org.tasks.R
import org.tasks.dialogs.Linkify import org.tasks.dialogs.Linkify
@ -23,7 +22,6 @@ class ViewHolderFactory @Inject constructor(
private val preferences: Preferences, private val preferences: Preferences,
private val chipProvider: ChipProvider, private val chipProvider: ChipProvider,
private val checkBoxProvider: CheckBoxProvider, private val checkBoxProvider: CheckBoxProvider,
private val taskCompleter: TaskCompleter,
private val linkify: Linkify, private val linkify: Linkify,
private val locale: Locale) { private val locale: Locale) {
private val textColorSecondary: Int = ResourceResolver.getData(context, android.R.attr.textColorSecondary) private val textColorSecondary: Int = ResourceResolver.getData(context, android.R.attr.textColorSecondary)
@ -51,7 +49,6 @@ class ViewHolderFactory @Inject constructor(
checkBoxProvider, checkBoxProvider,
textColorOverdue, textColorOverdue,
textColorSecondary, textColorSecondary,
taskCompleter,
callbacks, callbacks,
metrics, metrics,
background, background,

@ -207,7 +207,9 @@ class SubtaskControlSet : TaskEditControlFragment(), SubtaskViewHolder.Callbacks
} }
override fun complete(task: Task, completed: Boolean) { override fun complete(task: Task, completed: Boolean) {
taskCompleter.setComplete(task, completed) lifecycleScope.launch {
taskCompleter.setComplete(task, completed)
}
} }
private inner class RefreshReceiver : BroadcastReceiver() { private inner class RefreshReceiver : BroadcastReceiver() {

@ -34,7 +34,9 @@ class WidgetClickActivity : InjectingAppCompatActivity(), OnDismissHandler {
val task: Task = intent.getParcelableExtra(EXTRA_TASK)!! val task: Task = intent.getParcelableExtra(EXTRA_TASK)!!
when (action) { when (action) {
COMPLETE_TASK -> { COMPLETE_TASK -> {
taskCompleter.setComplete(task, !task.isCompleted) lifecycleScope.launch(NonCancellable) {
taskCompleter.setComplete(task, !task.isCompleted)
}
finish() finish()
} }
EDIT_TASK -> { EDIT_TASK -> {

Loading…
Cancel
Save