mirror of https://github.com/tasks/tasks
Complete rewrite of Google Task manual ordering
parent
bef060591a
commit
087aae0a7b
@ -0,0 +1,996 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 63,
|
||||
"identityHash": "6a0e3b6d4ed545092c478951e77574ba",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "notification",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `type` INTEGER NOT NULL, `location` INTEGER)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"columnName": "uid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "taskId",
|
||||
"columnName": "task",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timestamp",
|
||||
"columnName": "timestamp",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "location",
|
||||
"columnName": "location",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"uid"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_notification_task",
|
||||
"unique": true,
|
||||
"columnNames": [
|
||||
"task"
|
||||
],
|
||||
"createSql": "CREATE UNIQUE INDEX `index_notification_task` ON `${TABLE_NAME}` (`task`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "tagdata",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `name` TEXT, `color` INTEGER, `tagOrdering` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remoteId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "color",
|
||||
"columnName": "color",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "tagOrdering",
|
||||
"columnName": "tagOrdering",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "userActivity",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `message` TEXT, `picture` TEXT, `target_id` TEXT, `created_at` INTEGER)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remoteId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "message",
|
||||
"columnName": "message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "picture",
|
||||
"columnName": "picture",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "targetId",
|
||||
"columnName": "target_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created",
|
||||
"columnName": "created_at",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "task_attachments",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `task_id` TEXT, `name` TEXT, `path` TEXT, `content_type` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remoteId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "taskId",
|
||||
"columnName": "task_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "uri",
|
||||
"columnName": "path",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "contentType",
|
||||
"columnName": "content_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "task_list_metadata",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `tag_uuid` TEXT, `filter` TEXT, `task_ids` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remoteId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "tagUuid",
|
||||
"columnName": "tag_uuid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "filter",
|
||||
"columnName": "filter",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "taskIds",
|
||||
"columnName": "task_ids",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "tasks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT, `importance` INTEGER, `dueDate` INTEGER, `hideUntil` INTEGER, `created` INTEGER, `modified` INTEGER, `completed` INTEGER, `deleted` INTEGER, `notes` TEXT, `estimatedSeconds` INTEGER, `elapsedSeconds` INTEGER, `timerStart` INTEGER, `notificationFlags` INTEGER, `notifications` INTEGER, `lastNotified` INTEGER, `snoozeTime` INTEGER, `recurrence` TEXT, `repeatUntil` INTEGER, `calendarUri` TEXT, `remoteId` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "priority",
|
||||
"columnName": "importance",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "dueDate",
|
||||
"columnName": "dueDate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "hideUntil",
|
||||
"columnName": "hideUntil",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created",
|
||||
"columnName": "created",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "modified",
|
||||
"columnName": "modified",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "completed",
|
||||
"columnName": "completed",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleted",
|
||||
"columnName": "deleted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "notes",
|
||||
"columnName": "notes",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "estimatedSeconds",
|
||||
"columnName": "estimatedSeconds",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "elapsedSeconds",
|
||||
"columnName": "elapsedSeconds",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "timerStart",
|
||||
"columnName": "timerStart",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "notificationFlags",
|
||||
"columnName": "notificationFlags",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "notifications",
|
||||
"columnName": "notifications",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastNotified",
|
||||
"columnName": "lastNotified",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "snoozeTime",
|
||||
"columnName": "snoozeTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "recurrence",
|
||||
"columnName": "recurrence",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "repeatUntil",
|
||||
"columnName": "repeatUntil",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "calendarUri",
|
||||
"columnName": "calendarUri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remoteId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "t_rid",
|
||||
"unique": true,
|
||||
"columnNames": [
|
||||
"remoteId"
|
||||
],
|
||||
"createSql": "CREATE UNIQUE INDEX `t_rid` ON `${TABLE_NAME}` (`remoteId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "alarms",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `time` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "task",
|
||||
"columnName": "task",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "time",
|
||||
"columnName": "time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "places",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`place_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uid` TEXT, `name` TEXT, `address` TEXT, `phone` TEXT, `url` TEXT, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "place_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"columnName": "uid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "address",
|
||||
"columnName": "address",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "phone",
|
||||
"columnName": "phone",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "latitude",
|
||||
"columnName": "latitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "longitude",
|
||||
"columnName": "longitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"place_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "geofences",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`geofence_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `place` TEXT, `radius` INTEGER NOT NULL, `arrival` INTEGER NOT NULL, `departure` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "geofence_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "task",
|
||||
"columnName": "task",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "place",
|
||||
"columnName": "place",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "radius",
|
||||
"columnName": "radius",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "arrival",
|
||||
"columnName": "arrival",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "departure",
|
||||
"columnName": "departure",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"geofence_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "tags",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `name` TEXT, `tag_uid` TEXT, `task_uid` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "task",
|
||||
"columnName": "task",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "tagUid",
|
||||
"columnName": "tag_uid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "taskUid",
|
||||
"columnName": "task_uid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"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)",
|
||||
"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": "moved",
|
||||
"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": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"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)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "sql",
|
||||
"columnName": "sql",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "values",
|
||||
"columnName": "values",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "criterion",
|
||||
"columnName": "criterion",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "google_task_lists",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT, `remote_id` TEXT, `title` TEXT, `remote_order` INTEGER NOT NULL, `last_sync` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `color` INTEGER)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "account",
|
||||
"columnName": "account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remote_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteOrder",
|
||||
"columnName": "remote_order",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastSync",
|
||||
"columnName": "last_sync",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleted",
|
||||
"columnName": "deleted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "color",
|
||||
"columnName": "color",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "caldav_calendar",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT, `uuid` TEXT, `name` TEXT, `color` INTEGER NOT NULL, `ctag` TEXT, `url` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "account",
|
||||
"columnName": "account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "color",
|
||||
"columnName": "color",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "ctag",
|
||||
"columnName": "ctag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "caldav_tasks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `calendar` TEXT, `object` TEXT, `remote_id` TEXT, `etag` TEXT, `last_sync` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `vtodo` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "task",
|
||||
"columnName": "task",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "calendar",
|
||||
"columnName": "calendar",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "object",
|
||||
"columnName": "object",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remote_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "etag",
|
||||
"columnName": "etag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastSync",
|
||||
"columnName": "last_sync",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleted",
|
||||
"columnName": "deleted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "vtodo",
|
||||
"columnName": "vtodo",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "caldav_account",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uuid` TEXT, `name` TEXT, `url` TEXT, `username` TEXT, `password` TEXT, `error` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "username",
|
||||
"columnName": "username",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "password",
|
||||
"columnName": "password",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "error",
|
||||
"columnName": "error",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "google_task_accounts",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT, `error` TEXT, `etag` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "account",
|
||||
"columnName": "account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "error",
|
||||
"columnName": "error",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "etag",
|
||||
"columnName": "etag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"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, \"6a0e3b6d4ed545092c478951e77574ba\")"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import com.google.api.services.tasks.model.TaskList;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.tasks.data.GoogleTask;
|
||||
import org.tasks.data.GoogleTaskAccount;
|
||||
import org.tasks.data.GoogleTaskDao;
|
||||
import org.tasks.data.GoogleTaskList;
|
||||
import org.tasks.data.GoogleTaskListDao;
|
||||
import org.tasks.injection.InjectingTestCase;
|
||||
import org.tasks.injection.TestComponent;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class GtasksIndentActionTest extends InjectingTestCase {
|
||||
|
||||
@Inject GtasksListService gtasksListService;
|
||||
@Inject GoogleTaskListDao googleTaskListDao;
|
||||
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
|
||||
@Inject TaskDao taskDao;
|
||||
@Inject GoogleTaskDao googleTaskDao;
|
||||
|
||||
private Task task;
|
||||
private GoogleTaskList storeList;
|
||||
|
||||
@Test
|
||||
public void testIndentWithoutMetadata() {
|
||||
givenTask(taskWithoutMetadata());
|
||||
|
||||
whenIncreaseIndent();
|
||||
|
||||
// should not crash
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabled_testIndentWithMetadataButNoOtherTasks() {
|
||||
givenTask(taskWithMetadata(0, 0));
|
||||
|
||||
whenIncreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndentWithMetadata() {
|
||||
taskWithMetadata(0, 0);
|
||||
givenTask(taskWithMetadata(1, 0));
|
||||
|
||||
whenIncreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeindentWithMetadata() {
|
||||
givenTask(taskWithMetadata(0, 1));
|
||||
|
||||
whenDecreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeindentWithoutMetadata() {
|
||||
givenTask(taskWithoutMetadata());
|
||||
|
||||
whenDecreaseIndent();
|
||||
|
||||
// should not crash
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeindentWhenAlreadyZero() {
|
||||
givenTask(taskWithMetadata(0, 0));
|
||||
|
||||
whenDecreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndentWithChildren() {
|
||||
taskWithMetadata(0, 0);
|
||||
givenTask(taskWithMetadata(1, 0));
|
||||
Task child = taskWithMetadata(2, 1);
|
||||
|
||||
whenIncreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(1);
|
||||
thenExpectIndentationLevel(child, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeindentWithChildren() {
|
||||
taskWithMetadata(0, 0);
|
||||
givenTask(taskWithMetadata(1, 1));
|
||||
Task child = taskWithMetadata(2, 2);
|
||||
|
||||
whenDecreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(0);
|
||||
thenExpectIndentationLevel(child, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndentWithSiblings() {
|
||||
taskWithMetadata(0, 0);
|
||||
givenTask(taskWithMetadata(1, 0));
|
||||
Task sibling = taskWithMetadata(2, 0);
|
||||
|
||||
whenIncreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(1);
|
||||
thenExpectIndentationLevel(sibling, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndentWithChildrensChildren() {
|
||||
taskWithMetadata(0, 0);
|
||||
givenTask(taskWithMetadata(1, 0));
|
||||
Task child = taskWithMetadata(2, 1);
|
||||
Task grandchild = taskWithMetadata(3, 2);
|
||||
|
||||
whenIncreaseIndent();
|
||||
|
||||
thenExpectIndentationLevel(1);
|
||||
thenExpectIndentationLevel(child, 2);
|
||||
thenExpectIndentationLevel(grandchild, 3);
|
||||
}
|
||||
|
||||
// --- helpers
|
||||
|
||||
private void whenIncreaseIndent() {
|
||||
gtasksTaskListUpdater.indent(storeList, task.getId(), 1);
|
||||
}
|
||||
|
||||
private void whenDecreaseIndent() {
|
||||
gtasksTaskListUpdater.indent(storeList, task.getId(), -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
List<TaskList> items = new ArrayList<>();
|
||||
TaskList list = new TaskList();
|
||||
list.setId("list");
|
||||
list.setTitle("Test Tasks");
|
||||
items.add(list);
|
||||
GoogleTaskAccount account = new GoogleTaskAccount("account");
|
||||
googleTaskListDao.insert(account);
|
||||
gtasksListService.updateLists(account, items);
|
||||
|
||||
storeList = googleTaskListDao.getLists("account").get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(TestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private Task taskWithMetadata(long order, int indentation) {
|
||||
Task newTask = new Task();
|
||||
taskDao.createNew(newTask);
|
||||
GoogleTask metadata = new GoogleTask(newTask.getId(), "list");
|
||||
metadata.setIndent(indentation);
|
||||
metadata.setOrder(order);
|
||||
googleTaskDao.insert(metadata);
|
||||
return newTask;
|
||||
}
|
||||
|
||||
private void thenExpectIndentationLevel(int expected) {
|
||||
thenExpectIndentationLevel(task, expected);
|
||||
}
|
||||
|
||||
private void thenExpectIndentationLevel(Task targetTask, int expected) {
|
||||
GoogleTask metadata = googleTaskDao.getByTaskId(targetTask.getId());
|
||||
assertNotNull("task has metadata", metadata);
|
||||
int indentation = metadata.getIndent();
|
||||
assertTrue("indentation: " + indentation, indentation == expected);
|
||||
}
|
||||
|
||||
private void givenTask(Task taskToTest) {
|
||||
task = taskToTest;
|
||||
}
|
||||
|
||||
private Task taskWithoutMetadata() {
|
||||
Task task = new Task();
|
||||
taskDao.createNew(task);
|
||||
return task;
|
||||
}
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import com.google.api.services.tasks.model.TaskList;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.tasks.data.GoogleTask;
|
||||
import org.tasks.data.GoogleTaskAccount;
|
||||
import org.tasks.data.GoogleTaskDao;
|
||||
import org.tasks.data.GoogleTaskList;
|
||||
import org.tasks.data.GoogleTaskListDao;
|
||||
import org.tasks.injection.InjectingTestCase;
|
||||
import org.tasks.injection.TestComponent;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class GtasksTaskListUpdaterTest extends InjectingTestCase {
|
||||
|
||||
private static final int VALUE_UNSET = -1;
|
||||
|
||||
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
|
||||
@Inject GtasksListService gtasksListService;
|
||||
@Inject TaskDao taskDao;
|
||||
@Inject GoogleTaskDao googleTaskDao;
|
||||
@Inject GoogleTaskListDao googleTaskListDao;
|
||||
|
||||
@Test
|
||||
public void testBasicParentComputation() {
|
||||
Task[] tasks = givenTasksABCDE();
|
||||
|
||||
whenCalculatingParentsAndSiblings();
|
||||
|
||||
thenExpectParent(tasks[0], null);
|
||||
thenExpectParent(tasks[1], tasks[0]);
|
||||
thenExpectParent(tasks[2], tasks[0]);
|
||||
thenExpectParent(tasks[3], tasks[2]);
|
||||
thenExpectParent(tasks[4], null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicSiblingComputation() {
|
||||
Task[] tasks = givenTasksABCDE();
|
||||
|
||||
whenCalculatingParentsAndSiblings();
|
||||
|
||||
thenExpectSibling(tasks[0], null);
|
||||
thenExpectSibling(tasks[1], null);
|
||||
thenExpectSibling(tasks[2], tasks[1]);
|
||||
thenExpectSibling(tasks[3], null);
|
||||
thenExpectSibling(tasks[4], tasks[0]);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testMetadataParentComputation() {
|
||||
Task[] tasks = givenTasksABCDE();
|
||||
|
||||
thenExpectMetadataParent(tasks[0], null);
|
||||
thenExpectMetadataParent(tasks[1], tasks[0]);
|
||||
thenExpectMetadataParent(tasks[2], tasks[0]);
|
||||
thenExpectMetadataParent(tasks[3], tasks[2]);
|
||||
thenExpectMetadataParent(tasks[4], null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetadataOrderComputation() {
|
||||
Task[] tasks = givenTasksABCDE();
|
||||
|
||||
thenExpectMetadataIndentAndOrder(tasks[0], 0, 0);
|
||||
thenExpectMetadataIndentAndOrder(tasks[1], 1, 1);
|
||||
thenExpectMetadataIndentAndOrder(tasks[2], 2, 1);
|
||||
thenExpectMetadataIndentAndOrder(tasks[3], 3, 2);
|
||||
thenExpectMetadataIndentAndOrder(tasks[4], 4, 0);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testNewTaskOrder() {
|
||||
givenTasksABCDE();
|
||||
|
||||
Task newTask = createTask("F", VALUE_UNSET, 0);
|
||||
|
||||
thenExpectMetadataIndentAndOrder(newTask, 5, 0);
|
||||
}
|
||||
|
||||
// --- helpers
|
||||
|
||||
private void thenExpectMetadataIndentAndOrder(Task task, long order, int indent) {
|
||||
GoogleTask metadata = googleTaskDao.getByTaskId(task.getId());
|
||||
assertNotNull("metadata was found", metadata);
|
||||
assertEquals("order", order, metadata.getOrder());
|
||||
assertEquals("indentation", indent, metadata.getIndent());
|
||||
}
|
||||
|
||||
private void thenExpectMetadataParent(Task task, Task expectedParent) {
|
||||
GoogleTask metadata = googleTaskDao.getByTaskId(task.getId());
|
||||
long parent = metadata.getParent();
|
||||
if (expectedParent == null) {
|
||||
assertEquals("Task " + task.getTitle() + " parent none", 0, parent);
|
||||
} else {
|
||||
assertEquals(
|
||||
"Task " + task.getTitle() + " parent " + expectedParent.getTitle(),
|
||||
expectedParent.getId(),
|
||||
parent);
|
||||
}
|
||||
}
|
||||
|
||||
private void thenExpectSibling(Task task, Task expectedSibling) {
|
||||
long sibling = gtasksTaskListUpdater.siblings.get(task.getId());
|
||||
if (expectedSibling == null) {
|
||||
assertEquals("Task " + task.getTitle() + " sibling null", 0L, sibling);
|
||||
} else {
|
||||
assertEquals(
|
||||
"Task " + task.getTitle() + " sibling " + expectedSibling.getTitle(),
|
||||
expectedSibling.getId(),
|
||||
sibling);
|
||||
}
|
||||
}
|
||||
|
||||
private void thenExpectParent(Task task, Task expectedParent) {
|
||||
long parent = gtasksTaskListUpdater.parents.get(task.getId());
|
||||
if (expectedParent == null) {
|
||||
assertEquals("Task " + task.getTitle() + " parent null", 0L, parent);
|
||||
} else {
|
||||
assertEquals(
|
||||
"Task " + task.getTitle() + " parent " + expectedParent.getTitle(),
|
||||
expectedParent.getId(),
|
||||
parent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
List<TaskList> items = new ArrayList<>();
|
||||
TaskList list = new TaskList();
|
||||
list.setId("1");
|
||||
list.setTitle("Tim's Tasks");
|
||||
items.add(list);
|
||||
GoogleTaskAccount account = new GoogleTaskAccount("account");
|
||||
googleTaskListDao.insert(account);
|
||||
gtasksListService.updateLists(account, items);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(TestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void whenCalculatingParentsAndSiblings() {
|
||||
createParentSiblingMaps();
|
||||
}
|
||||
|
||||
private void createParentSiblingMaps() {
|
||||
for (GoogleTaskList list : googleTaskListDao.getLists("account")) {
|
||||
gtasksTaskListUpdater.updateParentSiblingMapsFor(list);
|
||||
}
|
||||
}
|
||||
|
||||
// A
|
||||
// B
|
||||
// C
|
||||
// D
|
||||
// E
|
||||
private Task[] givenTasksABCDE() {
|
||||
return new Task[] {
|
||||
createTask("A", 0, 0),
|
||||
createTask("B", 1, 1),
|
||||
createTask("C", 2, 1),
|
||||
createTask("D", 3, 2),
|
||||
createTask("E", 4, 0),
|
||||
};
|
||||
}
|
||||
|
||||
private Task createTask(String title, long order, int indent) {
|
||||
Task task = new Task();
|
||||
task.setTitle(title);
|
||||
taskDao.createNew(task);
|
||||
GoogleTask metadata = new GoogleTask(task.getId(), "1");
|
||||
if (order != VALUE_UNSET) {
|
||||
metadata.setOrder(order);
|
||||
}
|
||||
if (indent != VALUE_UNSET) {
|
||||
metadata.setIndent(indent);
|
||||
}
|
||||
googleTaskDao.insert(metadata);
|
||||
return task;
|
||||
}
|
||||
}
|
@ -1,313 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import com.google.api.services.tasks.model.TaskList;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.tasks.data.GoogleTask;
|
||||
import org.tasks.data.GoogleTaskAccount;
|
||||
import org.tasks.data.GoogleTaskDao;
|
||||
import org.tasks.data.GoogleTaskList;
|
||||
import org.tasks.data.GoogleTaskListDao;
|
||||
import org.tasks.injection.InjectingTestCase;
|
||||
import org.tasks.injection.TestComponent;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class GtasksTaskMovingTest extends InjectingTestCase {
|
||||
|
||||
private static final int VALUE_UNSET = -1;
|
||||
|
||||
@Inject GtasksListService gtasksListService;
|
||||
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
|
||||
@Inject TaskDao taskDao;
|
||||
@Inject GoogleTaskDao googleTaskDao;
|
||||
@Inject GoogleTaskListDao googleTaskListDao;
|
||||
|
||||
private Task A, B, C, D, E, F;
|
||||
private GoogleTaskList list;
|
||||
|
||||
/* Starting State:
|
||||
*
|
||||
* A
|
||||
* B
|
||||
* C
|
||||
* D
|
||||
* E
|
||||
* F
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testMoveDownFromListBottom() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(F, null);
|
||||
|
||||
thenExpectMetadataOrderAndIndent(E, 4, 0);
|
||||
thenExpectMetadataOrderAndIndent(F, 5, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveDownToListBottom() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(E, null);
|
||||
|
||||
thenExpectMetadataOrderAndIndent(E, 5, 0);
|
||||
thenExpectMetadataOrderAndIndent(F, 4, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveUpSimple() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(F, E);
|
||||
|
||||
thenExpectMetadataOrderAndIndent(E, 5, 0);
|
||||
thenExpectMetadataOrderAndIndent(F, 4, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveUpWithSubtasks() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(C, B);
|
||||
|
||||
/*
|
||||
* A
|
||||
* C
|
||||
* D
|
||||
* B
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 3, 1);
|
||||
thenExpectMetadataOrderAndIndent(C, 1, 1);
|
||||
thenExpectMetadataOrderAndIndent(D, 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveDownThroughSubtasks() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(B, E);
|
||||
|
||||
/*
|
||||
* A
|
||||
* C
|
||||
* D
|
||||
* B
|
||||
* E
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 3, 0);
|
||||
thenExpectMetadataOrderAndIndent(C, 1, 1);
|
||||
thenExpectMetadataOrderAndIndent(D, 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveUpAboveParent() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(B, A);
|
||||
|
||||
/*
|
||||
* B
|
||||
* A
|
||||
* C
|
||||
* D
|
||||
* E
|
||||
* F
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 1, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(C, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveDownWithChildren() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(C, F);
|
||||
|
||||
/*
|
||||
* A
|
||||
* B
|
||||
* E
|
||||
* C
|
||||
* D
|
||||
* F
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 1, 1);
|
||||
thenExpectMetadataOrderAndIndent(C, 3, 0);
|
||||
thenExpectMetadataOrderAndIndent(D, 4, 1);
|
||||
thenExpectMetadataOrderAndIndent(E, 2, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveDownIndentingTwice() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(D, F);
|
||||
|
||||
/*
|
||||
* A
|
||||
* B
|
||||
* C
|
||||
* E
|
||||
* D
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 1, 1);
|
||||
thenExpectMetadataOrderAndIndent(C, 2, 1);
|
||||
thenExpectMetadataOrderAndIndent(D, 4, 0);
|
||||
thenExpectMetadataOrderAndIndent(E, 3, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveUpMultiple() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(C, A);
|
||||
|
||||
/*
|
||||
* C
|
||||
* D
|
||||
* A
|
||||
* B
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 2, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 3, 1);
|
||||
thenExpectMetadataOrderAndIndent(C, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(D, 1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveUpIntoSublist() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(F, D);
|
||||
|
||||
/*
|
||||
* A
|
||||
* B
|
||||
* C
|
||||
* F
|
||||
* D
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 1, 1);
|
||||
thenExpectMetadataOrderAndIndent(C, 2, 1);
|
||||
thenExpectMetadataOrderAndIndent(D, 4, 2);
|
||||
thenExpectMetadataOrderAndIndent(E, 5, 0);
|
||||
thenExpectMetadataOrderAndIndent(F, 3, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveDownMultiple() {
|
||||
givenTasksABCDEF();
|
||||
|
||||
whenTriggerMove(B, F);
|
||||
|
||||
/*
|
||||
* A
|
||||
* C
|
||||
* D
|
||||
* E
|
||||
* B
|
||||
*/
|
||||
|
||||
thenExpectMetadataOrderAndIndent(A, 0, 0);
|
||||
thenExpectMetadataOrderAndIndent(B, 4, 0);
|
||||
thenExpectMetadataOrderAndIndent(C, 1, 1);
|
||||
thenExpectMetadataOrderAndIndent(D, 2, 2);
|
||||
thenExpectMetadataOrderAndIndent(E, 3, 0);
|
||||
thenExpectMetadataOrderAndIndent(F, 5, 0);
|
||||
}
|
||||
|
||||
// --- helpers
|
||||
|
||||
/** moveTo = null => move to end */
|
||||
private void whenTriggerMove(Task target, Task moveTo) {
|
||||
gtasksTaskListUpdater.moveTo(list, target.getId(), moveTo == null ? -1 : moveTo.getId());
|
||||
}
|
||||
|
||||
private void thenExpectMetadataOrderAndIndent(Task task, long order, int indent) {
|
||||
GoogleTask metadata = googleTaskDao.getByTaskId(task.getId());
|
||||
assertNotNull("metadata was found", metadata);
|
||||
assertEquals("order", order, metadata.getOrder());
|
||||
assertEquals("indentation", indent, metadata.getIndent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
List<TaskList> items = new ArrayList<>();
|
||||
TaskList taskList = new TaskList();
|
||||
taskList.setId("1");
|
||||
taskList.setTitle("Tim's Tasks");
|
||||
items.add(taskList);
|
||||
GoogleTaskAccount account = new GoogleTaskAccount("account");
|
||||
googleTaskListDao.insert(account);
|
||||
gtasksListService.updateLists(account, items);
|
||||
|
||||
list = googleTaskListDao.getLists("account").get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(TestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
// A
|
||||
// B
|
||||
// C
|
||||
// D
|
||||
// E
|
||||
// F
|
||||
private void givenTasksABCDEF() {
|
||||
A = createTask("A", 0, 0);
|
||||
B = createTask("B", 1, 1);
|
||||
C = createTask("C", 2, 1);
|
||||
D = createTask("D", 3, 2);
|
||||
E = createTask("E", 4, 0);
|
||||
F = createTask("F", 5, 0);
|
||||
}
|
||||
|
||||
private Task createTask(String title, long order, int indent) {
|
||||
Task task = new Task();
|
||||
task.setTitle(title);
|
||||
taskDao.createNew(task);
|
||||
GoogleTask metadata = new GoogleTask(task.getId(), "1");
|
||||
if (order != VALUE_UNSET) {
|
||||
metadata.setOrder(order);
|
||||
}
|
||||
if (indent != VALUE_UNSET) {
|
||||
metadata.setIndent(indent);
|
||||
}
|
||||
googleTaskDao.insert(metadata);
|
||||
return task;
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
package org.tasks.data;
|
||||
|
||||
import static com.natpryce.makeiteasy.MakeItEasy.with;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.tasks.makers.GoogleTaskMaker.REMOTE_ID;
|
||||
import static org.tasks.makers.GoogleTaskMaker.TASK;
|
||||
import static org.tasks.makers.GoogleTaskMaker.newGoogleTask;
|
||||
import static org.tasks.makers.GtaskListMaker.newGtaskList;
|
||||
import static org.tasks.makers.TaskMaker.newTask;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.tasks.injection.InjectingTestCase;
|
||||
import org.tasks.injection.TestComponent;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class GoogleTaskDaoTests extends InjectingTestCase {
|
||||
|
||||
@Inject GoogleTaskListDao googleTaskListDao;
|
||||
@Inject GoogleTaskDao googleTaskDao;
|
||||
@Inject TaskDao taskDao;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
googleTaskListDao.insert(newGtaskList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertAtTopOfEmptyList() {
|
||||
insertTop(newGoogleTask(with(REMOTE_ID, "1234")));
|
||||
List<GoogleTask> tasks = googleTaskDao.getByLocalOrder("1");
|
||||
assertEquals(1, tasks.size());
|
||||
GoogleTask task = tasks.get(0);
|
||||
assertEquals("1234", task.getRemoteId());
|
||||
assertEquals(0, task.getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertAtBottomOfEmptyList() {
|
||||
insertBottom(newGoogleTask(with(REMOTE_ID, "1234")));
|
||||
List<GoogleTask> tasks = googleTaskDao.getByLocalOrder("1");
|
||||
assertEquals(1, tasks.size());
|
||||
GoogleTask task = tasks.get(0);
|
||||
assertEquals("1234", task.getRemoteId());
|
||||
assertEquals(0, task.getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreviousIsNullForTopTask() {
|
||||
googleTaskDao.insertAndShift(newGoogleTask(), true);
|
||||
assertNull(googleTaskDao.getPrevious("1", 0, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPrevious() {
|
||||
insertTop(newGoogleTask());
|
||||
insertTop(newGoogleTask(with(REMOTE_ID, "1234")));
|
||||
|
||||
assertEquals("1234", googleTaskDao.getPrevious("1", 0, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertAtTopOfList() {
|
||||
insertTop(newGoogleTask(with(REMOTE_ID, "1234")));
|
||||
insertTop(newGoogleTask(with(REMOTE_ID, "5678")));
|
||||
|
||||
List<GoogleTask> tasks = googleTaskDao.getByLocalOrder("1");
|
||||
assertEquals(2, tasks.size());
|
||||
GoogleTask top = tasks.get(0);
|
||||
assertEquals("5678", top.getRemoteId());
|
||||
assertEquals(0, top.getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertAtTopOfListShiftsExisting() {
|
||||
insertTop(newGoogleTask(with(REMOTE_ID, "1234")));
|
||||
insertTop(newGoogleTask(with(REMOTE_ID, "5678")));
|
||||
|
||||
List<GoogleTask> tasks = googleTaskDao.getByLocalOrder("1");
|
||||
assertEquals(2, tasks.size());
|
||||
GoogleTask bottom = tasks.get(1);
|
||||
assertEquals("1234", bottom.getRemoteId());
|
||||
assertEquals(1, bottom.getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTaskFromRemoteId() {
|
||||
googleTaskDao.insert(newGoogleTask(with(REMOTE_ID, "1234"), with(TASK, 4)));
|
||||
assertEquals(4, googleTaskDao.getTask("1234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRemoteIdForTask() {
|
||||
googleTaskDao.insert(newGoogleTask(with(REMOTE_ID, "1234"), with(TASK, 4)));
|
||||
assertEquals("1234", googleTaskDao.getRemoteId(4L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveDownInList() {
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "1")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "2")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "3")), false);
|
||||
|
||||
GoogleTask two = googleTaskDao.getByRemoteId("2");
|
||||
|
||||
googleTaskDao.move(two, 0, 0);
|
||||
|
||||
assertEquals(0, googleTaskDao.getByRemoteId("2").getOrder());
|
||||
assertEquals(1, googleTaskDao.getByRemoteId("1").getOrder());
|
||||
assertEquals(2, googleTaskDao.getByRemoteId("3").getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveUpInList() {
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "1")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "2")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "3")), false);
|
||||
|
||||
GoogleTask one = googleTaskDao.getByRemoteId("1");
|
||||
|
||||
googleTaskDao.move(one, 0, 1);
|
||||
|
||||
assertEquals(0, googleTaskDao.getByRemoteId("2").getOrder());
|
||||
assertEquals(1, googleTaskDao.getByRemoteId("1").getOrder());
|
||||
assertEquals(2, googleTaskDao.getByRemoteId("3").getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveToTop() {
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "1")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "2")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "3")), false);
|
||||
|
||||
GoogleTask three = googleTaskDao.getByRemoteId("3");
|
||||
|
||||
googleTaskDao.move(three, 0, 0);
|
||||
|
||||
assertEquals(0, googleTaskDao.getByRemoteId("3").getOrder());
|
||||
assertEquals(1, googleTaskDao.getByRemoteId("1").getOrder());
|
||||
assertEquals(2, googleTaskDao.getByRemoteId("2").getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveToBottom() {
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "1")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "2")), false);
|
||||
googleTaskDao.insertAndShift(newGoogleTask(with(REMOTE_ID, "3")), false);
|
||||
|
||||
GoogleTask one = googleTaskDao.getByRemoteId("1");
|
||||
|
||||
googleTaskDao.move(one, 0, 2);
|
||||
|
||||
assertEquals(0, googleTaskDao.getByRemoteId("2").getOrder());
|
||||
assertEquals(1, googleTaskDao.getByRemoteId("3").getOrder());
|
||||
assertEquals(2, googleTaskDao.getByRemoteId("1").getOrder());
|
||||
}
|
||||
|
||||
private void insertTop(GoogleTask googleTask) {
|
||||
insert(googleTask, true);
|
||||
}
|
||||
|
||||
private void insertBottom(GoogleTask googleTask) {
|
||||
insert(googleTask, false);
|
||||
}
|
||||
|
||||
private void insert(GoogleTask googleTask, boolean top) {
|
||||
Task task = newTask();
|
||||
taskDao.createNew(task);
|
||||
googleTask.setTask(task.getId());
|
||||
googleTaskDao.insertAndShift(googleTask, top);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(TestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.tasks.makers;
|
||||
|
||||
import static com.natpryce.makeiteasy.Property.newProperty;
|
||||
import static org.tasks.makers.Maker.make;
|
||||
|
||||
import com.natpryce.makeiteasy.Instantiator;
|
||||
import com.natpryce.makeiteasy.Property;
|
||||
import com.natpryce.makeiteasy.PropertyValue;
|
||||
import com.todoroo.astrid.helper.UUIDHelper;
|
||||
import org.tasks.data.GoogleTask;
|
||||
|
||||
public class GoogleTaskMaker {
|
||||
|
||||
public static final Property<GoogleTask, String> LIST = newProperty();
|
||||
public static final Property<GoogleTask, Integer> ORDER = newProperty();
|
||||
public static final Property<GoogleTask, String> REMOTE_ID = newProperty();
|
||||
public static final Property<GoogleTask, Integer> TASK = newProperty();
|
||||
|
||||
private static final Instantiator<GoogleTask> instantiator = lookup -> {
|
||||
GoogleTask task = new GoogleTask();
|
||||
task.setListId(lookup.valueOf(LIST, "1"));
|
||||
task.setOrder(lookup.valueOf(ORDER, 0));
|
||||
task.setRemoteId(lookup.valueOf(REMOTE_ID, UUIDHelper.newUUID()));
|
||||
task.setTask(lookup.valueOf(TASK, 1));
|
||||
return task;
|
||||
};
|
||||
|
||||
@SafeVarargs
|
||||
public static GoogleTask newGoogleTask(PropertyValue<? super GoogleTask, ?>... properties) {
|
||||
return make(instantiator, properties);
|
||||
}
|
||||
}
|
@ -1,404 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import com.todoroo.astrid.api.GtasksFilter;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.data.GoogleTask;
|
||||
import org.tasks.data.GoogleTaskDao;
|
||||
import org.tasks.data.GoogleTaskList;
|
||||
import org.tasks.injection.ApplicationScope;
|
||||
import timber.log.Timber;
|
||||
|
||||
@ApplicationScope
|
||||
public class GtasksTaskListUpdater {
|
||||
|
||||
/** map of task -> parent task */
|
||||
final HashMap<Long, Long> parents = new HashMap<>();
|
||||
|
||||
/** map of task -> prior sibling */
|
||||
final HashMap<Long, Long> siblings = new HashMap<>();
|
||||
|
||||
private final GtasksSyncService gtasksSyncService;
|
||||
private final GoogleTaskDao googleTaskDao;
|
||||
|
||||
@Inject
|
||||
public GtasksTaskListUpdater(GtasksSyncService gtasksSyncService, GoogleTaskDao googleTaskDao) {
|
||||
this.gtasksSyncService = gtasksSyncService;
|
||||
this.googleTaskDao = googleTaskDao;
|
||||
}
|
||||
|
||||
public void initialize(Filter filter) {
|
||||
String query = GtasksFilter.toManualOrder(filter.getSqlQuery());
|
||||
filter.setFilterQueryOverride(query);
|
||||
}
|
||||
|
||||
// --- overrides
|
||||
|
||||
public GoogleTask getTaskMetadata(long taskId) {
|
||||
return googleTaskDao.getByTaskId(taskId);
|
||||
}
|
||||
|
||||
private void iterateThroughList(GoogleTaskList list, OrderedListIterator iterator) {
|
||||
String listId = list.getRemoteId();
|
||||
gtasksSyncService.iterateThroughList(listId, iterator, 0, false);
|
||||
}
|
||||
|
||||
private void onMovedOrIndented(GoogleTaskList googleTaskList, GoogleTask googleTask) {
|
||||
gtasksSyncService.triggerMoveForMetadata(googleTaskList, googleTask);
|
||||
}
|
||||
|
||||
// --- used during synchronization
|
||||
|
||||
public void correctOrderAndIndentForList(String listId) {
|
||||
orderAndIndentHelper(listId, new AtomicLong(0L), Task.NO_ID, 0, new HashSet<>());
|
||||
}
|
||||
|
||||
private void orderAndIndentHelper(
|
||||
final String listId,
|
||||
final AtomicLong order,
|
||||
final long parent,
|
||||
final int indentLevel,
|
||||
final Set<Long> alreadyChecked) {
|
||||
for (GoogleTask curr : googleTaskDao.byRemoteOrder(listId, parent)) {
|
||||
if (!alreadyChecked.contains(curr.getTask())) {
|
||||
curr.setIndent(indentLevel);
|
||||
curr.setOrder(order.getAndIncrement());
|
||||
googleTaskDao.update(curr);
|
||||
alreadyChecked.add(curr.getTask());
|
||||
|
||||
orderAndIndentHelper(listId, order, curr.getTask(), indentLevel + 1, alreadyChecked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateParentSiblingMapsFor(GoogleTaskList list) {
|
||||
final AtomicLong previousTask = new AtomicLong(Task.NO_ID);
|
||||
final AtomicInteger previousIndent = new AtomicInteger(-1);
|
||||
|
||||
iterateThroughList(
|
||||
list,
|
||||
(taskId, metadata) -> {
|
||||
int indent = metadata.getIndent();
|
||||
|
||||
try {
|
||||
long parent, sibling;
|
||||
if (indent > previousIndent.get()) {
|
||||
parent = previousTask.get();
|
||||
sibling = Task.NO_ID;
|
||||
} else if (indent == previousIndent.get()) {
|
||||
sibling = previousTask.get();
|
||||
parent = parents.get(sibling);
|
||||
} else {
|
||||
// move up once for each indent
|
||||
sibling = previousTask.get();
|
||||
for (int i = indent; i < previousIndent.get(); i++) {
|
||||
sibling = parents.get(sibling);
|
||||
}
|
||||
if (parents.containsKey(sibling)) {
|
||||
parent = parents.get(sibling);
|
||||
} else {
|
||||
parent = Task.NO_ID;
|
||||
}
|
||||
}
|
||||
parents.put(taskId, parent);
|
||||
siblings.put(taskId, sibling);
|
||||
} catch (Exception e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
|
||||
previousTask.set(taskId);
|
||||
previousIndent.set(indent);
|
||||
});
|
||||
}
|
||||
|
||||
/** Indent a task and all its children */
|
||||
public void indent(final GoogleTaskList list, final long targetTaskId, final int delta) {
|
||||
if (list == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateParentSiblingMapsFor(list);
|
||||
|
||||
final AtomicInteger targetTaskIndent = new AtomicInteger(-1);
|
||||
final AtomicInteger previousIndent = new AtomicInteger(-1);
|
||||
final AtomicLong previousTask = new AtomicLong(Task.NO_ID);
|
||||
final AtomicLong globalOrder = new AtomicLong(-1);
|
||||
|
||||
iterateThroughList(
|
||||
list,
|
||||
(taskId, googleTask) -> {
|
||||
int indent = googleTask.getIndent();
|
||||
|
||||
long order = globalOrder.incrementAndGet();
|
||||
googleTask.setOrder(order);
|
||||
|
||||
if (targetTaskId == taskId) {
|
||||
// if indenting is warranted, indent me and my children
|
||||
if (indent + delta <= previousIndent.get() + 1 && indent + delta >= 0) {
|
||||
targetTaskIndent.set(indent);
|
||||
googleTask.setIndent(indent + delta);
|
||||
|
||||
long newParent = computeNewParent(list, taskId, indent + delta - 1);
|
||||
if (newParent == taskId) {
|
||||
googleTask.setParent(Task.NO_ID);
|
||||
} else {
|
||||
googleTask.setParent(newParent);
|
||||
}
|
||||
saveAndUpdateModifiedDate(googleTask);
|
||||
}
|
||||
} else if (targetTaskIndent.get() > -1) {
|
||||
// found first task that is not beneath target
|
||||
if (indent <= targetTaskIndent.get()) {
|
||||
targetTaskIndent.set(-1);
|
||||
} else {
|
||||
googleTask.setIndent(indent + delta);
|
||||
saveAndUpdateModifiedDate(googleTask);
|
||||
}
|
||||
} else {
|
||||
previousIndent.set(indent);
|
||||
previousTask.set(taskId);
|
||||
}
|
||||
|
||||
saveAndUpdateModifiedDate(googleTask);
|
||||
});
|
||||
onMovedOrIndented(list, getTaskMetadata(targetTaskId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to iterate through a list and compute a new parent for the target task based on
|
||||
* the target parent's indent
|
||||
*/
|
||||
private long computeNewParent(GoogleTaskList list, long targetTaskId, int targetParentIndent) {
|
||||
final AtomicInteger desiredParentIndent = new AtomicInteger(targetParentIndent);
|
||||
final AtomicLong targetTask = new AtomicLong(targetTaskId);
|
||||
final AtomicLong lastPotentialParent = new AtomicLong(Task.NO_ID);
|
||||
final AtomicBoolean computedParent = new AtomicBoolean(false);
|
||||
|
||||
iterateThroughList(
|
||||
list,
|
||||
(taskId, googleTask) -> {
|
||||
if (targetTask.get() == taskId) {
|
||||
computedParent.set(true);
|
||||
}
|
||||
|
||||
int indent = googleTask.getIndent();
|
||||
if (!computedParent.get() && indent == desiredParentIndent.get()) {
|
||||
lastPotentialParent.set(taskId);
|
||||
}
|
||||
});
|
||||
|
||||
if (lastPotentialParent.get() == Task.NO_ID) {
|
||||
return Task.NO_ID;
|
||||
}
|
||||
return lastPotentialParent.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a task and all its children to the position right above taskIdToMoveto. Will change the
|
||||
* indent level to match taskIdToMoveTo.
|
||||
*/
|
||||
public void moveTo(GoogleTaskList list, final long targetTaskId, final long moveBeforeTaskId) {
|
||||
if (list == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node root = buildTreeModel(list);
|
||||
Node target = findNode(root, targetTaskId);
|
||||
|
||||
if (target != null && target.parent != null) {
|
||||
if (moveBeforeTaskId == -1) {
|
||||
target.parent.children.remove(target);
|
||||
root.children.add(target);
|
||||
target.parent = root;
|
||||
} else {
|
||||
Node sibling = findNode(root, moveBeforeTaskId);
|
||||
if (sibling != null && !ancestorOf(target, sibling)) {
|
||||
int index = sibling.parent.children.indexOf(sibling);
|
||||
|
||||
if (target.parent == sibling.parent && target.parent.children.indexOf(target) < index) {
|
||||
index--;
|
||||
}
|
||||
|
||||
target.parent.children.remove(target);
|
||||
sibling.parent.children.add(index, target);
|
||||
target.parent = sibling.parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverseTreeAndWriteValues(list, root, new AtomicLong(0), -1);
|
||||
onMovedOrIndented(list, getTaskMetadata(targetTaskId));
|
||||
}
|
||||
|
||||
// --- task moving
|
||||
|
||||
private boolean ancestorOf(Node ancestor, Node descendant) {
|
||||
if (descendant.parent == ancestor) {
|
||||
return true;
|
||||
}
|
||||
if (descendant.parent == null) {
|
||||
return false;
|
||||
}
|
||||
return ancestorOf(ancestor, descendant.parent);
|
||||
}
|
||||
|
||||
private void traverseTreeAndWriteValues(
|
||||
GoogleTaskList list, Node node, AtomicLong order, int indent) {
|
||||
if (node.taskId != Task.NO_ID) {
|
||||
GoogleTask googleTask = getTaskMetadata(node.taskId);
|
||||
if (googleTask == null) {
|
||||
googleTask = new GoogleTask(node.taskId, list.getRemoteId());
|
||||
}
|
||||
googleTask.setOrder(order.getAndIncrement());
|
||||
googleTask.setIndent(indent);
|
||||
boolean parentChanged = false;
|
||||
if (googleTask.getParent() != node.parent.taskId) {
|
||||
parentChanged = true;
|
||||
googleTask.setParent(node.parent.taskId);
|
||||
}
|
||||
saveAndUpdateModifiedDate(googleTask);
|
||||
if (parentChanged) {
|
||||
onMovedOrIndented(list, googleTask);
|
||||
}
|
||||
}
|
||||
|
||||
for (Node child : node.children) {
|
||||
traverseTreeAndWriteValues(list, child, order, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private Node findNode(Node node, long taskId) {
|
||||
if (node.taskId == taskId) {
|
||||
return node;
|
||||
}
|
||||
for (Node child : node.children) {
|
||||
Node found = findNode(child, taskId);
|
||||
if (found != null) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Node buildTreeModel(GoogleTaskList list) {
|
||||
final Node root = new Node(Task.NO_ID, null);
|
||||
final AtomicInteger previoustIndent = new AtomicInteger(-1);
|
||||
final AtomicReference<Node> currentNode = new AtomicReference<>(root);
|
||||
|
||||
iterateThroughList(
|
||||
list,
|
||||
(taskId, googleTask) -> {
|
||||
int indent = googleTask.getIndent();
|
||||
|
||||
int previousIndentValue = previoustIndent.get();
|
||||
if (indent == previousIndentValue) { // sibling
|
||||
Node parent = currentNode.get().parent;
|
||||
currentNode.set(new Node(taskId, parent));
|
||||
parent.children.add(currentNode.get());
|
||||
} else if (indent > previousIndentValue) { // child
|
||||
Node parent = currentNode.get();
|
||||
currentNode.set(new Node(taskId, parent));
|
||||
parent.children.add(currentNode.get());
|
||||
} else { // in a different tree
|
||||
Node node = currentNode.get().parent;
|
||||
for (int i = indent; i < previousIndentValue; i++) {
|
||||
node = node.parent;
|
||||
if (node == null) {
|
||||
node = root;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentNode.set(new Node(taskId, node));
|
||||
node.children.add(currentNode.get());
|
||||
}
|
||||
|
||||
previoustIndent.set(indent);
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
private void saveAndUpdateModifiedDate(GoogleTask googleTask) {
|
||||
googleTaskDao.update(googleTask);
|
||||
}
|
||||
|
||||
/** Apply an operation only to the children of the task */
|
||||
public void applyToChildren(GoogleTaskList list, long targetTaskId, OrderedListNodeVisitor visitor) {
|
||||
|
||||
Node root = buildTreeModel(list);
|
||||
Node target = findNode(root, targetTaskId);
|
||||
|
||||
if (target != null) {
|
||||
for (Node child : target.children) {
|
||||
applyVisitor(child, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyVisitor(Node node, OrderedListNodeVisitor visitor) {
|
||||
visitor.visitNode(node);
|
||||
for (Node child : node.children) {
|
||||
applyVisitor(child, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
// --- task cascading operations
|
||||
|
||||
/** Removes a task from the order hierarchy and un-indent children */
|
||||
public void onDeleteTask(GoogleTaskList list, final long targetTaskId) {
|
||||
if (list == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node root = buildTreeModel(list);
|
||||
Node target = findNode(root, targetTaskId);
|
||||
|
||||
if (target != null && target.parent != null) {
|
||||
int targetIndex = target.parent.children.indexOf(target);
|
||||
target.parent.children.remove(targetIndex);
|
||||
for (Node node : target.children) {
|
||||
node.parent = target.parent;
|
||||
target.parent.children.add(targetIndex++, node);
|
||||
}
|
||||
}
|
||||
|
||||
traverseTreeAndWriteValues(list, root, new AtomicLong(0), -1);
|
||||
}
|
||||
|
||||
public interface OrderedListIterator {
|
||||
|
||||
void processTask(long taskId, GoogleTask googleTask);
|
||||
}
|
||||
|
||||
public interface OrderedListNodeVisitor {
|
||||
|
||||
void visitNode(Node node);
|
||||
}
|
||||
|
||||
public static class Node {
|
||||
|
||||
public final long taskId;
|
||||
final ArrayList<Node> children = new ArrayList<>();
|
||||
Node parent;
|
||||
|
||||
Node(long taskId, Node parent) {
|
||||
this.taskId = taskId;
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.gtasks.api;
|
||||
|
||||
import com.google.api.services.tasks.model.Task;
|
||||
import java.io.IOException;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Encapsulates a request to the api to change the ordering on the given task
|
||||
*
|
||||
* @author Sam Bosley
|
||||
*/
|
||||
public class MoveRequest {
|
||||
|
||||
private final GtasksInvoker service;
|
||||
private final String taskId;
|
||||
private final String destinationList;
|
||||
private String parentId;
|
||||
private String priorSiblingId;
|
||||
|
||||
public MoveRequest(
|
||||
GtasksInvoker service,
|
||||
String taskId,
|
||||
String destinationList,
|
||||
String parentId,
|
||||
String priorSiblingId) {
|
||||
this.service = service;
|
||||
this.taskId = taskId;
|
||||
this.destinationList = destinationList;
|
||||
this.parentId = parentId;
|
||||
this.priorSiblingId = priorSiblingId;
|
||||
}
|
||||
|
||||
public Task push() throws IOException {
|
||||
try {
|
||||
return executePush();
|
||||
} catch (IOException e) {
|
||||
Timber.e(e);
|
||||
recover();
|
||||
return executePush();
|
||||
}
|
||||
}
|
||||
|
||||
private Task executePush() throws IOException {
|
||||
return service.moveGtask(destinationList, taskId, parentId, priorSiblingId);
|
||||
}
|
||||
|
||||
private void recover() {
|
||||
parentId = null;
|
||||
priorSiblingId = null;
|
||||
}
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.gtasks.sync;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
||||
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
|
||||
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
|
||||
import com.todoroo.astrid.gtasks.api.MoveRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.analytics.Tracker;
|
||||
import org.tasks.data.GoogleTask;
|
||||
import org.tasks.data.GoogleTaskDao;
|
||||
import org.tasks.data.GoogleTaskList;
|
||||
import org.tasks.data.GoogleTaskListDao;
|
||||
import org.tasks.gtasks.GoogleAccountManager;
|
||||
import org.tasks.gtasks.GtaskSyncAdapterHelper;
|
||||
import org.tasks.injection.ApplicationScope;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
||||
@ApplicationScope
|
||||
public class GtasksSyncService {
|
||||
|
||||
private final TaskDao taskDao;
|
||||
private final Preferences preferences;
|
||||
private final LinkedBlockingQueue<SyncOnSaveOperation> operationQueue =
|
||||
new LinkedBlockingQueue<>();
|
||||
private final GtaskSyncAdapterHelper gtaskSyncAdapterHelper;
|
||||
private final Tracker tracker;
|
||||
private final GoogleTaskDao googleTaskDao;
|
||||
private final GoogleAccountManager googleAccountManager;
|
||||
|
||||
@Inject
|
||||
public GtasksSyncService(
|
||||
TaskDao taskDao,
|
||||
Preferences preferences,
|
||||
GtaskSyncAdapterHelper gtaskSyncAdapterHelper,
|
||||
Tracker tracker,
|
||||
GoogleTaskDao googleTaskDao,
|
||||
GoogleTaskListDao googleTaskListDao,
|
||||
GoogleAccountManager googleAccountManager) {
|
||||
this.taskDao = taskDao;
|
||||
this.preferences = preferences;
|
||||
this.gtaskSyncAdapterHelper = gtaskSyncAdapterHelper;
|
||||
this.tracker = tracker;
|
||||
this.googleTaskDao = googleTaskDao;
|
||||
this.googleAccountManager = googleAccountManager;
|
||||
new OperationPushThread(operationQueue).start();
|
||||
}
|
||||
|
||||
public void triggerMoveForMetadata(GoogleTaskList googleTaskList, GoogleTask googleTask) {
|
||||
if (googleTask == null) {
|
||||
return;
|
||||
}
|
||||
if (googleTask.isSuppressSync()) {
|
||||
googleTask.setSuppressSync(false);
|
||||
return;
|
||||
}
|
||||
if (preferences.isSyncOngoing()) {
|
||||
return;
|
||||
}
|
||||
if (!gtaskSyncAdapterHelper.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
operationQueue.offer(new MoveOp(googleTaskList, googleTask));
|
||||
}
|
||||
|
||||
private void pushMetadataOnSave(GoogleTask model, GtasksInvoker invoker) throws IOException {
|
||||
AndroidUtilities.sleepDeep(1000L);
|
||||
|
||||
String taskId = model.getRemoteId();
|
||||
String listId = model.getListId();
|
||||
String parent = getRemoteParentId(model);
|
||||
String priorSibling = getRemoteSiblingId(listId, model);
|
||||
|
||||
MoveRequest move = new MoveRequest(invoker, taskId, listId, parent, priorSibling);
|
||||
com.google.api.services.tasks.model.Task result = move.push();
|
||||
// Update order googleTask from result
|
||||
if (result != null) {
|
||||
model.setRemoteOrder(Long.parseLong(result.getPosition()));
|
||||
model.setSuppressSync(true);
|
||||
googleTaskDao.update(model);
|
||||
}
|
||||
}
|
||||
|
||||
public void iterateThroughList(
|
||||
String listId,
|
||||
final GtasksTaskListUpdater.OrderedListIterator iterator,
|
||||
long startAtOrder,
|
||||
boolean reverse) {
|
||||
List<GoogleTask> tasks =
|
||||
reverse
|
||||
? googleTaskDao.getTasksFromReverse(listId, startAtOrder)
|
||||
: googleTaskDao.getTasksFrom(listId, startAtOrder);
|
||||
for (GoogleTask entry : tasks) {
|
||||
iterator.processTask(entry.getTask(), entry);
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the remote id string of the parent task */
|
||||
public String getRemoteParentId(GoogleTask googleTask) {
|
||||
String parent = null;
|
||||
long parentId = googleTask.getParent();
|
||||
GoogleTask parentTask = googleTaskDao.getByTaskId(parentId);
|
||||
if (parentTask != null) {
|
||||
parent = parentTask.getRemoteId();
|
||||
if (TextUtils.isEmpty(parent)) {
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
/** Gets the remote id string of the previous sibling task */
|
||||
public String getRemoteSiblingId(String listId, GoogleTask gtasksMetadata) {
|
||||
final AtomicInteger indentToMatch = new AtomicInteger(gtasksMetadata.getIndent());
|
||||
final AtomicLong parentToMatch = new AtomicLong(gtasksMetadata.getParent());
|
||||
final AtomicReference<String> sibling = new AtomicReference<>();
|
||||
GtasksTaskListUpdater.OrderedListIterator iterator =
|
||||
(taskId, googleTask) -> {
|
||||
Task t = taskDao.fetch(taskId);
|
||||
if (t == null || t.isDeleted()) {
|
||||
return;
|
||||
}
|
||||
int currIndent = googleTask.getIndent();
|
||||
long currParent = googleTask.getParent();
|
||||
|
||||
if (currIndent == indentToMatch.get() && currParent == parentToMatch.get()) {
|
||||
if (sibling.get() == null) {
|
||||
sibling.set(googleTask.getRemoteId());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
iterateThroughList(listId, iterator, gtasksMetadata.getOrder(), true);
|
||||
return sibling.get();
|
||||
}
|
||||
|
||||
interface SyncOnSaveOperation {
|
||||
|
||||
void op() throws IOException;
|
||||
}
|
||||
|
||||
private class MoveOp implements SyncOnSaveOperation {
|
||||
|
||||
final GoogleTask googleTask;
|
||||
private final GoogleTaskList googleTaskList;
|
||||
|
||||
MoveOp(GoogleTaskList googleTaskList, GoogleTask googleTask) {
|
||||
this.googleTaskList = googleTaskList;
|
||||
this.googleTask = googleTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void op() throws IOException {
|
||||
GtasksInvoker invoker = new GtasksInvoker(googleTaskList.getAccount(), googleAccountManager);
|
||||
pushMetadataOnSave(googleTask, invoker);
|
||||
}
|
||||
}
|
||||
|
||||
private class OperationPushThread extends Thread {
|
||||
|
||||
private final LinkedBlockingQueue<SyncOnSaveOperation> queue;
|
||||
|
||||
OperationPushThread(LinkedBlockingQueue<SyncOnSaveOperation> queue) {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//noinspection InfiniteLoopStatement
|
||||
while (true) {
|
||||
SyncOnSaveOperation op;
|
||||
try {
|
||||
op = queue.take();
|
||||
} catch (InterruptedException e) {
|
||||
Timber.e(e);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
op.op();
|
||||
} catch (UserRecoverableAuthIOException ignored) {
|
||||
|
||||
} catch (IOException e) {
|
||||
tracker.reportException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +1,41 @@
|
||||
package org.tasks.tasklist;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil.ItemCallback;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import com.todoroo.astrid.adapter.TaskAdapter;
|
||||
import java.util.List;
|
||||
import org.tasks.data.TaskContainer;
|
||||
|
||||
class DiffCallback extends ItemCallback<TaskContainer> {
|
||||
class DiffCallback extends DiffUtil.Callback {
|
||||
|
||||
private final TaskAdapter adapter;
|
||||
private final List<TaskContainer> oldList;
|
||||
private final List<TaskContainer> newList;
|
||||
@Deprecated private final TaskAdapter adapter;
|
||||
|
||||
public DiffCallback(TaskAdapter adapter) {
|
||||
DiffCallback(List<TaskContainer> oldList, List<TaskContainer> newList, TaskAdapter adapter) {
|
||||
this.oldList = oldList;
|
||||
this.newList = newList;
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull TaskContainer oldItem, @NonNull TaskContainer newItem) {
|
||||
return oldItem.getId() == newItem.getId();
|
||||
public int getOldListSize() {
|
||||
return oldList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(
|
||||
@NonNull TaskContainer oldItem, @NonNull TaskContainer newItem) {
|
||||
public int getNewListSize() {
|
||||
return newList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
TaskContainer oldItem = oldList.get(oldItemPosition);
|
||||
TaskContainer newItem = newList.get(newItemPosition);
|
||||
return oldItem.equals(newItem) && oldItem.getIndent() == adapter.getIndent(newItem);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue