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/com/todoroo/astrid/service/TaskCreator.kt

206 lines
8.0 KiB
Kotlin

package com.todoroo.astrid.service
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.PermaSql
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.DUE_DATE
import com.todoroo.astrid.data.Task.Companion.HIDE_UNTIL
import com.todoroo.astrid.data.Task.Companion.HIDE_UNTIL_NONE
import com.todoroo.astrid.data.Task.Companion.IMPORTANCE
import com.todoroo.astrid.data.Task.Companion.createDueDate
import com.todoroo.astrid.gcal.GCalHelper
import com.todoroo.astrid.helper.UUIDHelper
import com.todoroo.astrid.utility.TitleParser.parse
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.*
import org.tasks.data.Alarm.Companion.TYPE_RANDOM
import org.tasks.data.Alarm.Companion.whenDue
import org.tasks.data.Alarm.Companion.whenOverdue
import org.tasks.data.Alarm.Companion.whenStarted
import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils.startOfDay
import timber.log.Timber
import javax.inject.Inject
class TaskCreator @Inject constructor(
private val gcalHelper: GCalHelper,
private val preferences: Preferences,
private val tagDataDao: TagDataDao,
private val taskDao: TaskDao,
private val tagDao: TagDao,
private val googleTaskDao: GoogleTaskDao,
private val defaultFilterProvider: DefaultFilterProvider,
private val caldavDao: CaldavDao,
private val locationDao: LocationDao,
private val alarmDao: AlarmDao,
) {
suspend fun basicQuickAddTask(title: String): Task {
val task = createWithValues(title.trim { it <= ' ' })
taskDao.createNew(task)
val gcalCreateEventEnabled = preferences.isDefaultCalendarSet && task.hasDueDate() // $NON-NLS-1$
if (!isNullOrEmpty(task.title)
&& gcalCreateEventEnabled
&& isNullOrEmpty(task.calendarURI)) {
val calendarUri = gcalHelper.createTaskEvent(task, preferences.defaultCalendar)
task.calendarURI = calendarUri.toString()
}
createTags(task)
val addToTop = preferences.addTasksToTop()
if (task.hasTransitory(GoogleTask.KEY)) {
googleTaskDao.insertAndShift(
task,
CaldavTask(task.id, task.getTransitory<String>(GoogleTask.KEY)!!, remoteId = null),
addToTop
)
} else if (task.hasTransitory(CaldavTask.KEY)) {
caldavDao.insert(
task, CaldavTask(task.id, task.getTransitory<String>(CaldavTask.KEY)), addToTop)
} else {
val remoteList = defaultFilterProvider.getDefaultList()
if (remoteList is GtasksFilter) {
googleTaskDao.insertAndShift(
task,
CaldavTask(task.id, remoteList.remoteId, remoteId = null),
addToTop
)
} else if (remoteList is CaldavFilter) {
caldavDao.insert(
task, CaldavTask(task.id, remoteList.uuid), addToTop)
}
}
if (task.hasTransitory(Place.KEY)) {
val place = locationDao.getPlace(task.getTransitory<String>(Place.KEY)!!)
if (place != null) {
locationDao.insert(Geofence(place.uid, preferences))
}
}
taskDao.save(task, null)
alarmDao.insert(task.getDefaultAlarms())
return task
}
suspend fun createWithValues(title: String?): Task {
return create(null, title)
}
suspend fun createWithValues(filter: Filter?, title: String?): Task {
return create(filter?.valuesForNewTasks, title)
}
/**
* Create task from the given content values, saving it. This version doesn't need to start with a
* base task model.
*/
internal suspend fun create(values: Map<String, Any>?, title: String?): Task {
val task = Task()
task.creationDate = DateUtilities.now()
task.modificationDate = DateUtilities.now()
if (title != null) {
task.title = title.trim { it <= ' ' }
}
task.uuid = UUIDHelper.newUUID()
task.priority = preferences.defaultPriority
preferences.getStringValue(R.string.p_default_recurrence)
?.takeIf { it.isNotBlank() }
?.let {
task.recurrence = it
task.repeatFrom = if (preferences.getIntegerFromString(R.string.p_default_recurrence_from, 0) == 1) {
Task.RepeatFrom.COMPLETION_DATE
} else {
Task.RepeatFrom.DUE_DATE
}
}
preferences.getStringValue(R.string.p_default_location)
?.takeIf { it.isNotBlank() }
?.let { task.putTransitory(Place.KEY, it) }
task.setDefaultReminders(preferences)
val tags = ArrayList<String>()
values?.entries?.forEach { (key, value) ->
when (key) {
Tag.KEY -> tags.add(value as String)
GoogleTask.KEY, CaldavTask.KEY, Place.KEY -> task.putTransitory(key, value)
DUE_DATE.name -> value.substitute()?.toLongOrNull()?.let { task.dueDate =
createDueDate(Task.URGENCY_SPECIFIC_DAY, it) }
IMPORTANCE.name -> value.substitute()?.toIntOrNull()?.let { task.priority = it }
HIDE_UNTIL.name ->
value.substitute()?.toLongOrNull()?.let { task.hideUntil = it.startOfDay() }
}
}
if (values?.containsKey(DUE_DATE.name) != true) {
task.dueDate = createDueDate(
preferences.getIntegerFromString(R.string.p_default_urgency_key, Task.URGENCY_NONE),
0)
}
if (values?.containsKey(HIDE_UNTIL.name) != true) {
task.hideUntil = task.createHideUntil(
preferences.getIntegerFromString(R.string.p_default_hideUntil_key, HIDE_UNTIL_NONE),
0
)
}
if (tags.isEmpty()) {
preferences.getStringValue(R.string.p_default_tags)
?.split(",")
?.map { tagDataDao.getByUuid(it) }
?.mapNotNull { it?.name }
?.let { tags.addAll(it) }
}
try {
parse(tagDataDao, task, tags)
} catch (e: Throwable) {
Timber.e(e)
}
task.setTags(tags)
return task
}
suspend fun createTags(task: Task) {
for (tag in task.tags) {
var tagData = tagDataDao.getTagByName(tag)
if (tagData == null) {
tagData = TagData()
tagData.name = tag
tagDataDao.createNew(tagData)
}
tagDao.insert(Tag(task, tagData))
}
}
companion object {
fun Task.setDefaultReminders(preferences: Preferences) {
randomReminder = DateUtilities.ONE_HOUR * preferences.getIntegerFromString(
R.string.p_rmd_default_random_hours,
0
)
defaultReminders(preferences.defaultReminders)
ringFlags = preferences.defaultRingMode
}
private fun Any?.substitute(): String? =
(this as? String)?.let { PermaSql.replacePlaceholdersForNewTask(it) }
fun Task.getDefaultAlarms(): List<Alarm> = ArrayList<Alarm>().apply {
if (hasStartDate() && isNotifyAtStart) {
add(whenStarted(id))
}
if (hasDueDate()) {
if (isNotifyAtDeadline) {
add(whenDue(id))
}
if (isNotifyAfterDeadline) {
add(whenOverdue(id))
}
}
if (randomReminder > 0) {
add(Alarm(id, randomReminder, TYPE_RANDOM))
}
}
}
}