mirror of https://github.com/tasks/tasks
Use android-job to sync caldav tasks
parent
37f5243f46
commit
a20479d952
@ -0,0 +1,827 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 57,
|
||||
"identityHash": "3893260552baa9a57c4785a5734fcdef",
|
||||
"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)",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"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": "path",
|
||||
"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": "importance",
|
||||
"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": "locations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `name` TEXT, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL, `radius` INTEGER NOT NULL)",
|
||||
"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": "latitude",
|
||||
"columnName": "latitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "longitude",
|
||||
"columnName": "longitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "radius",
|
||||
"columnName": "radius",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_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}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `remote_id` TEXT, `list_id` TEXT, `parent` INTEGER NOT NULL, `indent` INTEGER NOT NULL, `order` INTEGER NOT NULL, `remote_order` INTEGER NOT NULL, `last_sync` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "task",
|
||||
"columnName": "task",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "remoteId",
|
||||
"columnName": "remote_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "listId",
|
||||
"columnName": "list_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "parent",
|
||||
"columnName": "parent",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "indent",
|
||||
"columnName": "indent",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "order",
|
||||
"columnName": "order",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"_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, `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": "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_account",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uuid` TEXT, `name` TEXT, `color` INTEGER NOT NULL, `ctag` TEXT, `url` TEXT, `username` TEXT, `password` 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": "color",
|
||||
"columnName": "color",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "ctag",
|
||||
"columnName": "ctag",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"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, `account` 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": "account",
|
||||
"columnName": "account",
|
||||
"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": []
|
||||
}
|
||||
],
|
||||
"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, \"3893260552baa9a57c4785a5734fcdef\")"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.os.Bundle;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Account {
|
||||
|
||||
private static final String AUTHORITY = "org.tasks";
|
||||
|
||||
private final AccountManager accountManager;
|
||||
private final android.accounts.Account account;
|
||||
|
||||
public Account(AccountManager accountManager, android.accounts.Account account) {
|
||||
this.accountManager = accountManager;
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return account.name;
|
||||
}
|
||||
|
||||
String getPassword() {
|
||||
return accountManager.getPassword(account);
|
||||
}
|
||||
|
||||
void setPassword(String password) {
|
||||
accountManager.setPassword(account, password);
|
||||
}
|
||||
|
||||
public android.accounts.Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
void setSynchronizationEnabled(boolean enabled) {
|
||||
ContentResolver.setSyncAutomatically(account, AUTHORITY, enabled);
|
||||
if (enabled) {
|
||||
ContentResolver
|
||||
.addPeriodicSync(account, AUTHORITY, Bundle.EMPTY, TimeUnit.HOURS.toSeconds(1));
|
||||
} else {
|
||||
ContentResolver.removePeriodicSync(account, AUTHORITY, Bundle.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Account{" +
|
||||
"account=" + account +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
class CalDAVAccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
|
||||
private final Context context;
|
||||
|
||||
public CalDAVAccountAuthenticator(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
|
||||
String authTokenType, String[] requiredFeatures, Bundle options) {
|
||||
Intent intent = new Intent(context, CalDAVSettingsActivity.class);
|
||||
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
|
||||
Bundle options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
|
||||
String authTokenType, Bundle options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
|
||||
String authTokenType, Bundle options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
|
||||
String[] features) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class CalDAVAccountAuthenticatorService extends Service {
|
||||
|
||||
private CalDAVAccountAuthenticator authenticator;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
authenticator = new CalDAVAccountAuthenticator(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return AccountManager.ACTION_AUTHENTICATOR_INTENT.equals(intent.getAction())
|
||||
? authenticator.getIBinder()
|
||||
: null;
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class CalDAVSyncService extends Service {
|
||||
|
||||
private static final Object lock = new Object();
|
||||
private static CalDAVSyncAdapter syncAdapter = null;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Timber.d("Service created");
|
||||
synchronized (lock) {
|
||||
if (syncAdapter == null) {
|
||||
syncAdapter = new CalDAVSyncAdapter(getApplicationContext(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
Timber.d("Service destroyed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return syncAdapter.getSyncAdapterBinder();
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import static com.google.common.collect.Iterables.tryFind;
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import com.google.common.base.Optional;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.service.TaskDeleter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.data.CaldavAccount;
|
||||
import org.tasks.data.CaldavDao;
|
||||
import org.tasks.injection.ApplicationScope;
|
||||
import org.tasks.injection.ForApplication;
|
||||
import org.tasks.preferences.PermissionChecker;
|
||||
import timber.log.Timber;
|
||||
|
||||
@ApplicationScope
|
||||
public class CaldavAccountManager {
|
||||
|
||||
private static final String AUTHORITY = "org.tasks";
|
||||
private static final String ACCOUNT_TYPE = "org.tasks.caldav";
|
||||
|
||||
private final PermissionChecker permissionChecker;
|
||||
private final android.accounts.AccountManager accountManager;
|
||||
private final LocalBroadcastManager localBroadcastManager;
|
||||
private final TaskDeleter taskDeleter;
|
||||
private final CaldavDao caldavDao;
|
||||
private final TaskDao taskDao;
|
||||
|
||||
@Inject
|
||||
public CaldavAccountManager(@ForApplication Context context, PermissionChecker permissionChecker,
|
||||
CaldavDao caldavDao, TaskDeleter taskDeleter,
|
||||
LocalBroadcastManager localBroadcastManager, TaskDao taskDao) {
|
||||
this.permissionChecker = permissionChecker;
|
||||
this.caldavDao = caldavDao;
|
||||
this.taskDao = taskDao;
|
||||
this.taskDeleter = taskDeleter;
|
||||
this.localBroadcastManager = localBroadcastManager;
|
||||
accountManager = android.accounts.AccountManager.get(context);
|
||||
syncAccountList();
|
||||
}
|
||||
|
||||
public Account getAccount(String uuid) {
|
||||
for (Account account : getAccounts()) {
|
||||
if (uuid.equals(account.getUuid())) {
|
||||
return account;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Account> getAccounts() {
|
||||
if (!permissionChecker.canAccessAccounts()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Account> accounts = new ArrayList<>();
|
||||
for (android.accounts.Account account : accountManager.getAccountsByType(ACCOUNT_TYPE)) {
|
||||
accounts.add(new Account(accountManager, account));
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
|
||||
boolean removeAccount(Account account) {
|
||||
return removeAccount(account.getAccount());
|
||||
}
|
||||
|
||||
boolean removeAccount(android.accounts.Account account) {
|
||||
try {
|
||||
return accountManager
|
||||
.removeAccount(account, null, null)
|
||||
.getResult();
|
||||
} catch (OperationCanceledException | IOException | AuthenticatorException e) {
|
||||
Timber.e(e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean addAccount(CaldavAccount caldavAccount, String password) {
|
||||
Timber.d("Adding %s", caldavAccount);
|
||||
android.accounts.Account account = new android.accounts.Account(caldavAccount.getUuid(),
|
||||
ACCOUNT_TYPE);
|
||||
return accountManager.addAccountExplicitly(account, password, null);
|
||||
}
|
||||
|
||||
private void syncAccountList() {
|
||||
List<CaldavAccount> oldAccountList = caldavDao.getAllOrderedByName();
|
||||
List<Account> newAccountList = getAccounts();
|
||||
|
||||
for (CaldavAccount local : oldAccountList) {
|
||||
Optional<Account> match = tryFind(newAccountList,
|
||||
remote -> local.getUuid().equals(remote.getUuid()));
|
||||
if (!match.isPresent()) {
|
||||
addAccount(local, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAccount(CaldavAccount account) {
|
||||
String uuid = account.getUuid();
|
||||
for (Task task : taskDao.getCaldavTasks(uuid)) {
|
||||
taskDeleter.markDeleted(task);
|
||||
}
|
||||
caldavDao.deleteTasksForAccount(uuid);
|
||||
caldavDao.delete(account);
|
||||
localBroadcastManager.broadcastRefreshList();
|
||||
}
|
||||
|
||||
public boolean initiateManualSync() {
|
||||
for (org.tasks.caldav.Account account : getAccounts()) {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
|
||||
ContentResolver.requestSync(account.getAccount(), AUTHORITY, extras);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void requestSynchronization() {
|
||||
for (org.tasks.caldav.Account account : getAccounts()) {
|
||||
ContentResolver.requestSync(account.getAccount(), AUTHORITY, new Bundle());
|
||||
}
|
||||
}
|
||||
|
||||
public void setBackgroundSynchronization(boolean enabled) {
|
||||
for (org.tasks.caldav.Account account : getAccounts()) {
|
||||
account.setSynchronizationEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import com.todoroo.astrid.api.CaldavFilter;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.data.CaldavAccount;
|
||||
import org.tasks.data.CaldavDao;
|
||||
import org.tasks.sync.SyncAdapters;
|
||||
|
||||
public class CaldavFilterExposer {
|
||||
|
||||
private final SyncAdapters syncAdapters;
|
||||
private final CaldavDao caldavDao;
|
||||
|
||||
@Inject
|
||||
public CaldavFilterExposer(CaldavDao caldavDao, SyncAdapters syncAdapters) {
|
||||
this.caldavDao = caldavDao;
|
||||
this.syncAdapters = syncAdapters;
|
||||
}
|
||||
|
||||
public List<Filter> getFilters() {
|
||||
if (!syncAdapters.isCaldavSyncEnabled()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<CaldavAccount> allOrderedByName = caldavDao.getAllOrderedByName();
|
||||
List<Filter> result = new ArrayList<>();
|
||||
for (CaldavAccount account : allOrderedByName) {
|
||||
result.add(new CaldavFilter(account));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Filter getFilterByUuid(String uuid) {
|
||||
if (syncAdapters.isCaldavSyncEnabled()) {
|
||||
CaldavAccount caldavAccount = caldavDao.getByUuid(uuid);
|
||||
if (caldavAccount != null) {
|
||||
return new CaldavFilter(caldavAccount);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,420 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.InputType;
|
||||
import android.view.MenuItem;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.LinearLayout;
|
||||
import at.bitfire.dav4android.exception.HttpException;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnFocusChange;
|
||||
import butterknife.OnTextChanged;
|
||||
import com.todoroo.astrid.activity.TaskListActivity;
|
||||
import com.todoroo.astrid.api.CaldavFilter;
|
||||
import com.todoroo.astrid.helper.UUIDHelper;
|
||||
import java.net.ConnectException;
|
||||
import java.net.IDN;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.activities.ColorPickerActivity;
|
||||
import org.tasks.analytics.Tracker;
|
||||
import org.tasks.analytics.Tracking;
|
||||
import org.tasks.data.CaldavAccount;
|
||||
import org.tasks.data.CaldavDao;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.ThemedInjectingAppCompatActivity;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import org.tasks.sync.SyncAdapters;
|
||||
import org.tasks.themes.ThemeCache;
|
||||
import org.tasks.themes.ThemeColor;
|
||||
import org.tasks.ui.DisplayableException;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class CaldavSettingsActivity extends ThemedInjectingAppCompatActivity
|
||||
implements Toolbar.OnMenuItemClickListener {
|
||||
|
||||
public static final String EXTRA_CALDAV_DATA = "caldavData"; //$NON-NLS-1$
|
||||
private static final String EXTRA_CALDAV_UUID = "uuid"; //$NON-NLS-1$
|
||||
public static final String ACTION_RELOAD = "accountRenamed";
|
||||
public static final String ACTION_DELETED = "accountDeleted";
|
||||
private static final String EXTRA_SELECTED_THEME = "extra_selected_theme";
|
||||
private static final String PASSWORD_MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
||||
private static final int REQUEST_COLOR_PICKER = 10109;
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject Preferences preferences;
|
||||
@Inject ThemeCache themeCache;
|
||||
@Inject ThemeColor themeColor;
|
||||
@Inject Tracker tracker;
|
||||
@Inject CaldavDao caldavDao;
|
||||
@Inject SyncAdapters syncAdapters;
|
||||
@BindView(R.id.root_layout) LinearLayout root;
|
||||
@BindView(R.id.url) TextInputEditText url;
|
||||
@BindView(R.id.user) TextInputEditText user;
|
||||
@BindView(R.id.password) TextInputEditText password;
|
||||
@BindView(R.id.url_layout) TextInputLayout urlLayout;
|
||||
@BindView(R.id.user_layout) TextInputLayout userLayout;
|
||||
@BindView(R.id.password_layout) TextInputLayout passwordLayout;
|
||||
@BindView(R.id.color) TextInputEditText color;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
private CaldavAccount caldavAccount;
|
||||
private int selectedTheme;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_caldav_settings);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
caldavAccount = getIntent().getParcelableExtra(EXTRA_CALDAV_DATA);
|
||||
|
||||
if (!isEmpty(caldavAccount.getPassword())) {
|
||||
password.setText(PASSWORD_MASK);
|
||||
}
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
if (caldavAccount == null) {
|
||||
selectedTheme = -1;
|
||||
} else {
|
||||
selectedTheme = caldavAccount.getColor();
|
||||
url.setText(caldavAccount.getUrl());
|
||||
user.setText(caldavAccount.getUsername());
|
||||
}
|
||||
} else {
|
||||
selectedTheme = savedInstanceState.getInt(EXTRA_SELECTED_THEME);
|
||||
}
|
||||
|
||||
final boolean backButtonSavesTask = preferences.backButtonSavesTask();
|
||||
toolbar.setTitle(
|
||||
caldavAccount == null ? getString(R.string.add_account) : caldavAccount.getName());
|
||||
toolbar.setNavigationIcon(ContextCompat.getDrawable(this,
|
||||
backButtonSavesTask ? R.drawable.ic_close_24dp : R.drawable.ic_save_24dp));
|
||||
toolbar.setNavigationOnClickListener(v -> {
|
||||
if (backButtonSavesTask) {
|
||||
discard();
|
||||
} else {
|
||||
save();
|
||||
}
|
||||
});
|
||||
toolbar.inflateMenu(R.menu.menu_tag_settings);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
toolbar.showOverflowMenu();
|
||||
|
||||
color.setInputType(InputType.TYPE_NULL);
|
||||
|
||||
if (caldavAccount == null) {
|
||||
toolbar.getMenu().findItem(R.id.delete).setVisible(false);
|
||||
url.requestFocus();
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(url, InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
updateTheme();
|
||||
}
|
||||
|
||||
@OnTextChanged(R.id.url)
|
||||
void onUrlChanged(CharSequence text) {
|
||||
urlLayout.setError(null);
|
||||
}
|
||||
|
||||
@OnTextChanged(R.id.user)
|
||||
void onUserChanged(CharSequence text) {
|
||||
userLayout.setError(null);
|
||||
}
|
||||
|
||||
@OnTextChanged(R.id.password)
|
||||
void onPasswordChanged(CharSequence text) {
|
||||
passwordLayout.setError(null);
|
||||
}
|
||||
|
||||
@OnFocusChange(R.id.password)
|
||||
void onPasswordFocused(boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
if (PASSWORD_MASK.equals(password.getText().toString())) {
|
||||
password.setText("");
|
||||
}
|
||||
} else {
|
||||
if (isEmpty(password.getText()) && !isEmpty(caldavAccount.getPassword())) {
|
||||
password.setText(PASSWORD_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(EXTRA_SELECTED_THEME, selectedTheme);
|
||||
}
|
||||
|
||||
@OnFocusChange(R.id.color)
|
||||
void onFocusChange(boolean focused) {
|
||||
if (focused) {
|
||||
color.clearFocus();
|
||||
showThemePicker();
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.color)
|
||||
protected void showThemePicker() {
|
||||
Intent intent = new Intent(CaldavSettingsActivity.this, ColorPickerActivity.class);
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_PALETTE, ColorPickerActivity.ColorPalette.COLORS);
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_SHOW_NONE, true);
|
||||
startActivityForResult(intent, REQUEST_COLOR_PICKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private String getNewURL() {
|
||||
return url.getText().toString().trim();
|
||||
}
|
||||
|
||||
private String getNewUsername() {
|
||||
return user.getText().toString().trim();
|
||||
}
|
||||
|
||||
private String getNewPassword() {
|
||||
String input = password.getText().toString().trim();
|
||||
return PASSWORD_MASK.equals(input) ? caldavAccount.getPassword() : input;
|
||||
}
|
||||
|
||||
private void save() {
|
||||
String username = getNewUsername();
|
||||
String url = getNewURL();
|
||||
String password = getNewPassword();
|
||||
|
||||
boolean failed = false;
|
||||
|
||||
if (isEmpty(url)) {
|
||||
urlLayout.setError(getString(R.string.url_required));
|
||||
failed = true;
|
||||
} else {
|
||||
Uri baseURL = Uri.parse(url);
|
||||
String scheme = baseURL.getScheme();
|
||||
if ("https".equalsIgnoreCase(scheme) || "http".equalsIgnoreCase(scheme)) {
|
||||
String host = baseURL.getHost();
|
||||
if (isEmpty(host)) {
|
||||
urlLayout.setError(getString(R.string.url_host_name_required));
|
||||
failed = true;
|
||||
} else {
|
||||
try {
|
||||
host = IDN.toASCII(host);
|
||||
} catch (Exception e) {
|
||||
Timber.e(e.getMessage(), e);
|
||||
}
|
||||
String path = baseURL.getEncodedPath();
|
||||
int port = baseURL.getPort();
|
||||
try {
|
||||
new URI(scheme, null, host, port, path, null, null);
|
||||
} catch (URISyntaxException e) {
|
||||
urlLayout.setError(e.getLocalizedMessage());
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
urlLayout.setError(getString(R.string.url_invalid_scheme));
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmpty(username)) {
|
||||
userLayout.setError(getString(R.string.username_required));
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (isEmpty(password)) {
|
||||
passwordLayout.setError(getString(R.string.password_required));
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (caldavAccount == null) {
|
||||
CaldavClient client = new CaldavClient(url, username, password);
|
||||
ProgressDialog dialog = dialogBuilder.newProgressDialog(R.string.contacting_server);
|
||||
dialog.show();
|
||||
client.getDisplayName()
|
||||
.doAfterTerminate(dialog::dismiss)
|
||||
.subscribe(this::addAccount, this::getDisplayNameFailed);
|
||||
} else if (needsValidation()) {
|
||||
CaldavClient client = new CaldavClient(url, username, password);
|
||||
ProgressDialog dialog = dialogBuilder.newProgressDialog(R.string.contacting_server);
|
||||
dialog.show();
|
||||
client.getDisplayName()
|
||||
.doAfterTerminate(dialog::dismiss)
|
||||
.subscribe(this::updateAccount, this::getDisplayNameFailed);
|
||||
} else if (hasChanges()) {
|
||||
updateAccount(caldavAccount.getName());
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void addAccount(String name) {
|
||||
CaldavAccount newAccount = new CaldavAccount(name, UUIDHelper.newUUID());
|
||||
newAccount.setColor(selectedTheme);
|
||||
newAccount.setUrl(getNewURL());
|
||||
newAccount.setUsername(getNewUsername());
|
||||
newAccount.setPassword(getNewPassword());
|
||||
newAccount.setId(caldavDao.insert(newAccount));
|
||||
setResult(RESULT_OK,
|
||||
new Intent().putExtra(TaskListActivity.OPEN_FILTER, new CaldavFilter(newAccount)));
|
||||
finish();
|
||||
}
|
||||
|
||||
private void updateAccount(String name) {
|
||||
caldavAccount.setName(name);
|
||||
caldavAccount.setUrl(getNewURL());
|
||||
caldavAccount.setUsername(getNewUsername());
|
||||
caldavAccount.setColor(selectedTheme);
|
||||
caldavAccount.setPassword(getNewPassword());
|
||||
caldavDao.update(caldavAccount);
|
||||
setResult(RESULT_OK,
|
||||
new Intent().putExtra(TaskListActivity.OPEN_FILTER, new CaldavFilter(caldavAccount)));
|
||||
finish();
|
||||
}
|
||||
|
||||
private void getDisplayNameFailed(Throwable t) {
|
||||
if (t instanceof HttpException) {
|
||||
showSnackbar(t.getMessage());
|
||||
} else if (t instanceof DisplayableException) {
|
||||
showSnackbar(((DisplayableException) t).getResId());
|
||||
} else if (t instanceof ConnectException) {
|
||||
showSnackbar(R.string.network_error);
|
||||
} else {
|
||||
showGenericError();
|
||||
}
|
||||
}
|
||||
|
||||
private void showGenericError() {
|
||||
showSnackbar(R.string.error_adding_account);
|
||||
}
|
||||
|
||||
private void showSnackbar(int resId) {
|
||||
showSnackbar(getString(resId));
|
||||
}
|
||||
|
||||
private void showSnackbar(String message) {
|
||||
Snackbar snackbar = Snackbar.make(root, message, 8000)
|
||||
.setActionTextColor(ContextCompat.getColor(this, R.color.snackbar_text_color));
|
||||
snackbar.getView()
|
||||
.setBackgroundColor(ContextCompat.getColor(this, R.color.snackbar_background));
|
||||
snackbar.show();
|
||||
}
|
||||
|
||||
private boolean hasChanges() {
|
||||
if (caldavAccount == null) {
|
||||
return selectedTheme >= 0 ||
|
||||
!isEmpty(getNewPassword()) || !isEmpty(getNewURL()) ||
|
||||
!isEmpty(getNewUsername());
|
||||
}
|
||||
return selectedTheme != caldavAccount.getColor() ||
|
||||
needsValidation();
|
||||
}
|
||||
|
||||
private boolean needsValidation() {
|
||||
return !getNewURL().equals(caldavAccount.getUrl()) ||
|
||||
!getNewUsername().equals(caldavAccount.getUsername()) ||
|
||||
!getNewPassword().equals(caldavAccount.getPassword());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(url.getWindowToken(), 0);
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (preferences.backButtonSavesTask()) {
|
||||
save();
|
||||
} else {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_COLOR_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
int index = data.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0);
|
||||
tracker.reportEvent(Tracking.Events.SET_TAG_COLOR, Integer.toString(index));
|
||||
selectedTheme = index;
|
||||
updateTheme();
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteAccount() {
|
||||
dialogBuilder.newMessageDialog(R.string.delete_tag_confirmation, caldavAccount.getName())
|
||||
.setPositiveButton(R.string.delete, (dialog, which) -> {
|
||||
if (caldavAccount != null) {
|
||||
caldavDao.delete(caldavAccount);
|
||||
setResult(RESULT_OK,
|
||||
new Intent(ACTION_DELETED).putExtra(EXTRA_CALDAV_UUID, caldavAccount.getUuid()));
|
||||
}
|
||||
finish();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void discard() {
|
||||
if (!hasChanges()) {
|
||||
finish();
|
||||
} else {
|
||||
dialogBuilder.newMessageDialog(R.string.discard_changes)
|
||||
.setPositiveButton(R.string.discard, (dialog, which) -> finish())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTheme() {
|
||||
ThemeColor themeColor;
|
||||
if (selectedTheme < 0) {
|
||||
themeColor = this.themeColor;
|
||||
color.setText(R.string.none);
|
||||
} else {
|
||||
themeColor = themeCache.getThemeColor(selectedTheme);
|
||||
color.setText(themeColor.getName());
|
||||
}
|
||||
themeColor.apply(toolbar);
|
||||
themeColor.applyToStatusBar(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.delete:
|
||||
deleteAccount();
|
||||
break;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package org.tasks.caldav;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.injection.DialogFragmentComponent;
|
||||
import org.tasks.injection.InjectingDialogFragment;
|
||||
|
||||
public class DeleteAccountDialog extends InjectingDialogFragment {
|
||||
|
||||
private static final String EXTRA_UUID = "extra_uuid";
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject CaldavAccountManager caldavAccountManager;
|
||||
private DeleteAccountDialogCallback callback;
|
||||
private String uuid;
|
||||
private ProgressDialog dialog;
|
||||
|
||||
public static DeleteAccountDialog newDeleteAccountDialog(String uuid) {
|
||||
DeleteAccountDialog dialog = new DeleteAccountDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(EXTRA_UUID, uuid);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
Bundle arguments = getArguments();
|
||||
uuid = arguments.getString(EXTRA_UUID);
|
||||
dialog = dialogBuilder.newProgressDialog(R.string.deleting_list);
|
||||
execute();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
callback = (DeleteAccountDialogCallback) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(DialogFragmentComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void execute() {
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
Account account = caldavAccountManager.getAccount(uuid);
|
||||
return account == null || caldavAccountManager.removeAccount(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (dialog.isShowing()) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
if (result) {
|
||||
callback.onListDeleted();
|
||||
} else {
|
||||
callback.deleteAccountFailed();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
public interface DeleteAccountDialogCallback {
|
||||
|
||||
void onListDeleted();
|
||||
|
||||
void deleteAccountFailed();
|
||||
}
|
||||
}
|
@ -1,13 +1,10 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
import org.tasks.caldav.CalDAVSyncAdapter;
|
||||
import org.tasks.gtasks.GoogleTaskSyncAdapter;
|
||||
|
||||
@Subcomponent(modules = SyncAdapterModule.class)
|
||||
public interface SyncAdapterComponent {
|
||||
|
||||
void inject(GoogleTaskSyncAdapter googleTaskSyncAdapter);
|
||||
|
||||
void inject(CalDAVSyncAdapter calDAVSyncAdapter);
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import com.evernote.android.job.Job;
|
||||
import org.tasks.caldav.CaldavSynchronizer;
|
||||
|
||||
public class CaldavSyncJob extends Job{
|
||||
|
||||
private final CaldavSynchronizer caldavSynchronizer;
|
||||
|
||||
CaldavSyncJob(CaldavSynchronizer caldavSynchronizer) {
|
||||
this.caldavSynchronizer = caldavSynchronizer;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Result onRunJob(@NonNull Params params) {
|
||||
return caldavSynchronizer.sync() ? Result.SUCCESS : Result.FAILURE;
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accountType="@string/account_type_caldav"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/CalDAV"
|
||||
android:smallIcon="@mipmap/ic_launcher" />
|
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accountType="@string/account_type_caldav"
|
||||
android:contentAuthority="org.tasks"
|
||||
android:supportsUploading="true"
|
||||
android:isAlwaysSyncable="true"
|
||||
android:userVisible="false" />
|
Loading…
Reference in New Issue