You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tasks/app/src/main/java/org/tasks/jobs/SyncWork.kt

151 lines
5.3 KiB
Kotlin

package org.tasks.jobs
2 years ago
import android.accounts.AccountManager
import android.content.ContentResolver
import android.content.Context
import android.net.ConnectivityManager
2 years ago
import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.core.net.ConnectivityManagerCompat
import androidx.hilt.work.HiltWorker
import androidx.work.WorkerParameters
2 years ago
import dagger.Lazy
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import org.tasks.LocalBroadcastManager
2 years ago
import org.tasks.R
4 years ago
import org.tasks.analytics.Firebase
2 years ago
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
2 years ago
import org.tasks.opentasks.OpenTasksSynchronizer
import org.tasks.preferences.Preferences
2 years ago
@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<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) {
2 years ago
override suspend fun run(): Result {
if (isBackground) {
2 years ago
ContextCompat.getSystemService(context, ConnectivityManager::class.java)?.apply {
if (restrictBackgroundStatus == ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED) {
return Result.failure()
}
}
}
synchronized(LOCK) {
if (preferences.getBoolean(syncStatus, false)) {
return Result.retry()
}
preferences.setBoolean(syncStatus, true)
}
localBroadcastManager.broadcastRefresh()
try {
doSync()
preferences.lastSync = System.currentTimeMillis()
} catch (e: Exception) {
firebase.reportException(e)
} finally {
preferences.setBoolean(syncStatus, false)
localBroadcastManager.broadcastRefresh()
}
return Result.success()
}
2 years ago
private val isImmediate: Boolean
get() = inputData.getBoolean(EXTRA_IMMEDIATE, false)
private val isBackground: Boolean
get() = inputData.getBoolean(EXTRA_BACKGROUND, false)
2 years ago
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)
}
}
}
}
2 years ago
private suspend fun getGoogleAccounts() =
googleTaskListDao.getAccounts()
2 years ago
private suspend fun getCaldavAccounts() =
caldavDao.getAccounts(TYPE_CALDAV, TYPE_TASKS, TYPE_ETEBASE)
companion object {
private val LOCK = Any()
const val EXTRA_IMMEDIATE = "extra_immediate"
const val EXTRA_BACKGROUND = "extra_background"
}
}