mirror of https://github.com/tasks/tasks
Move Room to data module
parent
6118121698
commit
6e14d07d0c
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
public class SyncFlags {
|
||||
public static final String SUPPRESS_SYNC = "suppress_sync";
|
||||
public static final String FORCE_CALDAV_SYNC = "force_caldav_sync";
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.todoroo.astrid.helper;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDHelper {
|
||||
|
||||
private static final long MIN_UUID = 100000000;
|
||||
|
||||
/** @return a pair consisting of the newly generated uuid and the corresponding proof text */
|
||||
public static String newUUID() {
|
||||
long uuid;
|
||||
do {
|
||||
uuid = UUID.randomUUID().getLeastSignificantBits() & 0x7fffffffffffffffL;
|
||||
} while (uuid < MIN_UUID);
|
||||
return Long.toString(uuid);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package org.tasks.data
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import org.tasks.R
|
||||
import org.tasks.caldav.BaseCaldavAccountSettingsActivity
|
||||
import org.tasks.caldav.CaldavAccountSettingsActivity
|
||||
import org.tasks.caldav.CaldavCalendarSettingsActivity
|
||||
import org.tasks.caldav.LocalListSettingsActivity
|
||||
import org.tasks.data.OpenTaskDao.Companion.isDavx5
|
||||
import org.tasks.data.OpenTaskDao.Companion.isDecSync
|
||||
import org.tasks.data.OpenTaskDao.Companion.isEteSync
|
||||
import org.tasks.etebase.EtebaseAccountSettingsActivity
|
||||
import org.tasks.etebase.EtebaseCalendarSettingsActivity
|
||||
import org.tasks.etesync.EteSyncAccountSettingsActivity
|
||||
import org.tasks.opentasks.OpenTaskAccountSettingsActivity
|
||||
import org.tasks.opentasks.OpenTasksListSettingsActivity
|
||||
import org.tasks.security.KeyStoreEncryption
|
||||
import org.tasks.sync.microsoft.MicrosoftListSettingsActivity
|
||||
|
||||
val CaldavAccount.prefTitle: Int
|
||||
get() = when {
|
||||
isTasksOrg -> R.string.tasks_org
|
||||
isCaldavAccount -> R.string.caldav
|
||||
isEtebaseAccount || uuid.isEteSync() -> R.string.etesync
|
||||
isEteSyncAccount -> R.string.etesync_v1
|
||||
uuid.isDavx5() -> R.string.davx5
|
||||
uuid.isDecSync() -> R.string.decsync
|
||||
isMicrosoft -> R.string.microsoft
|
||||
isGoogleTasks -> R.string.gtasks_GPr_header
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val CaldavAccount.prefIcon: Int
|
||||
get() = when {
|
||||
isTasksOrg -> R.drawable.ic_round_icon
|
||||
isCaldavAccount -> R.drawable.ic_webdav_logo
|
||||
isEtebaseAccount || isEteSyncAccount || uuid.isEteSync() -> R.drawable.ic_etesync
|
||||
uuid.isDavx5() -> R.drawable.ic_davx5_icon_green_bg
|
||||
uuid.isDecSync() -> R.drawable.ic_decsync
|
||||
isMicrosoft -> R.drawable.ic_microsoft_tasks
|
||||
isGoogleTasks -> R.drawable.ic_google
|
||||
else -> 0
|
||||
}
|
||||
|
||||
fun CaldavAccount.isTasksSubscription(context: Context): Boolean {
|
||||
val caldavUrl = context.getString(R.string.tasks_caldav_url)
|
||||
return url?.startsWith("${caldavUrl}/calendars/") == true &&
|
||||
!isPaymentRequired() &&
|
||||
!isLoggedOut()
|
||||
}
|
||||
|
||||
fun CaldavAccount.listSettingsClass(): Class<out Activity> = when(accountType) {
|
||||
CaldavAccount.TYPE_LOCAL -> LocalListSettingsActivity::class.java
|
||||
CaldavAccount.TYPE_ETESYNC, CaldavAccount.TYPE_OPENTASKS -> OpenTasksListSettingsActivity::class.java
|
||||
CaldavAccount.TYPE_ETEBASE -> EtebaseCalendarSettingsActivity::class.java
|
||||
CaldavAccount.TYPE_MICROSOFT -> MicrosoftListSettingsActivity::class.java
|
||||
else -> CaldavCalendarSettingsActivity::class.java
|
||||
}
|
||||
|
||||
val CaldavAccount.accountSettingsClass: Class<out BaseCaldavAccountSettingsActivity>
|
||||
get() = when {
|
||||
isCaldavAccount -> CaldavAccountSettingsActivity::class.java
|
||||
isEteSyncAccount -> EteSyncAccountSettingsActivity::class.java
|
||||
isEtebaseAccount -> EtebaseAccountSettingsActivity::class.java
|
||||
isOpenTasks -> OpenTaskAccountSettingsActivity::class.java
|
||||
else -> throw IllegalArgumentException("Unexpected account type: $this")
|
||||
}
|
||||
|
||||
fun CaldavAccount.getPassword(encryption: KeyStoreEncryption): String {
|
||||
return encryption.decrypt(password) ?: ""
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package org.tasks.data
|
||||
|
||||
import android.content.Context
|
||||
import com.todoroo.astrid.helper.UUIDHelper
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.tasks.R
|
||||
|
||||
private val mutex = Mutex()
|
||||
|
||||
suspend fun CaldavDao.setupLocalAccount(context: Context): CaldavAccount = mutex.withLock {
|
||||
val account = getLocalAccount()
|
||||
getLocalList(context, account)
|
||||
return account
|
||||
}
|
||||
|
||||
suspend fun CaldavDao.getLocalList(context: Context) = mutex.withLock {
|
||||
getLocalList(context, getLocalAccount())
|
||||
}
|
||||
|
||||
private suspend fun CaldavDao.getLocalAccount() = getAccountByUuid(CaldavDao.LOCAL) ?: CaldavAccount().apply {
|
||||
accountType = CaldavAccount.TYPE_LOCAL
|
||||
uuid = CaldavDao.LOCAL
|
||||
id = insert(this)
|
||||
}
|
||||
|
||||
private suspend fun CaldavDao.getLocalList(context: Context, account: CaldavAccount): CaldavCalendar =
|
||||
getCalendarsByAccount(account.uuid!!).getOrNull(0)
|
||||
?: CaldavCalendar(
|
||||
name = context.getString(R.string.default_list),
|
||||
uuid = UUIDHelper.newUUID(),
|
||||
account = account.uuid,
|
||||
).apply {
|
||||
insert(this)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.tasks.data
|
||||
|
||||
import com.todoroo.astrid.api.GtasksFilter
|
||||
|
||||
fun GoogleTaskFilters.toGtasksFilter(): GtasksFilter = GtasksFilter(
|
||||
list = googleTaskList,
|
||||
count = count,
|
||||
)
|
@ -0,0 +1,28 @@
|
||||
package org.tasks.data
|
||||
|
||||
import com.todoroo.astrid.data.Task
|
||||
import org.tasks.R
|
||||
import org.tasks.preferences.Preferences
|
||||
|
||||
suspend fun LocationDao.getLocation(task: Task, preferences: Preferences): Location? {
|
||||
if (task.isNew) {
|
||||
if (task.hasTransitory(Place.KEY)) {
|
||||
getPlace(task.getTransitory<String>(Place.KEY)!!)?.let {
|
||||
return Location(createGeofence(it.uid, preferences), it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return getGeofences(task.id)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun createGeofence(
|
||||
place: String?,
|
||||
preferences: Preferences,
|
||||
defaultReminders: Int = preferences.getIntegerFromString(R.string.p_default_location_reminder_key, 1)
|
||||
) = Geofence(
|
||||
place = place,
|
||||
isArrival = defaultReminders == 1 || defaultReminders == 3,
|
||||
isDeparture = defaultReminders == 2 || defaultReminders == 3,
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
package org.tasks.data
|
||||
|
||||
import android.content.Context
|
||||
|
||||
fun Location.open(context: Context?) {
|
||||
place.open(context)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.tasks.data
|
||||
|
||||
import org.tasks.filters.PlaceFilter
|
||||
|
||||
fun LocationFilters.toLocationFilter(): PlaceFilter = PlaceFilter(
|
||||
place = place,
|
||||
count = count,
|
||||
)
|
@ -0,0 +1,12 @@
|
||||
package org.tasks.data
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import org.tasks.extensions.Context.openUri
|
||||
import org.tasks.location.MapPosition
|
||||
|
||||
fun Place.open(context: Context?) =
|
||||
context?.openUri("geo:$latitude,$longitude?q=${Uri.encode(displayName)}")
|
||||
|
||||
val Place.mapPosition: MapPosition
|
||||
get() = MapPosition(latitude, longitude)
|
@ -0,0 +1,23 @@
|
||||
package org.tasks.data
|
||||
|
||||
import org.tasks.filters.AlphanumComparator
|
||||
|
||||
suspend fun TagDataDao.searchTags(query: String): List<TagData> = searchTagsInternal("%$query%").sort()
|
||||
|
||||
private val COMPARATOR = Comparator<TagData> { f1, f2 ->
|
||||
when {
|
||||
f1.order == NO_ORDER && f2.order == NO_ORDER -> f1.id!!.compareTo(f2.id!!)
|
||||
f1.order == NO_ORDER -> 1
|
||||
f2.order == NO_ORDER -> -1
|
||||
f1.order < f2.order -> -1
|
||||
f1.order > f2.order -> 1
|
||||
else -> AlphanumComparator.TAGDATA.compare(f1, f2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<TagData>.sort(): List<TagData> =
|
||||
if (all { it.order == NO_ORDER }) {
|
||||
sortedWith(AlphanumComparator.TAGDATA)
|
||||
} else {
|
||||
sortedWith(COMPARATOR)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.tasks.data
|
||||
|
||||
import com.todoroo.astrid.api.TagFilter
|
||||
|
||||
fun TagFilters.toTagFilter(): TagFilter = TagFilter(
|
||||
tagData = tagData,
|
||||
count = count,
|
||||
)
|
@ -0,0 +1,49 @@
|
||||
package org.tasks.data
|
||||
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import com.todoroo.andlib.sql.Field
|
||||
import com.todoroo.andlib.sql.Query
|
||||
import com.todoroo.astrid.api.Filter
|
||||
import com.todoroo.astrid.api.PermaSql
|
||||
import com.todoroo.astrid.data.Task
|
||||
import org.tasks.db.SuspendDbUtils.eachChunk
|
||||
import org.tasks.preferences.QueryPreferences
|
||||
import org.tasks.time.DateTimeUtils2.currentTimeMillis
|
||||
import timber.log.Timber
|
||||
|
||||
suspend fun TaskDao.fetchTasks(preferences: QueryPreferences, filter: Filter): List<TaskContainer> =
|
||||
fetchTasks {
|
||||
TaskListQuery.getQuery(preferences, filter)
|
||||
}
|
||||
|
||||
internal suspend fun TaskDao.setCollapsed(preferences: QueryPreferences, filter: Filter, collapsed: Boolean) {
|
||||
fetchTasks(preferences, filter)
|
||||
.filter(TaskContainer::hasChildren)
|
||||
.map(TaskContainer::id)
|
||||
.eachChunk { setCollapsed(it, collapsed) }
|
||||
}
|
||||
|
||||
suspend fun TaskDao.fetchFiltered(filter: Filter): List<Task> = fetchFiltered(filter.sql!!)
|
||||
|
||||
suspend fun TaskDao.fetchFiltered(queryTemplate: String): List<Task> {
|
||||
val query = getQuery(queryTemplate, Task.FIELDS)
|
||||
val start = if (BuildConfig.DEBUG) currentTimeMillis() else 0
|
||||
val tasks = fetchTasks(query)
|
||||
Timber.v("%sms: %s", currentTimeMillis() - start, query.sql)
|
||||
return tasks.map(TaskContainer::task)
|
||||
}
|
||||
|
||||
suspend fun TaskDao.count(filter: Filter): Int {
|
||||
val query = getQuery(filter.sql!!, Field.COUNT)
|
||||
val start = if (BuildConfig.DEBUG) currentTimeMillis() else 0
|
||||
val count = countRaw(query)
|
||||
Timber.v("%sms: %s", currentTimeMillis() - start, query.sql)
|
||||
return count
|
||||
}
|
||||
|
||||
private fun getQuery(queryTemplate: String, vararg fields: Field): SimpleSQLiteQuery =
|
||||
SimpleSQLiteQuery(
|
||||
Query.select(*fields)
|
||||
.withQueryTemplate(PermaSql.replacePlaceholdersForQuery(queryTemplate))
|
||||
.from(Task.TABLE)
|
||||
.toString())
|
@ -0,0 +1,89 @@
|
||||
package org.tasks.data
|
||||
|
||||
import com.todoroo.andlib.utility.DateUtilities
|
||||
import com.todoroo.astrid.data.Task
|
||||
import net.fortuna.ical4j.model.Recur
|
||||
import org.tasks.date.DateTimeUtils
|
||||
import org.tasks.date.DateTimeUtils.toDateTime
|
||||
import org.tasks.time.DateTimeUtils.startOfDay
|
||||
|
||||
/** Checks whether task is hidden. Requires HIDDEN_UNTIL */
|
||||
val Task.isHidden
|
||||
get() = hideUntil > DateUtilities.now()
|
||||
|
||||
/**
|
||||
* Create hide until for this task.
|
||||
*
|
||||
* @param setting one of the HIDE_UNTIL_* constants
|
||||
* @param customDate if specific day is set, this value
|
||||
*/
|
||||
fun Task.createHideUntil(setting: Int, customDate: Long): Long {
|
||||
val date: Long = when (setting) {
|
||||
Task.HIDE_UNTIL_NONE -> return 0
|
||||
Task.HIDE_UNTIL_DUE, Task.HIDE_UNTIL_DUE_TIME -> dueDate
|
||||
Task.HIDE_UNTIL_DAY_BEFORE -> dueDate - DateUtilities.ONE_DAY
|
||||
Task.HIDE_UNTIL_WEEK_BEFORE -> dueDate - DateUtilities.ONE_WEEK
|
||||
Task.HIDE_UNTIL_SPECIFIC_DAY, Task.HIDE_UNTIL_SPECIFIC_DAY_TIME -> customDate
|
||||
else -> throw IllegalArgumentException("Unknown setting $setting")
|
||||
}
|
||||
if (date <= 0) {
|
||||
return date
|
||||
}
|
||||
return if (setting == Task.HIDE_UNTIL_SPECIFIC_DAY_TIME ||
|
||||
setting == Task.HIDE_UNTIL_DUE_TIME && Task.hasDueTime(dueDate)
|
||||
) {
|
||||
date.toDateTime().withSecondOfMinute(1).withMillisOfSecond(0).millis
|
||||
} else {
|
||||
date.startOfDay()
|
||||
}
|
||||
}
|
||||
|
||||
val Task.isOverdue: Boolean
|
||||
get() {
|
||||
if (isCompleted || !hasDueDate()) {
|
||||
return false
|
||||
}
|
||||
val compareTo = if (hasDueTime()) DateUtilities.now() else DateTimeUtils.newDateTime().startOfDay().millis
|
||||
return dueDate < compareTo
|
||||
}
|
||||
|
||||
fun Task.setRecurrence(rrule: Recur?) {
|
||||
recurrence = rrule?.toString()
|
||||
}
|
||||
|
||||
fun Task.hasNotes(): Boolean {
|
||||
return !notes.isNullOrEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates due date for this task. If this due date has no time associated, we move it to the last
|
||||
* millisecond of the day.
|
||||
*
|
||||
* @param setting one of the URGENCY_* constants
|
||||
* @param customDate if specific day or day & time is set, this value
|
||||
*/
|
||||
fun createDueDate(setting: Int, customDate: Long): Long {
|
||||
val date: Long = when (setting) {
|
||||
Task.URGENCY_NONE -> 0
|
||||
Task.URGENCY_TODAY -> DateUtilities.now()
|
||||
Task.URGENCY_TOMORROW -> DateUtilities.now() + DateUtilities.ONE_DAY
|
||||
Task.URGENCY_DAY_AFTER -> DateUtilities.now() + 2 * DateUtilities.ONE_DAY
|
||||
Task.URGENCY_NEXT_WEEK -> DateUtilities.now() + DateUtilities.ONE_WEEK
|
||||
Task.URGENCY_IN_TWO_WEEKS -> DateUtilities.now() + 2 * DateUtilities.ONE_WEEK
|
||||
Task.URGENCY_SPECIFIC_DAY, Task.URGENCY_SPECIFIC_DAY_TIME -> customDate
|
||||
else -> throw IllegalArgumentException("Unknown setting $setting")
|
||||
}
|
||||
if (date <= 0) {
|
||||
return date
|
||||
}
|
||||
var dueDate = DateTimeUtils.newDateTime(date).withMillisOfSecond(0)
|
||||
dueDate = if (setting != Task.URGENCY_SPECIFIC_DAY_TIME) {
|
||||
dueDate
|
||||
.withHourOfDay(12)
|
||||
.withMinuteOfHour(0)
|
||||
.withSecondOfMinute(0) // Seconds == 0 means no due time
|
||||
} else {
|
||||
dueDate.withSecondOfMinute(1) // Seconds > 0 means due time exists
|
||||
}
|
||||
return dueDate.millis
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package org.tasks.filters
|
||||
|
||||
import androidx.room.Embedded
|
||||
import com.todoroo.astrid.api.CaldavFilter
|
||||
import org.tasks.data.CaldavCalendar
|
||||
|
||||
data class CaldavFilters(
|
||||
@JvmField @Embedded val caldavCalendar: CaldavCalendar,
|
||||
@JvmField val count: Int,
|
||||
@JvmField val principals: Int,
|
||||
) {
|
||||
fun toCaldavFilter(): CaldavFilter = CaldavFilter(
|
||||
calendar = caldavCalendar,
|
||||
principals = principals,
|
||||
count = count,
|
||||
)
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.tasks.filters
|
||||
|
||||
import androidx.room.Embedded
|
||||
import com.todoroo.astrid.api.GtasksFilter
|
||||
import org.tasks.data.CaldavCalendar
|
||||
|
||||
data class GoogleTaskFilters(
|
||||
@JvmField @Embedded val googleTaskList: CaldavCalendar,
|
||||
@JvmField val count: Int,
|
||||
) {
|
||||
fun toGtasksFilter(): GtasksFilter = GtasksFilter(
|
||||
list = googleTaskList,
|
||||
count = count,
|
||||
)
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package org.tasks.filters
|
||||
|
||||
import androidx.room.Embedded
|
||||
import org.tasks.data.Place
|
||||
|
||||
data class LocationFilters(
|
||||
@JvmField @Embedded var place: Place,
|
||||
@JvmField var count: Int
|
||||
) {
|
||||
fun toLocationFilter(): PlaceFilter = PlaceFilter(
|
||||
place = place,
|
||||
count = count,
|
||||
)
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.tasks.filters
|
||||
|
||||
import androidx.room.Embedded
|
||||
import com.todoroo.astrid.api.TagFilter
|
||||
import org.tasks.data.TagData
|
||||
|
||||
data class TagFilters(
|
||||
@JvmField @Embedded var tagData: TagData,
|
||||
@JvmField var count: Int,
|
||||
) {
|
||||
fun toTagFilter(): TagFilter = TagFilter(
|
||||
tagData = tagData,
|
||||
count = count,
|
||||
)
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.tasks.time;
|
||||
|
||||
public class FixedMillisProvider implements MillisProvider {
|
||||
|
||||
private final long millis;
|
||||
|
||||
public FixedMillisProvider(long millis) {
|
||||
this.millis = millis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMillis() {
|
||||
return millis;
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package org.tasks.time;
|
||||
|
||||
interface MillisProvider {
|
||||
|
||||
long getMillis();
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.tasks.time;
|
||||
|
||||
public class SystemMillisProvider implements MillisProvider {
|
||||
|
||||
@Override
|
||||
public long getMillis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue