Batch undo for completion snackbar

pull/1762/head
Alex Baker 4 years ago
parent 31797e2e9d
commit 7ddc681bf2

@ -12,7 +12,12 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.speech.RecognizerIntent import android.speech.RecognizerIntent
import android.view.* import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
@ -39,22 +44,40 @@ import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.adapter.TaskAdapter import com.todoroo.astrid.adapter.TaskAdapter
import com.todoroo.astrid.adapter.TaskAdapterProvider import com.todoroo.astrid.adapter.TaskAdapterProvider
import com.todoroo.astrid.api.* import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_OLD_DUE_DATE
import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_TASK_ID
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.IdListFilter
import com.todoroo.astrid.api.SearchFilter
import com.todoroo.astrid.api.TagFilter
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.repeats.RepeatTaskHelper import com.todoroo.astrid.repeats.RepeatTaskHelper
import com.todoroo.astrid.service.* import com.todoroo.astrid.service.TaskCompleter
import com.todoroo.astrid.service.TaskCreator
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
import kotlinx.coroutines.* import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.* import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.ShortcutManager import org.tasks.ShortcutManager
import org.tasks.activities.* import org.tasks.activities.FilterSettingsActivity
import org.tasks.activities.GoogleTaskListSettingsActivity
import org.tasks.activities.ListPicker
import org.tasks.activities.ListPicker.Companion.newListPicker import org.tasks.activities.ListPicker.Companion.newListPicker
import org.tasks.activities.PlaceSettingsActivity
import org.tasks.activities.TagSettingsActivity
import org.tasks.analytics.Firebase import org.tasks.analytics.Firebase
import org.tasks.caldav.BaseCaldavCalendarSettingsActivity import org.tasks.caldav.BaseCaldavCalendarSettingsActivity
import org.tasks.data.CaldavDao import org.tasks.data.CaldavDao
@ -76,12 +99,15 @@ import org.tasks.preferences.Device
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.sync.SyncAdapters import org.tasks.sync.SyncAdapters
import org.tasks.tags.TagPickerActivity import org.tasks.tags.TagPickerActivity
import org.tasks.tasklist.* import org.tasks.tasklist.DragAndDropRecyclerAdapter
import org.tasks.tasklist.PagedListRecyclerAdapter
import org.tasks.tasklist.TaskListRecyclerAdapter
import org.tasks.tasklist.TaskViewHolder
import org.tasks.tasklist.ViewHolderFactory
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.ThemeColor import org.tasks.themes.ThemeColor
import org.tasks.ui.TaskListViewModel import org.tasks.ui.TaskListViewModel
import java.time.format.FormatStyle import java.time.format.FormatStyle
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
@ -859,35 +885,46 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
private inner class RepeatConfirmationReceiver : BroadcastReceiver() { private inner class RepeatConfirmationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, 0) lifecycleScope.launch {
if (taskId > 0) { val tasks =
lifecycleScope.launch { (intent.getSerializableExtra(EXTRAS_TASK_ID) as? ArrayList<Long>)
val task = taskDao.fetch(taskId) ?: return@launch ?.let { taskDao.fetch(it) }
try { ?.takeIf { it.isNotEmpty() }
if (task.isRecurring && !task.isCompleted) { ?: return@launch
val oldDueDate = intent.getLongExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, 0) val isRecurringCompletion =
val newDueDate = intent.getLongExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, 0) tasks.size == 1 && tasks.first().let { it.isRecurring && !it.isCompleted }
val dueDateString = DateUtilities.getRelativeDateTime( val oldDueDate = if (isRecurringCompletion) {
context, newDueDate, locale.locale, FormatStyle.LONG, true) intent.getLongExtra(EXTRAS_OLD_DUE_DATE, 0)
makeSnackbar(R.string.repeat_snackbar, task.title, dueDateString) } else {
?.setAction(R.string.DLG_undo) { 0
lifecycleScope.launch(NonCancellable) { }
repeatTaskHelper.undoRepeat(task, oldDueDate, newDueDate) val undoCompletion = View.OnClickListener {
} lifecycleScope.launch {
} tasks
?.show() .partition { it.isRecurring }
} else { .let { (recurring, notRecurring) ->
makeSnackbar(R.string.snackbar_task_completed) recurring.forEach { repeatTaskHelper.undoRepeat(it, oldDueDate) }
?.setAction(R.string.DLG_undo) { taskCompleter.setComplete(notRecurring, 0L)
lifecycleScope.launch(NonCancellable) { }
taskCompleter.setComplete(task, false) }
} }
} if (isRecurringCompletion) {
?.show() val task = tasks.first()
} val text = getString(
} catch (e: Exception) { R.string.repeat_snackbar,
firebase.reportException(e) task.title,
DateUtilities.getRelativeDateTime(
context, task.dueDate, locale.locale, FormatStyle.LONG, true
)
)
makeSnackbar(text)?.setAction(R.string.DLG_undo, undoCompletion)?.show()
} else {
val text = if (tasks.size == 1) {
context.getString(R.string.snackbar_task_completed)
} else {
context.getString(R.string.snackbar_tasks_completed, tasks.size)
} }
makeSnackbar(text)?.setAction(R.string.DLG_undo, undoCompletion)?.show()
} }
} }
} }

@ -22,17 +22,7 @@ class AlarmService @Inject constructor(
private val alarmDao: AlarmDao, private val alarmDao: AlarmDao,
private val jobs: NotificationQueue) { private val jobs: NotificationQueue) {
suspend fun rescheduleAlarms(taskId: Long, oldDueDate: Long, newDueDate: Long) { suspend fun getAlarms(taskId: Long): List<Alarm> = alarmDao.getAlarms(taskId)
if (oldDueDate <= 0 || newDueDate <= 0) {
return
}
getAlarms(taskId)
.takeIf { it.isNotEmpty() }
?.onEach { it.time += newDueDate - oldDueDate }
?.let { synchronizeAlarms(taskId, it.toMutableSet()) }
}
private suspend fun getAlarms(taskId: Long): List<Alarm> = alarmDao.getAlarms(taskId)
/** /**
* Save the given array of alarms into the database * Save the given array of alarms into the database
@ -94,4 +84,4 @@ class AlarmService @Inject constructor(
companion object { companion object {
private const val NO_ALARM = Long.MAX_VALUE private const val NO_ALARM = Long.MAX_VALUE
} }
} }

@ -21,7 +21,4 @@ public class AstridApiConstants {
/** Extras name for old task due date */ /** Extras name for old task due date */
public static final String EXTRAS_OLD_DUE_DATE = "oldDueDate"; public static final String EXTRAS_OLD_DUE_DATE = "oldDueDate";
/** Extras name for new task due date */
public static final String EXTRAS_NEW_DUE_DATE = "newDueDate";
} }

