Merge sync work

pull/2003/head
Alex Baker 3 years ago
parent d589a89506
commit eaa47029e7

@ -53,7 +53,6 @@ class Tasks : Application(), Configuration.Provider {
buildSetup.setup() buildSetup.setup()
upgrade() upgrade()
preferences.isSyncOngoing = false preferences.isSyncOngoing = false
preferences.setBoolean(R.string.p_sync_ongoing_opentasks, false)
ThemeBase.getThemeBase(preferences, inventory, null).setDefaultNightMode() ThemeBase.getThemeBase(preferences, inventory, null).setDefaultNightMode()
localBroadcastManager.registerRefreshReceiver(RefreshBroadcastReceiver()) localBroadcastManager.registerRefreshReceiver(RefreshBroadcastReceiver())
backgroundWork() backgroundWork()

@ -2,12 +2,7 @@ package org.tasks.data
import android.content.Context import android.content.Context
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.room.Dao import androidx.room.*
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.api.FilterListItem.NO_ORDER import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.core.SortHelper.APPLE_EPOCH 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_lists ON cdl_uuid = cd_calendar
INNER JOIN caldav_accounts ON cda_uuid = cdl_account INNER JOIN caldav_accounts ON cda_uuid = cdl_account
WHERE cd_task = :id 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<Int>): Boolean
suspend fun getTasks(taskIds: List<Long>): List<CaldavTask> = suspend fun getTasks(taskIds: List<Long>): List<CaldavTask> =
taskIds.chunkedMap { getTasksInternal(it) } taskIds.chunkedMap { getTasksInternal(it) }

@ -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<Deferred<Unit>> = coroutineScope {
getAccounts().map {
async(Dispatchers.IO) {
caldavSynchronizer.sync(it)
}
}
}
private suspend fun getAccounts() =
caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS)
}

@ -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<Deferred<Unit>> = coroutineScope {
caldavDao.getAccounts(TYPE_ETEBASE)
.map {
async(Dispatchers.IO) {
synchronizer.sync(it)
}
}
}
}

@ -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<Deferred<Unit>> = coroutineScope {
googleTaskListDao
.getAccounts()
.mapIndexed { i, account ->
async(Dispatchers.IO) {
googleTaskSynchronizer.sync(account, i)
}
}
}
}

@ -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)
}
)
}
}
}
}

@ -1,30 +1,56 @@
package org.tasks.jobs package org.tasks.jobs
import android.accounts.AccountManager
import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import androidx.core.content.ContextCompat.getSystemService import android.os.Bundle
import androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED import androidx.core.content.ContextCompat
import androidx.core.net.ConnectivityManagerCompat
import androidx.hilt.work.HiltWorker
import androidx.work.WorkerParameters 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.LocalBroadcastManager
import org.tasks.R
import org.tasks.analytics.Firebase 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.injection.BaseWorker
import org.tasks.opentasks.OpenTasksSynchronizer
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
abstract class SyncWork constructor( @HiltWorker
context: Context, class SyncWork @AssistedInject constructor(
workerParams: WorkerParameters, @Assisted context: Context,
@Assisted workerParams: WorkerParameters,
firebase: Firebase, firebase: Firebase,
private val localBroadcastManager: LocalBroadcastManager, private val localBroadcastManager: LocalBroadcastManager,
private val preferences: Preferences private val preferences: Preferences,
private val caldavDao: CaldavDao,
private val caldavSynchronizer: Lazy<CaldavSynchronizer>,
private val etebaseSynchronizer: Lazy<EtebaseSynchronizer>,
private val googleTaskSynchronizer: Lazy<GoogleTaskSynchronizer>,
private val openTasksSynchronizer: Lazy<OpenTasksSynchronizer>,
private val googleTaskListDao: GoogleTaskListDao,
private val openTaskDao: OpenTaskDao,
private val inventory: Inventory
) : BaseWorker(context, workerParams, firebase) { ) : BaseWorker(context, workerParams, firebase) {
final override suspend fun run(): Result { override suspend fun run(): Result {
if (!enabled()) {
return Result.failure()
}
if (isBackground) { if (isBackground) {
getSystemService(context, ConnectivityManager::class.java)?.apply { ContextCompat.getSystemService(context, ConnectivityManager::class.java)?.apply {
if (restrictBackgroundStatus == RESTRICT_BACKGROUND_STATUS_ENABLED) { if (restrictBackgroundStatus == ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED) {
return Result.failure() return Result.failure()
} }
} }
@ -48,17 +74,68 @@ abstract class SyncWork constructor(
return Result.success() return Result.success()
} }
val isImmediate: Boolean private val isImmediate: Boolean
get() = inputData.getBoolean(EXTRA_IMMEDIATE, false) get() = inputData.getBoolean(EXTRA_IMMEDIATE, false)
private val isBackground: Boolean private val isBackground: Boolean
get() = inputData.getBoolean(EXTRA_BACKGROUND, false) 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<Deferred<Unit>> = coroutineScope {
getGoogleAccounts()
.mapIndexed { i, account ->
async(Dispatchers.IO) {
googleTaskSynchronizer.get().sync(account, i)
}
}
}
private suspend fun caldavJobs(): List<Deferred<Unit>> = 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 { companion object {
private val LOCK = Any() private val LOCK = Any()

@ -16,13 +16,7 @@ interface WorkManager {
fun migrateLocalTasks(caldavAccount: CaldavAccount) fun migrateLocalTasks(caldavAccount: CaldavAccount)
suspend fun googleTaskSync(immediate: Boolean) suspend fun sync(immediate: Boolean)
suspend fun caldavSync(immediate: Boolean)
suspend fun eteBaseSync(immediate: Boolean)
suspend fun openTaskSync(immediate: Boolean)
fun reverseGeocode(place: Place) fun reverseGeocode(place: Place)
@ -50,14 +44,8 @@ interface WorkManager {
const val TAG_BACKUP = "tag_backup" const val TAG_BACKUP = "tag_backup"
const val TAG_REFRESH = "tag_refresh" const val TAG_REFRESH = "tag_refresh"
const val TAG_MIDNIGHT_REFRESH = "tag_midnight_refresh" const val TAG_MIDNIGHT_REFRESH = "tag_midnight_refresh"
const val TAG_SYNC_GOOGLE_TASKS = "tag_sync_google_tasks" const val TAG_SYNC = "tag_sync"
const val TAG_SYNC_CALDAV = "tag_sync_caldav" const val TAG_BACKGROUND_SYNC = "tag_background_sync"
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_REMOTE_CONFIG = "tag_remote_config" const val TAG_REMOTE_CONFIG = "tag_remote_config"
const val TAG_MIGRATE_LOCAL = "tag_migrate_local" const val TAG_MIGRATE_LOCAL = "tag_migrate_local"
const val TAG_UPDATE_PURCHASES = "tag_update_purchases" const val TAG_UPDATE_PURCHASES = "tag_update_purchases"

@ -6,18 +6,9 @@ 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.Constraints import androidx.work.*
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 androidx.work.workDataOf
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
@ -25,14 +16,10 @@ 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.CaldavAccount import org.tasks.data.*
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_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.DriveUploader.Companion.EXTRA_PURGE 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.SyncWork.Companion.EXTRA_IMMEDIATE
import org.tasks.jobs.WorkManager.Companion.MAX_CLEANUP_LENGTH 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.REMOTE_CONFIG_INTERVAL_HOURS
import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC_CALDAV import org.tasks.jobs.WorkManager.Companion.TAG_BACKGROUND_SYNC
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_BACKUP import org.tasks.jobs.WorkManager.Companion.TAG_BACKUP
import org.tasks.jobs.WorkManager.Companion.TAG_MIDNIGHT_REFRESH 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_MIGRATE_LOCAL
import org.tasks.jobs.WorkManager.Companion.TAG_REFRESH import org.tasks.jobs.WorkManager.Companion.TAG_REFRESH
import org.tasks.jobs.WorkManager.Companion.TAG_REMOTE_CONFIG 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
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_UPDATE_PURCHASES import org.tasks.jobs.WorkManager.Companion.TAG_UPDATE_PURCHASES
import org.tasks.notifications.Throttle import org.tasks.notifications.Throttle
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
@ -109,36 +90,21 @@ class WorkManagerImpl constructor(
} }
} }
override suspend fun googleTaskSync(immediate: Boolean) = override suspend fun sync(immediate: Boolean) {
sync(immediate, TAG_SYNC_GOOGLE_TASKS, SyncGoogleTasksWork::class.java) Timber.d("sync(immediate = $immediate)")
val builder = OneTimeWorkRequest.Builder(SyncWork::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<out SyncWork>, requireNetwork: Boolean = true) {
Timber.d("sync(immediate = $immediate, $tag, $c, requireNetwork = $requireNetwork)")
val builder = OneTimeWorkRequest.Builder(c)
.setInputData(EXTRA_IMMEDIATE to immediate) .setInputData(EXTRA_IMMEDIATE to immediate)
if (requireNetwork) { .setConstraints(networkConstraints)
builder.setConstraints(networkConstraints)
}
if (!immediate) { if (!immediate) {
builder.setInitialDelay(1, TimeUnit.MINUTES) builder.setInitialDelay(1, TimeUnit.MINUTES)
} }
val append = withContext(Dispatchers.IO) { val append = withContext(Dispatchers.IO) {
workManager.getWorkInfosByTag(tag).get().any { workManager.getWorkInfosByTag(TAG_SYNC).get().any {
it.state == WorkInfo.State.RUNNING it.state == WorkInfo.State.RUNNING
} }
} }
enqueue(workManager.beginUniqueWork( enqueue(workManager.beginUniqueWork(
tag, TAG_SYNC,
if (append) APPEND_OR_REPLACE else REPLACE, if (append) APPEND_OR_REPLACE else REPLACE,
builder.build()) builder.build())
) )
@ -156,42 +122,23 @@ class WorkManagerImpl constructor(
override fun updateBackgroundSync() { override fun updateBackgroundSync() {
throttle.run { throttle.run {
scheduleBackgroundSync( val enabled = googleTaskListDao.accountCount() > 0 ||
TAG_BACKGROUND_SYNC_GOOGLE_TASKS, caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS, TYPE_ETEBASE).isNotEmpty() ||
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,
openTaskDao.shouldSync() openTaskDao.shouldSync()
)
}
}
private fun scheduleBackgroundSync(tag: String, c: Class<out SyncWork>, enabled: Boolean) {
Timber.d("scheduleBackgroundSync($tag, $c, enabled = $enabled)")
if (enabled) { if (enabled) {
val builder = PeriodicWorkRequest.Builder(c, 1, TimeUnit.HOURS) Timber.d("Enabling background sync")
val builder = PeriodicWorkRequest.Builder(SyncWork::class.java, 1, TimeUnit.HOURS)
.setInputData(EXTRA_BACKGROUND to true) .setInputData(EXTRA_BACKGROUND to true)
.setConstraints(networkConstraints) .setConstraints(networkConstraints)
workManager.enqueueUniquePeriodicWork( workManager.enqueueUniquePeriodicWork(
tag, ExistingPeriodicWorkPolicy.KEEP, builder.build()) TAG_BACKGROUND_SYNC,
ExistingPeriodicWorkPolicy.KEEP,
builder.build()
)
} else { } else {
workManager.cancelUniqueWork(tag) Timber.d("Disabling background sync")
workManager.cancelUniqueWork(TAG_BACKGROUND_SYNC)
}
} }
} }

@ -557,10 +557,8 @@ class Preferences @JvmOverloads constructor(
context.packageName + "_preferences" context.packageName + "_preferences"
private val syncFlags = listOf( private val syncFlags = listOf(
R.string.p_sync_ongoing_google_tasks, R.string.p_sync_ongoing,
R.string.p_sync_ongoing_caldav,
R.string.p_sync_ongoing_android, R.string.p_sync_ongoing_android,
R.string.p_sync_ongoing_etebase,
) )
} }
} }

@ -1,12 +1,9 @@
package org.tasks.sync package org.tasks.sync
import com.todoroo.astrid.data.SyncFlags import com.todoroo.astrid.data.SyncFlags
import com.todoroo.astrid.data.SyncFlags.FORCE_CALDAV_SYNC
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.*
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV 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.GoogleTaskListDao
import org.tasks.data.OpenTaskDao import org.tasks.data.OpenTaskDao
import org.tasks.jobs.WorkManager import org.tasks.jobs.WorkManager
import org.tasks.jobs.WorkManager.Companion.TAG_SYNC_CALDAV import org.tasks.jobs.WorkManager.Companion.TAG_SYNC
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.preferences.Preferences import org.tasks.preferences.Preferences
import java.util.concurrent.Executors.newSingleThreadExecutor import java.util.concurrent.Executors.newSingleThreadExecutor
import javax.inject.Inject import javax.inject.Inject
@ -38,14 +32,11 @@ class SyncAdapters @Inject constructor(
private val localBroadcastManager: LocalBroadcastManager private val localBroadcastManager: LocalBroadcastManager
) { ) {
private val scope = CoroutineScope(newSingleThreadExecutor().asCoroutineDispatcher() + SupervisorJob()) private val scope = CoroutineScope(newSingleThreadExecutor().asCoroutineDispatcher() + SupervisorJob())
private val googleTasks = Debouncer(TAG_SYNC_GOOGLE_TASKS) { workManager.googleTaskSync(it) } private val sync = Debouncer(TAG_SYNC) { workManager.sync(it) }
private val caldav = Debouncer(TAG_SYNC_CALDAV) { workManager.caldavSync(it) } private val syncStatus = Debouncer("sync_status") { newState ->
private val eteBaseSync = Debouncer(TAG_SYNC_ETEBASE) { workManager.eteBaseSync(it) } val currentState = preferences.getBoolean(R.string.p_sync_ongoing_android, false)
private val opentasks = Debouncer(TAG_SYNC_OPENTASK) { workManager.openTaskSync(it) } if (currentState != newState && isOpenTaskSyncEnabled()) {
private val syncStatus = Debouncer("sync_status") { preferences.setBoolean(R.string.p_sync_ongoing_android, newState)
if (preferences.getBoolean(R.string.p_sync_ongoing_android, false) != it
&& isOpenTaskSyncEnabled()) {
preferences.setBoolean(R.string.p_sync_ongoing_android, it)
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
} }
} }
@ -54,21 +45,12 @@ class SyncAdapters @Inject constructor(
if (task.checkTransitory(SyncFlags.SUPPRESS_SYNC)) { if (task.checkTransitory(SyncFlags.SUPPRESS_SYNC)) {
return@launch return@launch
} }
if (!task.googleTaskUpToDate(original) val needsGoogleTaskSync = !task.googleTaskUpToDate(original)
&& googleTaskDao.getAllByTaskId(task.id).isNotEmpty()) { && googleTaskDao.getAllByTaskId(task.id).isNotEmpty()
googleTasks.sync(false) val needsIcalendarSync = (task.checkTransitory(FORCE_CALDAV_SYNC) || !task.caldavUpToDate(original))
} && caldavDao.isAccountType(task.id, TYPE_ICALENDAR)
if (task.checkTransitory(SyncFlags.FORCE_CALDAV_SYNC) || !task.caldavUpToDate(original)) { if (needsGoogleTaskSync || needsIcalendarSync) {
if (caldavDao.isAccountType(task.id, TYPE_CALDAV) sync.sync(false)
|| 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)
}
} }
} }
@ -77,7 +59,7 @@ class SyncAdapters @Inject constructor(
} }
fun syncOpenTasks() = scope.launch { fun syncOpenTasks() = scope.launch {
opentasks.sync(true) sync.sync(true)
} }
fun sync() { fun sync() {
@ -86,33 +68,27 @@ class SyncAdapters @Inject constructor(
fun sync(immediate: Boolean) = scope.launch { fun sync(immediate: Boolean) = scope.launch {
val googleTasksEnabled = async { isGoogleTaskSyncEnabled() } val googleTasksEnabled = async { isGoogleTaskSyncEnabled() }
val caldavEnabled = async { isCaldavSyncEnabled() } val caldavEnabled = async { isSyncEnabled() }
val eteBaseEnabled = async { isEtebaseEnabled() }
val opentasksEnabled = async { isOpenTaskSyncEnabled() } val opentasksEnabled = async { isOpenTaskSyncEnabled() }
if (googleTasksEnabled.await()) { if (googleTasksEnabled.await() || caldavEnabled.await() || opentasksEnabled.await()) {
googleTasks.sync(immediate) sync.sync(immediate)
}
if (caldavEnabled.await()) {
caldav.sync(immediate)
}
if (eteBaseEnabled.await()) {
eteBaseSync.sync(immediate)
}
if (opentasksEnabled.await()) {
opentasks.sync(immediate)
} }
} }
private suspend fun isGoogleTaskSyncEnabled() = googleTaskListDao.getAccounts().isNotEmpty() private suspend fun isGoogleTaskSyncEnabled() = googleTaskListDao.getAccounts().isNotEmpty()
private suspend fun isCaldavSyncEnabled() = private suspend fun isSyncEnabled() =
caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS).isNotEmpty() caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS, TYPE_ETEBASE).isNotEmpty()
private suspend fun isEtebaseEnabled() = caldavDao.getAccounts(TYPE_ETEBASE).isNotEmpty()
private suspend fun isOpenTaskSyncEnabled() = openTaskDao.shouldSync() private suspend fun isOpenTaskSyncEnabled() = openTaskDao.shouldSync()
companion object {
private val TYPE_ICALENDAR = listOf(
TYPE_CALDAV,
TYPE_TASKS,
TYPE_ETEBASE,
TYPE_OPENTASKS
)
}
} }

@ -378,10 +378,7 @@
<string name="p_flipper">p_flipper</string> <string name="p_flipper">p_flipper</string>
<string name="p_debug_pro">debug_pro</string> <string name="p_debug_pro">debug_pro</string>
<string name="p_crash_main_queries">debug_crash_main_queries</string> <string name="p_crash_main_queries">debug_crash_main_queries</string>
<string name="p_sync_ongoing_google_tasks">sync_ongoing_google_tasks</string> <string name="p_sync_ongoing">sync_ongoing</string>
<string name="p_sync_ongoing_caldav">sync_ongoing_caldav</string>
<string name="p_sync_ongoing_etebase">sync_ongoing_etebase</string>
<string name="p_sync_ongoing_opentasks">sync_ongoing_opentasks</string>
<string name="p_sync_ongoing_android">sync_ongoing_android</string> <string name="p_sync_ongoing_android">sync_ongoing_android</string>
<string name="p_last_backup">last_backup</string> <string name="p_last_backup">last_backup</string>
<string name="p_show_description">show_description</string> <string name="p_show_description">show_description</string>

Loading…
Cancel
Save