|
|
@ -1,31 +1,24 @@
|
|
|
|
package org.tasks.opentasks
|
|
|
|
package org.tasks.opentasks
|
|
|
|
|
|
|
|
|
|
|
|
import android.content.ContentProviderOperation
|
|
|
|
import android.content.ContentProviderOperation
|
|
|
|
import android.content.ContentValues
|
|
|
|
|
|
|
|
import android.content.Context
|
|
|
|
import android.content.Context
|
|
|
|
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.data.Task.Companion.sanitizeRRule
|
|
|
|
|
|
|
|
import com.todoroo.astrid.service.TaskDeleter
|
|
|
|
import com.todoroo.astrid.service.TaskDeleter
|
|
|
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
|
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
|
|
import net.fortuna.ical4j.model.property.RRule
|
|
|
|
|
|
|
|
import org.dmfs.tasks.contract.TaskContract.Tasks
|
|
|
|
import org.dmfs.tasks.contract.TaskContract.Tasks
|
|
|
|
import org.tasks.LocalBroadcastManager
|
|
|
|
import org.tasks.LocalBroadcastManager
|
|
|
|
import org.tasks.R
|
|
|
|
import org.tasks.R
|
|
|
|
import org.tasks.analytics.Constants
|
|
|
|
import org.tasks.analytics.Constants
|
|
|
|
import org.tasks.analytics.Firebase
|
|
|
|
import org.tasks.analytics.Firebase
|
|
|
|
import org.tasks.billing.Inventory
|
|
|
|
import org.tasks.billing.Inventory
|
|
|
|
import org.tasks.caldav.CaldavConverter.toRemote
|
|
|
|
|
|
|
|
import org.tasks.caldav.iCalendar
|
|
|
|
import org.tasks.caldav.iCalendar
|
|
|
|
import org.tasks.data.*
|
|
|
|
import org.tasks.data.*
|
|
|
|
import org.tasks.data.CaldavAccount.Companion.openTaskType
|
|
|
|
import org.tasks.data.CaldavAccount.Companion.openTaskType
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.getInt
|
|
|
|
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.isDavx5
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.isDavx5
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.isDecSync
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.isDecSync
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.isEteSync
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.isEteSync
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.newAccounts
|
|
|
|
import org.tasks.data.OpenTaskDao.Companion.newAccounts
|
|
|
|
import org.tasks.time.DateTime
|
|
|
|
|
|
|
|
import org.tasks.time.DateTimeUtils.startOfDay
|
|
|
|
|
|
|
|
import timber.log.Timber
|
|
|
|
import timber.log.Timber
|
|
|
|
import java.util.*
|
|
|
|
import java.util.*
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Inject
|
|
|
@ -40,13 +33,10 @@ class OpenTasksSynchronizer @Inject constructor(
|
|
|
|
private val taskDao: TaskDao,
|
|
|
|
private val taskDao: TaskDao,
|
|
|
|
private val firebase: Firebase,
|
|
|
|
private val firebase: Firebase,
|
|
|
|
private val iCalendar: iCalendar,
|
|
|
|
private val iCalendar: iCalendar,
|
|
|
|
private val locationDao: LocationDao,
|
|
|
|
|
|
|
|
private val openTaskDao: OpenTaskDao,
|
|
|
|
private val openTaskDao: OpenTaskDao,
|
|
|
|
private val tagDataDao: TagDataDao,
|
|
|
|
private val tagDataDao: TagDataDao,
|
|
|
|
private val inventory: Inventory) {
|
|
|
|
private val inventory: Inventory) {
|
|
|
|
|
|
|
|
|
|
|
|
private val cr = context.contentResolver
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
suspend fun sync() {
|
|
|
|
suspend fun sync() {
|
|
|
|
val lists = openTaskDao.getListsByAccount()
|
|
|
|
val lists = openTaskDao.getListsByAccount()
|
|
|
|
lists.newAccounts(caldavDao)
|
|
|
|
lists.newAccounts(caldavDao)
|
|
|
@ -212,60 +202,21 @@ class OpenTasksSynchronizer @Inject constructor(
|
|
|
|
): Pair<CaldavTask, ContentProviderOperation>? {
|
|
|
|
): Pair<CaldavTask, ContentProviderOperation>? {
|
|
|
|
val caldavTask = caldavDao.getTask(task.id) ?: return null
|
|
|
|
val caldavTask = caldavDao.getTask(task.id) ?: return null
|
|
|
|
caldavTask.lastSync = task.modificationDate
|
|
|
|
caldavTask.lastSync = task.modificationDate
|
|
|
|
val values = ContentValues()
|
|
|
|
val remoteModel = openTaskDao.getTask(listId, caldavTask.remoteId!!)
|
|
|
|
values.put(Tasks.LIST_ID, listId)
|
|
|
|
?: at.bitfire.ical4android.Task()
|
|
|
|
values.put(Tasks.TITLE, task.title)
|
|
|
|
val isNew = remoteModel.uid.isNullOrBlank()
|
|
|
|
values.put(Tasks.DESCRIPTION, task.notes)
|
|
|
|
iCalendar.toVtodo(caldavTask, task, remoteModel)
|
|
|
|
values.put(Tasks.GEO, locationDao.getGeofences(task.id).toGeoString())
|
|
|
|
val builder = MyAndroidTask(remoteModel).toBuilder(openTaskDao.tasks, isNew)
|
|
|
|
values.put(Tasks.RRULE, if (task.isRecurring) {
|
|
|
|
|
|
|
|
val rrule = RRule(task.getRecurrenceWithoutFrom()!!.replace("RRULE:", ""))
|
|
|
|
|
|
|
|
if (task.repeatUntil > 0) {
|
|
|
|
|
|
|
|
rrule.recur.until = DateTime(task.repeatUntil).toUTC().toDateTime()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
RRule(rrule.value.sanitizeRRule()).value
|
|
|
|
|
|
|
|
} else null)
|
|
|
|
|
|
|
|
val allDay = !task.hasDueTime() && !task.hasStartTime()
|
|
|
|
|
|
|
|
values.put(Tasks.IS_ALLDAY, if (allDay) 1 else 0)
|
|
|
|
|
|
|
|
values.put(Tasks.DUE, when {
|
|
|
|
|
|
|
|
task.hasDueTime() -> task.dueDate
|
|
|
|
|
|
|
|
task.hasDueDate() -> task.dueDate.startOfDay()
|
|
|
|
|
|
|
|
else -> null
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
values.put(Tasks.DTSTART, when {
|
|
|
|
|
|
|
|
task.hasStartTime() -> task.hideUntil
|
|
|
|
|
|
|
|
task.hasStartDate() -> task.hideUntil.startOfDay()
|
|
|
|
|
|
|
|
else -> null
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
values.put(Tasks.COMPLETED_IS_ALLDAY, 0)
|
|
|
|
|
|
|
|
values.put(Tasks.COMPLETED, if (task.isCompleted) task.completionDate else null)
|
|
|
|
|
|
|
|
values.put(Tasks.STATUS, if (task.isCompleted) Tasks.STATUS_COMPLETED else null)
|
|
|
|
|
|
|
|
values.put(Tasks.PERCENT_COMPLETE, if (task.isCompleted) 100 else null)
|
|
|
|
|
|
|
|
if (!allDay || task.isCompleted) {
|
|
|
|
|
|
|
|
values.put(Tasks.TZ, TimeZone.getDefault().id)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
values.put(Tasks.PARENT_ID, null as Long?)
|
|
|
|
|
|
|
|
val existing = cr.query(
|
|
|
|
|
|
|
|
Tasks.getContentUri(openTaskDao.authority),
|
|
|
|
|
|
|
|
arrayOf(Tasks.PRIORITY),
|
|
|
|
|
|
|
|
"${Tasks.LIST_ID} = $listId AND ${Tasks._UID} = '${caldavTask.remoteId}'",
|
|
|
|
|
|
|
|
null,
|
|
|
|
|
|
|
|
null)?.use {
|
|
|
|
|
|
|
|
if (!it.moveToFirst()) {
|
|
|
|
|
|
|
|
return@use false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
values.put(Tasks.PRIORITY, toRemote(it.getInt(Tasks.PRIORITY), task.priority))
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
} ?: false
|
|
|
|
|
|
|
|
val operation = try {
|
|
|
|
val operation = try {
|
|
|
|
if (existing) {
|
|
|
|
if (isNew) {
|
|
|
|
openTaskDao.update(listId, caldavTask.remoteId!!, values)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (isEteSync) {
|
|
|
|
if (isEteSync) {
|
|
|
|
values.put(Tasks.SYNC2, caldavTask.remoteId)
|
|
|
|
builder.withValue(Tasks.SYNC2, caldavTask.remoteId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
values.put(Tasks._UID, caldavTask.remoteId)
|
|
|
|
builder.withValue(Tasks.LIST_ID, listId)
|
|
|
|
values.put(Tasks.PRIORITY, toRemote(task.priority, task.priority))
|
|
|
|
openTaskDao.insert(builder)
|
|
|
|
openTaskDao.insert(values)
|
|
|
|
} else {
|
|
|
|
|
|
|
|
openTaskDao.update(listId, caldavTask.remoteId!!, builder)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (e: Exception) {
|
|
|
|
} catch (e: Exception) {
|
|
|
|
firebase.reportException(e)
|
|
|
|
firebase.reportException(e)
|
|
|
@ -285,8 +236,4 @@ class OpenTasksSynchronizer @Inject constructor(
|
|
|
|
iCalendar.fromVtodo(calendar, existing, it, null, null, etag)
|
|
|
|
iCalendar.fromVtodo(calendar, existing, it, null, null, etag)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
|
|
|
private fun Location?.toGeoString(): String? = this?.let { "$longitude,$latitude" }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|