Convert GoogleTask to CaldavTask

pull/2146/head
Alex Baker 3 years ago
parent 513f8b017f
commit 2006e2c84b

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 88, "version": 88,
"identityHash": "d9d2cc4048325dbde272d8d4f8e3880f", "identityHash": "8ddd120bc22139ab9c9d69dbc727df37",
"entities": [ "entities": [
{ {
"tableName": "notification", "tableName": "notification",
@ -725,118 +725,6 @@
} }
] ]
}, },
{
"tableName": "google_tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`gt_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `gt_task` INTEGER NOT NULL, `gt_remote_id` TEXT, `gt_list_id` TEXT, `gt_parent` INTEGER NOT NULL, `gt_remote_parent` TEXT, `gt_moved` INTEGER NOT NULL, `gt_order` INTEGER NOT NULL, `gt_remote_order` INTEGER NOT NULL, `gt_last_sync` INTEGER NOT NULL, `gt_deleted` INTEGER NOT NULL, FOREIGN KEY(`gt_task`) REFERENCES `tasks`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
"columnName": "gt_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "task",
"columnName": "gt_task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteId",
"columnName": "gt_remote_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "listId",
"columnName": "gt_list_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "parent",
"columnName": "gt_parent",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteParent",
"columnName": "gt_remote_parent",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isMoved",
"columnName": "gt_moved",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "order",
"columnName": "gt_order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteOrder",
"columnName": "gt_remote_order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "lastSync",
"columnName": "gt_last_sync",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "deleted",
"columnName": "gt_deleted",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"gt_id"
],
"autoGenerate": true
},
"indices": [
{
"name": "gt_list_parent",
"unique": false,
"columnNames": [
"gt_list_id",
"gt_parent"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `gt_list_parent` ON `${TABLE_NAME}` (`gt_list_id`, `gt_parent`)"
},
{
"name": "index_google_tasks_gt_task",
"unique": false,
"columnNames": [
"gt_task"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_google_tasks_gt_task` ON `${TABLE_NAME}` (`gt_task`)"
}
],
"foreignKeys": [
{
"table": "tasks",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"gt_task"
],
"referencedColumns": [
"_id"
]
}
]
},
{ {
"tableName": "filters", "tableName": "filters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT, `sql` TEXT, `values` TEXT, `criterion` TEXT, `f_color` INTEGER, `f_icon` INTEGER, `f_order` INTEGER NOT NULL)", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT, `sql` TEXT, `values` TEXT, `criterion` TEXT, `f_color` INTEGER, `f_icon` INTEGER, `f_order` INTEGER NOT NULL)",
@ -981,7 +869,7 @@
}, },
{ {
"tableName": "caldav_tasks", "tableName": "caldav_tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cd_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `cd_task` INTEGER NOT NULL, `cd_calendar` TEXT, `cd_object` TEXT, `cd_remote_id` TEXT, `cd_etag` TEXT, `cd_last_sync` INTEGER NOT NULL, `cd_deleted` INTEGER NOT NULL, `cd_remote_parent` TEXT, `cd_order` INTEGER, FOREIGN KEY(`cd_task`) REFERENCES `tasks`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE )", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cd_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `cd_task` INTEGER NOT NULL, `cd_calendar` TEXT, `cd_object` TEXT, `cd_remote_id` TEXT, `cd_etag` TEXT, `cd_last_sync` INTEGER NOT NULL, `cd_deleted` INTEGER NOT NULL, `cd_remote_parent` TEXT, `gt_moved` INTEGER NOT NULL, `gt_remote_order` INTEGER NOT NULL, `gt_parent` INTEGER NOT NULL, `cd_order` INTEGER, FOREIGN KEY(`cd_task`) REFERENCES `tasks`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -1037,6 +925,24 @@
"affinity": "TEXT", "affinity": "TEXT",
"notNull": false "notNull": false
}, },
{
"fieldPath": "isMoved",
"columnName": "gt_moved",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteOrder",
"columnName": "gt_remote_order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "parent",
"columnName": "gt_parent",
"affinity": "INTEGER",
"notNull": true
},
{ {
"fieldPath": "order", "fieldPath": "order",
"columnName": "cd_order", "columnName": "cd_order",
@ -1397,7 +1303,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd9d2cc4048325dbde272d8d4f8e3880f')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8ddd120bc22139ab9c9d69dbc727df37')"
] ]
} }
} }

@ -13,7 +13,6 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Test import org.junit.Test
import org.tasks.data.GoogleTask
import org.tasks.data.GoogleTaskDao import org.tasks.data.GoogleTaskDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule

@ -49,7 +49,7 @@ class TaskMoverTest : InjectingTestCase() {
createTasks(1) createTasks(1)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1"))) googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
moveToGoogleTasks("2", 1) moveToGoogleTasks("2", 1)
assertEquals("2", googleTaskDao.getByTaskId(1)!!.listId) assertEquals("2", googleTaskDao.getByTaskId(1)!!.calendar)
} }
@Test @Test
@ -75,7 +75,7 @@ class TaskMoverTest : InjectingTestCase() {
assertTrue(deleted[0].deleted > 0) assertTrue(deleted[0].deleted > 0)
val task = googleTaskDao.getByTaskId(2)!! val task = googleTaskDao.getByTaskId(2)!!
assertEquals(1, task.parent) assertEquals(1, task.parent)
assertEquals("2", task.listId) assertEquals("2", task.calendar)
} }
@Test @Test
@ -194,7 +194,7 @@ class TaskMoverTest : InjectingTestCase() {
moveToGoogleTasks("2", 2) moveToGoogleTasks("2", 2)
val task = googleTaskDao.getByTaskId(2)!! val task = googleTaskDao.getByTaskId(2)!!
assertEquals(0L, task.parent) assertEquals(0L, task.parent)
assertEquals("2", task.listId) assertEquals("2", task.calendar)
} }
@Test @Test
@ -228,7 +228,7 @@ class TaskMoverTest : InjectingTestCase() {
createTasks(1) createTasks(1)
caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"))) caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1")))
moveToGoogleTasks("2", 1) moveToGoogleTasks("2", 1)
assertEquals("2", googleTaskDao.getByTaskId(1L)!!.listId) assertEquals("2", googleTaskDao.getByTaskId(1L)!!.calendar)
} }
@Test @Test

@ -264,7 +264,7 @@ class GoogleTaskDaoTests : InjectingTestCase() {
val googleTask = googleTaskDao.getByRemoteId(remoteId)!! val googleTask = googleTaskDao.getByRemoteId(remoteId)!!
val result = SubsetGoogleTask() val result = SubsetGoogleTask()
result.gt_id = googleTask.id result.gt_id = googleTask.id
result.gt_list_id = googleTask.listId result.gt_list_id = googleTask.calendar
result.gt_order = googleTask.order result.gt_order = googleTask.order
result.gt_parent = googleTask.parent result.gt_parent = googleTask.parent
return result return result

@ -980,7 +980,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
companion object { companion object {
const val TAGS_METADATA_JOIN = "for_tags" // $NON-NLS-1$ const val TAGS_METADATA_JOIN = "for_tags" // $NON-NLS-1$
const val GTASK_METADATA_JOIN = "googletask" // $NON-NLS-1$
const val CALDAV_METADATA_JOIN = "for_caldav" // $NON-NLS-1$ const val CALDAV_METADATA_JOIN = "for_caldav" // $NON-NLS-1$
const val ACTION_RELOAD = "action_reload" const val ACTION_RELOAD = "action_reload"
const val ACTION_DELETED = "action_deleted" const val ACTION_DELETED = "action_deleted"

@ -15,21 +15,21 @@ class GoogleTaskManualSortAdapter internal constructor(
override suspend fun moved(from: Int, to: Int, indent: Int) { override suspend fun moved(from: Int, to: Int, indent: Int) {
val task = getTask(from) val task = getTask(from)
val googleTask = task.googleTask val googleTask = task.caldavTask
val previous = if (to > 0) getTask(to - 1) else null val previous = if (to > 0) getTask(to - 1) else null
if (previous == null) { if (previous == null) {
googleTaskDao.move(googleTask, 0, 0) googleTaskDao.move(googleTask, 0, 0)
} else if (to == count || to <= from) { } else if (to == count || to <= from) {
when { when {
indent == 0 -> googleTaskDao.move(googleTask, 0, previous.getPrimarySort() + if (to == count) 0 else 1) indent == 0 -> googleTaskDao.move(googleTask, 0, previous.getPrimarySort() + if (to == count) 0 else 1)
previous.hasParent() && previous.parent == googleTask.parent -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort() + if (to == count) 0 else 1) previous.hasParent() && previous.parent == task.parent -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort() + if (to == count) 0 else 1)
previous.hasParent() -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort() + 1) previous.hasParent() -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort() + 1)
else -> googleTaskDao.move(googleTask, previous.id, 0) else -> googleTaskDao.move(googleTask, previous.id, 0)
} }
} else { } else {
when { when {
indent == 0 -> googleTaskDao.move(googleTask, 0, previous.getPrimarySort() + if (task.hasParent()) 1 else 0) indent == 0 -> googleTaskDao.move(googleTask, 0, previous.getPrimarySort() + if (task.hasParent()) 1 else 0)
previous.hasParent() && previous.parent == googleTask.parent -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort()) previous.hasParent() && previous.parent == task.parent -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort())
previous.hasParent() -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort() + 1) previous.hasParent() -> googleTaskDao.move(googleTask, previous.parent, previous.getSecondarySort() + 1)
else -> googleTaskDao.move(googleTask, previous.id, 0) else -> googleTaskDao.move(googleTask, previous.id, 0)
} }
@ -37,7 +37,7 @@ class GoogleTaskManualSortAdapter internal constructor(
taskDao.touch(task.id) taskDao.touch(task.id)
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
googleTaskDao.validateSorting(task.googleTaskList!!) googleTaskDao.validateSorting(task.caldav!!)
} }
} }
} }

@ -135,21 +135,15 @@ open class TaskAdapter(
open suspend fun moved(from: Int, to: Int, indent: Int) { open suspend fun moved(from: Int, to: Int, indent: Int) {
val task = getTask(from) val task = getTask(from)
val newParent = findParent(indent, to) val newParent = findParent(indent, to)
if (newParent?.id ?: 0 == task.parent) { if ((newParent?.id ?: 0) == task.parent) {
if (indent == 0) { if (indent == 0) {
changeSortGroup(task, if (from < to) to - 1 else to) changeSortGroup(task, if (from < to) to - 1 else to)
} }
return return
} else if (newParent != null) { } else if (newParent != null) {
when { if (task.caldav != newParent.caldav) {
task.isGoogleTask -> if (task.googleTaskList != newParent.googleTaskList) { caldavDao.markDeleted(listOf(task.id))
googleTaskDao.markDeleted(task.id) task.caldavTask = null
task.googletask = null
}
task.isCaldavTask -> if (task.caldav != newParent.caldav) {
caldavDao.markDeleted(listOf(task.id))
task.caldavTask = null
}
} }
} }
when { when {
@ -250,20 +244,21 @@ open class TaskAdapter(
} }
private suspend fun changeGoogleTaskParent(task: TaskContainer, newParent: TaskContainer?) { private suspend fun changeGoogleTaskParent(task: TaskContainer, newParent: TaskContainer?) {
val list = newParent?.googleTaskList ?: task.googleTaskList!! val list = newParent?.caldav ?: task.caldav!!
if (newParent == null || task.googleTaskList == newParent.googleTaskList) { if (newParent == null || task.caldav == newParent.caldav) {
googleTaskDao.move( googleTaskDao.move(
task.googleTask, task.caldavTask,
newParent?.id ?: 0, newParent?.id ?: 0,
if (newTasksOnTop) 0 else googleTaskDao.getBottom(list, newParent?.id ?: 0)) if (newTasksOnTop) 0 else googleTaskDao.getBottom(list, newParent?.id ?: 0)
)
} else { } else {
val googleTask = GoogleTask(task.id, list) val googleTask = CaldavTask(task.id, list)
googleTask.parent = newParent.id googleTask.parent = newParent.id
googleTaskDao.insertAndShift(googleTask, newTasksOnTop) googleTaskDao.insertAndShift(googleTask, newTasksOnTop)
task.googletask = SubsetGoogleTask().apply { task.caldavTask = SubsetCaldav().apply {
gt_id = googleTask.id cd_id = googleTask.id
gt_list_id = googleTask.listId cd_calendar = googleTask.calendar
gt_order = googleTask.order cd_order = googleTask.order ?: 0
gt_parent = googleTask.parent gt_parent = googleTask.parent
} }
} }

@ -12,6 +12,7 @@ import com.todoroo.astrid.data.Task;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.CaldavCalendar; import org.tasks.data.CaldavCalendar;
import org.tasks.data.CaldavTask;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.TaskDao; import org.tasks.data.TaskDao;
@ -57,12 +58,12 @@ public class GtasksFilter extends Filter {
private static QueryTemplate getQueryTemplate(CaldavCalendar list) { private static QueryTemplate getQueryTemplate(CaldavCalendar list) {
return new QueryTemplate() return new QueryTemplate()
.join(Join.left(GoogleTask.TABLE, Task.ID.eq(GoogleTask.TASK))) .join(Join.left(CaldavTask.TABLE, Task.ID.eq(CaldavTask.TASK)))
.where( .where(
Criterion.and( Criterion.and(
TaskDao.TaskCriteria.activeAndVisible(), TaskDao.TaskCriteria.activeAndVisible(),
GoogleTask.DELETED.eq(0), CaldavTask.DELETED.eq(0),
GoogleTask.LIST.eq(list.getUuid()))); CaldavTask.CALENDAR.eq(list.getUuid())));
} }
private static Map<String, Object> getValuesForNewTasks(CaldavCalendar list) { private static Map<String, Object> getValuesForNewTasks(CaldavCalendar list) {

@ -61,11 +61,6 @@ class SearchFilter : Filter {
.from(CaldavTask.TABLE) .from(CaldavTask.TABLE)
.join(Join.inner(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR))) .join(Join.inner(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR)))
.where(CaldavCalendar.NAME.like(matcher))), .where(CaldavCalendar.NAME.like(matcher))),
Task.ID.`in`(
Query.select(GoogleTask.TASK)
.from(GoogleTask.TABLE)
.join(Join.inner(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(GoogleTask.LIST)))
.where(CaldavCalendar.NAME.like(matcher)))
))) )))
} }
} }

@ -101,9 +101,8 @@ class BuiltInFilterExposer @Inject constructor(
Filter( Filter(
"No list", "No list",
QueryTemplate() QueryTemplate()
.join(Join.left(GoogleTask.TABLE, GoogleTask.TASK.eq(Task.ID)))
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID))) .join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.where(and(GoogleTask.ID.eq(null), CaldavTask.ID.eq(null))) .where(CaldavTask.ID.eq(null))
).apply { ).apply {
icon = R.drawable.ic_outline_cloud_off_24px icon = R.drawable.ic_outline_cloud_off_24px
} }
@ -116,13 +115,9 @@ class BuiltInFilterExposer @Inject constructor(
Filter( Filter(
"Missing list", "Missing list",
QueryTemplate() QueryTemplate()
.join(Join.left(GoogleTask.TABLE, GoogleTask.TASK.eq(Task.ID)))
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID))) .join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.join(Join.left(CaldavCalendar.TABLE.`as`("google_task_lists"), CaldavCalendar.TABLE.`as`("google_task_lists").column("cdl_uuid").eq(GoogleTask.LIST)))
.join(Join.left(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR))) .join(Join.left(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR)))
.where(or( .where(and(CaldavTask.ID.gt(0), CaldavCalendar.UUID.eq(null)))
and(GoogleTask.ID.gt(0), CaldavCalendar.TABLE.`as`("google_task_lists").column("cdl_uuid").eq(null)),
and(CaldavTask.ID.gt(0), CaldavCalendar.UUID.eq(null))))
).apply { ).apply {
icon = R.drawable.ic_outline_cloud_off_24px icon = R.drawable.ic_outline_cloud_off_24px
} }
@ -131,14 +126,10 @@ class BuiltInFilterExposer @Inject constructor(
Filter( Filter(
"Missing account", "Missing account",
QueryTemplate() QueryTemplate()
.join(Join.left(GoogleTask.TABLE, and(GoogleTask.TASK.eq(Task.ID))))
.join(Join.left(CaldavTask.TABLE, and(CaldavTask.TASK.eq(Task.ID)))) .join(Join.left(CaldavTask.TABLE, and(CaldavTask.TASK.eq(Task.ID))))
.join(Join.left(CaldavCalendar.TABLE.`as`("google_task_lists"), CaldavCalendar.TABLE.`as`("google_task_lists").column("cdl_uuid").eq(GoogleTask.LIST)))
.join(Join.left(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR))) .join(Join.left(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR)))
.join(Join.left(CaldavAccount.TABLE, CaldavAccount.UUID.eq(CaldavCalendar.ACCOUNT))) .join(Join.left(CaldavAccount.TABLE, CaldavAccount.UUID.eq(CaldavCalendar.ACCOUNT)))
.where(or( .where(and(CaldavTask.ID.gt(0), CaldavAccount.UUID.eq(null)))
and(GoogleTask.ID.gt(0), CaldavCalendar.TABLE.`as`("google_task_lists").column("cdl_uuid").eq(null)),
and(CaldavTask.ID.gt(0), CaldavAccount.UUID.eq(null))))
).apply { ).apply {
icon = R.drawable.ic_outline_cloud_off_24px icon = R.drawable.ic_outline_cloud_off_24px
} }

@ -176,7 +176,7 @@ public class SortHelper {
select = "tasks.created AS sort_created"; select = "tasks.created AS sort_created";
break; break;
case SORT_GTASKS: case SORT_GTASKS:
select = "google_tasks.gt_order AS sort_manual"; select = "caldav_tasks.cd_order AS sort_manual";
break; break;
case SORT_CALDAV: case SORT_CALDAV:
select = CALDAV_ORDER_COLUMN + " AS sort_manual"; select = CALDAV_ORDER_COLUMN + " AS sort_manual";

@ -22,7 +22,6 @@ import org.tasks.notifications.NotificationDao
Place::class, Place::class,
Geofence::class, Geofence::class,
Tag::class, Tag::class,
GoogleTask::class,
Filter::class, Filter::class,
CaldavCalendar::class, CaldavCalendar::class,
CaldavTask::class, CaldavTask::class,

@ -53,7 +53,7 @@ class GtasksListService @Inject constructor(
// check for lists that aren't on remote server // check for lists that aren't on remote server
for (listId in previousLists) { for (listId in previousLists) {
taskDeleter.deleteGoogleTaskList(googleTaskListDao.getById(listId)!!) taskDeleter.delete(googleTaskListDao.getById(listId)!!)
} }
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()
} }

@ -55,7 +55,7 @@ class TaskCreator @Inject constructor(
val addToTop = preferences.addTasksToTop() val addToTop = preferences.addTasksToTop()
if (task.hasTransitory(GoogleTask.KEY)) { if (task.hasTransitory(GoogleTask.KEY)) {
googleTaskDao.insertAndShift( googleTaskDao.insertAndShift(
GoogleTask(task.id, task.getTransitory<String>(GoogleTask.KEY)!!), addToTop) CaldavTask(task.id, task.getTransitory<String>(GoogleTask.KEY)!!), addToTop)
} else if (task.hasTransitory(CaldavTask.KEY)) { } else if (task.hasTransitory(CaldavTask.KEY)) {
caldavDao.insert( caldavDao.insert(
task, CaldavTask(task.id, task.getTransitory<String>(CaldavTask.KEY)), addToTop) task, CaldavTask(task.id, task.getTransitory<String>(CaldavTask.KEY)), addToTop)
@ -63,7 +63,7 @@ class TaskCreator @Inject constructor(
val remoteList = defaultFilterProvider.getDefaultList() val remoteList = defaultFilterProvider.getDefaultList()
if (remoteList is GtasksFilter) { if (remoteList is GtasksFilter) {
googleTaskDao.insertAndShift( googleTaskDao.insertAndShift(
GoogleTask(task.id, remoteList.remoteId), addToTop) CaldavTask(task.id, remoteList.remoteId), addToTop)
} else if (remoteList is CaldavFilter) { } else if (remoteList is CaldavFilter) {
caldavDao.insert( caldavDao.insert(
task, CaldavTask(task.id, remoteList.uuid), addToTop) task, CaldavTask(task.id, remoteList.uuid), addToTop)

@ -2,7 +2,6 @@ package com.todoroo.astrid.service
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import kotlinx.coroutines.runBlocking
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.caldav.VtodoCache import org.tasks.caldav.VtodoCache
import org.tasks.data.* import org.tasks.data.*
@ -66,12 +65,6 @@ class TaskDeleter @Inject constructor(
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
} }
fun deleteGoogleTaskList(list: CaldavCalendar) = runBlocking {
val tasks = deletionDao.deleteGoogleTaskList(list)
delete(tasks)
localBroadcastManager.broadcastRefreshList()
}
suspend fun delete(list: CaldavCalendar) { suspend fun delete(list: CaldavCalendar) {
vtodoCache.delete(list) vtodoCache.delete(list)
val tasks = deletionDao.delete(list) val tasks = deletionDao.delete(list)

@ -58,7 +58,7 @@ class TaskDuplicator @Inject constructor(
val googleTask = googleTaskDao.getByTaskId(originalId) val googleTask = googleTaskDao.getByTaskId(originalId)
val addToTop = preferences.addTasksToTop() val addToTop = preferences.addTasksToTop()
if (googleTask != null) { if (googleTask != null) {
googleTaskDao.insertAndShift(GoogleTask(clone.id, googleTask.listId!!), addToTop) googleTaskDao.insertAndShift(CaldavTask(clone.id, googleTask.calendar!!), addToTop)
} }
val caldavTask = caldavDao.getTask(originalId) val caldavTask = caldavDao.getTask(originalId)
if (caldavTask != null) { if (caldavTask != null) {

@ -82,21 +82,21 @@ class TaskMover @Inject constructor(
moveLocalTask(task, selectedList) moveLocalTask(task, selectedList)
} }
private suspend fun moveGoogleTask(task: Task, googleTask: GoogleTask, selected: Filter) { private suspend fun moveGoogleTask(task: Task, googleTask: CaldavTask, selected: Filter) {
if (selected is GtasksFilter && googleTask.listId == selected.remoteId) { if (selected is GtasksFilter && googleTask.calendar == selected.remoteId) {
return return
} }
val id = googleTask.task val id = googleTask.task
val children = googleTaskDao.getChildren(id) val children = googleTaskDao.getChildren(id)
val childIds = children.map(GoogleTask::task) val childIds = children.map(CaldavTask::task)
googleTaskDao.markDeleted(id, DateUtilities.now()) googleTaskDao.markDeleted(id, DateUtilities.now())
when(selected) { when(selected) {
is GtasksFilter -> { is GtasksFilter -> {
val listId = selected.remoteId val listId = selected.remoteId
googleTaskDao.insertAndShift(GoogleTask(id, listId), preferences.addTasksToTop()) googleTaskDao.insertAndShift(CaldavTask(id, listId), preferences.addTasksToTop())
children.takeIf { it.isNotEmpty() } children.takeIf { it.isNotEmpty() }
?.map { ?.map {
val newChild = GoogleTask(it.task, listId) val newChild = CaldavTask(it.task, listId)
newChild.order = it.order newChild.order = it.order
newChild.parent = id newChild.parent = id
newChild newChild
@ -178,10 +178,10 @@ class TaskMover @Inject constructor(
private suspend fun moveToGoogleTasks(id: Long, children: List<Long>, filter: GtasksFilter) { private suspend fun moveToGoogleTasks(id: Long, children: List<Long>, filter: GtasksFilter) {
taskDao.setParent(0, children) taskDao.setParent(0, children)
val listId = filter.remoteId val listId = filter.remoteId
googleTaskDao.insertAndShift(GoogleTask(id, listId), preferences.addTasksToTop()) googleTaskDao.insertAndShift(CaldavTask(id, listId), preferences.addTasksToTop())
children.takeIf { it.isNotEmpty() } children.takeIf { it.isNotEmpty() }
?.mapIndexed { index, task -> ?.mapIndexed { index, task ->
val newChild = GoogleTask(task, listId) val newChild = CaldavTask(task, listId)
newChild.order = index.toLong() newChild.order = index.toLong()
newChild.parent = id newChild.parent = id
newChild newChild

@ -8,6 +8,7 @@ import android.view.View
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.ProgressBar import android.widget.ProgressBar
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import com.google.api.services.tasks.model.TaskList import com.google.api.services.tasks.model.TaskList
import com.todoroo.astrid.activity.MainActivity import com.todoroo.astrid.activity.MainActivity
@ -15,6 +16,9 @@ import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.api.GtasksFilter import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.CaldavAccount import org.tasks.data.CaldavAccount
@ -177,9 +181,13 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private fun onListDeleted(deleted: Boolean) { private fun onListDeleted(deleted: Boolean) {
if (deleted) { if (deleted) {
taskDeleter.deleteGoogleTaskList(gtasksList) lifecycleScope.launch {
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED)) withContext(NonCancellable) {
finish() taskDeleter.delete(gtasksList)
}
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED))
finish()
}
} }
} }

@ -26,11 +26,11 @@ class BackupContainer(
val alarms: List<Alarm>, val alarms: List<Alarm>,
val geofences: List<Geofence>?, val geofences: List<Geofence>?,
val tags: List<Tag>, val tags: List<Tag>,
val google: List<GoogleTask>,
val comments: List<UserActivity>, val comments: List<UserActivity>,
val attachments: List<Attachment>?, val attachments: List<Attachment>?,
val caldavTasks: List<CaldavTask>?, val caldavTasks: List<CaldavTask>?,
val vtodo: String?, val vtodo: String?,
val google: List<GoogleTask> = emptyList(),
) { ) {
val locations: List<LegacyLocation> = emptyList() val locations: List<LegacyLocation> = emptyList()
} }

@ -37,9 +37,7 @@ class TasksJsonExporter @Inject constructor(
private val alarmDao: AlarmDao, private val alarmDao: AlarmDao,
private val locationDao: LocationDao, private val locationDao: LocationDao,
private val tagDao: TagDao, private val tagDao: TagDao,
private val googleTaskDao: GoogleTaskDao,
private val filterDao: FilterDao, private val filterDao: FilterDao,
private val googleTaskListDao: GoogleTaskListDao,
private val taskAttachmentDao: TaskAttachmentDao, private val taskAttachmentDao: TaskAttachmentDao,
private val caldavDao: CaldavDao, private val caldavDao: CaldavDao,
private val workManager: WorkManager, private val workManager: WorkManager,
@ -117,7 +115,6 @@ class TasksJsonExporter @Inject constructor(
alarmDao.getAlarms(taskId), alarmDao.getAlarms(taskId),
locationDao.getGeofencesForTask(taskId), locationDao.getGeofencesForTask(taskId),
tagDao.getTagsForTask(taskId), tagDao.getTagsForTask(taskId),
googleTaskDao.getAllByTaskId(taskId),
userActivityDao.getComments(taskId), userActivityDao.getComments(taskId),
taskAttachmentDao.getAttachmentsForTask(taskId), taskAttachmentDao.getAttachmentsForTask(taskId),
caldavTasks, caldavTasks,

@ -187,8 +187,14 @@ class TasksJsonImporter @Inject constructor(
userActivityDao.createNew(comment) userActivityDao.createNew(comment)
} }
for (googleTask in backup.google) { for (googleTask in backup.google) {
googleTask.task = taskId googleTaskDao.insert(
googleTaskDao.insert(googleTask) CaldavTask(
task = taskId,
calendar = googleTask.listId,
remoteId = googleTask.remoteId,
`object` = null,
)
)
} }
for (location in backup.locations) { for (location in backup.locations) {
val place = newPlace() val place = newPlace()

@ -28,13 +28,13 @@ import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import org.tasks.compose.* import org.tasks.compose.*
import org.tasks.data.GoogleTask import org.tasks.data.CaldavTask
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
@Composable @Composable
fun SubtaskRow( fun SubtaskRow(
filter: Filter?, filter: Filter?,
googleTask: GoogleTask?, googleTask: CaldavTask?,
desaturate: Boolean, desaturate: Boolean,
existingSubtasks: List<TaskContainer>, existingSubtasks: List<TaskContainer>,
newSubtasks: List<Task>, newSubtasks: List<Task>,
@ -63,7 +63,7 @@ fun SubtaskRow(
Column { Column {
val isGoogleTaskChild = val isGoogleTaskChild =
filter is GtasksFilter && googleTask != null && googleTask.parent > 0 && googleTask.listId == filter.remoteId filter is GtasksFilter && googleTask != null && googleTask.parent > 0 && googleTask.calendar == filter.remoteId
if (isGoogleTaskChild) { if (isGoogleTaskChild) {
DisabledText( DisabledText(
text = stringResource(id = org.tasks.R.string.subtasks_multilevel_google_task), text = stringResource(id = org.tasks.R.string.subtasks_multilevel_google_task),

@ -230,6 +230,7 @@ class CaldavAccount : Parcelable {
companion object { companion object {
val TABLE = Table("caldav_accounts") val TABLE = Table("caldav_accounts")
val UUID = TABLE.column("cda_uuid") val UUID = TABLE.column("cda_uuid")
val ACCOUNT_TYPE = TABLE.column("cda_account_type")
const val TYPE_CALDAV = 0 const val TYPE_CALDAV = 0
@Deprecated("use etebase") const val TYPE_ETESYNC = 1 @Deprecated("use etebase") const val TYPE_ETESYNC = 1

@ -108,10 +108,26 @@ ORDER BY CASE cda_account_type
return insert(caldavTask) return insert(caldavTask)
} }
@Query("SELECT MIN(IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000)) FROM caldav_tasks INNER JOIN tasks ON _id = cd_task WHERE cd_calendar = :calendar AND cd_deleted = 0 AND deleted = 0 AND parent = :parent") @Query("""
SELECT MIN(IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000))
FROM caldav_tasks
INNER JOIN tasks ON _id = cd_task
WHERE cd_calendar = :calendar
AND cd_deleted = 0
AND deleted = 0
AND parent = :parent
""")
internal abstract suspend fun findFirstTask(calendar: String, parent: Long): Long? internal abstract suspend fun findFirstTask(calendar: String, parent: Long): Long?
@Query("SELECT MAX(IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000)) FROM caldav_tasks INNER JOIN tasks ON _id = cd_task WHERE cd_calendar = :calendar AND cd_deleted = 0 AND deleted = 0 AND parent = :parent") @Query("""
SELECT MAX(IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000))
FROM caldav_tasks
INNER JOIN tasks ON _id = cd_task
WHERE cd_calendar = :calendar
AND cd_deleted = 0
AND deleted = 0
AND parent = :parent
""")
internal abstract suspend fun findLastTask(calendar: String, parent: Long): Long? internal abstract suspend fun findLastTask(calendar: String, parent: Long): Long?
@Insert @Insert
@ -250,12 +266,16 @@ SELECT EXISTS(SELECT 1
@Query(""" @Query("""
SELECT caldav_lists.*, COUNT(DISTINCT(tasks._id)) AS count, COUNT(DISTINCT(principal_access.id)) AS principals SELECT caldav_lists.*, COUNT(DISTINCT(tasks._id)) AS count, COUNT(DISTINCT(principal_access.id)) AS principals
FROM caldav_lists FROM caldav_lists
LEFT JOIN caldav_tasks LEFT JOIN caldav_tasks ON caldav_tasks.cd_calendar = caldav_lists.cdl_uuid
ON caldav_tasks.cd_calendar = caldav_lists.cdl_uuid LEFT JOIN tasks ON caldav_tasks.cd_task = tasks._id AND
LEFT JOIN tasks ON caldav_tasks.cd_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.deleted = 0 AND
tasks.hideUntil < :now AND cd_deleted = 0 tasks.completed = 0 AND
tasks.hideUntil < :now AND
cd_deleted = 0
LEFT JOIN principal_access ON caldav_lists.cdl_id = principal_access.list LEFT JOIN principal_access ON caldav_lists.cdl_id = principal_access.list
INNER JOIN caldav_accounts ON caldav_accounts.cda_uuid = caldav_lists.cdl_account
WHERE caldav_lists.cdl_account = :uuid WHERE caldav_lists.cdl_account = :uuid
AND caldav_accounts.cda_account_type != $TYPE_GOOGLE_TASKS
GROUP BY caldav_lists.cdl_uuid GROUP BY caldav_lists.cdl_uuid
""") """)
abstract suspend fun getCaldavFilters(uuid: String, now: Long = currentTimeMillis()): List<CaldavFilters> abstract suspend fun getCaldavFilters(uuid: String, now: Long = currentTimeMillis()): List<CaldavFilters>
@ -321,7 +341,18 @@ GROUP BY caldav_lists.cdl_uuid
@Query("UPDATE tasks SET modified = :modificationTime WHERE _id in (:ids)") @Query("UPDATE tasks SET modified = :modificationTime WHERE _id in (:ids)")
internal abstract suspend fun touchInternal(ids: List<Long>, modificationTime: Long = now()) internal abstract suspend fun touchInternal(ids: List<Long>, modificationTime: Long = now())
@Query("SELECT task.*, caldav_task.*, IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000) AS primary_sort FROM caldav_tasks AS caldav_task INNER JOIN tasks AS task ON _id = cd_task WHERE cd_calendar = :calendar AND parent = :parent AND cd_deleted = 0 AND deleted = 0 AND primary_sort >= :from AND primary_sort < IFNULL(:to, ${Long.MAX_VALUE}) ORDER BY primary_sort") @Query("""
SELECT task.*, caldav_task.*, IFNULL(cd_order, (created - $APPLE_EPOCH) / 1000) AS primary_sort
FROM caldav_tasks AS caldav_task
INNER JOIN tasks AS task ON _id = cd_task
WHERE cd_calendar = :calendar
AND parent = :parent
AND cd_deleted = 0
AND deleted = 0
AND primary_sort >= :from
AND primary_sort < IFNULL(:to, ${Long.MAX_VALUE})
ORDER BY primary_sort
""")
internal abstract suspend fun getTasksToShift(calendar: String, parent: Long, from: Long, to: Long?): List<CaldavTaskContainer> internal abstract suspend fun getTasksToShift(calendar: String, parent: Long, from: Long, to: Long?): List<CaldavTaskContainer>
@Query("UPDATE caldav_lists SET cdl_order = $NO_ORDER") @Query("UPDATE caldav_lists SET cdl_order = $NO_ORDER")

@ -52,8 +52,18 @@ class CaldavTask {
@ColumnInfo(name = "cd_remote_parent") @ColumnInfo(name = "cd_remote_parent")
var remoteParent: String? = null var remoteParent: String? = null
@ColumnInfo(name = "cd_order") @ColumnInfo(name = "gt_moved")
var isMoved: Boolean = false
@ColumnInfo(name = "gt_remote_order")
var remoteOrder: Long = 0
@ColumnInfo(name = "gt_parent")
var parent: Long = 0
@Transient @Transient
@Deprecated("For google tasks and importing old backup files")
@ColumnInfo(name = "cd_order")
var order: Long? = null var order: Long? = null
constructor() constructor()
@ -83,8 +93,9 @@ class CaldavTask {
const val KEY = "caldav" const val KEY = "caldav"
@JvmField val TABLE = Table("caldav_tasks") @JvmField val TABLE = Table("caldav_tasks")
val ID = TABLE.column("cd_id") val ID = TABLE.column("cd_id")
val PARENT = TABLE.column("gt_parent")
@JvmField val TASK = TABLE.column("cd_task") @JvmField val TASK = TABLE.column("cd_task")
@JvmField val DELETED = TABLE.column("cd_deleted") @JvmField val DELETED = TABLE.column("cd_deleted")
@JvmField val CALENDAR = TABLE.column("cd_calendar") @JvmField val CALENDAR = TABLE.column("cd_calendar")
} }
} }

@ -55,17 +55,6 @@ WHERE recurring = 1
ids.eachChunk(this::markDeletedInternal) ids.eachChunk(this::markDeletedInternal)
} }
@Query("SELECT gt_task FROM google_tasks WHERE gt_deleted = 0 AND gt_list_id = :listId")
internal abstract suspend fun getActiveGoogleTasks(listId: String): List<Long>
@Transaction
open suspend fun deleteGoogleTaskList(googleTaskList: CaldavCalendar): List<Long> {
val tasks = getActiveGoogleTasks(googleTaskList.uuid!!)
delete(tasks)
delete(googleTaskList)
return tasks
}
@Query("SELECT * FROM caldav_lists WHERE cdl_account = :account ORDER BY cdl_name ASC") @Query("SELECT * FROM caldav_lists WHERE cdl_account = :account ORDER BY cdl_name ASC")
abstract suspend fun getLists(account: String): List<CaldavCalendar> abstract suspend fun getLists(account: String): List<CaldavCalendar>
@ -95,14 +84,8 @@ WHERE recurring = 1
@Transaction @Transaction
open suspend fun delete(caldavAccount: CaldavAccount): List<Long> { open suspend fun delete(caldavAccount: CaldavAccount): List<Long> {
val deleted = ArrayList<Long>() val deleted = ArrayList<Long>()
if (caldavAccount.isGoogleTasks) { for (calendar in getCalendars(caldavAccount.uuid!!)) {
for (list in getLists(caldavAccount.uuid!!)) { deleted.addAll(delete(calendar))
deleted.addAll(deleteGoogleTaskList(list))
}
} else {
for (calendar in getCalendars(caldavAccount.uuid!!)) {
deleted.addAll(delete(calendar))
}
} }
deleteCaldavAccount(caldavAccount) deleteCaldavAccount(caldavAccount)
return deleted return deleted

@ -1,126 +1,15 @@
package org.tasks.data package org.tasks.data
import androidx.room.ColumnInfo @Deprecated("For backup use only")
import androidx.room.Entity data class GoogleTask(
import androidx.room.ForeignKey var remoteId: String? = "",
import androidx.room.Ignore var listId: String? = "",
import androidx.room.Index var remoteParent: String? = null,
import androidx.room.PrimaryKey var remoteOrder: Long = 0,
import com.todoroo.andlib.data.Table var lastSync: Long = 0,
import com.todoroo.astrid.data.Task var deleted: Long = 0,
) {
@Entity(
tableName = "google_tasks",
indices = [
Index(name = "gt_list_parent", value = ["gt_list_id", "gt_parent"])
],
foreignKeys = [
ForeignKey(
entity = Task::class,
parentColumns = ["_id"],
childColumns = ["gt_task"],
onDelete = ForeignKey.CASCADE,
),
]
)
class GoogleTask {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "gt_id")
@Transient
var id: Long = 0
@ColumnInfo(name = "gt_task", index = true)
@Transient
var task: Long = 0
@ColumnInfo(name = "gt_remote_id")
var remoteId: String? = ""
@ColumnInfo(name = "gt_list_id")
var listId: String? = ""
@ColumnInfo(name = "gt_parent")
@Transient
var parent: Long = 0
@ColumnInfo(name = "gt_remote_parent")
var remoteParent: String? = null
set(value) {
field = if (value?.isNotBlank() == true) value else null
}
@ColumnInfo(name = "gt_moved")
@Transient
var isMoved = false
@ColumnInfo(name = "gt_order")
@Transient
var order: Long = 0
@ColumnInfo(name = "gt_remote_order")
var remoteOrder: Long = 0
@ColumnInfo(name = "gt_last_sync")
var lastSync: Long = 0
@ColumnInfo(name = "gt_deleted")
var deleted: Long = 0
constructor()
@Ignore
constructor(task: Long, listId: String) {
this.task = task
this.listId = listId
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is GoogleTask) return false
if (id != other.id) return false
if (task != other.task) return false
if (remoteId != other.remoteId) return false
if (listId != other.listId) return false
if (parent != other.parent) return false
if (remoteParent != other.remoteParent) return false
if (isMoved != other.isMoved) return false
if (order != other.order) return false
if (remoteOrder != other.remoteOrder) return false
if (lastSync != other.lastSync) return false
if (deleted != other.deleted) return false
return true
}
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + task.hashCode()
result = 31 * result + remoteId.hashCode()
result = 31 * result + listId.hashCode()
result = 31 * result + parent.hashCode()
result = 31 * result + (remoteParent?.hashCode() ?: 0)
result = 31 * result + isMoved.hashCode()
result = 31 * result + order.hashCode()
result = 31 * result + remoteOrder.hashCode()
result = 31 * result + lastSync.hashCode()
result = 31 * result + deleted.hashCode()
return result
}
override fun toString(): String =
"GoogleTask(id=$id, task=$task, remoteId='$remoteId', listId='$listId', parent=$parent, remoteParent=$remoteParent, isMoved=$isMoved, order=$order, remoteOrder=$remoteOrder, lastSync=$lastSync, deleted=$deleted)"
val isNew: Boolean
get() = id == 0L
companion object { companion object {
const val KEY = "gtasks" const val KEY = "gtasks"
@JvmField val TABLE = Table("google_tasks")
val ID = TABLE.column("gt_id")
@JvmField val PARENT = TABLE.column("gt_parent")
@JvmField val TASK = TABLE.column("gt_task")
@JvmField val DELETED = TABLE.column("gt_deleted")
@JvmField val LIST = TABLE.column("gt_list_id")
} }
} }

@ -9,166 +9,219 @@ import org.tasks.time.DateTimeUtils.currentTimeMillis
@Dao @Dao
abstract class GoogleTaskDao { abstract class GoogleTaskDao {
@Insert @Insert
abstract suspend fun insert(task: GoogleTask): Long abstract suspend fun insert(task: CaldavTask): Long
@Insert @Insert
abstract suspend fun insert(tasks: Iterable<GoogleTask>) abstract suspend fun insert(tasks: Iterable<CaldavTask>)
@Transaction @Transaction
open suspend fun insertAndShift(task: GoogleTask, top: Boolean) { open suspend fun insertAndShift(task: CaldavTask, top: Boolean) {
if (top) { if (top) {
task.order = 0 task.order = 0
shiftDown(task.listId!!, task.parent, 0) shiftDown(task.calendar!!, task.parent, 0)
} else { } else {
task.order = getBottom(task.listId!!, task.parent) task.order = getBottom(task.calendar!!, task.parent)
} }
task.id = insert(task) task.id = insert(task)
} }
@Query("UPDATE google_tasks SET gt_order = gt_order + 1 WHERE gt_list_id = :listId AND gt_parent = :parent AND gt_order >= :position") @Query("UPDATE caldav_tasks SET cd_order = cd_order + 1 WHERE cd_calendar = :listId AND gt_parent = :parent AND cd_order >= :position")
internal abstract suspend fun shiftDown(listId: String, parent: Long, position: Long) internal abstract suspend fun shiftDown(listId: String, parent: Long, position: Long)
@Query("UPDATE google_tasks SET gt_order = gt_order - 1 WHERE gt_list_id = :listId AND gt_parent = :parent AND gt_order > :from AND gt_order <= :to") @Query("UPDATE caldav_tasks SET cd_order = cd_order - 1 WHERE cd_calendar = :listId AND gt_parent = :parent AND cd_order > :from AND cd_order <= :to")
internal abstract suspend fun shiftUp(listId: String, parent: Long, from: Long, to: Long) internal abstract suspend fun shiftUp(listId: String, parent: Long, from: Long, to: Long)
@Query("UPDATE google_tasks SET gt_order = gt_order + 1 WHERE gt_list_id = :listId AND gt_parent = :parent AND gt_order < :from AND gt_order >= :to") @Query("UPDATE caldav_tasks SET cd_order = cd_order + 1 WHERE cd_calendar = :listId AND gt_parent = :parent AND cd_order < :from AND cd_order >= :to")
internal abstract suspend fun shiftDown(listId: String, parent: Long, from: Long, to: Long) internal abstract suspend fun shiftDown(listId: String, parent: Long, from: Long, to: Long)
@Query("UPDATE google_tasks SET gt_order = gt_order - 1 WHERE gt_list_id = :listId AND gt_parent = :parent AND gt_order >= :position") @Query("UPDATE caldav_tasks SET cd_order = cd_order - 1 WHERE cd_calendar = :listId AND gt_parent = :parent AND cd_order >= :position")
internal abstract suspend fun shiftUp(listId: String, parent: Long, position: Long) internal abstract suspend fun shiftUp(listId: String, parent: Long, position: Long)
@Transaction @Transaction
open suspend fun move(task: SubsetGoogleTask, newParent: Long, newPosition: Long) { open suspend fun move(task: SubsetCaldav, newParent: Long, newPosition: Long) {
val previousParent = task.parent val previousParent = task.gt_parent
val previousPosition = task.order val previousPosition = task.cd_order!!
if (newParent == previousParent) { if (newParent == previousParent) {
if (previousPosition < newPosition) { if (previousPosition < newPosition) {
shiftUp(task.listId, newParent, previousPosition, newPosition) shiftUp(task.cd_calendar!!, newParent, previousPosition, newPosition)
} else { } else {
shiftDown(task.listId, newParent, previousPosition, newPosition) shiftDown(task.cd_calendar!!, newParent, previousPosition, newPosition)
} }
} else { } else {
shiftUp(task.listId, previousParent, previousPosition) shiftUp(task.cd_calendar!!, previousParent, previousPosition)
shiftDown(task.listId, newParent, newPosition) shiftDown(task.cd_calendar!!, newParent, newPosition)
} }
task.parent = newParent task.gt_parent = newParent
task.order = newPosition task.cd_order = newPosition
update(task) update(task)
} }
@Query("SELECT * FROM google_tasks WHERE gt_task = :taskId AND gt_deleted = 0 LIMIT 1") @Query("SELECT * FROM caldav_tasks WHERE cd_task = :taskId AND cd_deleted = 0 LIMIT 1")
abstract suspend fun getByTaskId(taskId: Long): GoogleTask? abstract suspend fun getByTaskId(taskId: Long): CaldavTask?
@Query("SELECT * FROM google_tasks WHERE gt_task = :taskId AND gt_deleted = 0 LIMIT 1") @Query("SELECT * FROM caldav_tasks WHERE cd_task = :taskId AND cd_deleted = 0 LIMIT 1")
abstract fun watchGoogleTask(taskId: Long): Flow<GoogleTask?> abstract fun watchGoogleTask(taskId: Long): Flow<CaldavTask?>
@Update @Update
abstract suspend fun update(googleTask: GoogleTask) abstract suspend fun update(googleTask: CaldavTask)
private suspend fun update(googleTask: SubsetGoogleTask) { private suspend fun update(googleTask: SubsetCaldav) {
update(googleTask.id, googleTask.parent, googleTask.order) update(googleTask.cd_id, googleTask.gt_parent, googleTask.cd_order!!)
} }
@Query("UPDATE google_tasks SET gt_order = :order, gt_parent = :parent, gt_moved = 1 WHERE gt_id = :id") @Query("UPDATE caldav_tasks SET cd_order = :order, gt_parent = :parent, gt_moved = 1 WHERE cd_id = :id")
abstract suspend fun update(id: Long, parent: Long, order: Long) abstract suspend fun update(id: Long, parent: Long, order: Long)
@Query("UPDATE google_tasks SET gt_deleted = :now WHERE gt_task = :task OR gt_parent = :task") @Query("UPDATE caldav_tasks SET cd_deleted = :now WHERE cd_task = :task OR gt_parent = :task")
abstract suspend fun markDeleted(task: Long, now: Long = currentTimeMillis()) abstract suspend fun markDeleted(task: Long, now: Long = currentTimeMillis())
@Delete @Delete
abstract suspend fun delete(deleted: GoogleTask) abstract suspend fun delete(deleted: CaldavTask)
@Query("SELECT * FROM google_tasks WHERE gt_remote_id = :remoteId LIMIT 1") @Query("SELECT * FROM caldav_tasks WHERE cd_remote_id = :remoteId LIMIT 1")
abstract suspend fun getByRemoteId(remoteId: String): GoogleTask? abstract suspend fun getByRemoteId(remoteId: String): CaldavTask?
@Query("SELECT * FROM google_tasks WHERE gt_task = :taskId AND gt_deleted > 0") @Query("SELECT * FROM caldav_tasks WHERE cd_task = :taskId AND cd_deleted > 0")
abstract suspend fun getDeletedByTaskId(taskId: Long): List<GoogleTask> abstract suspend fun getDeletedByTaskId(taskId: Long): List<CaldavTask>
@Query("SELECT * FROM google_tasks WHERE gt_task = :taskId") @Query("SELECT * FROM caldav_tasks WHERE cd_task = :taskId")
abstract suspend fun getAllByTaskId(taskId: Long): List<GoogleTask> abstract suspend fun getAllByTaskId(taskId: Long): List<CaldavTask>
@Query("SELECT DISTINCT gt_list_id FROM google_tasks WHERE gt_deleted = 0 AND gt_task IN (:tasks)") @Query("SELECT DISTINCT cd_calendar FROM caldav_tasks WHERE cd_deleted = 0 AND cd_task IN (:tasks)")
abstract suspend fun getLists(tasks: List<Long>): List<String> abstract suspend fun getLists(tasks: List<Long>): List<String>
@Query("SELECT gt_task FROM google_tasks WHERE gt_parent IN (:ids) AND gt_deleted = 0") @Query("SELECT cd_task FROM caldav_tasks WHERE gt_parent IN (:ids) AND cd_deleted = 0")
abstract suspend fun getChildren(ids: List<Long>): List<Long> abstract suspend fun getChildren(ids: List<Long>): List<Long>
suspend fun hasRecurringParent(ids: List<Long>): List<Long> = suspend fun hasRecurringParent(ids: List<Long>): List<Long> =
ids.chunkedMap { internalHasRecurringParent(it) } ids.chunkedMap { internalHasRecurringParent(it) }
@Query(""" @Query("""
SELECT gt_task SELECT cd_task
FROM google_tasks FROM caldav_tasks
INNER JOIN tasks ON gt_parent = _id INNER JOIN tasks ON gt_parent = _id
WHERE gt_task IN (:ids) WHERE cd_task IN (:ids)
AND gt_deleted = 0 AND cd_deleted = 0
AND tasks.recurrence IS NOT NULL AND tasks.recurrence IS NOT NULL
AND tasks.recurrence != '' AND tasks.recurrence != ''
AND tasks.completed = 0 AND tasks.completed = 0
""") """)
abstract suspend fun internalHasRecurringParent(ids: List<Long>): List<Long> abstract suspend fun internalHasRecurringParent(ids: List<Long>): List<Long>
@Query("SELECT tasks.* FROM tasks JOIN google_tasks ON tasks._id = gt_task WHERE gt_parent = :taskId") @Query("SELECT tasks.* FROM tasks JOIN caldav_tasks ON tasks._id = cd_task WHERE gt_parent = :taskId")
abstract suspend fun getChildTasks(taskId: Long): List<Task> abstract suspend fun getChildTasks(taskId: Long): List<Task>
@Query("SELECT tasks.* FROM tasks JOIN google_tasks ON tasks._id = gt_parent WHERE gt_task = :taskId") @Query("SELECT tasks.* FROM tasks JOIN caldav_tasks ON tasks._id = gt_parent WHERE cd_task = :taskId")
abstract suspend fun getParentTask(taskId: Long): Task? abstract suspend fun getParentTask(taskId: Long): Task?
@Query("SELECT * FROM google_tasks WHERE gt_parent = :id AND gt_deleted = 0") @Query("SELECT * FROM caldav_tasks WHERE gt_parent = :id AND cd_deleted = 0")
abstract suspend fun getChildren(id: Long): List<GoogleTask> abstract suspend fun getChildren(id: Long): List<CaldavTask>
@Query("SELECT IFNULL(MAX(gt_order), -1) + 1 FROM google_tasks WHERE gt_list_id = :listId AND gt_parent = :parent") @Query("SELECT IFNULL(MAX(cd_order), -1) + 1 FROM caldav_tasks WHERE cd_calendar = :listId AND gt_parent = :parent")
abstract suspend fun getBottom(listId: String, parent: Long): Long abstract suspend fun getBottom(listId: String, parent: Long): Long
@Query("SELECT gt_remote_id FROM google_tasks JOIN tasks ON tasks._id = gt_task WHERE deleted = 0 AND gt_list_id = :listId AND gt_parent = :parent AND gt_order < :order AND gt_remote_id IS NOT NULL AND gt_remote_id != '' ORDER BY gt_order DESC") @Query(
"""
SELECT cd_remote_id
FROM caldav_tasks
JOIN tasks ON tasks._id = cd_task
WHERE deleted = 0
AND cd_calendar = :listId
AND gt_parent = :parent
AND cd_order < :order
AND cd_remote_id IS NOT NULL
AND cd_remote_id != ''
ORDER BY cd_order DESC
"""
)
abstract suspend fun getPrevious(listId: String, parent: Long, order: Long): String? abstract suspend fun getPrevious(listId: String, parent: Long, order: Long): String?
@Query("SELECT gt_remote_id FROM google_tasks WHERE gt_task = :task") @Query("SELECT cd_remote_id FROM caldav_tasks WHERE cd_task = :task")
abstract suspend fun getRemoteId(task: Long): String? abstract suspend fun getRemoteId(task: Long): String?
@Query("SELECT gt_task FROM google_tasks WHERE gt_remote_id = :remoteId") @Query("SELECT cd_task FROM caldav_tasks WHERE cd_remote_id = :remoteId")
abstract suspend fun getTask(remoteId: String): Long? abstract suspend fun getTask(remoteId: String): Long?
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Query("SELECT google_tasks.*, gt_order AS primary_sort, NULL AS secondary_sort FROM google_tasks JOIN tasks ON tasks._id = gt_task WHERE gt_parent = 0 AND gt_list_id = :listId AND tasks.deleted = 0 UNION SELECT c.*, p.gt_order AS primary_sort, c.gt_order AS secondary_sort FROM google_tasks AS c LEFT JOIN google_tasks AS p ON c.gt_parent = p.gt_task JOIN tasks ON tasks._id = c.gt_task WHERE c.gt_parent > 0 AND c.gt_list_id = :listId AND tasks.deleted = 0 ORDER BY primary_sort ASC, secondary_sort ASC") @Query(
abstract suspend fun getByLocalOrder(listId: String): List<GoogleTask> """
SELECT caldav_tasks.*, cd_order AS primary_sort, NULL AS secondary_sort
FROM caldav_tasks
JOIN tasks ON tasks._id = cd_task
WHERE gt_parent = 0
AND cd_calendar = :listId
AND tasks.deleted = 0
UNION
SELECT c.*, p.cd_order AS primary_sort, c.cd_order AS secondary_sort
FROM caldav_tasks AS c
LEFT JOIN caldav_tasks AS p ON c.gt_parent = p.cd_task
JOIN tasks ON tasks._id = c.cd_task
WHERE c.gt_parent > 0
AND c.cd_calendar = :listId
AND tasks.deleted = 0
ORDER BY primary_sort ASC, secondary_sort ASC
"""
)
abstract suspend fun getByLocalOrder(listId: String): List<CaldavTask>
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Query("SELECT google_tasks.*, gt_remote_order AS primary_sort, NULL AS secondary_sort FROM google_tasks JOIN tasks ON tasks._id = gt_task WHERE gt_parent = 0 AND gt_list_id = :listId AND tasks.deleted = 0 UNION SELECT c.*, p.gt_remote_order AS primary_sort, c.gt_remote_order AS secondary_sort FROM google_tasks AS c LEFT JOIN google_tasks AS p ON c.gt_parent = p.gt_task JOIN tasks ON tasks._id = c.gt_task WHERE c.gt_parent > 0 AND c.gt_list_id = :listId AND tasks.deleted = 0 ORDER BY primary_sort ASC, secondary_sort ASC") @Query(
internal abstract suspend fun getByRemoteOrder(listId: String): List<GoogleTask> """
SELECT caldav_tasks.*, gt_remote_order AS primary_sort, NULL AS secondary_sort
FROM caldav_tasks
JOIN tasks ON tasks._id = cd_task
WHERE gt_parent = 0
AND cd_calendar = :listId
AND tasks.deleted = 0
UNION
SELECT c.*, p.gt_remote_order AS primary_sort, c.gt_remote_order AS secondary_sort
FROM caldav_tasks AS c
LEFT JOIN caldav_tasks AS p ON c.gt_parent = p.cd_task
JOIN tasks ON tasks._id = c.cd_task
WHERE c.gt_parent > 0
AND c.cd_calendar = :listId
AND tasks.deleted = 0
ORDER BY primary_sort ASC, secondary_sort ASC
"""
)
internal abstract suspend fun getByRemoteOrder(listId: String): List<CaldavTask>
@Query(""" @Query(
UPDATE google_tasks """
SET gt_parent = IFNULL((SELECT gt_task UPDATE caldav_tasks
FROM google_tasks AS p SET gt_parent = IFNULL((SELECT cd_task
WHERE google_tasks.gt_remote_parent IS NOT NULL FROM caldav_tasks AS p
AND google_tasks.gt_remote_parent != '' WHERE caldav_tasks.cd_remote_parent IS NOT NULL
AND p.gt_remote_id = google_tasks.gt_remote_parent AND caldav_tasks.cd_remote_parent != ''
AND p.gt_list_id = google_tasks.gt_list_id AND p.cd_remote_id = caldav_tasks.cd_remote_parent
AND p.gt_deleted = 0), 0) AND p.cd_calendar = caldav_tasks.cd_calendar
AND p.cd_deleted = 0), 0)
WHERE gt_moved = 0 WHERE gt_moved = 0
""") """
)
abstract suspend fun updateParents() abstract suspend fun updateParents()
@Query(""" @Query(
UPDATE google_tasks """
SET gt_parent = IFNULL((SELECT gt_task UPDATE caldav_tasks
FROM google_tasks AS p SET gt_parent = IFNULL((SELECT cd_task
WHERE google_tasks.gt_remote_parent IS NOT NULL FROM caldav_tasks AS p
AND google_tasks.gt_remote_parent != '' WHERE caldav_tasks.cd_remote_parent IS NOT NULL
AND p.gt_remote_id = google_tasks.gt_remote_parent AND caldav_tasks.cd_remote_parent != ''
AND p.gt_list_id = google_tasks.gt_list_id AND p.cd_remote_id = caldav_tasks.cd_remote_parent
AND p.gt_deleted = 0), 0) AND p.cd_calendar = caldav_tasks.cd_calendar
WHERE gt_list_id = :listId AND p.cd_deleted = 0), 0)
WHERE cd_calendar = :listId
AND gt_moved = 0 AND gt_moved = 0
""") """
)
abstract suspend fun updateParents(listId: String) abstract suspend fun updateParents(listId: String)
@Query(""" @Query("""
UPDATE google_tasks UPDATE caldav_tasks
SET gt_remote_parent = CASE WHEN :parent == '' THEN NULL ELSE :parent END, SET cd_remote_parent = CASE WHEN :parent == '' THEN NULL ELSE :parent END,
gt_remote_order = :position gt_remote_order = :position
WHERE gt_remote_id = :id WHERE cd_remote_id = :id
""") """)
abstract suspend fun updatePosition(id: String, parent: String?, position: String) abstract suspend fun updatePosition(id: String, parent: String?, position: String)

@ -30,8 +30,8 @@ interface GoogleTaskListDao {
@Query("SELECT caldav_lists.*, COUNT(tasks._id) AS count" @Query("SELECT caldav_lists.*, COUNT(tasks._id) AS count"
+ " FROM caldav_lists " + " FROM caldav_lists "
+ " LEFT JOIN google_tasks ON google_tasks.gt_list_id = caldav_lists.cdl_uuid" + " LEFT JOIN caldav_tasks ON caldav_tasks.cd_calendar = caldav_lists.cdl_uuid"
+ " LEFT JOIN tasks ON google_tasks.gt_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now AND gt_deleted = 0" + " LEFT JOIN tasks ON caldav_tasks.cd_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now AND cd_deleted = 0"
+ " WHERE caldav_lists.cdl_account = :account" + " WHERE caldav_lists.cdl_account = :account"
+ " GROUP BY caldav_lists.cdl_uuid") + " GROUP BY caldav_lists.cdl_uuid")
suspend fun getGoogleTaskFilters(account: String, now: Long = currentTimeMillis()): List<GoogleTaskFilters> suspend fun getGoogleTaskFilters(account: String, now: Long = currentTimeMillis()): List<GoogleTaskFilters>

@ -4,6 +4,7 @@ class SubsetCaldav {
var cd_id: Long = 0 var cd_id: Long = 0
var cd_calendar: String? = null var cd_calendar: String? = null
var cd_remote_parent: String? = null var cd_remote_parent: String? = null
var gt_parent: Long = 0
var cd_order: Long? = null var cd_order: Long? = null
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@ -13,6 +14,7 @@ class SubsetCaldav {
if (cd_id != other.cd_id) return false if (cd_id != other.cd_id) return false
if (cd_calendar != other.cd_calendar) return false if (cd_calendar != other.cd_calendar) return false
if (cd_remote_parent != other.cd_remote_parent) return false if (cd_remote_parent != other.cd_remote_parent) return false
if (gt_parent != other.gt_parent) return false
if (cd_order != other.cd_order) return false if (cd_order != other.cd_order) return false
return true return true
@ -22,10 +24,11 @@ class SubsetCaldav {
var result = cd_id.hashCode() var result = cd_id.hashCode()
result = 31 * result + (cd_calendar?.hashCode() ?: 0) result = 31 * result + (cd_calendar?.hashCode() ?: 0)
result = 31 * result + (cd_remote_parent?.hashCode() ?: 0) result = 31 * result + (cd_remote_parent?.hashCode() ?: 0)
result = 31 * result + cd_order.hashCode() result = 31 * result + (gt_parent.hashCode())
result = 31 * result + (cd_order.hashCode())
return result return result
} }
override fun toString(): String = override fun toString(): String =
"SubsetCaldav(cd_id=$cd_id, cd_calendar=$cd_calendar, cd_remote_parent=$cd_remote_parent, cd_order=$cd_order)" "SubsetCaldav(cd_id=$cd_id, cd_calendar=$cd_calendar, cd_remote_parent=$cd_remote_parent, gt_parent=$gt_parent, cd_order=$cd_order)"
} }

@ -1,70 +0,0 @@
package org.tasks.data;
import java.util.Objects;
public class SubsetGoogleTask {
public long gt_id;
public long gt_parent;
public String gt_list_id;
public long gt_order;
public long getId() {
return gt_id;
}
public String getListId() {
return gt_list_id;
}
public long getParent() {
return gt_parent;
}
public void setParent(long parent) {
gt_parent = parent;
}
public long getOrder() {
return gt_order;
}
public void setOrder(long order) {
gt_order = order;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SubsetGoogleTask)) {
return false;
}
SubsetGoogleTask that = (SubsetGoogleTask) o;
return gt_id == that.gt_id
&& gt_parent == that.gt_parent
&& gt_order == that.gt_order
&& Objects.equals(gt_list_id, that.gt_list_id);
}
@Override
public int hashCode() {
return Objects.hash(gt_id, gt_parent, gt_list_id, gt_order);
}
@Override
public String toString() {
return "SubsetGoogleTask{"
+ "gt_id="
+ gt_id
+ ", gt_parent="
+ gt_parent
+ ", gt_list_id='"
+ gt_list_id
+ '\''
+ ", gt_order="
+ gt_order
+ '}';
}
}

@ -7,9 +7,9 @@ import java.util.Objects;
public class TaskContainer { public class TaskContainer {
@Embedded public Task task; @Embedded public Task task;
@Embedded public SubsetGoogleTask googletask;
@Embedded public SubsetCaldav caldavTask; @Embedded public SubsetCaldav caldavTask;
@Embedded public Location location; @Embedded public Location location;
public boolean isGoogleTask;
public boolean parentComplete; public boolean parentComplete;
public String tags; public String tags;
public int children; public int children;
@ -23,16 +23,8 @@ public class TaskContainer {
return tags; return tags;
} }
public @Nullable String getGoogleTaskList() {
return isGoogleTask() ? googletask.getListId() : null;
}
public boolean isGoogleTask() {
return googletask != null;
}
public @Nullable String getCaldav() { public @Nullable String getCaldav() {
return isCaldavTask() ? caldavTask.getCd_calendar() : null; return caldavTask.getCd_calendar();
} }
public boolean isCaldavTask() { public boolean isCaldavTask() {
@ -127,7 +119,6 @@ public class TaskContainer {
&& indent == that.indent && indent == that.indent
&& targetIndent == that.targetIndent && targetIndent == that.targetIndent
&& Objects.equals(task, that.task) && Objects.equals(task, that.task)
&& Objects.equals(googletask, that.googletask)
&& Objects.equals(caldavTask, that.caldavTask) && Objects.equals(caldavTask, that.caldavTask)
&& Objects.equals(location, that.location) && Objects.equals(location, that.location)
&& Objects.equals(tags, that.tags) && Objects.equals(tags, that.tags)
@ -138,7 +129,6 @@ public class TaskContainer {
public int hashCode() { public int hashCode() {
return Objects.hash( return Objects.hash(
task, task,
googletask,
caldavTask, caldavTask,
location, location,
tags, tags,
@ -155,8 +145,6 @@ public class TaskContainer {
return "TaskContainer{" return "TaskContainer{"
+ "task=" + "task="
+ task + task
+ ", googletask="
+ googletask
+ ", caldavTask=" + ", caldavTask="
+ caldavTask + caldavTask
+ ", location=" + ", location="
@ -184,17 +172,16 @@ public class TaskContainer {
} }
public long getParent() { public long getParent() {
if (googletask != null) { if (isGoogleTask) {
return googletask.getParent(); return caldavTask.getGt_parent();
} else { } else {
return task.getParent(); return task.getParent();
} }
} }
public void setParent(long parent) { public void setParent(long parent) {
if (googletask != null) { if (isGoogleTask) {
task.setParent(0); caldavTask.setGt_parent(parent);
googletask.setParent(parent);
} else { } else {
task.setParent(parent); task.setParent(parent);
} }
@ -208,10 +195,6 @@ public class TaskContainer {
return children > 0; return children > 0;
} }
public SubsetGoogleTask getGoogleTask() {
return googletask;
}
public SubsetCaldav getCaldavTask() { public SubsetCaldav getCaldavTask() {
return caldavTask; return caldavTask;
} }

@ -61,11 +61,11 @@ abstract class TaskDao(private val database: Database) {
abstract suspend fun setCompletionDate(remoteIds: List<String>, completionDate: Long, updateTime: Long = now()) abstract suspend fun setCompletionDate(remoteIds: List<String>, completionDate: Long, updateTime: Long = now())
@Query("SELECT tasks.* FROM tasks " @Query("SELECT tasks.* FROM tasks "
+ "LEFT JOIN google_tasks ON tasks._id = google_tasks.gt_task " + "LEFT JOIN caldav_tasks ON tasks._id = caldav_tasks.cd_task "
+ "LEFT JOIN caldav_lists ON google_tasks.gt_list_id = caldav_lists.cdl_uuid " + "LEFT JOIN caldav_lists ON caldav_tasks.cd_calendar = caldav_lists.cdl_uuid "
+ "WHERE cdl_account = :account " + "WHERE cdl_account = :account "
+ "AND (tasks.modified > google_tasks.gt_last_sync OR google_tasks.gt_remote_id = '' OR google_tasks.gt_deleted > 0) " + "AND (tasks.modified > caldav_tasks.cd_last_sync OR caldav_tasks.cd_remote_id = '' OR caldav_tasks.cd_deleted > 0) "
+ "ORDER BY CASE WHEN gt_parent = 0 THEN 0 ELSE 1 END, gt_order ASC") + "ORDER BY CASE WHEN parent = 0 THEN 0 ELSE 1 END, `order` ASC")
abstract suspend fun getGoogleTasksToPush(account: String): List<Task> abstract suspend fun getGoogleTasksToPush(account: String): List<Task>
@Query(""" @Query("""
@ -130,11 +130,11 @@ abstract class TaskDao(private val database: Database) {
@Query(""" @Query("""
SELECT EXISTS(SELECT 1 FROM tasks WHERE parent > 0 AND deleted = 0) AS hasSubtasks, SELECT EXISTS(SELECT 1 FROM tasks WHERE parent > 0 AND deleted = 0) AS hasSubtasks,
EXISTS(SELECT 1 EXISTS(SELECT 1
FROM google_tasks FROM caldav_tasks
INNER JOIN tasks ON gt_task = _id INNER JOIN tasks ON cd_task = _id
WHERE deleted = 0 WHERE deleted = 0
AND gt_parent > 0 AND gt_parent > 0
AND gt_deleted = 0) AS hasGoogleSubtasks AND cd_deleted = 0) AS hasGoogleSubtasks
""") """)
abstract suspend fun getSubtaskInfo(): SubtaskInfo abstract suspend fun getSubtaskInfo(): SubtaskInfo
@ -246,10 +246,8 @@ FROM recursive_tasks
@Query(""" @Query("""
SELECT _id SELECT _id
FROM tasks FROM tasks
LEFT JOIN google_tasks ON _id = gt_task AND gt_deleted = 0
LEFT JOIN caldav_tasks ON _id = cd_task AND cd_deleted = 0 LEFT JOIN caldav_tasks ON _id = cd_task AND cd_deleted = 0
WHERE gt_id IS NULL WHERE cd_id IS NULL
AND cd_id IS NULL
AND parent = 0 AND parent = 0
""") """)
abstract suspend fun getLocalTasks(): List<Long> abstract suspend fun getLocalTasks(): List<Long>

@ -6,27 +6,26 @@ import com.todoroo.andlib.sql.Join
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import org.tasks.data.CaldavAccount.Companion.TYPE_GOOGLE_TASKS
import org.tasks.data.TaskListQueryNonRecursive.getNonRecursiveQuery import org.tasks.data.TaskListQueryNonRecursive.getNonRecursiveQuery
import org.tasks.data.TaskListQueryRecursive.getRecursiveQuery import org.tasks.data.TaskListQueryRecursive.getRecursiveQuery
import org.tasks.preferences.QueryPreferences import org.tasks.preferences.QueryPreferences
object TaskListQuery { object TaskListQuery {
private val JOIN_GTASK = Criterion.and(
Task.ID.eq(field("${TaskListFragment.GTASK_METADATA_JOIN}.gt_task")),
field("${TaskListFragment.GTASK_METADATA_JOIN}.gt_deleted").eq(0))
private val JOIN_CALDAV = Criterion.and( private val JOIN_CALDAV = Criterion.and(
Task.ID.eq(field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_task")), Task.ID.eq(field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_task")),
field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_deleted").eq(0)) field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_deleted").eq(0))
val JOINS = """ val JOINS = """
${Join.left(GoogleTask.TABLE.`as`(TaskListFragment.GTASK_METADATA_JOIN), JOIN_GTASK)}
${Join.left(CaldavTask.TABLE.`as`(TaskListFragment.CALDAV_METADATA_JOIN), JOIN_CALDAV)} ${Join.left(CaldavTask.TABLE.`as`(TaskListFragment.CALDAV_METADATA_JOIN), JOIN_CALDAV)}
${Join.left(CaldavCalendar.TABLE, field("${TaskListFragment.CALDAV_METADATA_JOIN}.cd_calendar").eq(CaldavCalendar.UUID))}
${Join.left(CaldavAccount.TABLE, CaldavCalendar.ACCOUNT.eq(CaldavAccount.UUID))}
${Join.left(Geofence.TABLE, Geofence.TASK.eq(Task.ID))} ${Join.left(Geofence.TABLE, Geofence.TASK.eq(Task.ID))}
${Join.left(Place.TABLE, Place.UID.eq(Geofence.PLACE))} ${Join.left(Place.TABLE, Place.UID.eq(Geofence.PLACE))}
""".trimIndent() """.trimIndent()
val FIELDS = listOf( val FIELDS = listOf(
field("tasks.*"), field("tasks.*"),
field("${TaskListFragment.GTASK_METADATA_JOIN}.*"),
field("${TaskListFragment.CALDAV_METADATA_JOIN}.*"), field("${TaskListFragment.CALDAV_METADATA_JOIN}.*"),
field("CASE ${CaldavAccount.ACCOUNT_TYPE} WHEN $TYPE_GOOGLE_TASKS THEN 1 ELSE 0 END").`as`("isGoogleTask"),
field("geofences.*"), field("geofences.*"),
field("places.*")) field("places.*"))

@ -35,13 +35,13 @@ internal object TaskListQueryRecursive {
""".trimIndent() """.trimIndent()
private val GOOGLE_SUBTASKS = private val GOOGLE_SUBTASKS =
QueryTemplate() QueryTemplate()
.join(Join.inner(RECURSIVE, GoogleTask.PARENT.eq(RECURSIVE_TASK))) .join(Join.inner(RECURSIVE, CaldavTask.PARENT.eq(RECURSIVE_TASK)))
.join(Join.inner(GoogleTask.TABLE, Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))) .join(Join.inner(CaldavTask.TABLE, Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0))))
.where(activeAndVisible()) .where(activeAndVisible())
private val ALL_SUBTASKS = private val ALL_SUBTASKS =
QueryTemplate() QueryTemplate()
.join(Join.inner(RECURSIVE, Criterion.or(GoogleTask.PARENT.eq(RECURSIVE_TASK), Task.PARENT.eq(RECURSIVE_TASK)))) .join(Join.inner(RECURSIVE, Criterion.or(CaldavTask.PARENT.eq(RECURSIVE_TASK), Task.PARENT.eq(RECURSIVE_TASK))))
.join(Join.left(GoogleTask.TABLE, Criterion.and(GoogleTask.TASK.eq(Task.ID), GoogleTask.DELETED.eq(0)))) .join(Join.left(CaldavTask.TABLE, Criterion.and(CaldavTask.TASK.eq(Task.ID), CaldavTask.DELETED.eq(0))))
.where(activeAndVisible()) .where(activeAndVisible())
fun getRecursiveQuery( fun getRecursiveQuery(
@ -85,7 +85,7 @@ internal object TaskListQueryRecursive {
when { when {
manualSort && filter is GtasksFilter -> { manualSort && filter is GtasksFilter -> {
sortMode = SortHelper.SORT_GTASKS sortMode = SortHelper.SORT_GTASKS
sortField = "google_tasks.gt_order" sortField = "caldav_tasks.cd_order"
} }
manualSort && filter is CaldavFilter -> { manualSort && filter is CaldavFilter -> {
sortMode = SortHelper.SORT_CALDAV sortMode = SortHelper.SORT_CALDAV
@ -141,12 +141,12 @@ internal object TaskListQueryRecursive {
private fun newGoogleTaskQuery(filter: GtasksFilter) = private fun newGoogleTaskQuery(filter: GtasksFilter) =
QueryTemplate() QueryTemplate()
.join(Join.inner( .join(Join.inner(
GoogleTask.TABLE, CaldavTask.TABLE,
Criterion.and( Criterion.and(
GoogleTask.LIST.eq(filter.remoteId), CaldavTask.CALENDAR.eq(filter.remoteId),
GoogleTask.PARENT.eq(0), CaldavTask.PARENT.eq(0),
GoogleTask.TASK.eq(Task.ID), CaldavTask.TASK.eq(Task.ID),
GoogleTask.DELETED.eq(0)))) CaldavTask.DELETED.eq(0))))
.where(activeAndVisible()) .where(activeAndVisible())
.toString() .toString()
} }

@ -137,10 +137,10 @@ class FilterCriteriaProvider @Inject constructor(
select(Task.ID) select(Task.ID)
.from(Task.TABLE) .from(Task.TABLE)
.join(left(Task.TABLE.`as`("children"), Task.ID.eq(field("children.parent")))) .join(left(Task.TABLE.`as`("children"), Task.ID.eq(field("children.parent"))))
.join(left(GoogleTask.TABLE, GoogleTask.PARENT.eq(Task.ID))) .join(left(CaldavTask.TABLE, CaldavTask.PARENT.eq(Task.ID)))
.where(or( .where(or(
isNotNull(field("children._id")), isNotNull(field("children._id")),
isNotNull(GoogleTask.ID) isNotNull(CaldavTask.ID)
)) ))
.toString() .toString()
) )
@ -151,10 +151,10 @@ class FilterCriteriaProvider @Inject constructor(
context.getString(R.string.custom_filter_is_subtask), context.getString(R.string.custom_filter_is_subtask),
select(Task.ID) select(Task.ID)
.from(Task.TABLE) .from(Task.TABLE)
.join(left(GoogleTask.TABLE, GoogleTask.TASK.eq(Task.ID))) .join(left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.where(or( .where(or(
field("${Task.PARENT}>0").eq(1), field("${Task.PARENT}>0").eq(1),
field("${GoogleTask.PARENT}>0").eq(1) field("${CaldavTask.PARENT}>0").eq(1)
)) ))
.toString() .toString()
) )
@ -298,14 +298,14 @@ class FilterCriteriaProvider @Inject constructor(
return MultipleSelectCriterion( return MultipleSelectCriterion(
IDENTIFIER_GTASKS, IDENTIFIER_GTASKS,
context.getString(R.string.CFC_gtasks_list_text), context.getString(R.string.CFC_gtasks_list_text),
select(GoogleTask.TASK) select(CaldavTask.TASK)
.from(GoogleTask.TABLE) .from(CaldavTask.TABLE)
.join(inner(Task.TABLE, GoogleTask.TASK.eq(Task.ID))) .join(inner(Task.TABLE, CaldavTask.TASK.eq(Task.ID)))
.where( .where(
and( and(
activeAndVisible(), activeAndVisible(),
GoogleTask.DELETED.eq(0), CaldavTask.DELETED.eq(0),
GoogleTask.LIST.eq("?"))) CaldavTask.CALENDAR.eq("?")))
.toString(), .toString(),
values, values,
listNames, listNames,

@ -179,7 +179,7 @@ class GoogleTaskSynchronizer @Inject constructor(
@Throws(IOException::class) @Throws(IOException::class)
private suspend fun pushTask(task: com.todoroo.astrid.data.Task, gtasksInvoker: GtasksInvoker) { private suspend fun pushTask(task: com.todoroo.astrid.data.Task, gtasksInvoker: GtasksInvoker) {
for (deleted in googleTaskDao.getDeletedByTaskId(task.id)) { for (deleted in googleTaskDao.getDeletedByTaskId(task.id)) {
gtasksInvoker.deleteGtask(deleted.listId, deleted.remoteId) gtasksInvoker.deleteGtask(deleted.calendar, deleted.remoteId)
googleTaskDao.delete(deleted) googleTaskDao.delete(deleted)
} }
val gtasksMetadata = googleTaskDao.getByTaskId(task.id) ?: return val gtasksMetadata = googleTaskDao.getByTaskId(task.id) ?: return
@ -189,14 +189,14 @@ class GoogleTaskSynchronizer @Inject constructor(
val defaultRemoteList = defaultFilterProvider.defaultList val defaultRemoteList = defaultFilterProvider.defaultList
var listId = if (defaultRemoteList is GtasksFilter) defaultRemoteList.remoteId else DEFAULT_LIST var listId = if (defaultRemoteList is GtasksFilter) defaultRemoteList.remoteId else DEFAULT_LIST
if (isNullOrEmpty(gtasksMetadata.remoteId)) { // Create case if (isNullOrEmpty(gtasksMetadata.remoteId)) { // Create case
val selectedList = gtasksMetadata.listId val selectedList = gtasksMetadata.calendar
if (!isNullOrEmpty(selectedList)) { if (!isNullOrEmpty(selectedList)) {
listId = selectedList listId = selectedList
} }
newlyCreated = true newlyCreated = true
} else { // update case } else { // update case
remoteId = gtasksMetadata.remoteId remoteId = gtasksMetadata.remoteId
listId = gtasksMetadata.listId listId = gtasksMetadata.calendar
remoteModel.id = remoteId remoteModel.id = remoteId
} }
@ -227,7 +227,7 @@ class GoogleTaskSynchronizer @Inject constructor(
val parent = gtasksMetadata.parent val parent = gtasksMetadata.parent
val localParent = if (parent > 0) googleTaskDao.getRemoteId(parent) else null val localParent = if (parent > 0) googleTaskDao.getRemoteId(parent) else null
val previous = googleTaskDao.getPrevious( val previous = googleTaskDao.getPrevious(
listId!!, if (isNullOrEmpty(localParent)) 0 else parent, gtasksMetadata.order) listId!!, if (isNullOrEmpty(localParent)) 0 else parent, gtasksMetadata.order ?: 0)
val created: Task? val created: Task?
created = try { created = try {
gtasksInvoker.createGtask(listId, remoteModel, localParent, previous) gtasksInvoker.createGtask(listId, remoteModel, localParent, previous)
@ -237,7 +237,7 @@ class GoogleTaskSynchronizer @Inject constructor(
if (created != null) { if (created != null) {
// Update the metadata for the newly created task // Update the metadata for the newly created task
gtasksMetadata.remoteId = created.id gtasksMetadata.remoteId = created.id
gtasksMetadata.listId = listId gtasksMetadata.calendar = listId
setOrderAndParent(gtasksMetadata, created) setOrderAndParent(gtasksMetadata, created)
} else { } else {
return return
@ -251,7 +251,7 @@ class GoogleTaskSynchronizer @Inject constructor(
val previous = googleTaskDao.getPrevious( val previous = googleTaskDao.getPrevious(
listId!!, listId!!,
if (isNullOrEmpty(localParent)) 0 else parent, if (isNullOrEmpty(localParent)) 0 else parent,
gtasksMetadata.order) gtasksMetadata.order ?: 0)
gtasksInvoker gtasksInvoker
.moveGtask(listId, remoteModel.id, localParent, previous) .moveGtask(listId, remoteModel.id, localParent, previous)
?.let { setOrderAndParent(gtasksMetadata, it) } ?.let { setOrderAndParent(gtasksMetadata, it) }
@ -303,7 +303,7 @@ class GoogleTaskSynchronizer @Inject constructor(
var googleTask = googleTaskDao.getByRemoteId(remoteId) var googleTask = googleTaskDao.getByRemoteId(remoteId)
var task: com.todoroo.astrid.data.Task? = null var task: com.todoroo.astrid.data.Task? = null
if (googleTask == null) { if (googleTask == null) {
googleTask = GoogleTask(0, "") googleTask = CaldavTask(0, "")
} else if (googleTask.task > 0) { } else if (googleTask.task > 0) {
task = taskDao.fetch(googleTask.task) task = taskDao.fetch(googleTask.task)
} }
@ -339,7 +339,7 @@ class GoogleTaskSynchronizer @Inject constructor(
val dueDate = GtasksApiUtilities.gtasksDueTimeToUnixTime(gtask.due?.let(::DateTime)) val dueDate = GtasksApiUtilities.gtasksDueTimeToUnixTime(gtask.due?.let(::DateTime))
mergeDates(createDueDate(com.todoroo.astrid.data.Task.URGENCY_SPECIFIC_DAY, dueDate), task) mergeDates(createDueDate(com.todoroo.astrid.data.Task.URGENCY_SPECIFIC_DAY, dueDate), task)
task.notes = getTruncatedValue(task.notes, gtask.notes, MAX_DESCRIPTION_LENGTH) task.notes = getTruncatedValue(task.notes, gtask.notes, MAX_DESCRIPTION_LENGTH)
googleTask.listId = listId googleTask.calendar = listId
if (task.title?.isNotBlank() == true || task.notes?.isNotBlank() == true) { if (task.title?.isNotBlank() == true || task.notes?.isNotBlank() == true) {
write(task, googleTask) write(task, googleTask)
} }
@ -351,13 +351,13 @@ class GoogleTaskSynchronizer @Inject constructor(
) )
} }
private suspend fun setOrderAndParent(googleTask: GoogleTask, task: Task) { private suspend fun setOrderAndParent(googleTask: CaldavTask, task: Task) {
task.position?.toLongOrNull()?.let { googleTask.remoteOrder = it } task.position?.toLongOrNull()?.let { googleTask.remoteOrder = it }
googleTask.remoteParent = task.parent?.takeIf { it.isNotBlank() } googleTask.remoteParent = task.parent?.takeIf { it.isNotBlank() }
googleTask.parent = googleTask.remoteParent?.let { googleTaskDao.getTask(it) } ?: 0L googleTask.parent = googleTask.remoteParent?.let { googleTaskDao.getTask(it) } ?: 0L
} }
private suspend fun write(task: com.todoroo.astrid.data.Task, googleTask: GoogleTask) { private suspend fun write(task: com.todoroo.astrid.data.Task, googleTask: CaldavTask) {
task.suppressSync() task.suppressSync()
task.suppressRefresh() task.suppressRefresh()
if (task.isNew) { if (task.isNew) {
@ -367,7 +367,7 @@ class GoogleTaskSynchronizer @Inject constructor(
taskDao.save(task) taskDao.save(task)
googleTask.lastSync = task.modificationDate googleTask.lastSync = task.modificationDate
googleTask.task = task.id googleTask.task = task.id
if (googleTask.isNew) { if (googleTask.id == 0L) {
googleTaskDao.insert(googleTask) googleTaskDao.insert(googleTask)
} else { } else {
googleTaskDao.update(googleTask) googleTaskDao.update(googleTask)

@ -170,7 +170,7 @@ class DefaultFilterProvider @Inject constructor(
val googleTask = googleTaskDao.getByTaskId(task.id) val googleTask = googleTaskDao.getByTaskId(task.id)
val caldavTask = caldavDao.getTask(task.id) val caldavTask = caldavDao.getTask(task.id)
if (googleTask != null) { if (googleTask != null) {
val googleTaskList = googleTaskListDao.getByRemoteId(googleTask.listId!!) val googleTaskList = googleTaskListDao.getByRemoteId(googleTask.calendar!!)
if (googleTaskList != null) { if (googleTaskList != null) {
originalList = GtasksFilter(googleTaskList) originalList = GtasksFilter(googleTaskList)
} }

@ -99,29 +99,16 @@ class ChipProvider @Inject constructor(
) )
} }
} }
if (!isSubtask && preferences.showListChip) { if (!isSubtask && preferences.showListChip && filter !is CaldavFilter) {
if (!isNullOrEmpty(task.googleTaskList) && filter !is GtasksFilter) { lists.getCaldavList(task.caldav)?.let { list ->
lists.getCaldavList(task.googleTaskList)?.let { list -> FilterChip(
FilterChip( filter = if (task.isGoogleTask) GtasksFilter(list) else CaldavFilter(list),
filter = GtasksFilter(list), defaultIcon = R.drawable.ic_list_24px,
defaultIcon = R.drawable.ic_list_24px, onClick = onClick,
onClick = onClick, showText = showText,
showText = showText, showIcon = showIcon,
showIcon = showIcon, colorProvider = this::getColor,
colorProvider = this::getColor, )
)
}
} else if (!isNullOrEmpty(task.caldav) && filter !is CaldavFilter) {
lists.getCaldavList(task.caldav)?.let { list ->
FilterChip(
filter = CaldavFilter(list),
defaultIcon = R.drawable.ic_list_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
} }
} }
val tagString = task.tagsString val tagString = task.tagsString

@ -16,6 +16,7 @@ import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.data.TaskDao import org.tasks.data.TaskDao
import org.tasks.filters.FilterProvider import org.tasks.filters.FilterProvider
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@ -51,7 +52,12 @@ class NavigationDrawerViewModel @Inject constructor(
.navDrawerItems() .navDrawerItems()
.onEach { .onEach {
if (it is Filter && it.count == -1) { if (it is Filter && it.count == -1) {
it.count = taskDao.count(it) it.count = try {
taskDao.count(it)
} catch (e: Exception) {
Timber.e(e)
0
}
} }
} }
.let { filters -> _viewState.update { it.copy(filters = filters) } } .let { filters -> _viewState.update { it.copy(filters = filters) } }

@ -23,7 +23,7 @@ import kotlinx.coroutines.launch
import org.tasks.R import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.SubtaskRow import org.tasks.compose.edit.SubtaskRow
import org.tasks.data.GoogleTask import org.tasks.data.CaldavTask
import org.tasks.data.GoogleTaskDao import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskDao.TaskCriteria.activeAndVisible import org.tasks.data.TaskDao.TaskCriteria.activeAndVisible
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
@ -111,18 +111,18 @@ class SubtaskControlSet : TaskEditControlFragment() {
private fun getQueryTemplate(task: Task): QueryTemplate = QueryTemplate() private fun getQueryTemplate(task: Task): QueryTemplate = QueryTemplate()
.join( .join(
Join.left( Join.left(
GoogleTask.TABLE, CaldavTask.TABLE,
Criterion.and( Criterion.and(
GoogleTask.PARENT.eq(task.id), CaldavTask.PARENT.eq(task.id),
GoogleTask.TASK.eq(Task.ID), CaldavTask.TASK.eq(Task.ID),
GoogleTask.DELETED.eq(0) CaldavTask.DELETED.eq(0)
) )
) )
) )
.where( .where(
Criterion.and( Criterion.and(
activeAndVisible(), activeAndVisible(),
Criterion.or(Task.PARENT.eq(task.id), GoogleTask.TASK.gt(0)) Criterion.or(Task.PARENT.eq(task.id), CaldavTask.TASK.gt(0))
) )
) )
} }

@ -292,7 +292,7 @@ class TaskEditViewModel @Inject constructor(
firebase?.addTask("subtasks") firebase?.addTask("subtasks")
when (selectedList.value) { when (selectedList.value) {
is GtasksFilter -> { is GtasksFilter -> {
val googleTask = GoogleTask(subtask.id, (selectedList.value as GtasksFilter).remoteId) val googleTask = CaldavTask(subtask.id, (selectedList.value as GtasksFilter).remoteId)
googleTask.parent = task.id googleTask.parent = task.id
googleTask.isMoved = true googleTask.isMoved = true
googleTaskDao.insertAndShift(googleTask, false) googleTaskDao.insertAndShift(googleTask, false)

@ -5,7 +5,6 @@ import android.widget.RemoteViews
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.CaldavFilter import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.TagFilter import com.todoroo.astrid.api.TagFilter
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
@ -74,10 +73,6 @@ class ChipProvider @Inject constructor(
} }
fun getListChip(filter: Filter?, task: TaskContainer): RemoteViews? { fun getListChip(filter: Filter?, task: TaskContainer): RemoteViews? {
task.googleTaskList
?.takeIf { filter !is GtasksFilter }
?.let { newChip(GtasksFilter(chipListCache.getCaldavList(it)), R.drawable.ic_list_24px) }
?.let { return it }
task.caldav task.caldav
?.takeIf { filter !is CaldavFilter } ?.takeIf { filter !is CaldavFilter }
?.let { newChip(CaldavFilter(chipListCache.getCaldavList(it)), R.drawable.ic_list_24px) } ?.let { newChip(CaldavFilter(chipListCache.getCaldavList(it)), R.drawable.ic_list_24px) }

@ -5,7 +5,6 @@ import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.helper.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.GoogleTask
import org.tasks.makers.Maker.make import org.tasks.makers.Maker.make
object GoogleTaskMaker { object GoogleTaskMaker {
@ -18,7 +17,7 @@ object GoogleTaskMaker {
private val instantiator = Instantiator<GoogleTask> { private val instantiator = Instantiator<GoogleTask> {
val task = GoogleTask() val task = GoogleTask()
task.listId = it.valueOf(LIST, "1") task.calendar = it.valueOf(LIST, "1")
task.order = it.valueOf(ORDER, 0) task.order = it.valueOf(ORDER, 0)
task.remoteId = it.valueOf(REMOTE_ID, UUIDHelper.newUUID()) task.remoteId = it.valueOf(REMOTE_ID, UUIDHelper.newUUID())
task.task = it.valueOf(TASK, 1) task.task = it.valueOf(TASK, 1)

Loading…
Cancel
Save