@ -19,7 +19,6 @@ import org.tasks.data.TaskContainer
import org.tasks.data.TaskDao import org.tasks.data.TaskDao
import org.tasks.date.DateTimeUtils.isAfterNow import org.tasks.date.DateTimeUtils.isAfterNow
import org.tasks.db.SuspendDbUtils.eachChunk import org.tasks.db.SuspendDbUtils.eachChunk
import org.tasks.jobs.WorkManager
import org.tasks.location.GeofenceApi import org.tasks.location.GeofenceApi
import org.tasks.notifications.NotificationManager import org.tasks.notifications.NotificationManager
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
@ -28,7 +27,6 @@ import org.tasks.sync.SyncAdapters
import javax.inject.Inject import javax.inject.Inject
class TaskDao @Inject constructor( class TaskDao @Inject constructor(
private val workManager: WorkManager,
private val taskDao: TaskDao, private val taskDao: TaskDao,
private val reminderService: ReminderService, private val reminderService: ReminderService,
private val refreshScheduler: RefreshScheduler, private val refreshScheduler: RefreshScheduler,
@ -100,10 +98,10 @@ class TaskDao @Inject constructor(
*/ */
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) = suspend fun saved(original: Task) =
fetch(original.id)?.let { fetch(original.id)?.let {
afterUpdate( afterUpdate(
it.apply { if (suppressRefresh) suppressRefresh() }, it.apply { if (original.isSuppressRefresh()) suppressRefresh() },
original original
) )
} }
@ -119,11 +117,6 @@ class TaskDao @Inject constructor(
val deletionDateModified = task.deletionDate != original?.deletionDate ?: 0 val deletionDateModified = task.deletionDate != original?.deletionDate ?: 0
val justCompleted = completionDateModified && task.isCompleted val justCompleted = completionDateModified && task.isCompleted
val justDeleted = deletionDateModified && task.isDeleted val justDeleted = deletionDateModified && task.isDeleted
if (justCompleted && task.isRecurring) {
workManager.scheduleRepeat(task)
} else if (!task.calendarURI.isNullOrBlank()) {
workManager.updateCalendar(task)
}
coroutineScope { coroutineScope {
launch(Dispatchers.Default) { launch(Dispatchers.Default) {
if (justCompleted || justDeleted) { if (justCompleted || justDeleted) {
@ -143,13 +136,10 @@ class TaskDao @Inject constructor(
} }
reminderService.scheduleAlarm(task) reminderService.scheduleAlarm(task)
refreshScheduler.scheduleRefresh(task) refreshScheduler.scheduleRefresh(task)
if (!task.checkTransitory(Task.TRANS_SUPPRESS_REFRESH)) { if (!task.isSuppressRefresh()) {
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
} }
syncAdapters.sync(task, original) syncAdapters.sync(task, original)
if (justCompleted && !task.isRecurring) {
localBroadcastManager.broadcastTaskCompleted(task.id, 0L, 0L)
}
} }
} }
} }

@ -370,6 +370,8 @@ class Task : Parcelable {
putTransitory(TRANS_SUPPRESS_REFRESH, true) putTransitory(TRANS_SUPPRESS_REFRESH, true)
} }
fun isSuppressRefresh() = checkTransitory(TRANS_SUPPRESS_REFRESH)
@Synchronized @Synchronized
fun putTransitory(key: String, value: Any) { fun putTransitory(key: String, value: Any) {
if (transitoryData == null) { if (transitoryData == null) {
@ -555,7 +557,7 @@ class Task : Parcelable {
const val URGENCY_NEXT_WEEK = 4 const val URGENCY_NEXT_WEEK = 4
const val URGENCY_IN_TWO_WEEKS = 5 const val URGENCY_IN_TWO_WEEKS = 5
const val TRANS_SUPPRESS_REFRESH = "suppress-refresh" private const val TRANS_SUPPRESS_REFRESH = "suppress-refresh"
private val INVALID_COUNT = ";?COUNT=-1".toRegex() private val INVALID_COUNT = ";?COUNT=-1".toRegex()
@ -620,4 +622,4 @@ class Task : Parcelable {
fun String?.withoutFrom(): String? = this?.replace(";?FROM=[^;]*".toRegex(), "") fun String?.withoutFrom(): String? = this?.replace(";?FROM=[^;]*".toRegex(), "")
} }
} }

@ -44,7 +44,7 @@ class RepeatTaskHelper @Inject constructor(
rrule = initRRule(recurrence) rrule = initRRule(recurrence)
count = rrule.count count = rrule.count
if (count == 1) { if (count == 1) {
localBroadcastManager.broadcastTaskCompleted(task.id, 0, 0) broadcastCompletion(task)
return return
} }
newDueDate = computeNextDueDate(task, recurrence, repeatAfterCompletion) newDueDate = computeNextDueDate(task, recurrence, repeatAfterCompletion)
@ -58,7 +58,7 @@ class RepeatTaskHelper @Inject constructor(
val oldDueDate = task.dueDate val oldDueDate = task.dueDate
val repeatUntil = task.repeatUntil val repeatUntil = task.repeatUntil
if (repeatFinished(newDueDate, repeatUntil)) { if (repeatFinished(newDueDate, repeatUntil)) {
localBroadcastManager.broadcastTaskCompleted(task.id, 0, 0) broadcastCompletion(task)
return return
} }
if (count > 1) { if (count > 1) {
@ -75,13 +75,18 @@ class RepeatTaskHelper @Inject constructor(
oldDueDate oldDueDate
.takeIf { it > 0 } .takeIf { it > 0 }
?: newDueDate - (computeNextDueDate(task, recurrence, repeatAfterCompletion) - newDueDate) ?: newDueDate - (computeNextDueDate(task, recurrence, repeatAfterCompletion) - newDueDate)
alarmService.rescheduleAlarms(task.id, previousDueDate, newDueDate) rescheduleAlarms(task.id, previousDueDate, newDueDate)
taskCompleter.setComplete(task, false) taskCompleter.setComplete(task, false)
localBroadcastManager.broadcastTaskCompleted(task.id, previousDueDate, newDueDate) broadcastCompletion(task, previousDueDate)
} }
suspend fun undoRepeat(task: Task, oldDueDate: Long, newDueDate: Long) { private fun broadcastCompletion(task: Task, oldDueDate: Long = 0L) {
task.setDueDateAdjustingHideUntil(oldDueDate) if (!task.isSuppressRefresh()) {
localBroadcastManager.broadcastTaskCompleted(task.id, oldDueDate)
}
}
suspend fun undoRepeat(task: Task, oldDueDate: Long) {
task.completionDate = 0L task.completionDate = 0L
try { try {
val recur = newRecur(task.recurrence!!) val recur = newRecur(task.recurrence!!)
@ -90,13 +95,31 @@ class RepeatTaskHelper @Inject constructor(
recur.count = count + 1 recur.count = count + 1
} }
task.setRecurrence(recur.toString(), task.repeatAfterCompletion()) task.setRecurrence(recur.toString(), task.repeatAfterCompletion())
val newDueDate = task.dueDate
task.setDueDateAdjustingHideUntil(
if (oldDueDate > 0) {
oldDueDate
} else {
newDueDate - (computeNextDueDate(task, task.recurrence!!, false) - newDueDate)
}
)
rescheduleAlarms(task.id, newDueDate, task.dueDate)
} catch (e: ParseException) { } catch (e: ParseException) {
Timber.e(e) Timber.e(e)
} }
alarmService.rescheduleAlarms(task.id, newDueDate, oldDueDate)
taskDao.save(task) taskDao.save(task)
} }
private suspend fun rescheduleAlarms(taskId: Long, oldDueDate: Long, newDueDate: Long) {
if (oldDueDate <= 0 || newDueDate <= 0) {
return
}
alarmService.getAlarms(taskId)
.takeIf { it.isNotEmpty() }
?.onEach { it.time += newDueDate - oldDueDate }
?.let { alarmService.synchronizeAlarms(taskId, it.toMutableSet()) }
}
companion object { companion object {
private val weekdayCompare = Comparator { object1: WeekDay, object2: WeekDay -> WeekDay.getCalendarDay(object1) - WeekDay.getCalendarDay(object2) } private val weekdayCompare = Comparator { object1: WeekDay, object2: WeekDay -> WeekDay.getCalendarDay(object1) - WeekDay.getCalendarDay(object2) }
private fun repeatFinished(newDueDate: Long, repeatUntil: Long): Boolean { private fun repeatFinished(newDueDate: Long, repeatUntil: Long): Boolean {

@ -8,7 +8,9 @@ import com.todoroo.andlib.utility.DateUtilities
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 dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.LocalBroadcastManager
import org.tasks.data.GoogleTaskDao import org.tasks.data.GoogleTaskDao
import org.tasks.jobs.WorkManager
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -19,6 +21,8 @@ class TaskCompleter @Inject internal constructor(
private val googleTaskDao: GoogleTaskDao, private val googleTaskDao: GoogleTaskDao,
private val preferences: Preferences, private val preferences: Preferences,
private val notificationManager: NotificationManager, private val notificationManager: NotificationManager,
private val localBroadcastManager: LocalBroadcastManager,
private val workManager: WorkManager,
) { ) {
suspend fun setComplete(taskId: Long) = suspend fun setComplete(taskId: Long) =
taskDao taskDao
@ -26,41 +30,50 @@ class TaskCompleter @Inject internal constructor(
?.let { setComplete(it, true) } ?.let { setComplete(it, true) }
?: Timber.e("Could not find task $taskId") ?: Timber.e("Could not find task $taskId")
suspend fun setComplete(item: Task, completed: Boolean) { suspend fun setComplete(item: Task, completed: Boolean, includeChildren: Boolean = true) {
val completionDate = if (completed) DateUtilities.now() else 0L val completionDate = if (completed) DateUtilities.now() else 0L
googleTaskDao ArrayList<Task?>()
.getChildTasks(item.id) .apply {
.let { if (includeChildren) {
if (completed) { addAll(googleTaskDao.getChildTasks(item.id))
it addAll(taskDao.getChildren(item.id).let { taskDao.fetch(it) })
} else { }
it if (!completed) {
.plus(googleTaskDao.getParentTask(item.id)) add(googleTaskDao.getParentTask(item.id))
.plus(taskDao.getParents(item.id).mapNotNull { ids -> taskDao.fetch(ids) }) addAll(taskDao.getParents(item.id).let { taskDao.fetch(it) })
} }
add(item)
} }
.plus(
taskDao.getChildren(item.id)
.takeIf { it.isNotEmpty() }
?.let { taskDao.fetch(it) }
?: emptyList()
)
.plus(listOf(item))
.filterNotNull() .filterNotNull()
.filter { it.isCompleted != completionDate > 0 } .filter { it.isCompleted != completionDate > 0 }
.let { setComplete(it, completionDate) } .let {
setComplete(it, completionDate)
if (completed && !item.isRecurring) {
localBroadcastManager.broadcastTaskCompleted(ArrayList(it.map(Task::id)))
}
}
} }
private suspend fun setComplete(tasks: List<Task>, completionDate: Long) { suspend fun setComplete(tasks: List<Task>, completionDate: Long) {
if (tasks.isEmpty()) {
return
}
val completed = completionDate > 0
taskDao.setCompletionDate(tasks.mapNotNull { it.remoteId }, completionDate) taskDao.setCompletionDate(tasks.mapNotNull { it.remoteId }, completionDate)
tasks.forEachIndexed { i, task -> tasks.forEachIndexed { i, original ->
taskDao.saved(task, i < tasks.size - 1) if (i < tasks.size - 1) {
original.suppressRefresh()
}
taskDao.saved(original)
}
tasks.forEach {
if (completed && it.isRecurring) {
workManager.scheduleRepeat(it)
} else if (!it.calendarURI.isNullOrBlank()) {
workManager.updateCalendar(it)
}
} }
if ( if (completed && notificationManager.currentInterruptionFilter == INTERRUPTION_FILTER_ALL) {
tasks.isNotEmpty() &&
completionDate > 0 &&
notificationManager.currentInterruptionFilter == INTERRUPTION_FILTER_ALL
) {
preferences preferences
.completionSound .completionSound
?.takeUnless { preferences.isCurrentlyQuietHours } ?.takeUnless { preferences.isCurrentlyQuietHours }

@ -1,14 +1,22 @@
package org.tasks; package org.tasks;
import static com.google.common.collect.Lists.newArrayList;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import dagger.hilt.android.qualifiers.ApplicationContext;
import javax.inject.Inject;
import org.tasks.widget.AppWidgetManager; import org.tasks.widget.AppWidgetManager;
import java.util.ArrayList;
import javax.inject.Inject;
import dagger.hilt.android.qualifiers.ApplicationContext;
public class LocalBroadcastManager { public class LocalBroadcastManager {
public static final String REFRESH = BuildConfig.APPLICATION_ID + ".REFRESH"; public static final String REFRESH = BuildConfig.APPLICATION_ID + ".REFRESH";
@ -63,11 +71,18 @@ public class LocalBroadcastManager {
localBroadcastManager.sendBroadcast(new Intent(REFRESH_PREFERENCES)); localBroadcastManager.sendBroadcast(new Intent(REFRESH_PREFERENCES));
} }
public void broadcastTaskCompleted(long id, long oldDueDate, long newDueDate) { public void broadcastTaskCompleted(long id, long oldDueDate) {
broadcastTaskCompleted(newArrayList(id), oldDueDate);
}
public void broadcastTaskCompleted(ArrayList<Long> id) {
broadcastTaskCompleted(id, 0);
}
private void broadcastTaskCompleted(ArrayList<Long> id, long oldDueDate) {
Intent intent = new Intent(TASK_COMPLETED); Intent intent = new Intent(TASK_COMPLETED);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, id); intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, id);
intent.putExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, oldDueDate); intent.putExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, oldDueDate);
intent.putExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, newDueDate);
localBroadcastManager.sendBroadcast(intent); localBroadcastManager.sendBroadcast(intent);
} }

@ -26,7 +26,9 @@ class AfterSaveWork @AssistedInject constructor(
override suspend fun run(): Result { override suspend fun run(): Result {
val taskId = inputData.getLong(EXTRA_ID, -1) val taskId = inputData.getLong(EXTRA_ID, -1)
val task = taskDao.fetch(taskId) ?: return Result.failure() val task = taskDao.fetch(taskId) ?: return Result.failure()
if (inputData.getBoolean(EXTRA_SUPPRESS_COMPLETION_SNACKBAR, false)) {
task.suppressRefresh()
}
gCalHelper.updateEvent(task) gCalHelper.updateEvent(task)
if (caldavDao.getAccountForTask(taskId)?.isSuppressRepeatingTasks != true) { if (caldavDao.getAccountForTask(taskId)?.isSuppressRepeatingTasks != true) {
@ -37,5 +39,6 @@ class AfterSaveWork @AssistedInject constructor(
companion object { companion object {
const val EXTRA_ID = "extra_id" const val EXTRA_ID = "extra_id"
const val EXTRA_SUPPRESS_COMPLETION_SNACKBAR = "extra_suppress_snackbar"
} }
} }

@ -6,9 +6,18 @@ import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import androidx.work.* import androidx.work.Constraints
import androidx.work.Data
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.ExistingWorkPolicy.APPEND_OR_REPLACE import androidx.work.ExistingWorkPolicy.APPEND_OR_REPLACE
import androidx.work.ExistingWorkPolicy.REPLACE import androidx.work.ExistingWorkPolicy.REPLACE
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequest
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkContinuation
import androidx.work.WorkInfo
import androidx.work.WorkRequest
import androidx.work.Worker
import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
@ -16,11 +25,15 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.tasks.BuildConfig import org.tasks.BuildConfig
import org.tasks.R import org.tasks.R
import org.tasks.data.* import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV
import org.tasks.data.CaldavAccount.Companion.TYPE_ETEBASE import org.tasks.data.CaldavAccount.Companion.TYPE_ETEBASE
import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS
import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskListDao
import org.tasks.data.OpenTaskDao
import org.tasks.data.Place
import org.tasks.date.DateTimeUtils.midnight import org.tasks.date.DateTimeUtils.midnight
import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.jobs.MigrateLocalWork.Companion.EXTRA_ACCOUNT import org.tasks.jobs.MigrateLocalWork.Companion.EXTRA_ACCOUNT
@ -66,6 +79,10 @@ class WorkManagerImpl constructor(
OneTimeWorkRequest.Builder(AfterSaveWork::class.java) OneTimeWorkRequest.Builder(AfterSaveWork::class.java)
.setInputData(Data.Builder() .setInputData(Data.Builder()
.putLong(AfterSaveWork.EXTRA_ID, task.id) .putLong(AfterSaveWork.EXTRA_ID, task.id)
.putBoolean(
AfterSaveWork.EXTRA_SUPPRESS_COMPLETION_SNACKBAR,
task.isSuppressRefresh()
)
.build())) .build()))
} }

@ -714,4 +714,5 @@ File %1$s contained %2$s.\n\n
<string name="completed">Completed</string> <string name="completed">Completed</string>
<string name="snackbar_task_completed">Task completed</string> <string name="snackbar_task_completed">Task completed</string>
<string name="completed_tasks_at_bottom">Move completed tasks to bottom</string> <string name="completed_tasks_at_bottom">Move completed tasks to bottom</string>
<string name="snackbar_tasks_completed">%d tasks completed</string>
</resources> </resources>

Loading…
Cancel
Save