diff --git a/app/src/main/java/org/tasks/Tasks.kt b/app/src/main/java/org/tasks/Tasks.kt index 243e45740..8e9afdb65 100644 --- a/app/src/main/java/org/tasks/Tasks.kt +++ b/app/src/main/java/org/tasks/Tasks.kt @@ -53,7 +53,6 @@ class Tasks : Application(), Configuration.Provider { buildSetup.setup() upgrade() preferences.isSyncOngoing = false - preferences.setBoolean(R.string.p_sync_ongoing_opentasks, false) ThemeBase.getThemeBase(preferences, inventory, null).setDefaultNightMode() localBroadcastManager.registerRefreshReceiver(RefreshBroadcastReceiver()) backgroundWork() diff --git a/app/src/main/java/org/tasks/data/CaldavDao.kt b/app/src/main/java/org/tasks/data/CaldavDao.kt index d904ccf41..c84ce9144 100644 --- a/app/src/main/java/org/tasks/data/CaldavDao.kt +++ b/app/src/main/java/org/tasks/data/CaldavDao.kt @@ -2,12 +2,7 @@ package org.tasks.data import android.content.Context import androidx.lifecycle.LiveData -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.Query -import androidx.room.Transaction -import androidx.room.Update +import androidx.room.* import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.astrid.api.FilterListItem.NO_ORDER import com.todoroo.astrid.core.SortHelper.APPLE_EPOCH @@ -176,9 +171,9 @@ SELECT EXISTS(SELECT 1 INNER JOIN caldav_lists ON cdl_uuid = cd_calendar INNER JOIN caldav_accounts ON cda_uuid = cdl_account WHERE cd_task = :id - AND cda_account_type = :type) + AND cda_account_type IN (:types)) """) - abstract suspend fun isAccountType(id: Long, type: Int): Boolean + abstract suspend fun isAccountType(id: Long, types: List): Boolean suspend fun getTasks(taskIds: List): List = taskIds.chunkedMap { getTasksInternal(it) } diff --git a/app/src/main/java/org/tasks/jobs/SyncCaldavWork.kt b/app/src/main/java/org/tasks/jobs/SyncCaldavWork.kt deleted file mode 100644 index 6d21cdd67..000000000 --- a/app/src/main/java/org/tasks/jobs/SyncCaldavWork.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.tasks.jobs - -import android.content.Context -import androidx.hilt.work.HiltWorker -import androidx.work.WorkerParameters -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import kotlinx.coroutines.* -import org.tasks.LocalBroadcastManager -import org.tasks.R -import org.tasks.analytics.Firebase -import org.tasks.billing.Inventory -import org.tasks.caldav.CaldavSynchronizer -import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV -import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS -import org.tasks.data.CaldavDao -import org.tasks.preferences.Preferences - -@HiltWorker -class SyncCaldavWork @AssistedInject constructor( - @Assisted context: Context, - @Assisted workerParams: WorkerParameters, - firebase: Firebase, - localBroadcastManager: LocalBroadcastManager, - preferences: Preferences, - private val caldavDao: CaldavDao, - private val caldavSynchronizer: CaldavSynchronizer, - private val inventory: Inventory -) : SyncWork(context, workerParams, firebase, localBroadcastManager, preferences) { - - override suspend fun enabled() = getAccounts().isNotEmpty() - - override val syncStatus = R.string.p_sync_ongoing_caldav - - override suspend fun doSync() { - caldavJobs().awaitAll() - inventory.updateTasksAccount() - } - - private suspend fun caldavJobs(): List> = coroutineScope { - getAccounts().map { - async(Dispatchers.IO) { - caldavSynchronizer.sync(it) - } - } - } - - private suspend fun getAccounts() = - caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS) -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/jobs/SyncEtebaseWork.kt b/app/src/main/java/org/tasks/jobs/SyncEtebaseWork.kt deleted file mode 100644 index 8161c80d5..000000000 --- a/app/src/main/java/org/tasks/jobs/SyncEtebaseWork.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.tasks.jobs - -import android.content.Context -import androidx.hilt.work.HiltWorker -import androidx.work.WorkerParameters -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import kotlinx.coroutines.* -import org.tasks.LocalBroadcastManager -import org.tasks.R -import org.tasks.analytics.Firebase -import org.tasks.data.CaldavAccount.Companion.TYPE_ETEBASE -import org.tasks.data.CaldavDao -import org.tasks.etebase.EtebaseSynchronizer -import org.tasks.preferences.Preferences - -@HiltWorker -class SyncEtebaseWork @AssistedInject constructor( - @Assisted context: Context, - @Assisted workerParams: WorkerParameters, - firebase: Firebase, - localBroadcastManager: LocalBroadcastManager, - preferences: Preferences, - private val caldavDao: CaldavDao, - private val synchronizer: EtebaseSynchronizer -) : SyncWork(context, workerParams, firebase, localBroadcastManager, preferences) { - - override suspend fun enabled() = caldavDao.getAccounts(TYPE_ETEBASE).isNotEmpty() - - override val syncStatus = R.string.p_sync_ongoing_etebase - - override suspend fun doSync() { - jobs().awaitAll() - } - - private suspend fun jobs(): List> = coroutineScope { - caldavDao.getAccounts(TYPE_ETEBASE) - .map { - async(Dispatchers.IO) { - synchronizer.sync(it) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/jobs/SyncGoogleTasksWork.kt b/app/src/main/java/org/tasks/jobs/SyncGoogleTasksWork.kt deleted file mode 100644 index be4176745..000000000 --- a/app/src/main/java/org/tasks/jobs/SyncGoogleTasksWork.kt +++ /dev/null @@ -1,47 +0,0 @@ -package org.tasks.jobs - -import android.content.Context -import androidx.hilt.work.HiltWorker -import androidx.work.WorkerParameters -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import kotlinx.coroutines.* -import org.tasks.LocalBroadcastManager -import org.tasks.R -import org.tasks.analytics.Firebase -import org.tasks.data.GoogleTaskListDao -import org.tasks.gtasks.GoogleTaskSynchronizer -import org.tasks.preferences.Preferences - -@HiltWorker -class SyncGoogleTasksWork @AssistedInject constructor( - @Assisted context: Context, - @Assisted workerParams: WorkerParameters, - firebase: Firebase, - localBroadcastManager: LocalBroadcastManager, - private val preferences: Preferences, - private val googleTaskListDao: GoogleTaskListDao, - private val googleTaskSynchronizer: GoogleTaskSynchronizer -) : SyncWork(context, workerParams, firebase, localBroadcastManager, preferences) { - - override suspend fun enabled() = googleTaskListDao.getAccounts().isNotEmpty() - - override val syncStatus = R.string.p_sync_ongoing_google_tasks - - override suspend fun doSync() { - if (preferences.isManualSort) { - preferences.isPositionHackEnabled = true - } - googleTaskJobs().awaitAll() - } - - private suspend fun googleTaskJobs(): List> = coroutineScope { - googleTaskListDao - .getAccounts() - .mapIndexed { i, account -> - async(Dispatchers.IO) { - googleTaskSynchronizer.sync(account, i) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt b/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt deleted file mode 100644 index 9a6f68a3b..000000000 --- a/app/src/main/java/org/tasks/jobs/SyncOpenTasksWork.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.tasks.jobs - -import android.accounts.AccountManager -import android.content.ContentResolver -import android.content.Context -import android.os.Bundle -import androidx.hilt.work.HiltWorker -import androidx.work.WorkerParameters -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import org.tasks.LocalBroadcastManager -import org.tasks.R -import org.tasks.analytics.Firebase -import org.tasks.data.OpenTaskDao -import org.tasks.data.OpenTaskDao.Companion.SUPPORTED_TYPES -import org.tasks.opentasks.OpenTasksSynchronizer -import org.tasks.preferences.Preferences - -@HiltWorker -class SyncOpenTasksWork @AssistedInject constructor( - @Assisted context: Context, - @Assisted workerParams: WorkerParameters, - firebase: Firebase, - localBroadcastManager: LocalBroadcastManager, - preferences: Preferences, - private val openTasksSynchronizer: OpenTasksSynchronizer, - private val openTaskDao: OpenTaskDao -) : SyncWork(context, workerParams, firebase, localBroadcastManager, preferences) { - override val syncStatus = R.string.p_sync_ongoing_opentasks - - override suspend fun enabled() = openTaskDao.shouldSync() - - override suspend fun doSync() { - openTasksSynchronizer.sync() - - if (isImmediate) { - AccountManager - .get(context) - .accounts - .filter { SUPPORTED_TYPES.contains(it.type) } - .forEach { - ContentResolver.requestSync( - it, - openTaskDao.authority, - Bundle().apply { - putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true) - putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true) - } - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/jobs/SyncWork.kt b/app/src/main/java/org/tasks/jobs/SyncWork.kt index 1b0d0706f..3c9c30169 100644 --- a/app/src/main/java/org/tasks/jobs/SyncWork.kt +++ b/app/src/main/java/org/tasks/jobs/SyncWork.kt @@ -1,30 +1,56 @@ package org.tasks.jobs +import android.accounts.AccountManager +import android.content.ContentResolver import android.content.Context import android.net.ConnectivityManager -import androidx.core.content.ContextCompat.getSystemService -import androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.core.net.ConnectivityManagerCompat +import androidx.hilt.work.HiltWorker import androidx.work.WorkerParameters +import dagger.Lazy +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import kotlinx.coroutines.* import org.tasks.LocalBroadcastManager +import org.tasks.R import org.tasks.analytics.Firebase +import org.tasks.billing.Inventory +import org.tasks.caldav.CaldavSynchronizer +import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV +import org.tasks.data.CaldavAccount.Companion.TYPE_ETEBASE +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.etebase.EtebaseSynchronizer +import org.tasks.gtasks.GoogleTaskSynchronizer import org.tasks.injection.BaseWorker +import org.tasks.opentasks.OpenTasksSynchronizer import org.tasks.preferences.Preferences -abstract class SyncWork constructor( - context: Context, - workerParams: WorkerParameters, - firebase: Firebase, - private val localBroadcastManager: LocalBroadcastManager, - private val preferences: Preferences +@HiltWorker +class SyncWork @AssistedInject constructor( + @Assisted context: Context, + @Assisted workerParams: WorkerParameters, + firebase: Firebase, + private val localBroadcastManager: LocalBroadcastManager, + private val preferences: Preferences, + private val caldavDao: CaldavDao, + private val caldavSynchronizer: Lazy, + private val etebaseSynchronizer: Lazy, + private val googleTaskSynchronizer: Lazy, + private val openTasksSynchronizer: Lazy, + private val googleTaskListDao: GoogleTaskListDao, + private val openTaskDao: OpenTaskDao, + private val inventory: Inventory ) : BaseWorker(context, workerParams, firebase) { - final override suspend fun run(): Result { - if (!enabled()) { - return Result.failure() - } + override suspend fun run(): Result { if (isBackground) { - getSystemService(context, ConnectivityManager::class.java)?.apply { - if (restrictBackgroundStatus == RESTRICT_BACKGROUND_STATUS_ENABLED) { + ContextCompat.getSystemService(context, ConnectivityManager::class.java)?.apply { + if (restrictBackgroundStatus == ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED) { return Result.failure() } } @@ -48,17 +74,68 @@ abstract class SyncWork constructor( return Result.success() } - val isImmediate: Boolean + private val isImmediate: Boolean get() = inputData.getBoolean(EXTRA_IMMEDIATE, false) private val isBackground: Boolean get() = inputData.getBoolean(EXTRA_BACKGROUND, false) - protected abstract val syncStatus: Int + private val syncStatus = R.string.p_sync_ongoing + + private suspend fun doSync() { + if (preferences.isManualSort) { + preferences.isPositionHackEnabled = true + } + googleTaskJobs().plus(caldavJobs()).awaitAll() + inventory.updateTasksAccount() + if (openTaskDao.shouldSync()) { + openTasksSynchronizer.get().sync() + + if (isImmediate) { + AccountManager + .get(context) + .accounts + .filter { OpenTaskDao.SUPPORTED_TYPES.contains(it.type) } + .forEach { + ContentResolver.requestSync( + it, + openTaskDao.authority, + Bundle().apply { + putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true) + putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true) + } + ) + } + } + } + } + + private suspend fun googleTaskJobs(): List> = coroutineScope { + getGoogleAccounts() + .mapIndexed { i, account -> + async(Dispatchers.IO) { + googleTaskSynchronizer.get().sync(account, i) + } + } + } + + private suspend fun caldavJobs(): List> = coroutineScope { + getCaldavAccounts().map { + async(Dispatchers.IO) { + when (it.accountType) { + TYPE_ETEBASE -> etebaseSynchronizer.get().sync(it) + TYPE_TASKS, + TYPE_CALDAV -> caldavSynchronizer.get().sync(it) + } + } + } + } - protected abstract suspend fun enabled(): Boolean + private suspend fun getGoogleAccounts() = + googleTaskListDao.getAccounts() - protected abstract suspend fun doSync() + private suspend fun getCaldavAccounts() = + caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS, TYPE_ETEBASE) companion object { private val LOCK = Any() diff --git a/app/src/main/java/org/tasks/jobs/WorkManager.kt b/app/src/main/java/org/tasks/jobs/WorkManager.kt index 4dee4dd79..79ce4084b 100644 --- a/app/src/main/java/org/tasks/jobs/WorkManager.kt +++ b/app/src/main/java/org/tasks/jobs/WorkManager.kt @@ -16,13 +16,7 @@ interface WorkManager { fun migrateLocalTasks(caldavAccount: CaldavAccount) - suspend fun googleTaskSync(immediate: Boolean) - - suspend fun caldavSync(immediate: Boolean) - - suspend fun eteBaseSync(immediate: Boolean) - - suspend fun openTaskSync(immediate: Boolean) + suspend fun sync(immediate: Boolean) fun reverseGeocode(place: Place) @@ -50,14 +44,8 @@ interface WorkManager { const val TAG_BACKUP = "tag_backup" const val TAG_REFRESH = "tag_refresh" const val TAG_MIDNIGHT_REFRESH = "tag_midnight_refresh" - const val TAG_SYNC_GOOGLE_TASKS = "tag_sync_google_tasks" - const val TAG_SYNC_CALDAV = "tag_sync_caldav" - const val TAG_SYNC_ETEBASE = "tag_sync_etebase" - const val TAG_SYNC_OPENTASK = "tag_sync_opentask" - const val TAG_BACKGROUND_SYNC_GOOGLE_TASKS = "tag_background_sync_google_tasks" - const val TAG_BACKGROUND_SYNC_CALDAV = "tag_background_sync_caldav" - const val TAG_BACKGROUND_SYNC_ETEBASE = "tag_background_sync_etebase" - const val TAG_BACKGROUND_SYNC_OPENTASKS = "tag_background_sync_opentasks" + const val TAG_SYNC = "tag_sync" + const val TAG_BACKGROUND_SYNC = "tag_background_sync" const val TAG_REMOTE_CONFIG = "tag_remote_config" const val TAG_MIGRATE_LOCAL = "tag_migrate_local" const val TAG_UPDATE_PURCHASES = "tag_update_purchases" diff --git a/app/src/main/java/org/tasks/jobs/WorkManagerImpl.kt b/app/src/main/java/org/tasks/jobs/WorkManagerImpl.kt index 5212e9c20..87e22ca1b 100644 --- a/app/src/main/java/org/tasks/jobs/WorkManagerImpl.kt +++ b/app/src/main/java/org/tasks/jobs/WorkManagerImpl.kt @@ -6,18 +6,9 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.net.Uri -import androidx.work.Constraints -import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.* import androidx.work.ExistingWorkPolicy.APPEND_OR_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 androidx.work.workDataOf import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.DateUtilities import com.todoroo.astrid.data.Task @@ -25,14 +16,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.tasks.BuildConfig import org.tasks.R -import org.tasks.data.CaldavAccount +import org.tasks.data.* import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV import org.tasks.data.CaldavAccount.Companion.TYPE_ETEBASE 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.newDateTime import org.tasks.jobs.DriveUploader.Companion.EXTRA_PURGE @@ -42,19 +29,13 @@ import org.tasks.jobs.SyncWork.Companion.EXTRA_BACKGROUND import org.tasks.jobs.SyncWork.Companion.EXTRA_IMMEDIATE import org.tasks.jobs.WorkManager.Companion.MAX_CLEANUP_LENGTH import org.tasks.jobs.WorkManager.Companion.REMOTE_CONFIG_INTERVAL_HOURS -import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC_CALDAV -import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC_ETEBASE -import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC_GOOGLE_TASKS -import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC_OPENTASKS +import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC import org.tasks.jobs.WorkManager.Companion.TAG_BACKUP import org.tasks.jobs.WorkManager.Companion.TAG_MIDNIGHT_REFRESH import org.tasks.jobs.WorkManager.Companion.TAG_MIGRATE_LOCAL import org.tasks.jobs.WorkManager.Companion.TAG_REFRESH import org.tasks.jobs.WorkManager.Companion.TAG_REMOTE_CONFIG -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_CALDAV -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_ETEBASE -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_GOOGLE_TASKS -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_OPENTASK +import org.tasks.jobs.WorkManager.Companion.TAG_SYNC import org.tasks.jobs.WorkManager.Companion.TAG_UPDATE_PURCHASES import org.tasks.notifications.Throttle import org.tasks.preferences.Preferences @@ -109,36 +90,21 @@ class WorkManagerImpl constructor( } } - override suspend fun googleTaskSync(immediate: Boolean) = - sync(immediate, TAG_SYNC_GOOGLE_TASKS, SyncGoogleTasksWork::class.java) - - override suspend fun caldavSync(immediate: Boolean) = - sync(immediate, TAG_SYNC_CALDAV, SyncCaldavWork::class.java) - - override suspend fun eteBaseSync(immediate: Boolean) = - sync(immediate, TAG_SYNC_ETEBASE, SyncEtebaseWork::class.java) - - override suspend fun openTaskSync(immediate: Boolean) = - sync(immediate, TAG_SYNC_OPENTASK, SyncOpenTasksWork::class.java, false) - - @SuppressLint("EnqueueWork") - private suspend fun sync(immediate: Boolean, tag: String, c: Class, requireNetwork: Boolean = true) { - Timber.d("sync(immediate = $immediate, $tag, $c, requireNetwork = $requireNetwork)") - val builder = OneTimeWorkRequest.Builder(c) + override suspend fun sync(immediate: Boolean) { + Timber.d("sync(immediate = $immediate)") + val builder = OneTimeWorkRequest.Builder(SyncWork::class.java) .setInputData(EXTRA_IMMEDIATE to immediate) - if (requireNetwork) { - builder.setConstraints(networkConstraints) - } + .setConstraints(networkConstraints) if (!immediate) { builder.setInitialDelay(1, TimeUnit.MINUTES) } val append = withContext(Dispatchers.IO) { - workManager.getWorkInfosByTag(tag).get().any { + workManager.getWorkInfosByTag(TAG_SYNC).get().any { it.state == WorkInfo.State.RUNNING } } enqueue(workManager.beginUniqueWork( - tag, + TAG_SYNC, if (append) APPEND_OR_REPLACE else REPLACE, builder.build()) ) @@ -156,42 +122,23 @@ class WorkManagerImpl constructor( override fun updateBackgroundSync() { throttle.run { - scheduleBackgroundSync( - TAG_BACKGROUND_SYNC_GOOGLE_TASKS, - SyncGoogleTasksWork::class.java, - googleTaskListDao.accountCount() > 0) - } - throttle.run { - scheduleBackgroundSync( - TAG_BACKGROUND_SYNC_CALDAV, - SyncCaldavWork::class.java, - caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS).isNotEmpty()) - } - throttle.run { - scheduleBackgroundSync( - TAG_BACKGROUND_SYNC_ETEBASE, - SyncEtebaseWork::class.java, - caldavDao.getAccounts(TYPE_ETEBASE).isNotEmpty()) - } - throttle.run { - scheduleBackgroundSync( - TAG_BACKGROUND_SYNC_OPENTASKS, - SyncOpenTasksWork::class.java, + val enabled = googleTaskListDao.accountCount() > 0 || + caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS, TYPE_ETEBASE).isNotEmpty() || openTaskDao.shouldSync() - ) - } - } - - private fun scheduleBackgroundSync(tag: String, c: Class, enabled: Boolean) { - Timber.d("scheduleBackgroundSync($tag, $c, enabled = $enabled)") - if (enabled) { - val builder = PeriodicWorkRequest.Builder(c, 1, TimeUnit.HOURS) + if (enabled) { + Timber.d("Enabling background sync") + val builder = PeriodicWorkRequest.Builder(SyncWork::class.java, 1, TimeUnit.HOURS) .setInputData(EXTRA_BACKGROUND to true) .setConstraints(networkConstraints) - workManager.enqueueUniquePeriodicWork( - tag, ExistingPeriodicWorkPolicy.KEEP, builder.build()) - } else { - workManager.cancelUniqueWork(tag) + workManager.enqueueUniquePeriodicWork( + TAG_BACKGROUND_SYNC, + ExistingPeriodicWorkPolicy.KEEP, + builder.build() + ) + } else { + Timber.d("Disabling background sync") + workManager.cancelUniqueWork(TAG_BACKGROUND_SYNC) + } } } diff --git a/app/src/main/java/org/tasks/preferences/Preferences.kt b/app/src/main/java/org/tasks/preferences/Preferences.kt index fa305c86b..588c69712 100644 --- a/app/src/main/java/org/tasks/preferences/Preferences.kt +++ b/app/src/main/java/org/tasks/preferences/Preferences.kt @@ -557,10 +557,8 @@ class Preferences @JvmOverloads constructor( context.packageName + "_preferences" private val syncFlags = listOf( - R.string.p_sync_ongoing_google_tasks, - R.string.p_sync_ongoing_caldav, + R.string.p_sync_ongoing, R.string.p_sync_ongoing_android, - R.string.p_sync_ongoing_etebase, ) } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/sync/SyncAdapters.kt b/app/src/main/java/org/tasks/sync/SyncAdapters.kt index 3fcf00f49..c1e5037e9 100644 --- a/app/src/main/java/org/tasks/sync/SyncAdapters.kt +++ b/app/src/main/java/org/tasks/sync/SyncAdapters.kt @@ -1,12 +1,9 @@ package org.tasks.sync import com.todoroo.astrid.data.SyncFlags +import com.todoroo.astrid.data.SyncFlags.FORCE_CALDAV_SYNC import com.todoroo.astrid.data.Task -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.asCoroutineDispatcher -import kotlinx.coroutines.async -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import org.tasks.LocalBroadcastManager import org.tasks.R import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV @@ -18,10 +15,7 @@ import org.tasks.data.GoogleTaskDao import org.tasks.data.GoogleTaskListDao import org.tasks.data.OpenTaskDao import org.tasks.jobs.WorkManager -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_CALDAV -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_ETEBASE -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_GOOGLE_TASKS -import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_OPENTASK +import org.tasks.jobs.WorkManager.Companion.TAG_SYNC import org.tasks.preferences.Preferences import java.util.concurrent.Executors.newSingleThreadExecutor import javax.inject.Inject @@ -38,14 +32,11 @@ class SyncAdapters @Inject constructor( private val localBroadcastManager: LocalBroadcastManager ) { private val scope = CoroutineScope(newSingleThreadExecutor().asCoroutineDispatcher() + SupervisorJob()) - private val googleTasks = Debouncer(TAG_SYNC_GOOGLE_TASKS) { workManager.googleTaskSync(it) } - private val caldav = Debouncer(TAG_SYNC_CALDAV) { workManager.caldavSync(it) } - private val eteBaseSync = Debouncer(TAG_SYNC_ETEBASE) { workManager.eteBaseSync(it) } - private val opentasks = Debouncer(TAG_SYNC_OPENTASK) { workManager.openTaskSync(it) } - private val syncStatus = Debouncer("sync_status") { - if (preferences.getBoolean(R.string.p_sync_ongoing_android, false) != it - && isOpenTaskSyncEnabled()) { - preferences.setBoolean(R.string.p_sync_ongoing_android, it) + private val sync = Debouncer(TAG_SYNC) { workManager.sync(it) } + private val syncStatus = Debouncer("sync_status") { newState -> + val currentState = preferences.getBoolean(R.string.p_sync_ongoing_android, false) + if (currentState != newState && isOpenTaskSyncEnabled()) { + preferences.setBoolean(R.string.p_sync_ongoing_android, newState) localBroadcastManager.broadcastRefresh() } } @@ -54,21 +45,12 @@ class SyncAdapters @Inject constructor( if (task.checkTransitory(SyncFlags.SUPPRESS_SYNC)) { return@launch } - if (!task.googleTaskUpToDate(original) - && googleTaskDao.getAllByTaskId(task.id).isNotEmpty()) { - googleTasks.sync(false) - } - if (task.checkTransitory(SyncFlags.FORCE_CALDAV_SYNC) || !task.caldavUpToDate(original)) { - if (caldavDao.isAccountType(task.id, TYPE_CALDAV) - || caldavDao.isAccountType(task.id, TYPE_TASKS)) { - caldav.sync(false) - } - if (caldavDao.isAccountType(task.id, TYPE_ETEBASE)) { - eteBaseSync.sync(false) - } - if (caldavDao.isAccountType(task.id, TYPE_OPENTASKS)) { - opentasks.sync(false) - } + val needsGoogleTaskSync = !task.googleTaskUpToDate(original) + && googleTaskDao.getAllByTaskId(task.id).isNotEmpty() + val needsIcalendarSync = (task.checkTransitory(FORCE_CALDAV_SYNC) || !task.caldavUpToDate(original)) + && caldavDao.isAccountType(task.id, TYPE_ICALENDAR) + if (needsGoogleTaskSync || needsIcalendarSync) { + sync.sync(false) } } @@ -77,7 +59,7 @@ class SyncAdapters @Inject constructor( } fun syncOpenTasks() = scope.launch { - opentasks.sync(true) + sync.sync(true) } fun sync() { @@ -86,33 +68,27 @@ class SyncAdapters @Inject constructor( fun sync(immediate: Boolean) = scope.launch { val googleTasksEnabled = async { isGoogleTaskSyncEnabled() } - val caldavEnabled = async { isCaldavSyncEnabled() } - val eteBaseEnabled = async { isEtebaseEnabled() } + val caldavEnabled = async { isSyncEnabled() } val opentasksEnabled = async { isOpenTaskSyncEnabled() } - if (googleTasksEnabled.await()) { - googleTasks.sync(immediate) - } - - if (caldavEnabled.await()) { - caldav.sync(immediate) - } - - if (eteBaseEnabled.await()) { - eteBaseSync.sync(immediate) - } - - if (opentasksEnabled.await()) { - opentasks.sync(immediate) + if (googleTasksEnabled.await() || caldavEnabled.await() || opentasksEnabled.await()) { + sync.sync(immediate) } } private suspend fun isGoogleTaskSyncEnabled() = googleTaskListDao.getAccounts().isNotEmpty() - private suspend fun isCaldavSyncEnabled() = - caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS).isNotEmpty() - - private suspend fun isEtebaseEnabled() = caldavDao.getAccounts(TYPE_ETEBASE).isNotEmpty() + private suspend fun isSyncEnabled() = + caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS, TYPE_ETEBASE).isNotEmpty() private suspend fun isOpenTaskSyncEnabled() = openTaskDao.shouldSync() + + companion object { + private val TYPE_ICALENDAR = listOf( + TYPE_CALDAV, + TYPE_TASKS, + TYPE_ETEBASE, + TYPE_OPENTASKS + ) + } } \ No newline at end of file diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index 3a9c1c863..0772ab072 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -378,10 +378,7 @@ p_flipper debug_pro debug_crash_main_queries - sync_ongoing_google_tasks - sync_ongoing_caldav - sync_ongoing_etebase - sync_ongoing_opentasks + sync_ongoing sync_ongoing_android last_backup show_description