Use SyncAdapter to push new tasks

pull/437/head
Alex Baker 8 years ago
parent 3235d5e6df
commit c224103e81

@ -96,7 +96,7 @@ public class GtasksListServiceTest extends DatabaseTestCase {
assertEquals( assertEquals(
asList(newGtaskList(with(REMOTE_ID, "1"), with(LAST_SYNC, 0L))), asList(newGtaskList(with(REMOTE_ID, "1"), with(LAST_SYNC, 0L))),
gtasksListService.getListsToUpdate(new TaskLists().setItems(asList(taskList)))); gtasksListService.getListsToUpdate(asList(taskList)));
} }
private void setLists(TaskList... list) { private void setLists(TaskList... list) {

@ -6,7 +6,6 @@
package com.todoroo.astrid.gtasks; package com.todoroo.astrid.gtasks;
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.todoroo.astrid.dao.StoreObjectDao; import com.todoroo.astrid.dao.StoreObjectDao;
import java.util.HashSet; import java.util.HashSet;
@ -80,9 +79,9 @@ public class GtasksListService {
} }
} }
public List<GtasksList> getListsToUpdate(TaskLists remoteLists) { public List<GtasksList> getListsToUpdate(List<TaskList> remoteLists) {
List<GtasksList> listsToUpdate = newArrayList(); List<GtasksList> listsToUpdate = newArrayList();
for (TaskList remoteList : remoteLists.getItems()) { for (TaskList remoteList : remoteLists) {
GtasksList localList = getList(remoteList.getId()); GtasksList localList = getList(remoteList.getId());
String listName = localList.getName(); String listName = localList.getName();
Long lastSync = localList.getLastSync(); Long lastSync = localList.getLastSync();

@ -5,7 +5,6 @@
*/ */
package com.todoroo.astrid.gtasks.sync; package com.todoroo.astrid.gtasks.sync;
import android.content.ContentValues;
import android.text.TextUtils; import android.text.TextUtils;
import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.data.Callback;
@ -15,7 +14,6 @@ import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Metadata;
@ -24,15 +22,12 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksMetadata; import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.OrderedMetadataListUpdater; import com.todoroo.astrid.gtasks.OrderedMetadataListUpdater;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksInvoker; import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.HttpNotFoundException;
import com.todoroo.astrid.gtasks.api.MoveRequest; import com.todoroo.astrid.gtasks.api.MoveRequest;
import org.tasks.gtasks.SyncAdapterHelper; import org.tasks.gtasks.SyncAdapterHelper;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@ -46,12 +41,9 @@ import timber.log.Timber;
@Singleton @Singleton
public class GtasksSyncService { public class GtasksSyncService {
private static final String DEFAULT_LIST = "@default"; //$NON-NLS-1$
private final MetadataDao metadataDao; private final MetadataDao metadataDao;
private final TaskDao taskDao; private final TaskDao taskDao;
private final GtasksPreferenceService gtasksPreferenceService; private final GtasksPreferenceService gtasksPreferenceService;
private final GtasksMetadata gtasksMetadataFactory;
private final GtasksInvoker gtasksInvoker; private final GtasksInvoker gtasksInvoker;
private final LinkedBlockingQueue<SyncOnSaveOperation> operationQueue = new LinkedBlockingQueue<>(); private final LinkedBlockingQueue<SyncOnSaveOperation> operationQueue = new LinkedBlockingQueue<>();
private final SyncAdapterHelper syncAdapterHelper; private final SyncAdapterHelper syncAdapterHelper;
@ -59,12 +51,11 @@ public class GtasksSyncService {
@Inject @Inject
public GtasksSyncService(MetadataDao metadataDao, TaskDao taskDao, public GtasksSyncService(MetadataDao metadataDao, TaskDao taskDao,
GtasksPreferenceService gtasksPreferenceService, GtasksPreferenceService gtasksPreferenceService,
GtasksMetadata gtasksMetadataFactory, GtasksInvoker gtasksInvoker, GtasksInvoker gtasksInvoker,
SyncAdapterHelper syncAdapterHelper) { SyncAdapterHelper syncAdapterHelper) {
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.taskDao = taskDao; this.taskDao = taskDao;
this.gtasksPreferenceService = gtasksPreferenceService; this.gtasksPreferenceService = gtasksPreferenceService;
this.gtasksMetadataFactory = gtasksMetadataFactory;
this.gtasksInvoker = gtasksInvoker; this.gtasksInvoker = gtasksInvoker;
this.syncAdapterHelper = syncAdapterHelper; this.syncAdapterHelper = syncAdapterHelper;
new OperationPushThread(operationQueue).start(); new OperationPushThread(operationQueue).start();
@ -100,10 +91,6 @@ public class GtasksSyncService {
} }
} }
public void enqueue(SyncOnSaveOperation operation) {
operationQueue.offer(operation);
}
private class OperationPushThread extends Thread { private class OperationPushThread extends Thread {
private final LinkedBlockingQueue<SyncOnSaveOperation> queue; private final LinkedBlockingQueue<SyncOnSaveOperation> queue;
@ -156,111 +143,6 @@ public class GtasksSyncService {
operationQueue.offer(new MoveOp(metadata)); operationQueue.offer(new MoveOp(metadata));
} }
/**
* Synchronize with server when data changes
*/
public void pushTaskOnSave(Task task, ContentValues values, GtasksInvoker invoker) throws IOException {
for (Metadata deleted : getDeleted(task.getId())) {
gtasksInvoker.deleteGtask(deleted.getValue(GtasksMetadata.LIST_ID), deleted.getValue(GtasksMetadata.ID));
metadataDao.delete(deleted.getId());
}
Metadata gtasksMetadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
com.google.api.services.tasks.model.Task remoteModel;
boolean newlyCreated = false;
String remoteId;
String listId = gtasksPreferenceService.getDefaultList();
if (listId == null) {
com.google.api.services.tasks.model.TaskList defaultList = invoker.getGtaskList(DEFAULT_LIST);
if (defaultList != null) {
listId = defaultList.getId();
gtasksPreferenceService.setDefaultList(listId);
} else {
listId = DEFAULT_LIST;
}
}
if (gtasksMetadata == null || !gtasksMetadata.containsNonNullValue(GtasksMetadata.ID) ||
TextUtils.isEmpty(gtasksMetadata.getValue(GtasksMetadata.ID))) { //Create case
if (gtasksMetadata == null) {
gtasksMetadata = gtasksMetadataFactory.createEmptyMetadata(task.getId());
}
if (gtasksMetadata.containsNonNullValue(GtasksMetadata.LIST_ID)) {
listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
}
remoteModel = new com.google.api.services.tasks.model.Task();
newlyCreated = true;
} else { //update case
remoteId = gtasksMetadata.getValue(GtasksMetadata.ID);
listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
remoteModel = new com.google.api.services.tasks.model.Task();
remoteModel.setId(remoteId);
}
//If task was newly created but without a title, don't sync--we're in the middle of
//creating a task which may end up being cancelled. Also don't sync new but already
//deleted tasks
if (newlyCreated &&
(!values.containsKey(Task.TITLE.name) || TextUtils.isEmpty(task.getTitle()) || task.getDeletionDate() > 0)) {
return;
}
//Update the remote model's changed properties
if (values.containsKey(Task.DELETION_DATE.name) && task.isDeleted()) {
remoteModel.setDeleted(true);
}
if (values.containsKey(Task.TITLE.name)) {
remoteModel.setTitle(task.getTitle());
}
if (values.containsKey(Task.NOTES.name)) {
remoteModel.setNotes(task.getNotes());
}
if (values.containsKey(Task.DUE_DATE.name) && task.hasDueDate()) {
remoteModel.setDue(GtasksApiUtilities.unixTimeToGtasksDueDate(task.getDueDate()));
}
if (values.containsKey(Task.COMPLETION_DATE.name)) {
if (task.isCompleted()) {
remoteModel.setCompleted(GtasksApiUtilities.unixTimeToGtasksCompletionTime(task.getCompletionDate()));
remoteModel.setStatus("completed"); //$NON-NLS-1$
} else {
remoteModel.setCompleted(null);
remoteModel.setStatus("needsAction"); //$NON-NLS-1$
}
}
if (!newlyCreated) {
try {
invoker.updateGtask(listId, remoteModel);
} catch(HttpNotFoundException e) {
Timber.e("Received 404 response, deleting %s", gtasksMetadata);
metadataDao.delete(gtasksMetadata.getId());
return;
}
} else {
String parent = getRemoteParentId(gtasksMetadata);
String priorSibling = getRemoteSiblingId(listId, gtasksMetadata);
com.google.api.services.tasks.model.Task created = invoker.createGtask(listId, remoteModel, parent, priorSibling);
if (created != null) {
//Update the metadata for the newly created task
gtasksMetadata.setValue(GtasksMetadata.ID, created.getId());
gtasksMetadata.setValue(GtasksMetadata.LIST_ID, listId);
} else {
return;
}
}
task.setModificationDate(DateUtilities.now());
gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L);
metadataDao.persist(gtasksMetadata);
task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
taskDao.saveExistingWithSqlConstraintCheck(task);
}
public void pushMetadataOnSave(Metadata model, GtasksInvoker invoker) throws IOException { public void pushMetadataOnSave(Metadata model, GtasksInvoker invoker) throws IOException {
AndroidUtilities.sleepDeep(1000L); AndroidUtilities.sleepDeep(1000L);
@ -303,16 +185,10 @@ public class GtasksSyncService {
}); });
} }
private List<Metadata> getDeleted(long taskId) {
return metadataDao.toList(Criterion.and(
MetadataDao.MetadataCriteria.byTaskAndwithKey(taskId, GtasksMetadata.METADATA_KEY),
MetadataDao.MetadataCriteria.isDeleted()));
}
/** /**
* Gets the remote id string of the parent task * Gets the remote id string of the parent task
*/ */
private String getRemoteParentId(Metadata gtasksMetadata) { public String getRemoteParentId(Metadata gtasksMetadata) {
String parent = null; String parent = null;
if (gtasksMetadata.containsNonNullValue(GtasksMetadata.PARENT_TASK)) { if (gtasksMetadata.containsNonNullValue(GtasksMetadata.PARENT_TASK)) {
long parentId = gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK); long parentId = gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK);
@ -330,7 +206,7 @@ public class GtasksSyncService {
/** /**
* Gets the remote id string of the previous sibling task * Gets the remote id string of the previous sibling task
*/ */
private String getRemoteSiblingId(String listId, Metadata gtasksMetadata) { public String getRemoteSiblingId(String listId, Metadata gtasksMetadata) {
final AtomicInteger indentToMatch = new AtomicInteger(gtasksMetadata.getValue(GtasksMetadata.INDENT)); final AtomicInteger indentToMatch = new AtomicInteger(gtasksMetadata.getValue(GtasksMetadata.INDENT));
final AtomicLong parentToMatch = new AtomicLong(gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK)); final AtomicLong parentToMatch = new AtomicLong(gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK));
final AtomicReference<String> sibling = new AtomicReference<>(); final AtomicReference<String> sibling = new AtomicReference<>();

@ -30,7 +30,6 @@ import com.google.api.services.tasks.model.TaskLists;
import com.google.api.services.tasks.model.Tasks; import com.google.api.services.tasks.model.Tasks;
import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
@ -46,7 +45,9 @@ import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksMetadata; import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksPreferenceService; 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.GtasksInvoker; import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.HttpNotFoundException;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService; import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer; import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer;
import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.service.TaskService;
@ -82,6 +83,8 @@ import static org.tasks.date.DateTimeUtils.newDateTime;
*/ */
public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter { public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
private static final String DEFAULT_LIST = "@default"; //$NON-NLS-1$
@Inject GtasksPreferenceService gtasksPreferenceService; @Inject GtasksPreferenceService gtasksPreferenceService;
@Inject Broadcaster broadcaster; @Inject Broadcaster broadcaster;
@Inject TaskService taskService; @Inject TaskService taskService;
@ -93,7 +96,7 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
@Inject GtasksInvoker gtasksInvoker; @Inject GtasksInvoker gtasksInvoker;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject MetadataDao metadataDao; @Inject MetadataDao metadataDao;
@Inject GtasksMetadata gtasksMetadataFactory;
public GoogleTaskSyncAdapter(Context context, boolean autoInitialize) { public GoogleTaskSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize); super(context, autoInitialize);
@ -144,12 +147,13 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
} }
private void synchronize() { private void synchronize() {
TaskLists remoteLists = null; pushLocalChanges();
List<TaskList> gtaskLists = new ArrayList<>();
try { try {
List<TaskList> gtaskLists = new ArrayList<>();
String nextPageToken = null; String nextPageToken = null;
do { do {
remoteLists = gtasksInvoker.allGtaskLists(nextPageToken); TaskLists remoteLists = gtasksInvoker.allGtaskLists(nextPageToken);
if (remoteLists == null) { if (remoteLists == null) {
break; break;
} }
@ -167,63 +171,145 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
Timber.e(e, e.getMessage()); Timber.e(e, e.getMessage());
} }
if (remoteLists == null) { for (final GtasksList list : gtasksListService.getListsToUpdate(gtaskLists)) {
fetchAndApplyRemoteChanges(list);
}
}
private void pushLocalChanges() {
List<Task> tasks = taskDao.toList(Query.select(Task.PROPERTIES)
.join(Join.left(Metadata.TABLE, Criterion.and(MetadataDao.MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY), Task.ID.eq(Metadata.TASK))))
.where(Criterion.or(Task.MODIFICATION_DATE.gt(GtasksMetadata.LAST_SYNC), GtasksMetadata.ID.eq(""))));
for (Task task : tasks) {
try {
pushTask(task, task.getMergedValues(), gtasksInvoker);
} catch (IOException e) {
Timber.e(e, e.getMessage());
}
}
}
/**
* Synchronize with server when data changes
*/
private void pushTask(Task task, ContentValues values, GtasksInvoker invoker) throws IOException {
for (Metadata deleted : getDeleted(task.getId())) {
gtasksInvoker.deleteGtask(deleted.getValue(GtasksMetadata.LIST_ID), deleted.getValue(GtasksMetadata.ID));
metadataDao.delete(deleted.getId());
}
Metadata gtasksMetadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
com.google.api.services.tasks.model.Task remoteModel;
boolean newlyCreated = false;
String remoteId;
String listId = gtasksPreferenceService.getDefaultList();
if (listId == null) {
com.google.api.services.tasks.model.TaskList defaultList = invoker.getGtaskList(DEFAULT_LIST);
if (defaultList != null) {
listId = defaultList.getId();
gtasksPreferenceService.setDefaultList(listId);
} else {
listId = DEFAULT_LIST;
}
}
if (gtasksMetadata == null || !gtasksMetadata.containsNonNullValue(GtasksMetadata.ID) ||
TextUtils.isEmpty(gtasksMetadata.getValue(GtasksMetadata.ID))) { //Create case
if (gtasksMetadata == null) {
gtasksMetadata = gtasksMetadataFactory.createEmptyMetadata(task.getId());
}
if (gtasksMetadata.containsNonNullValue(GtasksMetadata.LIST_ID)) {
listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
}
remoteModel = new com.google.api.services.tasks.model.Task();
newlyCreated = true;
} else { //update case
remoteId = gtasksMetadata.getValue(GtasksMetadata.ID);
listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
remoteModel = new com.google.api.services.tasks.model.Task();
remoteModel.setId(remoteId);
}
//If task was newly created but without a title, don't sync--we're in the middle of
//creating a task which may end up being cancelled. Also don't sync new but already
//deleted tasks
if (newlyCreated &&
(!values.containsKey(Task.TITLE.name) || TextUtils.isEmpty(task.getTitle()) || task.getDeletionDate() > 0)) {
return; return;
} }
for (final GtasksList list : gtasksListService.getListsToUpdate(remoteLists)) { //Update the remote model's changed properties
synchronizeListHelper(list, gtasksInvoker); if (values.containsKey(Task.DELETION_DATE.name) && task.isDeleted()) {
remoteModel.setDeleted(true);
} }
pushUpdated(gtasksInvoker); if (values.containsKey(Task.TITLE.name)) {
} remoteModel.setTitle(task.getTitle());
}
if (values.containsKey(Task.NOTES.name)) {
remoteModel.setNotes(task.getNotes());
}
if (values.containsKey(Task.DUE_DATE.name) && task.hasDueDate()) {
remoteModel.setDue(GtasksApiUtilities.unixTimeToGtasksDueDate(task.getDueDate()));
}
if (values.containsKey(Task.COMPLETION_DATE.name)) {
if (task.isCompleted()) {
remoteModel.setCompleted(GtasksApiUtilities.unixTimeToGtasksCompletionTime(task.getCompletionDate()));
remoteModel.setStatus("completed"); //$NON-NLS-1$
} else {
remoteModel.setCompleted(null);
remoteModel.setStatus("needsAction"); //$NON-NLS-1$
}
}
private synchronized void pushUpdated(GtasksInvoker invoker) { if (!newlyCreated) {
TodorooCursor<Task> queued = taskService.query(Query.select(Task.PROPERTIES). try {
join(Join.left(Metadata.TABLE, Criterion.and(MetadataDao.MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY), Task.ID.eq(Metadata.TASK)))).where( invoker.updateGtask(listId, remoteModel);
Criterion.or(Task.MODIFICATION_DATE.gt(GtasksMetadata.LAST_SYNC), Metadata.KEY.isNull()))); } catch(HttpNotFoundException e) {
pushTasks(queued, invoker); Timber.e("Received 404 response, deleting %s", gtasksMetadata);
} metadataDao.delete(gtasksMetadata.getId());
return;
}
} else {
String parent = gtasksSyncService.getRemoteParentId(gtasksMetadata);
String priorSibling = gtasksSyncService.getRemoteSiblingId(listId, gtasksMetadata);
private synchronized void pushTasks(TodorooCursor<Task> queued, GtasksInvoker invoker) { com.google.api.services.tasks.model.Task created = invoker.createGtask(listId, remoteModel, parent, priorSibling);
try {
for (queued.moveToFirst(); !queued.isAfterLast(); queued.moveToNext()) { if (created != null) {
Task task = new Task(queued); //Update the metadata for the newly created task
try { gtasksMetadata.setValue(GtasksMetadata.ID, created.getId());
gtasksSyncService.pushTaskOnSave(task, task.getMergedValues(), invoker); gtasksMetadata.setValue(GtasksMetadata.LIST_ID, listId);
} catch (IOException e) { } else {
Timber.e(e, e.getMessage()); return;
}
} }
} finally {
queued.close();
} }
task.setModificationDate(DateUtilities.now());
gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L);
metadataDao.persist(gtasksMetadata);
task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
taskDao.saveExistingWithSqlConstraintCheck(task);
}
private List<Metadata> getDeleted(long taskId) {
return metadataDao.toList(Criterion.and(
MetadataDao.MetadataCriteria.byTaskAndwithKey(taskId, GtasksMetadata.METADATA_KEY),
MetadataDao.MetadataCriteria.isDeleted()));
} }
private synchronized void synchronizeListHelper(GtasksList list, GtasksInvoker invoker) { private synchronized void fetchAndApplyRemoteChanges(GtasksList list) {
String listId = list.getRemoteId(); String listId = list.getRemoteId();
long lastSyncDate = list.getLastSync(); long lastSyncDate = list.getLastSync();
/**
* Find tasks which have been associated with the list internally, but have not yet been
* pushed to Google Tasks (and so haven't yet got a valid ID).
*/
Criterion not_pushed_tasks = Criterion.and(
Metadata.KEY.eq(GtasksMetadata.METADATA_KEY),
GtasksMetadata.LIST_ID.eq(listId),
GtasksMetadata.ID.eq("")
);
TodorooCursor<Task> qs = taskService.query(Query.select(Task.PROPERTIES).
join(Join.left(Metadata.TABLE, Criterion.and(MetadataDao.MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY), Task.ID.eq(Metadata.TASK)))).where(not_pushed_tasks)
);
pushTasks(qs, invoker);
boolean includeDeletedAndHidden = lastSyncDate != 0; boolean includeDeletedAndHidden = lastSyncDate != 0;
try { try {
List<com.google.api.services.tasks.model.Task> tasks = new ArrayList<>(); List<com.google.api.services.tasks.model.Task> tasks = new ArrayList<>();
String nextPageToken = null; String nextPageToken = null;
do { do {
Tasks taskList = invoker.getAllGtasksFromListId(listId, includeDeletedAndHidden, Tasks taskList = gtasksInvoker.getAllGtasksFromListId(listId, includeDeletedAndHidden,
includeDeletedAndHidden, lastSyncDate + 1000L, nextPageToken); includeDeletedAndHidden, lastSyncDate + 1000L, nextPageToken);
if (taskList == null) { if (taskList == null) {
break; break;

@ -5,23 +5,14 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
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.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.service.TaskService;
import org.tasks.gtasks.SyncAdapterHelper; import org.tasks.gtasks.SyncAdapterHelper;
import org.tasks.injection.BroadcastComponent; import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.InjectingBroadcastReceiver; import org.tasks.injection.InjectingBroadcastReceiver;
import java.io.IOException;
import javax.inject.Inject; import javax.inject.Inject;
public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver { public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver {
@ -29,9 +20,6 @@ public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver {
private static final Property<?>[] TASK_PROPERTIES = { Task.ID, Task.TITLE, private static final Property<?>[] TASK_PROPERTIES = { Task.ID, Task.TITLE,
Task.NOTES, Task.DUE_DATE, Task.COMPLETION_DATE, Task.DELETION_DATE }; Task.NOTES, Task.DUE_DATE, Task.COMPLETION_DATE, Task.DELETION_DATE };
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject GtasksSyncService gtasksSyncService;
@Inject TaskDao taskDao;
@Inject SyncAdapterHelper syncAdapterHelper; @Inject SyncAdapterHelper syncAdapterHelper;
@Override @Override
@ -50,12 +38,8 @@ public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver {
if(model.checkTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC)) { if(model.checkTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC)) {
return; return;
} }
if (gtasksPreferenceService.isOngoing() && !model.checkTransitory(TaskService.TRANS_REPEAT_COMPLETE)) { //Don't try and sync changes that occur during a normal sync
return;
}
if (checkValuesForProperties(setValues, TASK_PROPERTIES) || model.checkTransitory(SyncFlags.FORCE_SYNC)) { if (checkValuesForProperties(setValues, TASK_PROPERTIES) || model.checkTransitory(SyncFlags.FORCE_SYNC)) {
Task toPush = taskDao.fetch(model.getId(), TASK_PROPERTIES); syncAdapterHelper.requestSynchronization();
gtasksSyncService.enqueue(new TaskPushOp(toPush));
} }
} }
@ -64,23 +48,6 @@ public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver {
component.inject(this); component.inject(this);
} }
private class TaskPushOp implements GtasksSyncService.SyncOnSaveOperation {
protected Task model;
protected long creationDate = DateUtilities.now();
public TaskPushOp(Task model) {
this.model = model;
}
@Override
public void op(GtasksInvoker invoker) throws IOException {
if(DateUtilities.now() - creationDate < 1000) {
AndroidUtilities.sleepDeep(1000 - (DateUtilities.now() - creationDate));
}
gtasksSyncService.pushTaskOnSave(model, model.getMergedValues(), invoker);
}
}
/** /**
* Checks to see if any of the values changed are among the properties we sync * Checks to see if any of the values changed are among the properties we sync
* @return false if none of the properties we sync were changed, true otherwise * @return false if none of the properties we sync were changed, true otherwise

@ -505,15 +505,7 @@ public class TaskListFragment extends InjectingListFragment implements
return; return;
} }
final Activity activity = getActivity(); refresh();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
} }
} }

@ -7,7 +7,6 @@ package com.todoroo.astrid.gtasks;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import org.tasks.R;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import javax.inject.Inject; import javax.inject.Inject;
@ -81,8 +80,4 @@ public class GtasksPreferenceService {
public void recordSyncStart() { public void recordSyncStart() {
preferences.setBoolean(IDENTIFIER + PREF_ONGOING, true); preferences.setBoolean(IDENTIFIER + PREF_ONGOING, true);
} }
public int getSyncInterval() {
return preferences.getIntegerFromString(R.string.gtasks_GPr_interval_key, 0);
}
} }

@ -105,7 +105,6 @@ public class RepeatTaskCompleteListener extends InjectingBroadcastReceiver {
task.setReminderSnooze(0L); task.setReminderSnooze(0L);
task.setCompletionDate(0L); task.setCompletionDate(0L);
task.setDueDateAdjustingHideUntil(newDueDate); task.setDueDateAdjustingHideUntil(newDueDate);
task.putTransitory(TaskService.TRANS_REPEAT_COMPLETE, true);
gcalHelper.rescheduleRepeatingTask(task); gcalHelper.rescheduleRepeatingTask(task);
taskService.save(task); taskService.save(task);

@ -47,8 +47,6 @@ import timber.log.Timber;
@Singleton @Singleton
public class TaskService { public class TaskService {
public static final String TRANS_REPEAT_COMPLETE = "repeat-complete"; //$NON-NLS-1$
private final TagDataDao tagDataDao; private final TagDataDao tagDataDao;
private final TaskDao taskDao; private final TaskDao taskDao;
private final Broadcaster broadcaster; private final Broadcaster broadcaster;

@ -54,6 +54,14 @@ public class SyncAdapterHelper {
return true; return true;
} }
public void requestSynchronization() {
Account account = getAccount();
if (account == null) {
return;
}
ContentResolver.requestSync(account, AUTHORITY, new Bundle());
}
public boolean isEnabled() { public boolean isEnabled() {
return preferences.getBoolean(R.string.sync_gtasks, false) && getAccount() != null; return preferences.getBoolean(R.string.sync_gtasks, false) && getAccount() != null;
} }

@ -2,5 +2,5 @@
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.google" android:accountType="com.google"
android:contentAuthority="org.tasks" android:contentAuthority="org.tasks"
android:supportsUploading="true" android:supportsUploading="false"
android:userVisible="false" /> android:userVisible="false" />
Loading…
Cancel
Save