Add support for multiple google task accounts

pull/685/merge
Alex Baker 8 years ago
parent abfd6051f4
commit 07f9d72219

@ -0,0 +1,903 @@
{
"formatVersion": 1,
"database": {
"version": 59,
"identityHash": "1320507f7cf294e38cdd2d22d1ce4496",
"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": "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": "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, `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)",
"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
}
],
"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)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "account",
"columnName": "account",
"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, \"1320507f7cf294e38cdd2d22d1ce4496\")"
]
}
}

@ -11,6 +11,7 @@ import org.tasks.data.GoogleTaskList;
public class GtaskListMaker { public class GtaskListMaker {
public static final Property<GoogleTaskList, Long> ID = newProperty(); public static final Property<GoogleTaskList, Long> ID = newProperty();
public static final Property<GoogleTaskList, String> ACCOUNT = newProperty();
public static final Property<GoogleTaskList, String> REMOTE_ID = newProperty(); public static final Property<GoogleTaskList, String> REMOTE_ID = newProperty();
public static final Property<GoogleTaskList, Long> LAST_SYNC = newProperty(); public static final Property<GoogleTaskList, Long> LAST_SYNC = newProperty();
public static final Property<GoogleTaskList, String> NAME = newProperty(); public static final Property<GoogleTaskList, String> NAME = newProperty();
@ -22,6 +23,7 @@ public class GtaskListMaker {
{ {
setDeleted(0L); setDeleted(0L);
setId(lookup.valueOf(GtaskListMaker.ID, 0L)); setId(lookup.valueOf(GtaskListMaker.ID, 0L));
setAccount(lookup.valueOf(ACCOUNT, "account"));
setRemoteId(lookup.valueOf(REMOTE_ID, "1")); setRemoteId(lookup.valueOf(REMOTE_ID, "1"));
setTitle(lookup.valueOf(NAME, "Default")); setTitle(lookup.valueOf(NAME, "Default"));
setRemoteOrder(lookup.valueOf(ORDER, 0)); setRemoteOrder(lookup.valueOf(ORDER, 0));

@ -18,8 +18,10 @@ import javax.inject.Inject;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.injection.InjectingTestCase; import org.tasks.injection.InjectingTestCase;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
@ -28,6 +30,7 @@ import org.tasks.injection.TestComponent;
public class GtasksIndentActionTest extends InjectingTestCase { public class GtasksIndentActionTest extends InjectingTestCase {
@Inject GtasksListService gtasksListService; @Inject GtasksListService gtasksListService;
@Inject GoogleTaskListDao googleTaskListDao;
@Inject GtasksTaskListUpdater gtasksTaskListUpdater; @Inject GtasksTaskListUpdater gtasksTaskListUpdater;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject GoogleTaskDao googleTaskDao; @Inject GoogleTaskDao googleTaskDao;
@ -159,9 +162,11 @@ public class GtasksIndentActionTest extends InjectingTestCase {
list.setId("list"); list.setId("list");
list.setTitle("Test Tasks"); list.setTitle("Test Tasks");
items.add(list); items.add(list);
gtasksListService.updateLists(items); GoogleTaskAccount account = new GoogleTaskAccount("account");
googleTaskListDao.insert(account);
gtasksListService.updateLists(account, items);
storeList = gtasksListService.getLists().get(0); storeList = googleTaskListDao.getActiveLists("account").get(0);
} }
@Override @Override
@ -199,4 +204,5 @@ public class GtasksIndentActionTest extends InjectingTestCase {
taskDao.createNew(task); taskDao.createNew(task);
return task; return task;
} }
} }

@ -22,6 +22,7 @@ import javax.inject.Inject;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.tasks.LocalBroadcastManager; import org.tasks.LocalBroadcastManager;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
@ -87,7 +88,7 @@ public class GtasksListServiceTest extends InjectingTestCase {
assertEquals( assertEquals(
singletonList(newGtaskList(with(ID, 2L), with(REMOTE_ID, "2"))), singletonList(newGtaskList(with(ID, 2L), with(REMOTE_ID, "2"))),
googleTaskListDao.getActiveLists()); googleTaskListDao.getActiveLists("account"));
} }
@Test @Test
@ -122,6 +123,8 @@ public class GtasksListServiceTest extends InjectingTestCase {
} }
private void setLists(TaskList... list) { private void setLists(TaskList... list) {
gtasksListService.updateLists(asList(list)); GoogleTaskAccount account = new GoogleTaskAccount("account");
googleTaskListDao.insert(account);
gtasksListService.updateLists(account, asList(list));
} }
} }

@ -5,17 +5,12 @@
*/ */
package com.todoroo.astrid.gtasks; package com.todoroo.astrid.gtasks;
import static android.support.test.InstrumentationRegistry.getTargetContext;
import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertNull;
import android.content.Context;
import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import dagger.Module;
import dagger.Provides;
import dagger.Subcomponent;
import javax.inject.Inject; import javax.inject.Inject;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -23,7 +18,6 @@ import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.injection.InjectingTestCase; import org.tasks.injection.InjectingTestCase;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
import org.tasks.preferences.Preferences;
@SuppressWarnings("nls") @SuppressWarnings("nls")
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@ -36,7 +30,7 @@ public class GtasksMetadataServiceTest extends InjectingTestCase {
@Override @Override
protected void inject(TestComponent component) { protected void inject(TestComponent component) {
component.plus(new GtasksMetadataServiceTestModule(getTargetContext())).inject(this); component.inject(this);
} }
@Test @Test
@ -94,30 +88,4 @@ public class GtasksMetadataServiceTest extends InjectingTestCase {
taskDao.createNew(task); taskDao.createNew(task);
return task; return task;
} }
@Subcomponent(modules = GtasksMetadataServiceTest.GtasksMetadataServiceTestModule.class)
public interface GtasksMetadataServiceTestComponent {
void inject(GtasksMetadataServiceTest gtasksMetadataServiceTest);
}
@Module
public class GtasksMetadataServiceTestModule {
private final GtasksTestPreferenceService service;
public GtasksMetadataServiceTestModule(Context context) {
service = new GtasksTestPreferenceService(new Preferences(context, null));
}
@Provides
public GtasksTestPreferenceService getGtasksTestPreferenceService() {
return service;
}
@Provides
public GtasksPreferenceService getGtasksPreferenceService() {
return service;
}
}
} }

@ -19,8 +19,10 @@ import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.injection.InjectingTestCase; import org.tasks.injection.InjectingTestCase;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
@ -34,6 +36,7 @@ public class GtasksTaskListUpdaterTest extends InjectingTestCase {
@Inject GtasksListService gtasksListService; @Inject GtasksListService gtasksListService;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject GoogleTaskDao googleTaskDao; @Inject GoogleTaskDao googleTaskDao;
@Inject GoogleTaskListDao googleTaskListDao;
@Test @Test
public void testBasicParentComputation() { public void testBasicParentComputation() {
@ -149,7 +152,9 @@ public class GtasksTaskListUpdaterTest extends InjectingTestCase {
list.setId("1"); list.setId("1");
list.setTitle("Tim's Tasks"); list.setTitle("Tim's Tasks");
items.add(list); items.add(list);
gtasksListService.updateLists(items); GoogleTaskAccount account = new GoogleTaskAccount("account");
googleTaskListDao.insert(account);
gtasksListService.updateLists(account, items);
} }
@Override @Override
@ -162,7 +167,7 @@ public class GtasksTaskListUpdaterTest extends InjectingTestCase {
} }
private void createParentSiblingMaps() { private void createParentSiblingMaps() {
for (GoogleTaskList list : gtasksListService.getLists()) { for (GoogleTaskList list : googleTaskListDao.getActiveLists("account")) {
gtasksTaskListUpdater.updateParentSiblingMapsFor(list); gtasksTaskListUpdater.updateParentSiblingMapsFor(list);
} }
} }

@ -18,8 +18,10 @@ import javax.inject.Inject;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.injection.InjectingTestCase; import org.tasks.injection.InjectingTestCase;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
@ -33,6 +35,7 @@ public class GtasksTaskMovingTest extends InjectingTestCase {
@Inject GtasksTaskListUpdater gtasksTaskListUpdater; @Inject GtasksTaskListUpdater gtasksTaskListUpdater;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject GoogleTaskDao googleTaskDao; @Inject GoogleTaskDao googleTaskDao;
@Inject GoogleTaskListDao googleTaskListDao;
private Task A, B, C, D, E, F; private Task A, B, C, D, E, F;
private GoogleTaskList list; private GoogleTaskList list;
@ -265,9 +268,11 @@ public class GtasksTaskMovingTest extends InjectingTestCase {
taskList.setId("1"); taskList.setId("1");
taskList.setTitle("Tim's Tasks"); taskList.setTitle("Tim's Tasks");
items.add(taskList); items.add(taskList);
gtasksListService.updateLists(items); GoogleTaskAccount account = new GoogleTaskAccount("account");
googleTaskListDao.insert(account);
gtasksListService.updateLists(account, items);
list = gtasksListService.getLists().get(0); list = googleTaskListDao.getActiveLists("account").get(0);
} }
@Override @Override

@ -1,20 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* <p>See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.gtasks;
import org.tasks.preferences.Preferences;
public class GtasksTestPreferenceService extends GtasksPreferenceService {
public GtasksTestPreferenceService(Preferences preferences) {
super(preferences);
}
@Override
public long getLastSyncDate() {
return 0L;
}
}

@ -22,9 +22,6 @@ import org.tasks.jobs.BackupServiceTests;
@Component(modules = TestModule.class) @Component(modules = TestModule.class)
public interface TestComponent { public interface TestComponent {
GtasksMetadataServiceTest.GtasksMetadataServiceTestComponent plus(
GtasksMetadataServiceTest.GtasksMetadataServiceTestModule gtasksMetadataServiceTestModule);
void inject(GtasksIndentActionTest gtasksIndentActionTest); void inject(GtasksIndentActionTest gtasksIndentActionTest);
void inject(GtasksTaskMovingTest gtasksTaskMovingTest); void inject(GtasksTaskMovingTest gtasksTaskMovingTest);
@ -54,4 +51,6 @@ public interface TestComponent {
void inject(AlarmJobServiceTest alarmServiceTest); void inject(AlarmJobServiceTest alarmServiceTest);
void inject(RepeatTaskHelperTest repeatTaskHelperTest); void inject(RepeatTaskHelperTest repeatTaskHelperTest);
void inject(GtasksMetadataServiceTest gtasksMetadataServiceTest);
} }

@ -41,7 +41,6 @@ import com.todoroo.astrid.api.CustomFilter;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.BuiltInFilterExposer; import com.todoroo.astrid.core.BuiltInFilterExposer;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksSubtaskListFragment; import com.todoroo.astrid.gtasks.GtasksSubtaskListFragment;
import com.todoroo.astrid.service.TaskCreator; import com.todoroo.astrid.service.TaskCreator;
import com.todoroo.astrid.service.TaskDeleter; import com.todoroo.astrid.service.TaskDeleter;
@ -95,7 +94,6 @@ public class TaskListFragment extends InjectingFragment
@Inject TaskDeleter taskDeleter; @Inject TaskDeleter taskDeleter;
@Inject @ForActivity Context context; @Inject @ForActivity Context context;
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject CheckBoxes checkBoxes; @Inject CheckBoxes checkBoxes;
@Inject TaskCreator taskCreator; @Inject TaskCreator taskCreator;
@ -414,7 +412,7 @@ public class TaskListFragment extends InjectingFragment
// TODO: compare indents in diff callback, then animate this // TODO: compare indents in diff callback, then animate this
loadTaskListContent(!(this instanceof GtasksSubtaskListFragment)); loadTaskListContent(!(this instanceof GtasksSubtaskListFragment));
setSyncOngoing(gtasksPreferenceService.isOngoing()); setSyncOngoing(preferences.isSyncOngoing());
} }
/* /*

@ -20,7 +20,6 @@ import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat; import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.util.Pair; import android.support.v4.util.Pair;
import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -28,11 +27,9 @@ import android.widget.ArrayAdapter;
import android.widget.CheckedTextView; import android.widget.CheckedTextView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.google.common.base.Strings;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CustomFilterActivity; import com.todoroo.astrid.core.CustomFilterActivity;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -43,6 +40,7 @@ import org.tasks.billing.Inventory;
import org.tasks.billing.PurchaseActivity; import org.tasks.billing.PurchaseActivity;
import org.tasks.caldav.CaldavCalendarSettingsActivity; import org.tasks.caldav.CaldavCalendarSettingsActivity;
import org.tasks.data.CaldavAccount; import org.tasks.data.CaldavAccount;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.filters.FilterCounter; import org.tasks.filters.FilterCounter;
import org.tasks.filters.FilterProvider; import org.tasks.filters.FilterProvider;
import org.tasks.filters.NavigationDrawerAction; import org.tasks.filters.NavigationDrawerAction;
@ -50,7 +48,6 @@ import org.tasks.filters.NavigationDrawerSeparator;
import org.tasks.filters.NavigationDrawerSubheader; import org.tasks.filters.NavigationDrawerSubheader;
import org.tasks.locale.Locale; import org.tasks.locale.Locale;
import org.tasks.preferences.BasicPreferences; import org.tasks.preferences.BasicPreferences;
import org.tasks.preferences.Preferences;
import org.tasks.themes.Theme; import org.tasks.themes.Theme;
import org.tasks.themes.ThemeCache; import org.tasks.themes.ThemeCache;
import org.tasks.ui.NavigationDrawerFragment; import org.tasks.ui.NavigationDrawerFragment;
@ -68,7 +65,6 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
private final Theme theme; private final Theme theme;
private final Locale locale; private final Locale locale;
private final Inventory inventory; private final Inventory inventory;
private final Preferences preferences;
private final FilterListUpdateReceiver filterListUpdateReceiver = new FilterListUpdateReceiver(); private final FilterListUpdateReceiver filterListUpdateReceiver = new FilterListUpdateReceiver();
private final List<FilterListItem> items = new ArrayList<>(); private final List<FilterListItem> items = new ArrayList<>();
private final LayoutInflater inflater; private final LayoutInflater inflater;
@ -84,8 +80,7 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
Theme theme, Theme theme,
ThemeCache themeCache, ThemeCache themeCache,
Locale locale, Locale locale,
Inventory inventory, Inventory inventory) {
Preferences preferences) {
super(activity, 0); super(activity, 0);
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.filterCounter = filterCounter; this.filterCounter = filterCounter;
@ -93,7 +88,6 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
this.theme = theme; this.theme = theme;
this.locale = locale; this.locale = locale;
this.inventory = inventory; this.inventory = inventory;
this.preferences = preferences;
this.inflater = theme.getLayoutInflater(activity); this.inflater = theme.getLayoutInflater(activity);
this.themeCache = themeCache; this.themeCache = themeCache;
} }
@ -230,8 +224,7 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
return getView(position, convertView, parent); return getView(position, convertView, parent);
} }
private void addSubMenu( private void addSubMenu(final int titleResource, List<Filter> filters, boolean hideIfEmpty) {
final int titleResource, List<Filter> filters, boolean hideIfEmpty) {
addSubMenu(activity.getResources().getString(titleResource), filters, hideIfEmpty); addSubMenu(activity.getResources().getString(titleResource), filters, hideIfEmpty);
} }
@ -264,19 +257,12 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
item.icon = R.drawable.ic_cloud_off_black_24dp; item.icon = R.drawable.ic_cloud_off_black_24dp;
add(item); add(item);
String googleTaskTitle = preferences.getStringValue(GtasksPreferenceService.PREF_USER_NAME); for (Pair<GoogleTaskAccount, List<Filter>> filters : filterProvider.getGoogleTaskFilters()) {
if (Strings.isNullOrEmpty(googleTaskTitle)) { addSubMenu(filters.first.getAccount(), filters.second, true);
googleTaskTitle = activity.getResources().getString(R.string.gtasks_GPr_header);
} }
addSubMenu(googleTaskTitle, filterProvider.getGoogleTaskFilters(), true);
for (Pair<CaldavAccount, List<Filter>> filters : filterProvider.getCaldavFilters()) { for (Pair<CaldavAccount, List<Filter>> filters : filterProvider.getCaldavFilters()) {
CaldavAccount account = filters.first; addSubMenu(filters.first.getName(), filters.second, true);
String caldavTitle = account.getName();
if (TextUtils.isEmpty(caldavTitle)) {
caldavTitle = activity.getString(R.string.CalDAV);
}
addSubMenu(caldavTitle, filters.second, true);
} }
notifyDataSetChanged(); notifyDataSetChanged();
@ -309,31 +295,24 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
NavigationDrawerFragment.REQUEST_NEW_LIST)); NavigationDrawerFragment.REQUEST_NEW_LIST));
} }
List<Filter> googleTaskFilters = filterProvider.getGoogleTaskFilters(); for (Pair<GoogleTaskAccount, List<Filter>> filters : filterProvider.getGoogleTaskFilters()) {
if (!googleTaskFilters.isEmpty()) { GoogleTaskAccount account = filters.first;
String title = preferences.getStringValue(GtasksPreferenceService.PREF_USER_NAME); addSubMenu(account.getAccount(), filters.second, !navigationDrawer);
if (Strings.isNullOrEmpty(title)) {
title = activity.getResources().getString(R.string.gtasks_GPr_header);
}
addSubMenu(title, googleTaskFilters, true);
if (navigationDrawer) { if (navigationDrawer) {
add( add(
new NavigationDrawerAction( new NavigationDrawerAction(
activity.getResources().getString(R.string.new_list), activity.getResources().getString(R.string.new_list),
R.drawable.ic_add_24dp, R.drawable.ic_add_24dp,
new Intent(activity, GoogleTaskListSettingsActivity.class), new Intent(activity, GoogleTaskListSettingsActivity.class)
.putExtra(GoogleTaskListSettingsActivity.EXTRA_ACCOUNT, account),
NavigationDrawerFragment.REQUEST_NEW_GTASK_LIST)); NavigationDrawerFragment.REQUEST_NEW_GTASK_LIST));
} }
} }
for (Pair<CaldavAccount, List<Filter>> filters : filterProvider.getCaldavFilters()) { for (Pair<CaldavAccount, List<Filter>> filters : filterProvider.getCaldavFilters()) {
CaldavAccount account = filters.first; CaldavAccount account = filters.first;
String title = account.getName(); addSubMenu(account.getName(), filters.second, !navigationDrawer);
if (TextUtils.isEmpty(title)) {
title = activity.getString(R.string.CalDAV);
}
addSubMenu(title, filters.second, !navigationDrawer);
if (navigationDrawer) { if (navigationDrawer) {
add( add(

@ -21,6 +21,7 @@ import org.tasks.data.CaldavTask;
import org.tasks.data.Filter; import org.tasks.data.Filter;
import org.tasks.data.FilterDao; import org.tasks.data.FilterDao;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
@ -56,9 +57,10 @@ import timber.log.Timber;
GoogleTaskList.class, GoogleTaskList.class,
CaldavCalendar.class, CaldavCalendar.class,
CaldavTask.class, CaldavTask.class,
CaldavAccount.class CaldavAccount.class,
GoogleTaskAccount.class
}, },
version = 58 version = 59
) )
public abstract class Database extends RoomDatabase { public abstract class Database extends RoomDatabase {

@ -6,13 +6,18 @@
package com.todoroo.astrid.gtasks; package com.todoroo.astrid.gtasks;
import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import android.support.v4.util.Pair;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.GtasksFilter; import com.todoroo.astrid.api.GtasksFilter;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.sync.SyncAdapters; import org.tasks.sync.SyncAdapters;
/** /**
@ -24,22 +29,20 @@ public class GtasksFilterExposer {
private final GtasksListService gtasksListService; private final GtasksListService gtasksListService;
private final SyncAdapters syncAdapters; private final SyncAdapters syncAdapters;
private final GoogleTaskListDao googleTaskListDao;
@Inject @Inject
public GtasksFilterExposer(GtasksListService gtasksListService, SyncAdapters syncAdapters) { public GtasksFilterExposer(GtasksListService gtasksListService, SyncAdapters syncAdapters, GoogleTaskListDao googleTaskListDao) {
this.gtasksListService = gtasksListService; this.gtasksListService = gtasksListService;
this.syncAdapters = syncAdapters; this.syncAdapters = syncAdapters;
this.googleTaskListDao = googleTaskListDao;
} }
public List<Filter> getFilters() { public List<Pair<GoogleTaskAccount, List<Filter>>> getFilters() {
// if we aren't logged in (or we are logged in to astrid.com), don't expose features List<Pair<GoogleTaskAccount, List<Filter>>> listFilters = newArrayList();
if (!syncAdapters.isGoogleTaskSyncEnabled()) { for (GoogleTaskAccount account : googleTaskListDao.getAccounts()) {
return emptyList(); List<GoogleTaskList> lists = googleTaskListDao.getActiveLists(account.getAccount());
} listFilters.add(new Pair<>(account, transform(lists, GtasksFilter::new)));
List<Filter> listFilters = newArrayList();
for (GoogleTaskList list : gtasksListService.getLists()) {
listFilters.add(filterFromList(list));
} }
return listFilters; return listFilters;
} }

@ -17,6 +17,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.LocalBroadcastManager; import org.tasks.LocalBroadcastManager;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
@ -44,10 +45,6 @@ public class GtasksListService {
this.taskDao = taskDao; this.taskDao = taskDao;
} }
public List<GoogleTaskList> getLists() {
return googleTaskListDao.getActiveLists();
}
public GoogleTaskList getList(long id) { public GoogleTaskList getList(long id) {
return googleTaskListDao.getById(id); return googleTaskListDao.getById(id);
} }
@ -57,8 +54,8 @@ public class GtasksListService {
* *
* @param remoteLists remote information about your lists * @param remoteLists remote information about your lists
*/ */
public synchronized void updateLists(List<TaskList> remoteLists) { public synchronized void updateLists(GoogleTaskAccount account, List<TaskList> remoteLists) {
List<GoogleTaskList> lists = getLists(); List<GoogleTaskList> lists = googleTaskListDao.getActiveLists(account.getAccount());
Set<Long> previousLists = new HashSet<>(); Set<Long> previousLists = new HashSet<>();
for (GoogleTaskList list : lists) { for (GoogleTaskList list : lists) {
@ -79,9 +76,16 @@ public class GtasksListService {
String title = remote.getTitle(); String title = remote.getTitle();
if (local == null) { if (local == null) {
Timber.d("Adding new gtask list %s", title); GoogleTaskList byRemoteId = googleTaskListDao.findExistingList(id);
local = new GoogleTaskList(); if (byRemoteId != null) {
local.setRemoteId(id); byRemoteId.setAccount(account.getAccount());
local = byRemoteId;
} else {
Timber.d("Adding new gtask list %s", title);
local = new GoogleTaskList();
local.setAccount(account.getAccount());
local.setRemoteId(id);
}
} }
local.setTitle(title); local.setTitle(title);
@ -126,11 +130,6 @@ public class GtasksListService {
} }
public GoogleTaskList getList(String listId) { public GoogleTaskList getList(String listId) {
for (GoogleTaskList list : getLists()) { return googleTaskListDao.getByRemoteId(listId);
if (list != null && list.getRemoteId().equals(listId)) {
return list;
}
}
return null;
} }
} }

@ -1,55 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* <p>See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.gtasks;
import com.todoroo.andlib.utility.DateUtilities;
import javax.inject.Inject;
import org.tasks.preferences.Preferences;
/**
* Methods for working with GTasks preferences
*
* @author timsu
*/
public class GtasksPreferenceService {
private static final String IDENTIFIER = "gtasks"; // $NON-NLS-1$
public static final String PREF_USER_NAME = IDENTIFIER + "_user"; // $NON-NLS-1$
private static final String PREF_LAST_SYNC = "_last_sync"; // $NON-NLS-1$
private final Preferences preferences;
@Inject
public GtasksPreferenceService(Preferences preferences) {
this.preferences = preferences;
}
public String getUserName() {
return preferences.getStringValue(PREF_USER_NAME);
}
public void setUserName(String userName) {
preferences.setString(PREF_USER_NAME, userName);
}
/** @return Last Successful Sync Date, or 0 */
public long getLastSyncDate() {
return preferences.getLong(IDENTIFIER + PREF_LAST_SYNC, 0);
}
/** Deletes Last Successful Sync Date */
public void clearLastSyncDate() {
preferences.clear(IDENTIFIER + PREF_LAST_SYNC);
}
/** Set Last Successful Sync Date */
public void recordSuccessfulSync() {
preferences.setLong(IDENTIFIER + PREF_LAST_SYNC, DateUtilities.now() + 1000);
}
public boolean isOngoing() {
return preferences.isSyncOngoing();
}
}

@ -58,8 +58,8 @@ public class GtasksTaskListUpdater {
gtasksSyncService.iterateThroughList(listId, iterator, 0, false); gtasksSyncService.iterateThroughList(listId, iterator, 0, false);
} }
private void onMovedOrIndented(GoogleTask googleTask) { private void onMovedOrIndented(GoogleTaskList googleTaskList, GoogleTask googleTask) {
gtasksSyncService.triggerMoveForMetadata(googleTask); gtasksSyncService.triggerMoveForMetadata(googleTaskList, googleTask);
} }
// --- used during synchronization // --- used during synchronization
@ -176,7 +176,7 @@ public class GtasksTaskListUpdater {
saveAndUpdateModifiedDate(googleTask); saveAndUpdateModifiedDate(googleTask);
}); });
onMovedOrIndented(getTaskMetadata(targetTaskId)); onMovedOrIndented(list, getTaskMetadata(targetTaskId));
} }
/** /**
@ -242,7 +242,7 @@ public class GtasksTaskListUpdater {
} }
traverseTreeAndWriteValues(list, root, new AtomicLong(0), -1); traverseTreeAndWriteValues(list, root, new AtomicLong(0), -1);
onMovedOrIndented(getTaskMetadata(targetTaskId)); onMovedOrIndented(list, getTaskMetadata(targetTaskId));
} }
// --- task moving // --- task moving
@ -273,7 +273,7 @@ public class GtasksTaskListUpdater {
} }
saveAndUpdateModifiedDate(googleTask); saveAndUpdateModifiedDate(googleTask);
if (parentChanged) { if (parentChanged) {
onMovedOrIndented(googleTask); onMovedOrIndented(list, googleTask);
} }
} }

@ -13,15 +13,12 @@ import com.google.api.services.tasks.TasksScopes;
import com.google.api.services.tasks.model.Task; import com.google.api.services.tasks.model.Task;
import com.google.api.services.tasks.model.TaskList; import com.google.api.services.tasks.model.TaskList;
import com.google.api.services.tasks.model.TaskLists; import com.google.api.services.tasks.model.TaskLists;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import javax.inject.Inject;
import org.tasks.BuildConfig; import org.tasks.BuildConfig;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.gtasks.GoogleTasksUnsuccessfulResponseHandler; import org.tasks.gtasks.GoogleTasksUnsuccessfulResponseHandler;
import org.tasks.gtasks.PlayServices; import org.tasks.gtasks.PlayServices;
import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication;
import timber.log.Timber; import timber.log.Timber;
/** /**
@ -30,32 +27,23 @@ import timber.log.Timber;
* *
* @author Sam Bosley * @author Sam Bosley
*/ */
@ApplicationScope
public class GtasksInvoker { public class GtasksInvoker {
private final GoogleAccountCredential credential; private final GoogleAccountCredential credential;
private final PlayServices playServices; private final PlayServices playServices;
private final Tasks service; private final Tasks service;
@Inject public GtasksInvoker(Context context, PlayServices playServices, String account) {
public GtasksInvoker(
@ForApplication Context context,
GtasksPreferenceService preferenceService,
PlayServices playServices) {
credential =
GoogleAccountCredential.usingOAuth2(context, Collections.singletonList(TasksScopes.TASKS));
this.playServices = playServices; this.playServices = playServices;
setUserName(preferenceService.getUserName()); credential =
GoogleAccountCredential.usingOAuth2(context, Collections.singletonList(TasksScopes.TASKS))
.setSelectedAccountName(account);
service = service =
new Tasks.Builder(new NetHttpTransport(), new JacksonFactory(), credential) new Tasks.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
.setApplicationName(String.format("Tasks/%s", BuildConfig.VERSION_NAME)) .setApplicationName(String.format("Tasks/%s", BuildConfig.VERSION_NAME))
.build(); .build();
} }
public void setUserName(String username) {
credential.setSelectedAccountName(username);
}
public TaskLists allGtaskLists(String pageToken) throws IOException { public TaskLists allGtaskLists(String pageToken) throws IOException {
return execute(service.tasklists().list().setPageToken(pageToken)); return execute(service.tasklists().list().setPageToken(pageToken));
} }

@ -10,10 +10,10 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Toast; import android.widget.Toast;
import com.todoroo.andlib.utility.DialogUtilities; import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.tasks.gtasks.GoogleAccountManager; import org.tasks.gtasks.GoogleAccountManager;
import org.tasks.gtasks.PlayServices; import org.tasks.gtasks.PlayServices;
@ -30,26 +30,20 @@ public class GtasksLoginActivity extends InjectingAppCompatActivity {
public static final int RC_REQUEST_OAUTH = 10987; public static final int RC_REQUEST_OAUTH = 10987;
private static final int RC_CHOOSE_ACCOUNT = 10988; private static final int RC_CHOOSE_ACCOUNT = 10988;
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject GoogleAccountManager accountManager; @Inject GoogleAccountManager accountManager;
@Inject GtasksInvoker gtasksInvoker;
@Inject PlayServices playServices; @Inject PlayServices playServices;
@Inject GoogleTaskListDao googleTaskListDao;
private String accountName; private String accountName;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final String existingUsername = gtasksPreferenceService.getUserName(); Intent chooseAccountIntent =
if (existingUsername != null && accountManager.hasAccount(existingUsername)) { android.accounts.AccountManager.newChooseAccountIntent(
getAuthToken(existingUsername); null, null, new String[] {"com.google"}, false, null, null, null, null);
} else { startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT);
Intent chooseAccountIntent =
android.accounts.AccountManager.newChooseAccountIntent(
null, null, new String[] {"com.google"}, false, null, null, null, null);
startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT);
}
} }
@Override @Override
@ -71,9 +65,12 @@ public class GtasksLoginActivity extends InjectingAppCompatActivity {
new AuthResultHandler() { new AuthResultHandler() {
@Override @Override
public void authenticationSuccessful(String accountName) { public void authenticationSuccessful(String accountName) {
gtasksPreferenceService.setUserName(accountName); if (googleTaskListDao.getAccount(accountName) == null) {
gtasksInvoker.setUserName(accountName); GoogleTaskAccount googleTaskAccount = new GoogleTaskAccount();
setResult(RESULT_OK); googleTaskAccount.setAccount(accountName);
googleTaskListDao.insert(googleTaskAccount);
setResult(RESULT_OK);
}
finish(); finish();
DialogUtilities.dismissDialog(GtasksLoginActivity.this, pd); DialogUtilities.dismissDialog(GtasksLoginActivity.this, pd);
} }

@ -5,12 +5,12 @@
*/ */
package com.todoroo.astrid.gtasks.sync; package com.todoroo.astrid.gtasks.sync;
import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.api.GtasksInvoker; import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.MoveRequest; import com.todoroo.astrid.gtasks.api.MoveRequest;
@ -24,44 +24,53 @@ import javax.inject.Inject;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.gtasks.GtaskSyncAdapterHelper; import org.tasks.gtasks.GtaskSyncAdapterHelper;
import org.tasks.gtasks.PlayServices;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication;
import org.tasks.preferences.Preferences;
import timber.log.Timber; import timber.log.Timber;
@ApplicationScope @ApplicationScope
public class GtasksSyncService { public class GtasksSyncService {
private final Context context;
private final TaskDao taskDao; private final TaskDao taskDao;
private final GtasksPreferenceService gtasksPreferenceService; private final Preferences preferences;
private final GtasksInvoker gtasksInvoker;
private final LinkedBlockingQueue<SyncOnSaveOperation> operationQueue = private final LinkedBlockingQueue<SyncOnSaveOperation> operationQueue =
new LinkedBlockingQueue<>(); new LinkedBlockingQueue<>();
private final GtaskSyncAdapterHelper gtaskSyncAdapterHelper; private final GtaskSyncAdapterHelper gtaskSyncAdapterHelper;
private final Tracker tracker; private final Tracker tracker;
private final GoogleTaskDao googleTaskDao; private final GoogleTaskDao googleTaskDao;
private final PlayServices playServices;
@Inject @Inject
public GtasksSyncService( public GtasksSyncService(
@ForApplication Context context,
TaskDao taskDao, TaskDao taskDao,
GtasksPreferenceService gtasksPreferenceService, Preferences preferences,
GtasksInvoker gtasksInvoker,
GtaskSyncAdapterHelper gtaskSyncAdapterHelper, GtaskSyncAdapterHelper gtaskSyncAdapterHelper,
Tracker tracker, Tracker tracker,
GoogleTaskDao googleTaskDao) { GoogleTaskDao googleTaskDao,
GoogleTaskListDao googleTaskListDao,
PlayServices playServices) {
this.context = context;
this.taskDao = taskDao; this.taskDao = taskDao;
this.gtasksPreferenceService = gtasksPreferenceService; this.preferences = preferences;
this.gtasksInvoker = gtasksInvoker;
this.gtaskSyncAdapterHelper = gtaskSyncAdapterHelper; this.gtaskSyncAdapterHelper = gtaskSyncAdapterHelper;
this.tracker = tracker; this.tracker = tracker;
this.googleTaskDao = googleTaskDao; this.googleTaskDao = googleTaskDao;
this.playServices = playServices;
new OperationPushThread(operationQueue).start(); new OperationPushThread(operationQueue).start();
} }
public void clearCompleted(String listId) { public void clearCompleted(GoogleTaskList googleTaskList) {
operationQueue.offer(new ClearOp(listId)); operationQueue.offer(new ClearOp(googleTaskList));
} }
public void triggerMoveForMetadata(final GoogleTask googleTask) { public void triggerMoveForMetadata(GoogleTaskList googleTaskList, GoogleTask googleTask) {
if (googleTask == null) { if (googleTask == null) {
return; return;
} }
@ -69,16 +78,14 @@ public class GtasksSyncService {
googleTask.setSuppressSync(false); googleTask.setSuppressSync(false);
return; return;
} }
if (gtasksPreferenceService if (preferences.isSyncOngoing()) {
.isOngoing()) // Don't try and sync changes that occur during a normal sync
{
return; return;
} }
if (!gtaskSyncAdapterHelper.isEnabled()) { if (!gtaskSyncAdapterHelper.isEnabled()) {
return; return;
} }
operationQueue.offer(new MoveOp(googleTask)); operationQueue.offer(new MoveOp(googleTaskList, googleTask));
} }
private void pushMetadataOnSave(GoogleTask model, GtasksInvoker invoker) throws IOException { private void pushMetadataOnSave(GoogleTask model, GtasksInvoker invoker) throws IOException {
@ -154,34 +161,38 @@ public class GtasksSyncService {
interface SyncOnSaveOperation { interface SyncOnSaveOperation {
void op(GtasksInvoker invoker) throws IOException; void op() throws IOException;
} }
private class MoveOp implements SyncOnSaveOperation { private class MoveOp implements SyncOnSaveOperation {
private final GoogleTaskList googleTaskList;
final GoogleTask googleTask; final GoogleTask googleTask;
MoveOp(GoogleTask googleTask) { MoveOp(GoogleTaskList googleTaskList, GoogleTask googleTask) {
this.googleTaskList = googleTaskList;
this.googleTask = googleTask; this.googleTask = googleTask;
} }
@Override @Override
public void op(GtasksInvoker invoker) throws IOException { public void op() throws IOException {
GtasksInvoker invoker = new GtasksInvoker(context, playServices, googleTaskList.getAccount());
pushMetadataOnSave(googleTask, invoker); pushMetadataOnSave(googleTask, invoker);
} }
} }
private class ClearOp implements SyncOnSaveOperation { private class ClearOp implements SyncOnSaveOperation {
private final String listId; private GoogleTaskList googleTaskList;
ClearOp(String listId) { ClearOp(GoogleTaskList googleTaskList) {
this.listId = listId; this.googleTaskList = googleTaskList;
} }
@Override @Override
public void op(GtasksInvoker invoker) throws IOException { public void op() throws IOException {
invoker.clearCompleted(listId); GtasksInvoker invoker = new GtasksInvoker(context, playServices, googleTaskList.getAccount());
invoker.clearCompleted(googleTaskList.getRemoteId());
} }
} }
@ -205,7 +216,7 @@ public class GtasksSyncService {
continue; continue;
} }
try { try {
op.op(gtasksInvoker); op.op();
} catch (UserRecoverableAuthIOException ignored) { } catch (UserRecoverableAuthIOException ignored) {
} catch (IOException e) { } catch (IOException e) {

@ -5,10 +5,11 @@
*/ */
package com.todoroo.astrid.service; package com.todoroo.astrid.service;
import static com.google.common.base.Strings.isNullOrEmpty;
import android.content.Context; import android.content.Context;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.os.Environment; import android.os.Environment;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
@ -26,6 +27,7 @@ import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking; import org.tasks.analytics.Tracking;
import org.tasks.data.Filter; import org.tasks.data.Filter;
import org.tasks.data.FilterDao; import org.tasks.data.FilterDao;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
import org.tasks.data.Tag; import org.tasks.data.Tag;
@ -43,7 +45,8 @@ public class StartupService {
private static final int V4_8_0 = 380; private static final int V4_8_0 = 380;
private static final int V4_9_5 = 434; private static final int V4_9_5 = 434;
private static final int V5_3_0 = 491; private static final int V5_3_0 = 491;
private static final int V5_3_1 = 501; private static final int V6_0_beta_1 = 522;
private static final int V6_0_beta_2 = 523;
private final Database database; private final Database database;
private final Preferences preferences; private final Preferences preferences;
@ -119,9 +122,12 @@ public class StartupService {
if (from < V5_3_0) { if (from < V5_3_0) {
migrateFilters(); migrateFilters();
} }
if (from < V5_3_1) { if (from < V6_0_beta_1) {
migrateDefaultSyncList(); migrateDefaultSyncList();
} }
if (from < V6_0_beta_2) {
migrateGoogleTaskAccount();
}
tracker.reportEvent(Tracking.Events.UPGRADE, Integer.toString(from)); tracker.reportEvent(Tracking.Events.UPGRADE, Integer.toString(from));
} }
preferences.setCurrentVersion(to); preferences.setCurrentVersion(to);
@ -166,8 +172,15 @@ public class StartupService {
} }
private void migrateDefaultSyncList() { private void migrateDefaultSyncList() {
String account = preferences.getStringValue("gtasks_user");
if (isNullOrEmpty(account)) {
return;
}
String defaultGoogleTaskList = preferences.getStringValue("gtasks_defaultlist"); String defaultGoogleTaskList = preferences.getStringValue("gtasks_defaultlist");
if (!Strings.isNullOrEmpty(defaultGoogleTaskList)) { if (isNullOrEmpty(defaultGoogleTaskList)) {
// TODO: look up default list
} else {
GoogleTaskList googleTaskList = googleTaskListDao.getByRemoteId(defaultGoogleTaskList); GoogleTaskList googleTaskList = googleTaskListDao.getByRemoteId(defaultGoogleTaskList);
if (googleTaskList != null) { if (googleTaskList != null) {
defaultFilterProvider.setDefaultRemoteList(new GtasksFilter(googleTaskList)); defaultFilterProvider.setDefaultRemoteList(new GtasksFilter(googleTaskList));
@ -175,6 +188,15 @@ public class StartupService {
} }
} }
private void migrateGoogleTaskAccount() {
String account = preferences.getStringValue("gtasks_user");
if (!isNullOrEmpty(account)) {
GoogleTaskAccount googleTaskAccount = new GoogleTaskAccount();
googleTaskAccount.setAccount(account);
googleTaskListDao.insert(googleTaskAccount);
}
}
private String migrate(String input) { private String migrate(String input) {
return input return input
.replaceAll( .replaceAll(

@ -46,7 +46,7 @@ public class SyncV2Service {
() -> { () -> {
callback.started(); callback.started();
try { try {
gtasksSyncService.clearCompleted(list.getRemoteId()); gtasksSyncService.clearCompleted(list);
} finally { } finally {
callback.finished(); callback.finished();
} }

@ -1,7 +1,6 @@
package org.tasks; package org.tasks;
import com.jakewharton.threetenabp.AndroidThreeTen; import com.jakewharton.threetenabp.AndroidThreeTen;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.service.StartupService; import com.todoroo.astrid.service.StartupService;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
@ -24,7 +23,6 @@ public class Tasks extends InjectingApplication {
@Inject Badger badger; @Inject Badger badger;
@Inject JobManager jobManager; @Inject JobManager jobManager;
@Inject JobCreator jobCreator; @Inject JobCreator jobCreator;
@Inject GtasksPreferenceService gtasksPreferenceService;
@Override @Override
public void onCreate() { public void onCreate() {

@ -27,6 +27,7 @@ import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking; import org.tasks.analytics.Tracking;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
@ -46,6 +47,7 @@ public class GoogleTaskListSettingsActivity extends ThemedInjectingAppCompatActi
DeleteListDialog.DeleteListDialogCallback, DeleteListDialog.DeleteListDialogCallback,
RenameListDialog.RenameListDialogCallback { RenameListDialog.RenameListDialogCallback {
public static final String EXTRA_ACCOUNT = "extra_account";
public static final String EXTRA_STORE_DATA = "extra_store_data"; public static final String EXTRA_STORE_DATA = "extra_store_data";
public static final String ACTION_DELETED = "action_deleted"; public static final String ACTION_DELETED = "action_deleted";
public static final String ACTION_RELOAD = "action_reload"; public static final String ACTION_RELOAD = "action_reload";
@ -82,10 +84,13 @@ public class GoogleTaskListSettingsActivity extends ThemedInjectingAppCompatActi
setContentView(R.layout.activity_google_task_list_settings); setContentView(R.layout.activity_google_task_list_settings);
ButterKnife.bind(this); ButterKnife.bind(this);
gtasksList = getIntent().getParcelableExtra(EXTRA_STORE_DATA); Intent intent = getIntent();
gtasksList = intent.getParcelableExtra(EXTRA_STORE_DATA);
if (gtasksList == null) { if (gtasksList == null) {
isNewList = true; isNewList = true;
gtasksList = new GoogleTaskList(); gtasksList = new GoogleTaskList();
GoogleTaskAccount account = intent.getParcelableExtra(EXTRA_ACCOUNT);
gtasksList.setAccount(account.getAccount());
} }
if (savedInstanceState == null) { if (savedInstanceState == null) {
@ -165,9 +170,9 @@ public class GoogleTaskListSettingsActivity extends ThemedInjectingAppCompatActi
} }
if (isNewList) { if (isNewList) {
newCreateListDialog(newName).show(getSupportFragmentManager(), FRAG_TAG_CREATE_LIST_DIALOG); newCreateListDialog(gtasksList.getAccount(), newName).show(getSupportFragmentManager(), FRAG_TAG_CREATE_LIST_DIALOG);
} else if (nameChanged()) { } else if (nameChanged()) {
newRenameListDialog(gtasksList.getRemoteId(), newName) newRenameListDialog(gtasksList, newName)
.show(getSupportFragmentManager(), FRAG_TAG_RENAME_LIST_DIALOG); .show(getSupportFragmentManager(), FRAG_TAG_RENAME_LIST_DIALOG);
} else { } else {
if (colorChanged()) { if (colorChanged()) {
@ -204,7 +209,7 @@ public class GoogleTaskListSettingsActivity extends ThemedInjectingAppCompatActi
.setPositiveButton( .setPositiveButton(
R.string.delete, R.string.delete,
(dialog, which) -> (dialog, which) ->
newDeleteListDialog(gtasksList.getRemoteId()) newDeleteListDialog(gtasksList)
.show(getSupportFragmentManager(), FRAG_TAG_DELETE_LIST_DIALOG)) .show(getSupportFragmentManager(), FRAG_TAG_DELETE_LIST_DIALOG))
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.show(); .show();

@ -16,7 +16,6 @@ public class Tracking {
TIMER_START(R.string.tracking_category_timer, R.string.tracking_action_start), TIMER_START(R.string.tracking_category_timer, R.string.tracking_action_start),
GTASK_ENABLED(R.string.tracking_category_google_tasks, R.string.tracking_action_on), GTASK_ENABLED(R.string.tracking_category_google_tasks, R.string.tracking_action_on),
GTASK_DISABLED(R.string.tracking_category_google_tasks, R.string.tracking_action_off), GTASK_DISABLED(R.string.tracking_category_google_tasks, R.string.tracking_action_off),
GTASK_LOGOUT(R.string.tracking_category_google_tasks, R.string.tracking_action_clear),
GTASK_NEW_LIST(R.string.tracking_category_google_tasks, R.string.tracking_action_new_list), GTASK_NEW_LIST(R.string.tracking_category_google_tasks, R.string.tracking_action_new_list),
GTASK_RENAME_LIST( GTASK_RENAME_LIST(
R.string.tracking_category_google_tasks, R.string.tracking_action_rename_list), R.string.tracking_category_google_tasks, R.string.tracking_action_rename_list),

@ -7,6 +7,7 @@ import static at.bitfire.dav4android.XmlUtils.NS_WEBDAV;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import at.bitfire.dav4android.BasicDigestAuthHandler; import at.bitfire.dav4android.BasicDigestAuthHandler;
import at.bitfire.dav4android.DavCalendar;
import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.PropertyCollection; import at.bitfire.dav4android.PropertyCollection;
import at.bitfire.dav4android.XmlUtils; import at.bitfire.dav4android.XmlUtils;
@ -158,18 +159,13 @@ class CaldavClient {
Timber.d("%s does not support tasks", member); Timber.d("%s does not support tasks", member);
continue; continue;
} }
Timber.d("Found %s", member);
urls.add(member); urls.add(member);
} }
if (urls.isEmpty()) {
throw new DisplayableException(R.string.caldav_no_supported_calendars);
}
return urls; return urls;
} }
public Completable deleteCollection() { public Completable deleteCollection() {
return Completable.fromAction(() -> return Completable.fromAction(() -> davResource.delete(null))
davResource.delete(null))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }

@ -0,0 +1,100 @@
package org.tasks.data;
import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.Ignore;
import android.arch.persistence.room.PrimaryKey;
import android.os.Parcel;
import android.os.Parcelable;
@Entity(tableName = "google_task_accounts")
public class GoogleTaskAccount implements Parcelable {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "_id")
private transient long id;
@ColumnInfo(name = "account")
private String account;
public GoogleTaskAccount() {}
@Ignore
public GoogleTaskAccount(Parcel source) {
id = source.readLong();
account = source.readString();
}
@Ignore
public GoogleTaskAccount(String account) {
this.account = account;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof GoogleTaskAccount)) {
return false;
}
GoogleTaskAccount that = (GoogleTaskAccount) o;
if (id != that.id) {
return false;
}
return account != null ? account.equals(that.account) : that.account == null;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (account != null ? account.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "GoogleTaskAccount{" + "id=" + id + ", account='" + account + '\'' + '}';
}
public static final Creator<GoogleTaskAccount> CREATOR =
new Creator<GoogleTaskAccount>() {
@Override
public GoogleTaskAccount createFromParcel(Parcel source) {
return new GoogleTaskAccount(source);
}
@Override
public GoogleTaskAccount[] newArray(int size) {
return new GoogleTaskAccount[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(account);
}
}

@ -49,9 +49,6 @@ public interface GoogleTaskDao {
@Query("SELECT * FROM google_tasks WHERE task = :taskId") @Query("SELECT * FROM google_tasks WHERE task = :taskId")
List<GoogleTask> getAllByTaskId(long taskId); List<GoogleTask> getAllByTaskId(long taskId);
@Query("DELETE FROM google_tasks")
void deleteAll();
@Query("SELECT DISTINCT list_id FROM google_tasks WHERE deleted = 0 AND task IN (:tasks)") @Query("SELECT DISTINCT list_id FROM google_tasks WHERE deleted = 0 AND task IN (:tasks)")
List<String> getLists(List<Long> tasks); List<String> getLists(List<Long> tasks);
} }

@ -27,6 +27,9 @@ public class GoogleTaskList implements Parcelable {
@ColumnInfo(name = "_id") @ColumnInfo(name = "_id")
private transient long id; private transient long id;
@ColumnInfo(name = "account")
private String account;
@ColumnInfo(name = "remote_id") @ColumnInfo(name = "remote_id")
private String remoteId; private String remoteId;
@ -50,6 +53,7 @@ public class GoogleTaskList implements Parcelable {
@Ignore @Ignore
public GoogleTaskList(Parcel parcel) { public GoogleTaskList(Parcel parcel) {
id = parcel.readLong(); id = parcel.readLong();
account = parcel.readString();
remoteId = parcel.readString(); remoteId = parcel.readString();
title = parcel.readString(); title = parcel.readString();
remoteOrder = parcel.readInt(); remoteOrder = parcel.readInt();
@ -66,6 +70,14 @@ public class GoogleTaskList implements Parcelable {
this.id = id; this.id = id;
} }
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getRemoteId() { public String getRemoteId() {
return remoteId; return remoteId;
} }
@ -137,6 +149,9 @@ public class GoogleTaskList implements Parcelable {
if (deleted != that.deleted) { if (deleted != that.deleted) {
return false; return false;
} }
if (account != null ? !account.equals(that.account) : that.account != null) {
return false;
}
if (remoteId != null ? !remoteId.equals(that.remoteId) : that.remoteId != null) { if (remoteId != null ? !remoteId.equals(that.remoteId) : that.remoteId != null) {
return false; return false;
} }
@ -149,6 +164,7 @@ public class GoogleTaskList implements Parcelable {
@Override @Override
public int hashCode() { public int hashCode() {
int result = (int) (id ^ (id >>> 32)); int result = (int) (id ^ (id >>> 32));
result = 31 * result + (account != null ? account.hashCode() : 0);
result = 31 * result + (remoteId != null ? remoteId.hashCode() : 0); result = 31 * result + (remoteId != null ? remoteId.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0); result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + remoteOrder; result = 31 * result + remoteOrder;
@ -163,6 +179,9 @@ public class GoogleTaskList implements Parcelable {
return "GoogleTaskList{" return "GoogleTaskList{"
+ "id=" + "id="
+ id + id
+ ", account='"
+ account
+ '\''
+ ", remoteId='" + ", remoteId='"
+ remoteId + remoteId
+ '\'' + '\''
@ -188,6 +207,7 @@ public class GoogleTaskList implements Parcelable {
@Override @Override
public void writeToParcel(Parcel parcel, int i) { public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(id); parcel.writeLong(id);
parcel.writeString(account);
parcel.writeString(remoteId); parcel.writeString(remoteId);
parcel.writeString(title); parcel.writeString(title);
parcel.writeInt(remoteOrder); parcel.writeInt(remoteOrder);

@ -4,29 +4,48 @@ import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Insert; import android.arch.persistence.room.Insert;
import android.arch.persistence.room.OnConflictStrategy; import android.arch.persistence.room.OnConflictStrategy;
import android.arch.persistence.room.Query; import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;
import java.util.List; import java.util.List;
@Dao @Dao
public interface GoogleTaskListDao { public interface GoogleTaskListDao {
@Query("SELECT * FROM google_task_accounts")
List<GoogleTaskAccount> getAccounts();
@Query("SELECT * FROM google_task_accounts WHERE account = :account COLLATE NOCASE LIMIT 1")
GoogleTaskAccount getAccount(String account);
@Query("SELECT * FROM google_task_lists WHERE _id = :id") @Query("SELECT * FROM google_task_lists WHERE _id = :id")
GoogleTaskList getById(long id); GoogleTaskList getById(long id);
@Query("SELECT * FROM google_task_lists WHERE deleted = 0 ORDER BY title ASC") @Query("SELECT * FROM google_task_lists WHERE account = :account AND deleted = 0 ORDER BY title ASC")
List<GoogleTaskList> getActiveLists(); List<GoogleTaskList> getActiveLists(String account);
@Query("SELECT * FROM google_task_lists WHERE remote_id = :remoteId LIMIT 1") @Query("SELECT * FROM google_task_lists WHERE remote_id = :remoteId LIMIT 1")
GoogleTaskList getByRemoteId(String remoteId); GoogleTaskList getByRemoteId(String remoteId);
@Query("SELECT * FROM google_task_lists WHERE remote_id = :remoteId AND IFNULL(account, '') = '' LIMIT 1")
GoogleTaskList findExistingList(String remoteId);
@Query("SELECT * FROM google_task_lists") @Query("SELECT * FROM google_task_lists")
List<GoogleTaskList> getAll(); List<GoogleTaskList> getAll();
@Query("SELECT * FROM google_task_lists WHERE deleted = 0")
List<GoogleTaskList> getAllActiveLists();
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
long insertOrReplace(GoogleTaskList googleTaskList); long insertOrReplace(GoogleTaskList googleTaskList);
@Insert @Insert
void insert(GoogleTaskList googleTaskList); void insert(GoogleTaskList googleTaskList);
@Insert
void insert(GoogleTaskAccount googleTaskAccount);
@Update
void update(GoogleTaskList googleTaskList);
@Query("DELETE FROM google_task_lists WHERE _id = :id") @Query("DELETE FROM google_task_lists WHERE _id = :id")
void deleteById(long id); void deleteById(long id);
} }

@ -192,6 +192,17 @@ public class Migrations {
} }
}; };
private static final Migration MIGRATION_58_59 =
new Migration(58, 59) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL(
"CREATE TABLE IF NOT EXISTS `google_task_accounts` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT)");
database.execSQL(
"ALTER TABLE `google_task_lists` ADD COLUMN `account` TEXT");
}
};
public static final Migration[] MIGRATIONS = public static final Migration[] MIGRATIONS =
new Migration[] { new Migration[] {
MIGRATION_35_36, MIGRATION_35_36,
@ -207,7 +218,8 @@ public class Migrations {
MIGRATION_51_52, MIGRATION_51_52,
MIGRATION_52_53, MIGRATION_52_53,
MIGRATION_53_54, MIGRATION_53_54,
MIGRATION_54_58 MIGRATION_54_58,
MIGRATION_58_59
}; };
private static Migration NOOP(int from, int to) { private static Migration NOOP(int from, int to) {

@ -26,6 +26,7 @@ import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.data.Tag; import org.tasks.data.Tag;
import org.tasks.data.TagData; import org.tasks.data.TagData;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
@ -42,8 +43,8 @@ public class FilterCriteriaProvider {
private final Context context; private final Context context;
private final TagService tagService; private final TagService tagService;
private final GtasksListService gtasksListService;
private final Resources r; private final Resources r;
private final GoogleTaskListDao googleTaskListDao;
private final SyncAdapters syncAdapters; private final SyncAdapters syncAdapters;
@Inject @Inject
@ -51,13 +52,14 @@ public class FilterCriteriaProvider {
@ForApplication Context context, @ForApplication Context context,
TagService tagService, TagService tagService,
GtasksListService gtasksListService, GtasksListService gtasksListService,
SyncAdapters syncAdapters) { SyncAdapters syncAdapters,
GoogleTaskListDao googleTaskListDao) {
this.context = context; this.context = context;
this.tagService = tagService; this.tagService = tagService;
this.gtasksListService = gtasksListService;
this.syncAdapters = syncAdapters; this.syncAdapters = syncAdapters;
r = context.getResources(); r = context.getResources();
this.googleTaskListDao = googleTaskListDao;
} }
public List<CustomFilterCriterion> getAll() { public List<CustomFilterCriterion> getAll() {
@ -186,7 +188,7 @@ public class FilterCriteriaProvider {
} }
private CustomFilterCriterion getGtasksFilterCriteria() { private CustomFilterCriterion getGtasksFilterCriteria() {
List<GoogleTaskList> lists = gtasksListService.getLists(); List<GoogleTaskList> lists = googleTaskListDao.getAllActiveLists();
String[] listNames = new String[lists.size()]; String[] listNames = new String[lists.size()];
String[] listIds = new String[lists.size()]; String[] listIds = new String[lists.size()];

@ -14,6 +14,7 @@ import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.caldav.CaldavFilterExposer; import org.tasks.caldav.CaldavFilterExposer;
import org.tasks.data.CaldavAccount; import org.tasks.data.CaldavAccount;
import org.tasks.data.GoogleTaskAccount;
public class FilterProvider { public class FilterProvider {
@ -56,7 +57,7 @@ public class FilterProvider {
return tagFilterExposer.getFilters(); return tagFilterExposer.getFilters();
} }
public List<Filter> getGoogleTaskFilters() { public List<Pair<GoogleTaskAccount, List<Filter>>> getGoogleTaskFilters() {
return gtasksFilterExposer.getFilters(); return gtasksFilterExposer.getFilters();
} }

@ -3,6 +3,7 @@ package org.tasks.gtasks;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@ -14,21 +15,26 @@ import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.tasks.injection.DialogFragmentComponent; import org.tasks.injection.DialogFragmentComponent;
import org.tasks.injection.ForApplication;
import org.tasks.injection.InjectingDialogFragment; import org.tasks.injection.InjectingDialogFragment;
import timber.log.Timber; import timber.log.Timber;
public class CreateListDialog extends InjectingDialogFragment { public class CreateListDialog extends InjectingDialogFragment {
private static final String EXTRA_ACCOUNT = "extra_account";
private static final String EXTRA_NAME = "extra_name"; private static final String EXTRA_NAME = "extra_name";
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject GtasksInvoker gtasksInvoker; @Inject @ForApplication Context context;
@Inject PlayServices playServices;
private CreateListDialogCallback callback; private CreateListDialogCallback callback;
private ProgressDialog dialog; private ProgressDialog dialog;
private String account;
private String name; private String name;
public static CreateListDialog newCreateListDialog(String name) { public static CreateListDialog newCreateListDialog(String account, String name) {
CreateListDialog dialog = new CreateListDialog(); CreateListDialog dialog = new CreateListDialog();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(EXTRA_ACCOUNT, account);
args.putString(EXTRA_NAME, name); args.putString(EXTRA_NAME, name);
dialog.setArguments(args); dialog.setArguments(args);
return dialog; return dialog;
@ -39,6 +45,7 @@ public class CreateListDialog extends InjectingDialogFragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setRetainInstance(true); setRetainInstance(true);
Bundle arguments = getArguments(); Bundle arguments = getArguments();
account = arguments.getString(EXTRA_ACCOUNT);
name = arguments.getString(EXTRA_NAME); name = arguments.getString(EXTRA_NAME);
dialog = dialogBuilder.newProgressDialog(R.string.creating_new_list); dialog = dialogBuilder.newProgressDialog(R.string.creating_new_list);
execute(); execute();
@ -67,7 +74,7 @@ public class CreateListDialog extends InjectingDialogFragment {
@Override @Override
protected TaskList doInBackground(Void... voids) { protected TaskList doInBackground(Void... voids) {
try { try {
return gtasksInvoker.createGtaskList(name); return new GtasksInvoker(context, playServices, account).createGtaskList(name);
} catch (IOException e) { } catch (IOException e) {
Timber.e(e); Timber.e(e);
return null; return null;

@ -3,6 +3,7 @@ package org.tasks.gtasks;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@ -11,24 +12,27 @@ import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import java.io.IOException; import java.io.IOException;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.GoogleTaskList;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.tasks.injection.DialogFragmentComponent; import org.tasks.injection.DialogFragmentComponent;
import org.tasks.injection.ForApplication;
import org.tasks.injection.InjectingDialogFragment; import org.tasks.injection.InjectingDialogFragment;
import timber.log.Timber; import timber.log.Timber;
public class DeleteListDialog extends InjectingDialogFragment { public class DeleteListDialog extends InjectingDialogFragment {
private static final String EXTRA_ID = "extra_id"; private static final String EXTRA_LIST = "extra_list";
@Inject @ForApplication Context context;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject GtasksInvoker gtasksInvoker; @Inject PlayServices playServices;
private DeleteListDialogCallback callback; private DeleteListDialogCallback callback;
private String id; private GoogleTaskList googleTaskList;
private ProgressDialog dialog; private ProgressDialog dialog;
public static DeleteListDialog newDeleteListDialog(String id) { public static DeleteListDialog newDeleteListDialog(GoogleTaskList googleTaskList) {
DeleteListDialog dialog = new DeleteListDialog(); DeleteListDialog dialog = new DeleteListDialog();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(EXTRA_ID, id); args.putParcelable(EXTRA_LIST, googleTaskList);
dialog.setArguments(args); dialog.setArguments(args);
return dialog; return dialog;
} }
@ -38,7 +42,7 @@ public class DeleteListDialog extends InjectingDialogFragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setRetainInstance(true); setRetainInstance(true);
Bundle arguments = getArguments(); Bundle arguments = getArguments();
id = arguments.getString(EXTRA_ID); googleTaskList = arguments.getParcelable(EXTRA_LIST);
dialog = dialogBuilder.newProgressDialog(R.string.deleting_list); dialog = dialogBuilder.newProgressDialog(R.string.deleting_list);
execute(); execute();
} }
@ -66,7 +70,8 @@ public class DeleteListDialog extends InjectingDialogFragment {
@Override @Override
protected Boolean doInBackground(Void... voids) { protected Boolean doInBackground(Void... voids) {
try { try {
gtasksInvoker.deleteGtaskList(id); new GtasksInvoker(context, playServices, googleTaskList.getAccount())
.deleteGtaskList(googleTaskList.getRemoteId());
return true; return true;
} catch (IOException e) { } catch (IOException e) {
Timber.e(e); Timber.e(e);

@ -7,7 +7,6 @@ import static java.util.Arrays.asList;
import android.accounts.Account; import android.accounts.Account;
import android.content.Context; import android.content.Context;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -18,17 +17,14 @@ public class GoogleAccountManager {
private final PermissionChecker permissionChecker; private final PermissionChecker permissionChecker;
private final android.accounts.AccountManager accountManager; private final android.accounts.AccountManager accountManager;
private final GtasksPreferenceService gtasksPreferenceService;
@Inject @Inject
public GoogleAccountManager( public GoogleAccountManager(
@ForApplication Context context, @ForApplication Context context,
PermissionChecker permissionChecker, PermissionChecker permissionChecker) {
GtasksPreferenceService gtasksPreferenceService) {
this.permissionChecker = permissionChecker; this.permissionChecker = permissionChecker;
accountManager = android.accounts.AccountManager.get(context); accountManager = android.accounts.AccountManager.get(context);
this.gtasksPreferenceService = gtasksPreferenceService;
} }
public List<String> getAccounts() { public List<String> getAccounts() {
@ -45,10 +41,6 @@ public class GoogleAccountManager {
: Collections.emptyList(); : Collections.emptyList();
} }
public Account getSelectedAccount() {
return getAccount(gtasksPreferenceService.getUserName());
}
public Account getAccount(final String name) { public Account getAccount(final String name) {
if (Strings.isNullOrEmpty(name)) { if (Strings.isNullOrEmpty(name)) {
return null; return null;

@ -19,7 +19,6 @@ import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.SyncFlags; import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksListService; import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities; import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksInvoker; import com.todoroo.astrid.gtasks.api.GtasksInvoker;
@ -35,6 +34,7 @@ import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.data.GoogleTask; import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
@ -50,50 +50,47 @@ public class GoogleTaskSynchronizer {
private static final String DEFAULT_LIST = "@default"; // $NON-NLS-1$ private static final String DEFAULT_LIST = "@default"; // $NON-NLS-1$
private final Context context; private final Context context;
private final GtasksPreferenceService gtasksPreferenceService;
private final GoogleTaskListDao googleTaskListDao; private final GoogleTaskListDao googleTaskListDao;
private final GtasksSyncService gtasksSyncService; private final GtasksSyncService gtasksSyncService;
private final GtasksListService gtasksListService; private final GtasksListService gtasksListService;
private final GtasksTaskListUpdater gtasksTaskListUpdater; private final GtasksTaskListUpdater gtasksTaskListUpdater;
private final Preferences preferences; private final Preferences preferences;
private final GtasksInvoker gtasksInvoker;
private final TaskDao taskDao; private final TaskDao taskDao;
private final Tracker tracker; private final Tracker tracker;
private final NotificationManager notificationManager; private final NotificationManager notificationManager;
private final GoogleTaskDao googleTaskDao; private final GoogleTaskDao googleTaskDao;
private final TaskCreator taskCreator; private final TaskCreator taskCreator;
private final DefaultFilterProvider defaultFilterProvider; private final DefaultFilterProvider defaultFilterProvider;
private final PlayServices playServices;
@Inject @Inject
public GoogleTaskSynchronizer( public GoogleTaskSynchronizer(
@ForApplication Context context, @ForApplication Context context,
GtasksPreferenceService gtasksPreferenceService,
GoogleTaskListDao googleTaskListDao, GoogleTaskListDao googleTaskListDao,
GtasksSyncService gtasksSyncService, GtasksSyncService gtasksSyncService,
GtasksListService gtasksListService, GtasksListService gtasksListService,
GtasksTaskListUpdater gtasksTaskListUpdater, GtasksTaskListUpdater gtasksTaskListUpdater,
Preferences preferences, Preferences preferences,
GtasksInvoker gtasksInvoker,
TaskDao taskDao, TaskDao taskDao,
Tracker tracker, Tracker tracker,
NotificationManager notificationManager, NotificationManager notificationManager,
GoogleTaskDao googleTaskDao, GoogleTaskDao googleTaskDao,
TaskCreator taskCreator, TaskCreator taskCreator,
DefaultFilterProvider defaultFilterProvider) { DefaultFilterProvider defaultFilterProvider,
PlayServices playServices) {
this.context = context; this.context = context;
this.gtasksPreferenceService = gtasksPreferenceService;
this.googleTaskListDao = googleTaskListDao; this.googleTaskListDao = googleTaskListDao;
this.gtasksSyncService = gtasksSyncService; this.gtasksSyncService = gtasksSyncService;
this.gtasksListService = gtasksListService; this.gtasksListService = gtasksListService;
this.gtasksTaskListUpdater = gtasksTaskListUpdater; this.gtasksTaskListUpdater = gtasksTaskListUpdater;
this.preferences = preferences; this.preferences = preferences;
this.gtasksInvoker = gtasksInvoker;
this.taskDao = taskDao; this.taskDao = taskDao;
this.tracker = tracker; this.tracker = tracker;
this.notificationManager = notificationManager; this.notificationManager = notificationManager;
this.googleTaskDao = googleTaskDao; this.googleTaskDao = googleTaskDao;
this.taskCreator = taskCreator; this.taskCreator = taskCreator;
this.defaultFilterProvider = defaultFilterProvider; this.defaultFilterProvider = defaultFilterProvider;
this.playServices = playServices;
} }
public static void mergeDates(long remoteDueDate, Task local) { public static void mergeDates(long remoteDueDate, Task local) {
@ -112,23 +109,20 @@ public class GoogleTaskSynchronizer {
} }
public void sync() { public void sync() {
String account = gtasksPreferenceService.getUserName(); for (GoogleTaskAccount account : googleTaskListDao.getAccounts()) {
if (TextUtils.isEmpty(account)) { Timber.d("%s: start sync", account);
return; try {
} synchronize(account);
Timber.d("%s: start sync", account); } catch (UserRecoverableAuthIOException e) {
try { Timber.e(e);
synchronize(); sendNotification(context, e.getIntent());
gtasksPreferenceService.recordSuccessfulSync(); } catch (IOException e) {
} catch (UserRecoverableAuthIOException e) { Timber.e(e);
Timber.e(e); } catch (Exception e) {
sendNotification(context, e.getIntent()); tracker.reportException(e);
} catch (IOException e) { } finally {
Timber.e(e); Timber.d("%s: end sync", account);
} catch (Exception e) { }
tracker.reportException(e);
} finally {
Timber.d("%s: end sync", account);
} }
} }
@ -150,8 +144,9 @@ public class GoogleTaskSynchronizer {
notificationManager.notify(Constants.NOTIFICATION_SYNC_ERROR, builder, true, false, false); notificationManager.notify(Constants.NOTIFICATION_SYNC_ERROR, builder, true, false, false);
} }
private void synchronize() throws IOException { private void synchronize(GoogleTaskAccount account) throws IOException {
pushLocalChanges(); GtasksInvoker gtasksInvoker = new GtasksInvoker(context, playServices, account.getAccount());
pushLocalChanges(gtasksInvoker);
List<TaskList> gtaskLists = new ArrayList<>(); List<TaskList> gtaskLists = new ArrayList<>();
String nextPageToken = null; String nextPageToken = null;
@ -166,7 +161,7 @@ public class GoogleTaskSynchronizer {
} }
nextPageToken = remoteLists.getNextPageToken(); nextPageToken = remoteLists.getNextPageToken();
} while (nextPageToken != null); } while (nextPageToken != null);
gtasksListService.updateLists(gtaskLists); gtasksListService.updateLists(account, gtaskLists);
Filter defaultRemoteList = defaultFilterProvider.getDefaultRemoteList(); Filter defaultRemoteList = defaultFilterProvider.getDefaultRemoteList();
if (defaultRemoteList instanceof GtasksFilter) { if (defaultRemoteList instanceof GtasksFilter) {
GoogleTaskList list = GoogleTaskList list =
@ -176,11 +171,11 @@ public class GoogleTaskSynchronizer {
} }
} }
for (final GoogleTaskList list : gtasksListService.getListsToUpdate(gtaskLists)) { for (final GoogleTaskList list : gtasksListService.getListsToUpdate(gtaskLists)) {
fetchAndApplyRemoteChanges(list); fetchAndApplyRemoteChanges(gtasksInvoker, list);
} }
} }
private void pushLocalChanges() throws UserRecoverableAuthIOException { private void pushLocalChanges(GtasksInvoker gtasksInvoker) throws UserRecoverableAuthIOException {
List<Task> tasks = taskDao.getGoogleTasksToPush(); List<Task> tasks = taskDao.getGoogleTasksToPush();
for (Task task : tasks) { for (Task task : tasks) {
try { try {
@ -193,7 +188,7 @@ public class GoogleTaskSynchronizer {
} }
} }
private void pushTask(Task task, GtasksInvoker invoker) throws IOException { private void pushTask(Task task, GtasksInvoker gtasksInvoker) throws IOException {
for (GoogleTask deleted : googleTaskDao.getDeletedByTaskId(task.getId())) { for (GoogleTask deleted : googleTaskDao.getDeletedByTaskId(task.getId())) {
gtasksInvoker.deleteGtask(deleted.getListId(), deleted.getRemoteId()); gtasksInvoker.deleteGtask(deleted.getListId(), deleted.getRemoteId());
googleTaskDao.delete(deleted); googleTaskDao.delete(deleted);
@ -257,7 +252,7 @@ public class GoogleTaskSynchronizer {
if (!newlyCreated) { if (!newlyCreated) {
try { try {
invoker.updateGtask(listId, remoteModel); gtasksInvoker.updateGtask(listId, remoteModel);
} catch (HttpNotFoundException e) { } catch (HttpNotFoundException e) {
Timber.e(e); Timber.e(e);
googleTaskDao.delete(gtasksMetadata); googleTaskDao.delete(gtasksMetadata);
@ -268,7 +263,7 @@ public class GoogleTaskSynchronizer {
String priorSibling = gtasksSyncService.getRemoteSiblingId(listId, gtasksMetadata); String priorSibling = gtasksSyncService.getRemoteSiblingId(listId, gtasksMetadata);
com.google.api.services.tasks.model.Task created = com.google.api.services.tasks.model.Task created =
invoker.createGtask(listId, remoteModel, parent, priorSibling); gtasksInvoker.createGtask(listId, remoteModel, parent, priorSibling);
if (created != null) { if (created != null) {
// Update the metadata for the newly created task // Update the metadata for the newly created task
@ -290,7 +285,7 @@ public class GoogleTaskSynchronizer {
taskDao.save(task); taskDao.save(task);
} }
private synchronized void fetchAndApplyRemoteChanges(GoogleTaskList list) private synchronized void fetchAndApplyRemoteChanges(GtasksInvoker gtasksInvoker, GoogleTaskList list)
throws UserRecoverableAuthIOException { throws UserRecoverableAuthIOException {
String listId = list.getRemoteId(); String listId = list.getRemoteId();
long lastSyncDate = list.getLastSync(); long lastSyncDate = list.getLastSync();

@ -1,20 +1,19 @@
package org.tasks.gtasks; package org.tasks.gtasks;
import android.accounts.Account;
import android.app.Activity; import android.app.Activity;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking; import org.tasks.analytics.Tracking;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
public class GtaskSyncAdapterHelper { public class GtaskSyncAdapterHelper {
private static final String AUTHORITY = "org.tasks";
private final GoogleAccountManager accountManager; private final GoogleAccountManager accountManager;
private final Preferences preferences; private final Preferences preferences;
private final PlayServices playServices; private final PlayServices playServices;
private final GoogleTaskListDao googleTaskListDao;
private final Tracker tracker; private final Tracker tracker;
@Inject @Inject
@ -22,25 +21,25 @@ public class GtaskSyncAdapterHelper {
GoogleAccountManager accountManager, GoogleAccountManager accountManager,
Preferences preferences, Preferences preferences,
PlayServices playServices, PlayServices playServices,
GoogleTaskListDao googleTaskListDao,
Tracker tracker) { Tracker tracker) {
this.accountManager = accountManager; this.accountManager = accountManager;
this.preferences = preferences; this.preferences = preferences;
this.playServices = playServices; this.playServices = playServices;
this.googleTaskListDao = googleTaskListDao;
this.tracker = tracker; this.tracker = tracker;
} }
public boolean isEnabled() { public boolean isEnabled() {
return preferences.getBoolean(R.string.sync_gtasks, false) return hasAccounts() && playServices.isPlayServicesAvailable();
&& playServices.isPlayServicesAvailable()
&& getAccount() != null;
} }
private Account getAccount() { private boolean hasAccounts() {
return accountManager.getSelectedAccount(); return !googleTaskListDao.getAccounts().isEmpty();
} }
public void checkPlayServices(Activity activity) { public void checkPlayServices(Activity activity) {
if (preferences.getBoolean(R.string.sync_gtasks, false) if (hasAccounts()
&& !playServices.refreshAndCheck() && !playServices.refreshAndCheck()
&& !preferences.getBoolean(R.string.warned_play_services, false)) { && !preferences.getBoolean(R.string.warned_play_services, false)) {
preferences.setBoolean(R.string.warned_play_services, true); preferences.setBoolean(R.string.warned_play_services, true);

@ -3,6 +3,7 @@ package org.tasks.gtasks;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@ -12,26 +13,29 @@ import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import java.io.IOException; import java.io.IOException;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.GoogleTaskList;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.tasks.injection.DialogFragmentComponent; import org.tasks.injection.DialogFragmentComponent;
import org.tasks.injection.ForApplication;
import org.tasks.injection.InjectingDialogFragment; import org.tasks.injection.InjectingDialogFragment;
import timber.log.Timber; import timber.log.Timber;
public class RenameListDialog extends InjectingDialogFragment { public class RenameListDialog extends InjectingDialogFragment {
private static final String EXTRA_NAME = "extra_name"; private static final String EXTRA_NAME = "extra_name";
private static final String EXTRA_ID = "extra_id"; private static final String EXTRA_LIST = "extra_list";
@Inject @ForApplication Context context;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject GtasksInvoker gtasksInvoker; @Inject PlayServices playServices;
private RenameListDialogCallback callback; private RenameListDialogCallback callback;
private ProgressDialog dialog; private ProgressDialog dialog;
private String id; private GoogleTaskList googleTaskList;
private String name; private String name;
public static RenameListDialog newRenameListDialog(String id, String name) { public static RenameListDialog newRenameListDialog(GoogleTaskList googleTaskList, String name) {
RenameListDialog dialog = new RenameListDialog(); RenameListDialog dialog = new RenameListDialog();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(EXTRA_ID, id); args.putParcelable(EXTRA_LIST, googleTaskList);
args.putString(EXTRA_NAME, name); args.putString(EXTRA_NAME, name);
dialog.setArguments(args); dialog.setArguments(args);
return dialog; return dialog;
@ -42,7 +46,7 @@ public class RenameListDialog extends InjectingDialogFragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setRetainInstance(true); setRetainInstance(true);
Bundle arguments = getArguments(); Bundle arguments = getArguments();
id = arguments.getString(EXTRA_ID); googleTaskList = arguments.getParcelable(EXTRA_LIST);
name = arguments.getString(EXTRA_NAME); name = arguments.getString(EXTRA_NAME);
dialog = dialogBuilder.newProgressDialog(R.string.renaming_list); dialog = dialogBuilder.newProgressDialog(R.string.renaming_list);
execute(); execute();
@ -71,7 +75,8 @@ public class RenameListDialog extends InjectingDialogFragment {
@Override @Override
protected TaskList doInBackground(Void... voids) { protected TaskList doInBackground(Void... voids) {
try { try {
return gtasksInvoker.renameGtaskList(id, name); return new GtasksInvoker(context, playServices, googleTaskList.getAccount())
.renameGtaskList(googleTaskList.getRemoteId(), name);
} catch (IOException e) { } catch (IOException e) {
Timber.e(e); Timber.e(e);
return null; return null;

@ -12,6 +12,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.CaldavDao; import org.tasks.data.CaldavDao;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import timber.log.Timber; import timber.log.Timber;
@ -30,15 +31,18 @@ public class JobManager {
private final com.evernote.android.job.JobManager jobManager; private final com.evernote.android.job.JobManager jobManager;
private final Preferences preferences; private final Preferences preferences;
private final CaldavDao caldavDao; private final CaldavDao caldavDao;
private final GoogleTaskListDao googleTaskListDao;
@Inject @Inject
public JobManager( public JobManager(
com.evernote.android.job.JobManager jobManager, com.evernote.android.job.JobManager jobManager,
Preferences preferences, Preferences preferences,
CaldavDao caldavDao) { CaldavDao caldavDao,
GoogleTaskListDao googleTaskListDao) {
this.jobManager = jobManager; this.jobManager = jobManager;
this.preferences = preferences; this.preferences = preferences;
this.caldavDao = caldavDao; this.caldavDao = caldavDao;
this.googleTaskListDao = googleTaskListDao;
} }
public void scheduleNotification(long time) { public void scheduleNotification(long time) {
@ -81,8 +85,7 @@ public class JobManager {
: forceBackgroundEnabled; : forceBackgroundEnabled;
boolean accountsPresent = boolean accountsPresent =
forceAccountPresent == null forceAccountPresent == null
? (preferences.getBoolean(R.string.sync_gtasks, false) ? (googleTaskListDao.getAccounts().size() > 0 || caldavDao.getAccounts().size() > 0)
|| caldavDao.getAccounts().size() > 0)
: forceAccountPresent; : forceAccountPresent;
boolean onlyOnWifi = boolean onlyOnWifi =
forceOnlyOnUnmetered == null forceOnlyOnUnmetered == null

@ -9,12 +9,9 @@ import static org.tasks.PermissionUtil.verifyPermissions;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity; import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
@ -25,7 +22,9 @@ import org.tasks.billing.PurchaseActivity;
import org.tasks.caldav.CaldavAccountSettingsActivity; import org.tasks.caldav.CaldavAccountSettingsActivity;
import org.tasks.data.CaldavAccount; import org.tasks.data.CaldavAccount;
import org.tasks.data.CaldavDao; import org.tasks.data.CaldavDao;
import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskDao; import org.tasks.data.GoogleTaskDao;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.tasks.gtasks.GoogleAccountManager; import org.tasks.gtasks.GoogleAccountManager;
import org.tasks.gtasks.GtaskSyncAdapterHelper; import org.tasks.gtasks.GtaskSyncAdapterHelper;
@ -37,14 +36,17 @@ import org.tasks.preferences.ActivityPermissionRequestor;
import org.tasks.preferences.PermissionChecker; import org.tasks.preferences.PermissionChecker;
import org.tasks.preferences.PermissionRequestor; import org.tasks.preferences.PermissionRequestor;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import timber.log.Timber;
public class SynchronizationPreferences extends InjectingPreferenceActivity { public class SynchronizationPreferences extends InjectingPreferenceActivity {
private static final String KEY_ADD_GOOGLE_TASKS = "add_google_tasks";
private static final String KEY_ADD_CALDAV = "add_caldav";
private static final int REQUEST_LOGIN = 0; private static final int REQUEST_LOGIN = 0;
private static final int REQUEST_CALDAV_SETTINGS = 101; private static final int REQUEST_CALDAV_SETTINGS = 101;
private static final int REQUEST_CALDAV_SUBSCRIBE = 102; private static final int REQUEST_CALDAV_SUBSCRIBE = 102;
private static final int REQUEST_GOOGLE_TASKS_SUBSCRIBE = 103;
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject ActivityPermissionRequestor permissionRequestor; @Inject ActivityPermissionRequestor permissionRequestor;
@Inject PermissionChecker permissionChecker; @Inject PermissionChecker permissionChecker;
@Inject Tracker tracker; @Inject Tracker tracker;
@ -53,6 +55,7 @@ public class SynchronizationPreferences extends InjectingPreferenceActivity {
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject SyncAdapters syncAdapters; @Inject SyncAdapters syncAdapters;
@Inject GoogleTaskDao googleTaskDao; @Inject GoogleTaskDao googleTaskDao;
@Inject GoogleTaskListDao googleTaskListDao;
@Inject GoogleAccountManager googleAccountManager; @Inject GoogleAccountManager googleAccountManager;
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject JobManager jobManager; @Inject JobManager jobManager;
@ -65,49 +68,52 @@ public class SynchronizationPreferences extends InjectingPreferenceActivity {
addPreferencesFromResource(R.xml.preferences_synchronization); addPreferencesFromResource(R.xml.preferences_synchronization);
PreferenceCategory caldavPreferences = (PreferenceCategory) findPreference(getString(R.string.CalDAV)); PreferenceCategory caldavPreferences =
(PreferenceCategory) findPreference(getString(R.string.CalDAV));
for (CaldavAccount caldavAccount : caldavDao.getAccounts()) { for (CaldavAccount caldavAccount : caldavDao.getAccounts()) {
Preference accountPreferences = new Preference(this); Preference accountPreferences = new Preference(this);
accountPreferences.setTitle(caldavAccount.getName()); accountPreferences.setTitle(caldavAccount.getName());
accountPreferences.setSummary(caldavAccount.getUrl()); accountPreferences.setSummary(caldavAccount.getUrl());
accountPreferences.setOnPreferenceClickListener(preference -> { accountPreferences.setOnPreferenceClickListener(
Intent intent = new Intent(this, CaldavAccountSettingsActivity.class); preference -> {
intent.putExtra(CaldavAccountSettingsActivity.EXTRA_CALDAV_DATA, caldavAccount); Intent intent = new Intent(this, CaldavAccountSettingsActivity.class);
startActivityForResult(intent, REQUEST_CALDAV_SETTINGS); intent.putExtra(CaldavAccountSettingsActivity.EXTRA_CALDAV_DATA, caldavAccount);
return false; startActivityForResult(intent, REQUEST_CALDAV_SETTINGS);
}); return false;
});
caldavPreferences.addPreference(accountPreferences); caldavPreferences.addPreference(accountPreferences);
} }
Preference addCaldavAccount = new Preference(this); Preference addCaldavAccount = new Preference(this);
addCaldavAccount.setKey(getString(R.string.add_account)); addCaldavAccount.setKey(KEY_ADD_CALDAV);
addCaldavAccount.setTitle(R.string.add_account); addCaldavAccount.setTitle(R.string.add_account);
caldavPreferences.addPreference(addCaldavAccount); caldavPreferences.addPreference(addCaldavAccount);
final CheckBoxPreference gtaskPreference = PreferenceCategory googleTaskPreferences =
(CheckBoxPreference) findPreference(getString(R.string.sync_gtasks)); (PreferenceCategory) findPreference(getString(R.string.gtasks_GPr_header));
gtaskPreference.setChecked(syncAdapters.isGoogleTaskSyncEnabled()); for (GoogleTaskAccount googleTaskAccount : googleTaskListDao.getAccounts()) {
gtaskPreference.setOnPreferenceChangeListener( String account = googleTaskAccount.getAccount();
(preference, newValue) -> { if (googleAccountManager.getAccount(account) == null) {
if ((boolean) newValue) { Timber.e("Can't access %s", account);
continue;
}
Preference accountPreferences = new Preference(this);
accountPreferences.setTitle(account);
accountPreferences.setOnPreferenceClickListener(
preference -> {
if (!playServices.refreshAndCheck()) { if (!playServices.refreshAndCheck()) {
playServices.resolve(SynchronizationPreferences.this); playServices.resolve(SynchronizationPreferences.this);
} else if (permissionRequestor.requestAccountPermissions()) { } else if (permissionRequestor.requestAccountPermissions()) {
requestLogin(); requestLogin();
} }
return false; return false;
} else { });
jobManager.updateBackgroundSync(); googleTaskPreferences.addPreference(accountPreferences);
tracker.reportEvent(Tracking.Events.GTASK_DISABLED);
return true;
}
});
if (gtasksPreferenceService.getLastSyncDate() > 0) {
gtaskPreference.setSummary(
getString(
R.string.sync_status_success,
DateUtilities.getDateStringWithTime(
SynchronizationPreferences.this, gtasksPreferenceService.getLastSyncDate())));
} }
Preference addGoogleTaskAccount = new Preference(this);
addGoogleTaskAccount.setKey(KEY_ADD_GOOGLE_TASKS);
addGoogleTaskAccount.setTitle(R.string.add_account);
googleTaskPreferences.addPreference(addGoogleTaskAccount);
findPreference(getString(R.string.p_background_sync_unmetered_only)) findPreference(getString(R.string.p_background_sync_unmetered_only))
.setOnPreferenceChangeListener( .setOnPreferenceChangeListener(
(preference, o) -> { (preference, o) -> {
@ -120,24 +126,6 @@ public class SynchronizationPreferences extends InjectingPreferenceActivity {
jobManager.updateBackgroundSync(null, (Boolean) o, null); jobManager.updateBackgroundSync(null, (Boolean) o, null);
return true; return true;
}); });
findPreference(getString(R.string.sync_SPr_forget_key))
.setOnPreferenceClickListener(
preference -> {
dialogBuilder
.newMessageDialog(R.string.sync_forget_confirm)
.setPositiveButton(
android.R.string.ok,
(dialog, which) -> {
gtasksPreferenceService.clearLastSyncDate();
gtasksPreferenceService.setUserName(null);
googleTaskDao.deleteAll();
tracker.reportEvent(Tracking.Events.GTASK_LOGOUT);
gtaskPreference.setChecked(false);
})
.setNegativeButton(android.R.string.cancel, null)
.show();
return true;
});
} }
private void requestLogin() { private void requestLogin() {
@ -149,28 +137,55 @@ public class SynchronizationPreferences extends InjectingPreferenceActivity {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
Preference addCaldavAccount = findPreference(R.string.add_account); Preference addCaldavAccount = findPreference(KEY_ADD_CALDAV);
Preference addGoogleTasks = findPreference(KEY_ADD_GOOGLE_TASKS);
if (inventory.hasPro()) { if (inventory.hasPro()) {
addCaldavAccount.setSummary(null); addCaldavAccount.setSummary(null);
addCaldavAccount.setOnPreferenceClickListener(preference -> { addGoogleTasks.setSummary(null);
addCaldavAccount(); addCaldavAccount.setOnPreferenceClickListener(
return false; preference -> {
}); addCaldavAccount();
return false;
});
addGoogleTasks.setOnPreferenceClickListener(
preference -> {
requestLogin();
return false;
});
} else { } else {
addCaldavAccount.setSummary(R.string.requires_pro_subscription); addCaldavAccount.setSummary(R.string.requires_pro_subscription);
addCaldavAccount.setOnPreferenceClickListener(preference -> { addCaldavAccount.setOnPreferenceClickListener(
startActivityForResult(new Intent(this, PurchaseActivity.class), REQUEST_CALDAV_SUBSCRIBE); preference -> {
return false; startActivityForResult(
}); new Intent(this, PurchaseActivity.class), REQUEST_CALDAV_SUBSCRIBE);
return false;
});
if (googleTaskListDao.getAccounts().isEmpty()) {
addGoogleTasks.setSummary(null);
addGoogleTasks.setOnPreferenceClickListener(
preference -> {
requestLogin();
return false;
});
} else {
addGoogleTasks.setSummary(R.string.requires_pro_subscription);
addGoogleTasks.setOnPreferenceClickListener(
preference -> {
startActivityForResult(
new Intent(this, PurchaseActivity.class), REQUEST_GOOGLE_TASKS_SUBSCRIBE);
return false;
});
}
} }
if (!permissionChecker.canAccessAccounts()) { if (!permissionChecker.canAccessAccounts()) {
((CheckBoxPreference) findPreference(getString(R.string.sync_gtasks))).setChecked(false); // TODO: clear google task preference category
} }
} }
private void addCaldavAccount() { private void addCaldavAccount() {
startActivityForResult(new Intent(this, CaldavAccountSettingsActivity.class), REQUEST_CALDAV_SETTINGS); startActivityForResult(
new Intent(this, CaldavAccountSettingsActivity.class), REQUEST_CALDAV_SETTINGS);
} }
@Override @Override
@ -180,24 +195,32 @@ public class SynchronizationPreferences extends InjectingPreferenceActivity {
if (enabled) { if (enabled) {
tracker.reportEvent(Tracking.Events.GTASK_ENABLED); tracker.reportEvent(Tracking.Events.GTASK_ENABLED);
jobManager.updateBackgroundSync(); jobManager.updateBackgroundSync();
restart();
} }
((CheckBoxPreference) findPreference(getString(R.string.sync_gtasks))).setChecked(enabled);
} else if (requestCode == REQUEST_CALDAV_SETTINGS) { } else if (requestCode == REQUEST_CALDAV_SETTINGS) {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
jobManager.updateBackgroundSync(); jobManager.updateBackgroundSync();
Intent intent = getIntent(); restart();
finish();
startActivity(intent);
} }
} else if (requestCode == REQUEST_CALDAV_SUBSCRIBE) { } else if (requestCode == REQUEST_CALDAV_SUBSCRIBE) {
if (inventory.hasPro()) { if (inventory.hasPro()) {
addCaldavAccount(); addCaldavAccount();
} }
} else if (requestCode == REQUEST_GOOGLE_TASKS_SUBSCRIBE) {
if (inventory.hasPro()) {
requestLogin();
}
} else { } else {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
} }
private void restart() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
@Override @Override
public void onRequestPermissionsResult( public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

@ -129,10 +129,7 @@
<string name="tmrw">غدا</string> <string name="tmrw">غدا</string>
<string name="yest">أمس</string> <string name="yest">أمس</string>
<string name="DLG_wait">إنتظر من فضلك...</string> <string name="DLG_wait">إنتظر من فضلك...</string>
<string name="sync_status_success">آخر تحيين:\n%s</string>
<string name="sync_SPr_interval_title">تحيين في الخلفية</string> <string name="sync_SPr_interval_title">تحيين في الخلفية</string>
<string name="sync_SPr_forget">خروج</string>
<string name="sync_forget_confirm">تسجيل الخروج/ مسح معلومات المزامنه؟</string>
<string name="widget_show_due_date">أظهر تواريخ الإستحقاق</string> <string name="widget_show_due_date">أظهر تواريخ الإستحقاق</string>
<string name="widget_show_checkboxes">إظهار مربعات التعليم</string> <string name="widget_show_checkboxes">إظهار مربعات التعليم</string>
<string name="widget_show_header">إظهار الهايدر</string> <string name="widget_show_header">إظهار الهايدر</string>

@ -300,11 +300,7 @@
<string name="tmrw">Утре</string> <string name="tmrw">Утре</string>
<string name="yest">Вчера</string> <string name="yest">Вчера</string>
<string name="DLG_wait">Моля, изчакайте...</string> <string name="DLG_wait">Моля, изчакайте...</string>
<string name="sync_status_success">Последна синхронизация:\n%s</string>
<string name="sync_SPr_interval_title">Синхронзиране във фонов режим</string> <string name="sync_SPr_interval_title">Синхронзиране във фонов режим</string>
<string name="sync_SPr_forget">Излизане</string>
<string name="sync_SPr_forget_description">Изчистване на всички данни от синхронзация</string>
<string name="sync_forget_confirm">Изход/изчистване на данните от синхронизация?</string>
<string name="widget_show_due_date">Покажи крайните дати</string> <string name="widget_show_due_date">Покажи крайните дати</string>
<string name="widget_show_checkboxes">Покажи отметки</string> <string name="widget_show_checkboxes">Покажи отметки</string>
<string name="widget_show_header">Покажи хедър</string> <string name="widget_show_header">Покажи хедър</string>

@ -110,11 +110,7 @@
<string name="tomorrow">Demà</string> <string name="tomorrow">Demà</string>
<string name="yesterday">Ahir</string> <string name="yesterday">Ahir</string>
<string name="DLG_wait">Si us plau, espera...</string> <string name="DLG_wait">Si us plau, espera...</string>
<string name="sync_status_success">Última sincronització:\n%s</string>
<string name="sync_SPr_interval_title">Sincronitzar en segon pla</string> <string name="sync_SPr_interval_title">Sincronitzar en segon pla</string>
<string name="sync_SPr_forget">Surt</string>
<string name="sync_SPr_forget_description">Esborra tota la informació de sincronització</string>
<string name="sync_forget_confirm">Tancar sessió / esborra la informació de sincronització?</string>
<string name="source_code">Codi font</string> <string name="source_code">Codi font</string>
<string name="translations">Contribuir traduccions</string> <string name="translations">Contribuir traduccions</string>
<string name="contact_developer">Contacta amb el desenvolupador</string> <string name="contact_developer">Contacta amb el desenvolupador</string>

@ -207,11 +207,7 @@
<string name="tmrw">Zítra</string> <string name="tmrw">Zítra</string>
<string name="yest">Včera</string> <string name="yest">Včera</string>
<string name="DLG_wait">Čekejte prosím...</string> <string name="DLG_wait">Čekejte prosím...</string>
<string name="sync_status_success">Poslední synchronizace:\n%s</string>
<string name="sync_SPr_interval_title">Synchronizace na pozadí</string> <string name="sync_SPr_interval_title">Synchronizace na pozadí</string>
<string name="sync_SPr_forget">Odhlásit se</string>
<string name="sync_SPr_forget_description">Smazat všechny synchronizační data</string>
<string name="sync_forget_confirm">Odhlásit se / vymazat synchronizační data?</string>
<string name="widget_show_due_date">Ukázat data splnění</string> <string name="widget_show_due_date">Ukázat data splnění</string>
<string name="widget_show_checkboxes">Ukázat zaškrtávací políčka</string> <string name="widget_show_checkboxes">Ukázat zaškrtávací políčka</string>
<string name="widget_show_header">Zobraz záhlaví</string> <string name="widget_show_header">Zobraz záhlaví</string>

@ -93,7 +93,5 @@
<string name="yesterday">I går</string> <string name="yesterday">I går</string>
<string name="DLG_wait">Vent venligst...</string> <string name="DLG_wait">Vent venligst...</string>
<string name="sync_SPr_interval_title">Baggrunds Synk</string> <string name="sync_SPr_interval_title">Baggrunds Synk</string>
<string name="sync_SPr_forget">Log af</string>
<string name="sync_SPr_forget_description">Sletter al synkroniserings data</string>
<string name="source_code">Kildekode</string> <string name="source_code">Kildekode</string>
</resources> </resources>

@ -293,11 +293,7 @@
<string name="tmrw">Morg.</string> <string name="tmrw">Morg.</string>
<string name="yest">Gest.</string> <string name="yest">Gest.</string>
<string name="DLG_wait">Bitte warten...</string> <string name="DLG_wait">Bitte warten...</string>
<string name="sync_status_success">Letzte Synchronisierung:\n%s</string>
<string name="sync_SPr_interval_title">Hintergrund-Synchronisierung</string> <string name="sync_SPr_interval_title">Hintergrund-Synchronisierung</string>
<string name="sync_SPr_forget">Abmelden</string>
<string name="sync_SPr_forget_description">Alle Synchronisationsdaten löschen</string>
<string name="sync_forget_confirm">Ausloggen / Synchronisierte Daten löschen?</string>
<string name="widget_show_due_date">Zeige Fälligkeitsdaten</string> <string name="widget_show_due_date">Zeige Fälligkeitsdaten</string>
<string name="widget_show_checkboxes">Checkboxen anzeigen</string> <string name="widget_show_checkboxes">Checkboxen anzeigen</string>
<string name="widget_show_header">Kopf anzeigen</string> <string name="widget_show_header">Kopf anzeigen</string>

@ -181,8 +181,6 @@
<string name="tmrw">Αύριο</string> <string name="tmrw">Αύριο</string>
<string name="yest">Χθές</string> <string name="yest">Χθές</string>
<string name="DLG_wait">Παρακαλώ περιμένετε...</string> <string name="DLG_wait">Παρακαλώ περιμένετε...</string>
<string name="sync_status_success">Τελευταίος συγχρονισμός:\n%s</string>
<string name="sync_SPr_interval_title">Συγχρονισμός παρασκηνίου</string> <string name="sync_SPr_interval_title">Συγχρονισμός παρασκηνίου</string>
<string name="sync_SPr_forget">Αποσύνδεση</string>
<string name="TLA_menu_donate">Δωρίστε</string> <string name="TLA_menu_donate">Δωρίστε</string>
</resources> </resources>

@ -296,11 +296,7 @@
<string name="tmrw">Mñna</string> <string name="tmrw">Mñna</string>
<string name="yest">Ayer</string> <string name="yest">Ayer</string>
<string name="DLG_wait">Por favor, espere...</string> <string name="DLG_wait">Por favor, espere...</string>
<string name="sync_status_success">Ultima sincronización:\n%s</string>
<string name="sync_SPr_interval_title">Sincronización en segundo plano</string> <string name="sync_SPr_interval_title">Sincronización en segundo plano</string>
<string name="sync_SPr_forget">Cerrar sesión</string>
<string name="sync_SPr_forget_description">Limpia todos los datos de la sincronización</string>
<string name="sync_forget_confirm">Cerrar sesión/Limpiar datos de sincronización?</string>
<string name="widget_show_due_date">Mostrar fechas de vencimiento</string> <string name="widget_show_due_date">Mostrar fechas de vencimiento</string>
<string name="widget_show_checkboxes">Mostrar casillas de verificación</string> <string name="widget_show_checkboxes">Mostrar casillas de verificación</string>
<string name="widget_show_header">Mostrar encabezado</string> <string name="widget_show_header">Mostrar encabezado</string>

@ -194,7 +194,6 @@
<string name="yest">دیروز</string> <string name="yest">دیروز</string>
<string name="DLG_wait">لطفا منتظر بمانید...</string> <string name="DLG_wait">لطفا منتظر بمانید...</string>
<string name="sync_SPr_interval_title">سینک پیش زمینه</string> <string name="sync_SPr_interval_title">سینک پیش زمینه</string>
<string name="sync_SPr_forget">خروج از حساب کاربری</string>
<string name="widget_show_due_date">نمایش تاریخ موعود</string> <string name="widget_show_due_date">نمایش تاریخ موعود</string>
<string name="widget_show_checkboxes">نمایش محل تیک</string> <string name="widget_show_checkboxes">نمایش محل تیک</string>
<string name="widget_show_header">نمایش سربرگ</string> <string name="widget_show_header">نمایش سربرگ</string>

@ -301,11 +301,7 @@
<string name="tmrw">Huominen</string> <string name="tmrw">Huominen</string>
<string name="yest">Eilinen</string> <string name="yest">Eilinen</string>
<string name="DLG_wait">Ole hyvä ja odota...</string> <string name="DLG_wait">Ole hyvä ja odota...</string>
<string name="sync_status_success">Viimeisin synkronointi:\n%s</string>
<string name="sync_SPr_interval_title">Tausta synkronointi</string> <string name="sync_SPr_interval_title">Tausta synkronointi</string>
<string name="sync_SPr_forget">Kirjaudu ulos</string>
<string name="sync_SPr_forget_description">Tyhjennä kaikki synkronointidata</string>
<string name="sync_forget_confirm">Kirjaudu ulos/tyhjennä synkronointidata</string>
<string name="widget_show_due_date">Näytä määräpäivät</string> <string name="widget_show_due_date">Näytä määräpäivät</string>
<string name="widget_show_checkboxes">Näytä valintaruudut</string> <string name="widget_show_checkboxes">Näytä valintaruudut</string>
<string name="widget_show_header">Näytä otsikot</string> <string name="widget_show_header">Näytä otsikot</string>

@ -286,11 +286,7 @@
<string name="tmrw">Demain</string> <string name="tmrw">Demain</string>
<string name="yest">Hier</string> <string name="yest">Hier</string>
<string name="DLG_wait">Veuillez patienter...</string> <string name="DLG_wait">Veuillez patienter...</string>
<string name="sync_status_success">Dernière synchro. :\n%s</string>
<string name="sync_SPr_interval_title">Synchro. en arrière-plan</string> <string name="sync_SPr_interval_title">Synchro. en arrière-plan</string>
<string name="sync_SPr_forget">Se déconnecter</string>
<string name="sync_SPr_forget_description">Supprimer définitivement toutes les données de synchronisation</string>
<string name="sync_forget_confirm">Se déconnecter/supprimer définitivement toutes les données de synchronisation ?</string>
<string name="widget_show_due_date">Montrer les dates échéantes</string> <string name="widget_show_due_date">Montrer les dates échéantes</string>
<string name="widget_show_checkboxes">Montrer les cases à cocher</string> <string name="widget_show_checkboxes">Montrer les cases à cocher</string>
<string name="widget_show_header">Montrer l\'en-tête</string> <string name="widget_show_header">Montrer l\'en-tête</string>

@ -223,11 +223,7 @@
<string name="tmrw">Mñna</string> <string name="tmrw">Mñna</string>
<string name="yest">Ayer</string> <string name="yest">Ayer</string>
<string name="DLG_wait">Por favor, espere...</string> <string name="DLG_wait">Por favor, espere...</string>
<string name="sync_status_success">Ultima sincronización:\n%s</string>
<string name="sync_SPr_interval_title">Sincronización en segundo plano</string> <string name="sync_SPr_interval_title">Sincronización en segundo plano</string>
<string name="sync_SPr_forget">Cerrar sesión</string>
<string name="sync_SPr_forget_description">Limpia todos los datos de la sincronización</string>
<string name="sync_forget_confirm">Cerrar sesión/Limpiar datos de sincronización?</string>
<string name="widget_show_due_date">Mostrar fechas de vencimiento</string> <string name="widget_show_due_date">Mostrar fechas de vencimiento</string>
<string name="widget_show_checkboxes">Mostrar casillas de verificación</string> <string name="widget_show_checkboxes">Mostrar casillas de verificación</string>
<string name="widget_show_header">Mostrar encabezado</string> <string name="widget_show_header">Mostrar encabezado</string>

@ -300,11 +300,7 @@
<string name="tmrw">Holn</string> <string name="tmrw">Holn</string>
<string name="yest">Tegn</string> <string name="yest">Tegn</string>
<string name="DLG_wait">Kérlek, várj...</string> <string name="DLG_wait">Kérlek, várj...</string>
<string name="sync_status_success">Utolsó szinkronizáció:\n%s</string>
<string name="sync_SPr_interval_title">Szinkronizáció a háttérben</string> <string name="sync_SPr_interval_title">Szinkronizáció a háttérben</string>
<string name="sync_SPr_forget">Kijelentkezés</string>
<string name="sync_SPr_forget_description">Az összes szinkronizációs adat törlése</string>
<string name="sync_forget_confirm">Kijelentkezés és szinkronizációs adatok törlése?</string>
<string name="widget_show_due_date">Határidők megjelenítése</string> <string name="widget_show_due_date">Határidők megjelenítése</string>
<string name="widget_show_checkboxes">Jelölőnégyzetek megjelenítése</string> <string name="widget_show_checkboxes">Jelölőnégyzetek megjelenítése</string>
<string name="widget_show_header">Fejléc megjelenítése</string> <string name="widget_show_header">Fejléc megjelenítése</string>

@ -297,11 +297,7 @@
<string name="tmrw">Domani</string> <string name="tmrw">Domani</string>
<string name="yest">Ieri</string> <string name="yest">Ieri</string>
<string name="DLG_wait">Attendi...</string> <string name="DLG_wait">Attendi...</string>
<string name="sync_status_success">Ultima Sincronizzazione:\n%s</string>
<string name="sync_SPr_interval_title">Sincronizzazione eseguita in background</string> <string name="sync_SPr_interval_title">Sincronizzazione eseguita in background</string>
<string name="sync_SPr_forget">Esci</string>
<string name="sync_SPr_forget_description">Cancella tutti i dati di sincronizzazione</string>
<string name="sync_forget_confirm">Esci / cancella i file di sincronizzazione?</string>
<string name="widget_show_due_date">Mostra scadenze</string> <string name="widget_show_due_date">Mostra scadenze</string>
<string name="widget_show_checkboxes">Mostra caselle selezione</string> <string name="widget_show_checkboxes">Mostra caselle selezione</string>
<string name="widget_show_header">Mostra intestazione</string> <string name="widget_show_header">Mostra intestazione</string>

@ -248,11 +248,7 @@
<string name="tmrw">מחר</string> <string name="tmrw">מחר</string>
<string name="yest">אתמול</string> <string name="yest">אתמול</string>
<string name="DLG_wait">אנא המתן...</string> <string name="DLG_wait">אנא המתן...</string>
<string name="sync_status_success">סנכרון אחרון:\n%s</string>
<string name="sync_SPr_interval_title">סנכרון ברקע</string> <string name="sync_SPr_interval_title">סנכרון ברקע</string>
<string name="sync_SPr_forget">התנתק</string>
<string name="sync_SPr_forget_description">מסיר את כל נתוני הסנכרון</string>
<string name="sync_forget_confirm">צא מהחשבון \\ הסר נתוני סנכרון?</string>
<string name="widget_show_due_date">הצג תאריכי יעד</string> <string name="widget_show_due_date">הצג תאריכי יעד</string>
<string name="widget_show_checkboxes">הצג תיבות סימון</string> <string name="widget_show_checkboxes">הצג תיבות סימון</string>
<string name="widget_show_header">הצג כותרת</string> <string name="widget_show_header">הצג כותרת</string>

@ -298,11 +298,7 @@
<string name="tmrw">明日</string> <string name="tmrw">明日</string>
<string name="yest">昨日</string> <string name="yest">昨日</string>
<string name="DLG_wait">お待ちください</string> <string name="DLG_wait">お待ちください</string>
<string name="sync_status_success">前回の同期:\n%s</string>
<string name="sync_SPr_interval_title">バックグラウンド同期</string> <string name="sync_SPr_interval_title">バックグラウンド同期</string>
<string name="sync_SPr_forget">ログアウト</string>
<string name="sync_SPr_forget_description">すべての同期データを消去します</string>
<string name="sync_forget_confirm">ログアウトと同期データを消去しますか?</string>
<string name="widget_show_due_date">期限を表示</string> <string name="widget_show_due_date">期限を表示</string>
<string name="widget_show_checkboxes">チェックボックスを表示</string> <string name="widget_show_checkboxes">チェックボックスを表示</string>
<string name="widget_show_header">ヘッダーを表示</string> <string name="widget_show_header">ヘッダーを表示</string>

@ -302,11 +302,7 @@
<string name="tmrw">내일</string> <string name="tmrw">내일</string>
<string name="yest">어제</string> <string name="yest">어제</string>
<string name="DLG_wait">잠시 기다리세요...</string> <string name="DLG_wait">잠시 기다리세요...</string>
<string name="sync_status_success">마지막 동기화: \n%s</string>
<string name="sync_SPr_interval_title">백그라운드 동기화</string> <string name="sync_SPr_interval_title">백그라운드 동기화</string>
<string name="sync_SPr_forget">로그아웃</string>
<string name="sync_SPr_forget_description">모든 동기화 자료 삭제</string>
<string name="sync_forget_confirm">로그아웃 / 모든 동기화 데이터 삭제?</string>
<string name="widget_show_due_date">완료 예정일 표시</string> <string name="widget_show_due_date">완료 예정일 표시</string>
<string name="widget_show_checkboxes">체크박스 표시</string> <string name="widget_show_checkboxes">체크박스 표시</string>
<string name="widget_show_header">헤더 표시</string> <string name="widget_show_header">헤더 표시</string>

@ -297,11 +297,7 @@
<string name="tmrw">Ryt</string> <string name="tmrw">Ryt</string>
<string name="yest">Vakar</string> <string name="yest">Vakar</string>
<string name="DLG_wait">Prašome palaukti...</string> <string name="DLG_wait">Prašome palaukti...</string>
<string name="sync_status_success">Paskutinė sinchronizacija:\n%s</string>
<string name="sync_SPr_interval_title">Foninis sinchronizavimas</string> <string name="sync_SPr_interval_title">Foninis sinchronizavimas</string>
<string name="sync_SPr_forget">Atsijungti</string>
<string name="sync_SPr_forget_description">Išvalo visą sinchronizacijos informaciją</string>
<string name="sync_forget_confirm">Atsijungti/išvalyti sinchronizacijos informaciją?</string>
<string name="widget_show_due_date">Rodyti pabaigos terminus</string> <string name="widget_show_due_date">Rodyti pabaigos terminus</string>
<string name="widget_show_checkboxes">Rodyti žymimus kvadratėlius</string> <string name="widget_show_checkboxes">Rodyti žymimus kvadratėlius</string>
<string name="widget_show_header">Rodyti antraštę</string> <string name="widget_show_header">Rodyti antraštę</string>

@ -133,11 +133,7 @@
<string name="tomorrow">I morgen</string> <string name="tomorrow">I morgen</string>
<string name="yesterday">I går</string> <string name="yesterday">I går</string>
<string name="DLG_wait">Vennligst vent...</string> <string name="DLG_wait">Vennligst vent...</string>
<string name="sync_status_success">Siste synkronisering:\n%s</string>
<string name="sync_SPr_interval_title">Bakgrunnssynkronisering</string> <string name="sync_SPr_interval_title">Bakgrunnssynkronisering</string>
<string name="sync_SPr_forget">Logg ut</string>
<string name="sync_SPr_forget_description">Sletter all synkroniseringsdata</string>
<string name="sync_forget_confirm">Logg ut / slett synkroniseringsdata?</string>
<string name="widget_show_due_date">Vis tidsfrister</string> <string name="widget_show_due_date">Vis tidsfrister</string>
<string name="widget_show_checkboxes">Vis avmerkingsbokser</string> <string name="widget_show_checkboxes">Vis avmerkingsbokser</string>
<string name="widget_show_settings">Vis innstillinger</string> <string name="widget_show_settings">Vis innstillinger</string>

@ -296,11 +296,7 @@
<string name="tmrw">mrgn</string> <string name="tmrw">mrgn</string>
<string name="yest">gisteren</string> <string name="yest">gisteren</string>
<string name="DLG_wait">Even geduld a.u.b.</string> <string name="DLG_wait">Even geduld a.u.b.</string>
<string name="sync_status_success">Vorige:\n%s</string>
<string name="sync_SPr_interval_title">Achtergrond synchronisatie</string> <string name="sync_SPr_interval_title">Achtergrond synchronisatie</string>
<string name="sync_SPr_forget">Afmelden</string>
<string name="sync_SPr_forget_description">Alle synchronisatie gegevens verwijderen</string>
<string name="sync_forget_confirm">Afmelden / synchronisatie gegevens verwijderen?</string>
<string name="widget_show_due_date">Toon eind datums</string> <string name="widget_show_due_date">Toon eind datums</string>
<string name="widget_show_checkboxes">Toon vinkboxjes</string> <string name="widget_show_checkboxes">Toon vinkboxjes</string>
<string name="widget_show_header">Toon titel</string> <string name="widget_show_header">Toon titel</string>

@ -276,11 +276,7 @@
<string name="tmrw">jtr</string> <string name="tmrw">jtr</string>
<string name="yest">wcz</string> <string name="yest">wcz</string>
<string name="DLG_wait">Proszę czekać...</string> <string name="DLG_wait">Proszę czekać...</string>
<string name="sync_status_success">Ostatnia synchronizacja:\n%s</string>
<string name="sync_SPr_interval_title">Synchronizacja w tle</string> <string name="sync_SPr_interval_title">Synchronizacja w tle</string>
<string name="sync_SPr_forget">Wyloguj</string>
<string name="sync_SPr_forget_description">Czyści wszystkie dane synchronizacji</string>
<string name="sync_forget_confirm">Wyloguj / wyczyść dane synchronizacji?</string>
<string name="widget_show_due_date">Pokaż terminy</string> <string name="widget_show_due_date">Pokaż terminy</string>
<string name="widget_show_checkboxes">Pokaż przyciski wyboru</string> <string name="widget_show_checkboxes">Pokaż przyciski wyboru</string>
<string name="widget_show_header">Pokaż nagłówek</string> <string name="widget_show_header">Pokaż nagłówek</string>

@ -220,11 +220,7 @@
<string name="tmrw">amanhã</string> <string name="tmrw">amanhã</string>
<string name="yest">ontem</string> <string name="yest">ontem</string>
<string name="DLG_wait">Por favor, aguarde...</string> <string name="DLG_wait">Por favor, aguarde...</string>
<string name="sync_status_success">Última sincronização:\n%s</string>
<string name="sync_SPr_interval_title">Sincronização em segundo plano</string> <string name="sync_SPr_interval_title">Sincronização em segundo plano</string>
<string name="sync_SPr_forget">Desconectar</string>
<string name="sync_SPr_forget_description">Limpar todos os dados de sincronização</string>
<string name="sync_forget_confirm">Desconectar / limpar dados de sincronização?</string>
<string name="widget_show_due_date">Mostrar vencimentos</string> <string name="widget_show_due_date">Mostrar vencimentos</string>
<string name="widget_show_checkboxes">Mostrar tarefas ocultas</string> <string name="widget_show_checkboxes">Mostrar tarefas ocultas</string>
<string name="widget_show_header">Mostrar ocultas</string> <string name="widget_show_header">Mostrar ocultas</string>

@ -298,11 +298,7 @@
<string name="tmrw">Amanhã</string> <string name="tmrw">Amanhã</string>
<string name="yest">Ontem</string> <string name="yest">Ontem</string>
<string name="DLG_wait">Por favor aguarde...</string> <string name="DLG_wait">Por favor aguarde...</string>
<string name="sync_status_success">Última sincronização:\n%s</string>
<string name="sync_SPr_interval_title">Sincronização em segundo plano</string> <string name="sync_SPr_interval_title">Sincronização em segundo plano</string>
<string name="sync_SPr_forget">Sair</string>
<string name="sync_SPr_forget_description">Remove todos os dados de sincronização</string>
<string name="sync_forget_confirm">Sair/limpar dados de sincronização?</string>
<string name="widget_show_due_date">Mostrar datas limite</string> <string name="widget_show_due_date">Mostrar datas limite</string>
<string name="widget_show_checkboxes">Mostrar caixas de seleção</string> <string name="widget_show_checkboxes">Mostrar caixas de seleção</string>
<string name="widget_show_header">Mostrar cabeçalho</string> <string name="widget_show_header">Mostrar cabeçalho</string>

@ -298,11 +298,7 @@
<string name="tmrw">Завт</string> <string name="tmrw">Завт</string>
<string name="yest">Вчера</string> <string name="yest">Вчера</string>
<string name="DLG_wait">Пожалуйста, подождите…</string> <string name="DLG_wait">Пожалуйста, подождите…</string>
<string name="sync_status_success">Последняя синхр.:\n%s</string>
<string name="sync_SPr_interval_title">Фоновая синхр.</string> <string name="sync_SPr_interval_title">Фоновая синхр.</string>
<string name="sync_SPr_forget">Выйти</string>
<string name="sync_SPr_forget_description">Очищает все данные синхронизации</string>
<string name="sync_forget_confirm">Выйти и очистить данные синхронизации?</string>
<string name="widget_show_due_date">Показать даты</string> <string name="widget_show_due_date">Показать даты</string>
<string name="widget_show_checkboxes">Показать флажки</string> <string name="widget_show_checkboxes">Показать флажки</string>
<string name="widget_show_header">Показать заголовок</string> <string name="widget_show_header">Показать заголовок</string>

@ -298,11 +298,7 @@
<string name="tmrw">Zajtra</string> <string name="tmrw">Zajtra</string>
<string name="yest">Včera</string> <string name="yest">Včera</string>
<string name="DLG_wait">Prosím čakaj...</string> <string name="DLG_wait">Prosím čakaj...</string>
<string name="sync_status_success">Posledná synchronizácia:\n%s</string>
<string name="sync_SPr_interval_title">Synchronizácia na pozadí</string> <string name="sync_SPr_interval_title">Synchronizácia na pozadí</string>
<string name="sync_SPr_forget">Odhlásiť sa</string>
<string name="sync_SPr_forget_description">Vymaže všetky údaje synchronizácie</string>
<string name="sync_forget_confirm">Odhlásiť sa/vymazať údaje synchronizácie?</string>
<string name="widget_show_due_date">Ukázať dátumy vypršania </string> <string name="widget_show_due_date">Ukázať dátumy vypršania </string>
<string name="widget_show_checkboxes">Ukázať zaškrtávacie políčka </string> <string name="widget_show_checkboxes">Ukázať zaškrtávacie políčka </string>
<string name="widget_show_header">Ukázať záhlavia </string> <string name="widget_show_header">Ukázať záhlavia </string>

@ -187,10 +187,6 @@
<string name="tmrw">Jutr</string> <string name="tmrw">Jutr</string>
<string name="yest">Včer</string> <string name="yest">Včer</string>
<string name="DLG_wait">Prosimo, počakajte...</string> <string name="DLG_wait">Prosimo, počakajte...</string>
<string name="sync_status_success">Najnovejše usklajevanje:\n%s</string>
<string name="sync_SPr_interval_title">Usklajevanje v ozadju</string> <string name="sync_SPr_interval_title">Usklajevanje v ozadju</string>
<string name="sync_SPr_forget">Odjava</string>
<string name="sync_SPr_forget_description">Zbriše vse usklajene podatke</string>
<string name="sync_forget_confirm">Odjava/brisanje usklajenih podatkov?</string>
<string name="TLA_menu_donate">Donirajte</string> <string name="TLA_menu_donate">Donirajte</string>
</resources> </resources>

@ -223,11 +223,7 @@
<string name="tmrw">imorn</string> <string name="tmrw">imorn</string>
<string name="yest">Igår</string> <string name="yest">Igår</string>
<string name="DLG_wait">Var god vänta...</string> <string name="DLG_wait">Var god vänta...</string>
<string name="sync_status_success">Synkroniserades senast:\n%s</string>
<string name="sync_SPr_interval_title">Bakgrundssynkronisering</string> <string name="sync_SPr_interval_title">Bakgrundssynkronisering</string>
<string name="sync_SPr_forget">Logga ut</string>
<string name="sync_SPr_forget_description">Rensar alla synkroniseringsdata</string>
<string name="sync_forget_confirm">Logga ut / rensa synkroniseringsdata?</string>
<string name="widget_show_due_date">Visa förfallodatum</string> <string name="widget_show_due_date">Visa förfallodatum</string>
<string name="widget_show_checkboxes">Visa kryssrutor</string> <string name="widget_show_checkboxes">Visa kryssrutor</string>
<string name="widget_show_header">Visa rubrik</string> <string name="widget_show_header">Visa rubrik</string>

@ -302,11 +302,7 @@
<string name="tmrw">Yarın</string> <string name="tmrw">Yarın</string>
<string name="yest">Dün</string> <string name="yest">Dün</string>
<string name="DLG_wait">Lütfen bekleyin...</string> <string name="DLG_wait">Lütfen bekleyin...</string>
<string name="sync_status_success">Son eşzamanlama:\n%s</string>
<string name="sync_SPr_interval_title">Arka planda eşzamanla</string> <string name="sync_SPr_interval_title">Arka planda eşzamanla</string>
<string name="sync_SPr_forget">Çıkış Yap</string>
<string name="sync_SPr_forget_description">Tüm eşzamanlama verilerini temizle</string>
<string name="sync_forget_confirm">Çıkış yap/eşzamanlama verisini temizle?</string>
<string name="widget_show_due_date">Bitiş tarihlerini göster</string> <string name="widget_show_due_date">Bitiş tarihlerini göster</string>
<string name="widget_show_checkboxes">Onay kutularını göster</string> <string name="widget_show_checkboxes">Onay kutularını göster</string>
<string name="widget_show_header">Başlığı göster</string> <string name="widget_show_header">Başlığı göster</string>

@ -226,11 +226,7 @@
<string name="tmrw">Звтр</string> <string name="tmrw">Звтр</string>
<string name="yest">Вчр</string> <string name="yest">Вчр</string>
<string name="DLG_wait">Будь ласка, зачекайте...</string> <string name="DLG_wait">Будь ласка, зачекайте...</string>
<string name="sync_status_success">Остання синхр.:\n%s</string>
<string name="sync_SPr_interval_title">Фонова синхронізація</string> <string name="sync_SPr_interval_title">Фонова синхронізація</string>
<string name="sync_SPr_forget">Вийти</string>
<string name="sync_SPr_forget_description">Очищує всю синхронізовану інформацію</string>
<string name="sync_forget_confirm">Вийти/очистити синхронізовану інофрмацію?</string>
<string name="widget_show_due_date">Показувати дату виконання</string> <string name="widget_show_due_date">Показувати дату виконання</string>
<string name="widget_show_checkboxes">Показати галочки</string> <string name="widget_show_checkboxes">Показати галочки</string>
<string name="widget_show_header">Показати заголовок</string> <string name="widget_show_header">Показати заголовок</string>

@ -297,11 +297,7 @@
<string name="tmrw">明天</string> <string name="tmrw">明天</string>
<string name="yest">昨天</string> <string name="yest">昨天</string>
<string name="DLG_wait">请稍候...</string> <string name="DLG_wait">请稍候...</string>
<string name="sync_status_success">上次同步:\n%s</string>
<string name="sync_SPr_interval_title">后台同步</string> <string name="sync_SPr_interval_title">后台同步</string>
<string name="sync_SPr_forget">登出</string>
<string name="sync_SPr_forget_description">清除所有同步资料</string>
<string name="sync_forget_confirm">登出/清除同步资料?</string>
<string name="widget_show_due_date">显示截止日期</string> <string name="widget_show_due_date">显示截止日期</string>
<string name="widget_show_checkboxes">显示复选框</string> <string name="widget_show_checkboxes">显示复选框</string>
<string name="widget_show_header">显示标题</string> <string name="widget_show_header">显示标题</string>

@ -189,11 +189,7 @@
<string name="tmrw">明天</string> <string name="tmrw">明天</string>
<string name="yest">昨天</string> <string name="yest">昨天</string>
<string name="DLG_wait">請稍候...</string> <string name="DLG_wait">請稍候...</string>
<string name="sync_status_success">上次同步:\n%s</string>
<string name="sync_SPr_interval_title">後台同步</string> <string name="sync_SPr_interval_title">後台同步</string>
<string name="sync_SPr_forget">登出</string>
<string name="sync_SPr_forget_description">清除所有同步資料</string>
<string name="sync_forget_confirm">登出/清除同步資料?</string>
<string name="widget_show_due_date">顯示到期日</string> <string name="widget_show_due_date">顯示到期日</string>
<string name="widget_show_checkboxes">顯示核取方塊</string> <string name="widget_show_checkboxes">顯示核取方塊</string>
<string name="widget_show_header">顯示標頭</string> <string name="widget_show_header">顯示標頭</string>

@ -149,10 +149,6 @@
<!-- on calendar end at dealline if true, start at deadline if false --> <!-- on calendar end at dealline if true, start at deadline if false -->
<string name="p_end_at_deadline">p_end_at_deadline</string> <string name="p_end_at_deadline">p_end_at_deadline</string>
<!-- ============================================================ SYNC == -->
<string name="sync_SPr_forget_key">sync_forget</string>
<!-- ============================================================ OTHER == --> <!-- ============================================================ OTHER == -->
<!-- Default Calendar Preference Key (do not translate) --> <!-- Default Calendar Preference Key (do not translate) -->
@ -187,7 +183,6 @@
<string name="TEA_ctrl_comments">TEA_ctrl_comments</string> <string name="TEA_ctrl_comments">TEA_ctrl_comments</string>
<string name="TEA_ctrl_gcal">TEA_ctrl_gcal</string> <string name="TEA_ctrl_gcal">TEA_ctrl_gcal</string>
<string name="TEA_ctrl_google_task_list">TEA_ctrl_gtask</string> <string name="TEA_ctrl_google_task_list">TEA_ctrl_gtask</string>
<string name="sync_gtasks">sync_gtasks</string>
<string name="p_geofence_radius">geolocation_radius</string> <string name="p_geofence_radius">geolocation_radius</string>
<string name="p_geofence_responsiveness">geofence_responsiveness</string> <string name="p_geofence_responsiveness">geofence_responsiveness</string>
<string name="p_show_hidden_tasks">show_hidden_tasks</string> <string name="p_show_hidden_tasks">show_hidden_tasks</string>
@ -242,7 +237,6 @@
<string name="tracking_action_delete_list">Delete List</string> <string name="tracking_action_delete_list">Delete List</string>
<string name="tracking_action_on">On</string> <string name="tracking_action_on">On</string>
<string name="tracking_action_off">Off</string> <string name="tracking_action_off">Off</string>
<string name="tracking_action_clear">Clear</string>
<string name="tracking_action_clear_completed">Clear completed</string> <string name="tracking_action_clear_completed">Clear completed</string>
<string name="tracking_action_custom">Custom</string> <string name="tracking_action_custom">Custom</string>
<string name="tracking_action_preset">Preset</string> <string name="tracking_action_preset">Preset</string>

@ -669,20 +669,9 @@ File %1$s contained %2$s.\n\n
<!-- ================================================== SyncPreferences == --> <!-- ================================================== SyncPreferences == -->
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
<string name="sync_status_success">Last sync:\n%s</string>
<!-- Preference: Synchronization Interval Title --> <!-- Preference: Synchronization Interval Title -->
<string name="sync_SPr_interval_title">Background sync</string> <string name="sync_SPr_interval_title">Background sync</string>
<!-- Sync: Clear Data Title -->
<string name="sync_SPr_forget">Log out</string>
<!-- Sync: Clear Data Description -->
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
<!-- confirmation dialog for sync log out -->
<string name="sync_forget_confirm">Log out/clear synchronization data?</string>
<string name="widget_show_due_date">Show due dates</string> <string name="widget_show_due_date">Show due dates</string>
<string name="widget_show_checkboxes">Show checkboxes</string> <string name="widget_show_checkboxes">Show checkboxes</string>
<string name="widget_show_header">Show header</string> <string name="widget_show_header">Show header</string>
@ -877,7 +866,6 @@ File %1$s contained %2$s.\n\n
<string name="tasker_list_notification">List notification</string> <string name="tasker_list_notification">List notification</string>
<string name="help">Help</string> <string name="help">Help</string>
<string name="caldav_home_set_not_found">Home set not found</string> <string name="caldav_home_set_not_found">Home set not found</string>
<string name="caldav_no_supported_calendars">Could not find any calendars with VTODO support</string>
<string name="network_error">Connection failed</string> <string name="network_error">Connection failed</string>
<string name="background_sync_unmetered_only">Only on unmetered connections</string> <string name="background_sync_unmetered_only">Only on unmetered connections</string>
<string name="upgrade">Upgrade</string> <string name="upgrade">Upgrade</string>

@ -6,21 +6,9 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/synchronization"> android:title="@string/synchronization">
<PreferenceCategory android:title="@string/gtasks_GPr_header"> <PreferenceCategory
android:key="@string/gtasks_GPr_header"
<com.todoroo.astrid.ui.MultilineCheckboxPreference android:title="@string/gtasks_GPr_header"/>
android:defaultValue="false"
android:key="@string/sync_gtasks"
android:title="@string/enabled"/>
<com.todoroo.astrid.ui.MultilinePreference
android:dependency="@string/sync_gtasks"
android:key="@string/sync_SPr_forget_key"
android:summary="@string/sync_SPr_forget_description"
android:title="@string/sync_SPr_forget">
</com.todoroo.astrid.ui.MultilinePreference>
</PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:key="@string/CalDAV" android:key="@string/CalDAV"

Loading…
Cancel
Save