Gtasks V2 sync provider

pull/14/head
Sam Bosley 14 years ago
parent d5b704badf
commit c498eabba6

@ -67,6 +67,12 @@ public class Metadata extends AbstractModel {
public static final StringProperty VALUE5 = new StringProperty(
TABLE, "value5");
public static final StringProperty VALUE6 = new StringProperty(
TABLE, "value6");
public static final StringProperty VALUE7 = new StringProperty(
TABLE, "value7");
/** Unixtime Metadata was created */
public static final LongProperty CREATION_DATE = new LongProperty(
TABLE, "created");

@ -399,12 +399,6 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<receiver android:name="com.todoroo.astrid.gtasks.GtasksSyncActionExposer">
<intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_SYNC_ACTIONS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.todoroo.astrid.gtasks.GtasksStartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />

@ -69,11 +69,13 @@ import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.sync.ActFmInvoker;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncProvider;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.gtasks.auth.ModernAuthManager;
import com.todoroo.astrid.helper.SyncResultCallbackAdapter;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.SyncV2Service;
import com.todoroo.astrid.service.TaskService;
/**
@ -92,6 +94,8 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
protected TaskService taskService;
@Autowired
protected ActFmPreferenceService actFmPreferenceService;
@Autowired protected SyncV2Service syncService;
private final ActFmInvoker actFmInvoker = new ActFmInvoker();
private Random rand;
@ -475,7 +479,17 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
finish();
if (!noSync) {
new ActFmSyncProvider().synchronize(ActFmLoginActivity.this, showToast);
new Thread() {
@Override
public void run() {
syncService.synchronizeActiveTasks(false, new SyncResultCallbackAdapter() {
@Override
public void finished() {
ContextManager.getContext().sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
}
});
}
}.start();
}
try {

@ -76,8 +76,6 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
startTaskFetcher(manual, callback, finisher);
pushQueued(callback, finisher);
callback.incrementProgress(50);
}
@ -110,6 +108,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
actFmSyncService.fetchActiveTasks(manual, new Runnable() {
@Override
public void run() {
pushQueued(callback, finisher);
callback.incrementProgress(30);
if(finisher.decrementAndGet() == 0)
callback.finished();

@ -75,6 +75,7 @@ public class GtasksFilterExposer extends BroadcastReceiver implements AstridFilt
filter.customWrapperActivity = new ComponentName(ContextManager.getContext(), TaskListWrapperActivity.class);
Bundle extras = new Bundle();
extras.putBoolean(TaskListActivity.TOKEN_OVERRIDE_ANIM, true);
extras.putLong(GtasksListActivity.TOKEN_STORE_ID, list.getId());
filter.customExtras = extras;
return filter;

@ -1,6 +1,7 @@
package com.todoroo.astrid.gtasks;
import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.astrid.data.StoreObject;
@ -27,4 +28,7 @@ public class GtasksList {
public static final IntegerProperty ORDER = new IntegerProperty(StoreObject.TABLE,
StoreObject.VALUE2.name);
public static final LongProperty LAST_SYNC = new LongProperty(StoreObject.TABLE,
StoreObject.VALUE3.name);
}

@ -10,6 +10,7 @@ import com.commonsware.cwac.tlv.TouchListView;
import com.commonsware.cwac.tlv.TouchListView.DropListener;
import com.commonsware.cwac.tlv.TouchListView.SwipeListener;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
@ -18,27 +19,50 @@ import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.DraggableTaskListActivity;
import com.todoroo.astrid.adapter.TaskAdapter.OnCompletedTaskListener;
import com.todoroo.astrid.dao.StoreObjectDao;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.sync.GtasksSyncOnSaveService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
public class GtasksListActivity extends DraggableTaskListActivity {
protected static final int MENU_CLEAR_COMPLETED_ID = MENU_ADDON_INTENT_ID + 1;
public static final String TOKEN_STORE_ID = "storeId";
protected static final int MENU_REFRESH_ID = MENU_SYNC_ID;
private static final String LAST_FETCH_KEY_GTASKS = "gtasksLastFetch";
@Autowired private StoreObjectDao storeObjectDao;
@Autowired private GtasksTaskListUpdater gtasksTaskListUpdater;
@Autowired private GtasksSyncOnSaveService gtasksSyncOnSaveService;
@Autowired private GtasksSyncService gtasksSyncService;
@Autowired private GtasksMetadataService gtasksMetadataService;
@Autowired private GtasksPreferenceService gtasksPreferenceService;
private StoreObject list;
@Override
protected IntegerProperty getIndentProperty() {
return GtasksMetadata.INDENT;
}
private static final Property<?>[] LIST_PROPERTIES = new Property<?>[] {
StoreObject.ID,
StoreObject.TYPE,
GtasksList.REMOTE_ID,
GtasksList.ORDER,
GtasksList.NAME,
GtasksList.LAST_SYNC
};
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
public void onActivityCreated(Bundle icicle) {
super.onActivityCreated(icicle);
getTouchListView().setDropListener(dropListener);
getTouchListView().setSwipeListener(swipeListener);
@ -57,6 +81,9 @@ public class GtasksListActivity extends DraggableTaskListActivity {
setCompletedForItemAndSubtasks(item, newState);
}
});
long storeObjectId = getActivity().getIntent().getLongExtra(TOKEN_STORE_ID, 0);
list = storeObjectDao.fetch(storeObjectId, LIST_PROPERTIES);
}
private final TouchListView.DropListener dropListener = new DropListener() {
@ -69,7 +96,7 @@ public class GtasksListActivity extends DraggableTaskListActivity {
gtasksTaskListUpdater.moveTo(targetTaskId, -1);
else
gtasksTaskListUpdater.moveTo(targetTaskId, destinationTaskId);
gtasksSyncOnSaveService.triggerMoveForMetadata(gtasksMetadataService.getTaskMetadata(targetTaskId));
gtasksSyncService.triggerMoveForMetadata(gtasksMetadataService.getTaskMetadata(targetTaskId));
loadTaskListContent(true);
}
};
@ -79,7 +106,7 @@ public class GtasksListActivity extends DraggableTaskListActivity {
public void swipeRight(int which) {
long targetTaskId = taskAdapter.getItemId(which);
gtasksTaskListUpdater.indent(targetTaskId, 1);
gtasksSyncOnSaveService.triggerMoveForMetadata(gtasksMetadataService.getTaskMetadata(targetTaskId));
gtasksSyncService.triggerMoveForMetadata(gtasksMetadataService.getTaskMetadata(targetTaskId));
loadTaskListContent(true);
}
@ -87,11 +114,18 @@ public class GtasksListActivity extends DraggableTaskListActivity {
public void swipeLeft(int which) {
long targetTaskId = taskAdapter.getItemId(which);
gtasksTaskListUpdater.indent(targetTaskId, -1);
gtasksSyncOnSaveService.triggerMoveForMetadata(gtasksMetadataService.getTaskMetadata(targetTaskId));
gtasksSyncService.triggerMoveForMetadata(gtasksMetadataService.getTaskMetadata(targetTaskId));
loadTaskListContent(true);
}
};
@Override
protected void initiateAutomaticSync() {
if (list != null && DateUtilities.now() - list.getValue(GtasksList.LAST_SYNC) > DateUtilities.ONE_HOUR) {
syncService.synchronizeList(list, false, syncResultCallback);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
@ -101,12 +135,17 @@ public class GtasksListActivity extends DraggableTaskListActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == MENU_CLEAR_COMPLETED_ID) {
// handle my own menus
switch (item.getItemId()) {
case MENU_REFRESH_ID:
syncService.synchronizeList(list, true, syncResultCallback);
return true;
case MENU_CLEAR_COMPLETED_ID:
clearCompletedTasks();
return true;
} else {
return super.onOptionsItemSelected(item);
}
return super.onOptionsItemSelected(item);
}
private void clearCompletedTasks() {
@ -147,6 +186,17 @@ public class GtasksListActivity extends DraggableTaskListActivity {
}.start();
}
@Override
protected void addSyncRefreshMenuItem(Menu menu) {
if(gtasksPreferenceService.isLoggedIn()) {
MenuItem item = menu.add(Menu.NONE, MENU_REFRESH_ID, Menu.NONE,
R.string.actfm_TVA_menu_refresh);
item.setIcon(R.drawable.ic_menu_refresh);
} else {
super.addSyncRefreshMenuItem(menu);
}
}
private void setCompletedForItemAndSubtasks(Task item, boolean completedState) {
final TodorooCursor<Task> tasks = taskService.fetchFiltered(filter.sqlQuery, null, Task.ID, Task.COMPLETION_DATE);
final long itemId = item.getId();

@ -16,7 +16,7 @@ import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.api.FilterWithCustomIntent;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.gtasks.api.GtasksService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator;
public class GtasksListAdder extends Activity {
@ -51,7 +51,7 @@ public class GtasksListAdder extends Activity {
String token = gtasksPreferenceService.getToken();
try {
token = GtasksTokenValidator.validateAuthToken(activity, token);
GtasksService service = new GtasksService(token);
GtasksInvoker service = new GtasksInvoker(token);
String title = editText.getText().toString();
if (TextUtils.isEmpty(title)) //Don't create a list without a title
return;

@ -37,6 +37,12 @@ public class GtasksMetadata {
public static final LongProperty ORDER = new LongProperty(Metadata.TABLE,
Metadata.VALUE5.name);
public static final LongProperty GTASKS_ORDER = new LongProperty(Metadata.TABLE,
Metadata.VALUE6.name);
public static final LongProperty LAST_SYNC = new LongProperty(Metadata.TABLE,
Metadata.VALUE7.name);
/**
* Creates default GTasks metadata item
* @param taskId if > 0, will set metadata task field
@ -49,7 +55,7 @@ public class GtasksMetadata {
String defaultList = Preferences.getStringValue(GtasksPreferenceService.PREF_DEFAULT_LIST);
if(defaultList == null)
defaultList = ""; //$NON-NLS-1$
defaultList = "@default"; //$NON-NLS-1$
metadata.setValue(LIST_ID, defaultList);
metadata.setValue(PARENT_TASK, AbstractModel.NO_ID);

@ -11,6 +11,7 @@ import java.util.concurrent.atomic.AtomicReference;
import android.text.TextUtils;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
@ -75,6 +76,39 @@ public final class GtasksMetadataService extends SyncMetadataService<GtasksTaskC
return GtasksMetadata.ID.neq(""); //$NON-NLS-1$
}
@Override
public void findLocalMatch(GtasksTaskContainer remoteTask) {
if(remoteTask.task.getId() != Task.NO_ID)
return;
TodorooCursor<Metadata> cursor = metadataDao.query(Query.select(Metadata.PROPERTIES).
where(Criterion.and(MetadataCriteria.withKey(getMetadataKey()),
getLocalMatchCriteria(remoteTask))));
try {
if(cursor.getCount() == 0)
return;
cursor.moveToFirst();
remoteTask.task.setId(cursor.get(Metadata.TASK));
remoteTask.gtaskMetadata = new Metadata(cursor);
} finally {
cursor.close();
}
}
public long localIdForGtasksId(String gtasksId) {
TodorooCursor<Metadata> metadata = metadataDao.query(Query.select(Metadata.TASK).where(
Criterion.and(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY), GtasksMetadata.ID.eq(gtasksId))));
try {
if (metadata.getCount() > 0) {
metadata.moveToFirst();
return (new Metadata(metadata).getValue(Metadata.TASK));
} else {
return AbstractModel.NO_ID;
}
} finally {
metadata.close();
}
}
@Override
protected TodorooCursor<Task> filterLocallyUpdated(TodorooCursor<Task> tasks, long lastSyncDate) {
HashSet<Long> taskIds = new HashSet<Long>();
@ -82,8 +116,8 @@ public final class GtasksMetadataService extends SyncMetadataService<GtasksTaskC
taskIds.add(tasks.get(Task.ID));
TodorooCursor<Metadata> metadata = metadataDao.query(Query.select(Metadata.TASK).where(
Criterion.and(MetadataCriteria.withKey(GtasksSyncMetadata.METADATA_KEY),
GtasksSyncMetadata.LAST_SYNC.gt(lastSyncDate))));
Criterion.and(MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
GtasksMetadata.LAST_SYNC.gt(lastSyncDate))));
for(metadata.moveToFirst(); !metadata.isAfterLast(); metadata.moveToNext())
taskIds.remove(metadata.get(Metadata.TASK));

@ -25,10 +25,6 @@ public class GtasksPreferenceService extends SyncProviderUtilities {
return R.string.gtasks_GPr_interval_key;
}
public int getSyncOnSaveKey() {
return R.string.gtasks_GPr_sync_on_save_key;
}
public boolean migrationHasOccurred() {
return Preferences.getBoolean(PREF_MIGRATION_HAS_OCCURRED, false);
}

@ -1,9 +1,6 @@
package com.todoroo.astrid.gtasks;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
@ -59,25 +56,4 @@ public class GtasksPreferences extends SyncProviderPreferences {
super.onPause();
new GtasksBackgroundService().scheduleService();
}
@Override
public void updatePreferences(Preference preference, Object value) {
final Resources r = getResources();
if (r.getString(R.string.gtasks_GPr_sync_on_save_key).equals(preference.getKey())) {
preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference changed, Object newValue) {
if (((Boolean) newValue).booleanValue()) {
startSync();
}
return true;
}
});
} else {
super.updatePreferences(preference, value);
}
}
}

@ -1,49 +0,0 @@
package com.todoroo.astrid.gtasks;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.data.Metadata;
/**
* Metadata entries for synchronizing a GTasks Task
* @author Tim Su <tim@todoroo.com>
*
*/
public class GtasksSyncMetadata {
/** metadata key */
public static final String METADATA_KEY = "gtasks-sync"; //$NON-NLS-1$
/** last sync date*/
public static final LongProperty LAST_SYNC = new LongProperty(Metadata.TABLE,
Metadata.VALUE1.name);
/**
* Helper to set value
* @param metadataDao
* @param id
* @param property
* @param now
*/
public static <T> void set(MetadataDao metadataDao, long taskId,
Property<T> property, T value) {
TodorooCursor<Metadata> cursor = metadataDao.query(Query.select(Metadata.PROPERTIES).
where(MetadataCriteria.byTaskAndwithKey(taskId, METADATA_KEY)));
Metadata metadata = new Metadata();
if(cursor.getCount() == 0) {
metadata.setValue(Metadata.TASK, taskId);
metadata.setValue(Metadata.KEY, METADATA_KEY);
} else {
cursor.moveToFirst();
metadata.readFromCursor(cursor);
}
metadata.setValue(property, value);
metadataDao.persist(metadata);
}
}

@ -10,10 +10,15 @@ import java.util.concurrent.atomic.AtomicReference;
import android.text.TextUtils;
import android.util.Log;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
@ -23,6 +28,7 @@ public class GtasksTaskListUpdater {
@Autowired private GtasksListService gtasksListService;
@Autowired private GtasksMetadataService gtasksMetadataService;
@Autowired private MetadataDao metadataDao;
/** map of task -> parent task */
final HashMap<Long, Long> parents = new HashMap<Long, Long>();
@ -321,6 +327,28 @@ public class GtasksTaskListUpdater {
});
}
public void correctOrderAndIndentForList(String listId) {
orderAndIndentHelper(listId, new AtomicLong(0L), Task.NO_ID, 0);
}
private void orderAndIndentHelper(String listId, AtomicLong order, long parent, int indentLevel) {
TodorooCursor<Metadata> metadata = metadataDao.query(Query.select(Metadata.PROPERTIES)
.where(Criterion.and(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY), GtasksMetadata.LIST_ID.eq(listId), GtasksMetadata.PARENT_TASK.eq(parent)))
.orderBy(Order.asc(GtasksMetadata.GTASKS_ORDER)));
if (metadata.getCount() > 0) {
Metadata curr = new Metadata();
for (metadata.moveToFirst(); !metadata.isAfterLast(); metadata.moveToNext()) {
curr.readFromCursor(metadata);
curr.setValue(GtasksMetadata.INDENT, indentLevel);
curr.setValue(GtasksMetadata.ORDER, order.getAndIncrement());
metadataDao.saveExisting(curr);
orderAndIndentHelper(listId, order, curr.getValue(Metadata.TASK), indentLevel + 1);
}
}
}
/**
* Create a local tree of tasks to expedite sibling and parent lookups
*/

@ -13,7 +13,7 @@ public class CreateRequest extends PushRequest {
private String parent;
private String priorSiblingId;
public CreateRequest(GtasksService service, String listId, Task toUpdate, String parent, String priorSiblingId) {
public CreateRequest(GtasksInvoker service, String listId, Task toUpdate, String parent, String priorSiblingId) {
super(service, listId, toUpdate);
this.parent = parent;
this.priorSiblingId = priorSiblingId;

@ -9,7 +9,7 @@ import com.google.api.client.util.DateTime;
public class GtasksApiUtilities {
public static DateTime unixTimeToGtasksCompletionTime(long time) {
if (time <= 0) return null;
if (time < 0) return null;
return new DateTime(new Date(time), TimeZone.getDefault());
}
@ -44,7 +44,7 @@ public class GtasksApiUtilities {
* @return
*/
public static DateTime unixTimeToGtasksDueDate(long time) {
if (time <= 0) return null;
if (time < 0) return null;
Date date = new Date(time);
date.setHours(0);
date.setMinutes(0);

@ -31,7 +31,7 @@ import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator;
*
*/
@SuppressWarnings("nls")
public class GtasksService {
public class GtasksInvoker {
private Tasks service;
private GoogleAccessProtectedResource accessProtectedResource;
private String token;
@ -43,7 +43,7 @@ public class GtasksService {
public static final String AUTH_TOKEN_TYPE = "Manage your tasks"; //"oauth2:https://www.googleapis.com/auth/tasks";
public GtasksService(String authToken) {
public GtasksInvoker(String authToken) {
DependencyInjectionService.getInstance().inject(this);
authenticate(authToken);
}
@ -162,15 +162,16 @@ public class GtasksService {
}
}
public com.google.api.services.tasks.model.Tasks getAllGtasksFromTaskList(TaskList list, boolean includeDeleted, boolean includeHidden) throws IOException {
return getAllGtasksFromListId(list.getId(), includeDeleted, includeHidden);
public com.google.api.services.tasks.model.Tasks getAllGtasksFromTaskList(TaskList list, boolean includeDeleted, boolean includeHidden, long lastSyncDate) throws IOException {
return getAllGtasksFromListId(list.getId(), includeDeleted, includeHidden, lastSyncDate);
}
public com.google.api.services.tasks.model.Tasks getAllGtasksFromListId(String listId, boolean includeDeleted, boolean includeHidden) throws IOException {
public com.google.api.services.tasks.model.Tasks getAllGtasksFromListId(String listId, boolean includeDeleted, boolean includeHidden, long lastSyncDate) throws IOException {
com.google.api.services.tasks.model.Tasks toReturn = null;
List request = service.tasks.list(listId);
request.setShowDeleted(includeDeleted);
request.setShowHidden(includeHidden);
request.setUpdatedMin(GtasksApiUtilities.unixTimeToGtasksCompletionTime(lastSyncDate).toStringRfc3339());
try {
toReturn = request.execute();
} catch (IOException e) {

@ -14,7 +14,7 @@ public class MoveListRequest extends PushRequest {
private String dstList;
private final String newParent;
public MoveListRequest(GtasksService service, String idTask, String srcList, String dstList, String newParent) {
public MoveListRequest(GtasksInvoker service, String idTask, String srcList, String dstList, String newParent) {
super(service, srcList, new Task());
this.idTaskToMove = idTask;
this.dstList = dstList;

@ -14,7 +14,7 @@ public class MoveRequest extends PushRequest {
private String parentId;
private String priorSiblingId;
public MoveRequest(GtasksService service, String taskId, String destinationList, String parentId, String priorSiblingId) {
public MoveRequest(GtasksInvoker service, String taskId, String destinationList, String parentId, String priorSiblingId) {
super(service, destinationList, null);
this.taskId = taskId;
this.parentId = parentId;

@ -12,9 +12,9 @@ import com.google.api.services.tasks.model.Task;
public abstract class PushRequest {
protected String listId;
protected Task toPush;
protected GtasksService service;
protected GtasksInvoker service;
public PushRequest(GtasksService service, String listId, Task toPush) {
public PushRequest(GtasksInvoker service, String listId, Task toPush) {
this.service = service;
this.listId = listId;
this.toPush = toPush;
@ -34,10 +34,10 @@ public abstract class PushRequest {
this.toPush = toPush;
}
public GtasksService getService() {
public GtasksInvoker getService() {
return service;
}
public void setService(GtasksService service) {
public void setService(GtasksInvoker service) {
this.service = service;
}

@ -11,7 +11,7 @@ import com.google.api.services.tasks.model.Task;
*/
public class UpdateRequest extends PushRequest {
public UpdateRequest(GtasksService service, String listId, Task toUpdate) {
public UpdateRequest(GtasksInvoker service, String listId, Task toUpdate) {
super(service, listId, toUpdate);
}

@ -44,11 +44,13 @@ import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.gtasks.GtasksBackgroundService;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.GtasksService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.helper.SyncResultCallbackAdapter;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.SyncV2Service;
/**
* This activity allows users to sign in or log in to Google Tasks
@ -61,6 +63,8 @@ public class GtasksLoginActivity extends ListActivity {
@Autowired private GtasksPreferenceService gtasksPreferenceService;
@Autowired private SyncV2Service syncService;
// --- ui initialization
private GoogleAccountManager accountManager;
@ -139,7 +143,7 @@ public class GtasksLoginActivity extends ListActivity {
}.start();
}
};
accountManager.manager.getAuthToken(a, GtasksService.AUTH_TOKEN_TYPE, null, this, callback, null);
accountManager.manager.getAuthToken(a, GtasksInvoker.AUTH_TOKEN_TYPE, null, this, callback, null);
}
private void onAuthCancel() {
@ -157,8 +161,17 @@ public class GtasksLoginActivity extends ListActivity {
* Perform synchronization
*/
protected void synchronize() {
startService(new Intent(null, null,
this, GtasksBackgroundService.class));
new Thread() {
@Override
public void run() {
syncService.synchronizeActiveTasks(false, new SyncResultCallbackAdapter() {
@Override
public void finished() {
ContextManager.getContext().sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
}
});
}
}.start();
setResult(RESULT_OK);
finish();
}

@ -14,7 +14,7 @@ import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.GoogleTasksException;
import com.todoroo.astrid.gtasks.api.GtasksService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
public class GtasksTokenValidator {
@ -27,7 +27,7 @@ public class GtasksTokenValidator {
public static String validateAuthToken(Context c, String token) throws GoogleTasksException {
GoogleAccountManager accountManager = new GoogleAccountManager(ContextManager.getContext());
GtasksService testService = new GtasksService(token);
GtasksInvoker testService = new GtasksInvoker(token);
try {
testService.ping();
return token;
@ -39,13 +39,13 @@ public class GtasksTokenValidator {
}
accountManager.invalidateAuthToken(token);
AccountManagerFuture<Bundle> future = accountManager.manager.getAuthToken(a, GtasksService.AUTH_TOKEN_TYPE, false, null, null);
AccountManagerFuture<Bundle> future = accountManager.manager.getAuthToken(a, GtasksInvoker.AUTH_TOKEN_TYPE, false, null, null);
try {
if (future.getResult().containsKey(AccountManager.KEY_AUTHTOKEN)) {
Bundle result = future.getResult();
token = result.getString(AccountManager.KEY_AUTHTOKEN);
testService = new GtasksService(token);
testService = new GtasksInvoker(token);
try { //Make sure the new token works--if not, we may have network problems
testService.ping();
return token;
@ -54,12 +54,12 @@ public class GtasksTokenValidator {
String manufacturer = android.os.Build.MANUFACTURER.toLowerCase();
if (!manufacturer.contains("samsung")) { // Try with the notifyAuthFailure set to true in case it was that that broke things
accountManager.invalidateAuthToken(token);
future = accountManager.manager.getAuthToken(a, GtasksService.AUTH_TOKEN_TYPE, true, null, null);
future = accountManager.manager.getAuthToken(a, GtasksInvoker.AUTH_TOKEN_TYPE, true, null, null);
try {
if (future.getResult().containsKey(AccountManager.KEY_AUTHTOKEN)) {
result = future.getResult();
token = result.getString(AccountManager.KEY_AUTHTOKEN);
testService = new GtasksService(token);
testService = new GtasksInvoker(token);
try {
testService.ping();
return token;

@ -18,7 +18,7 @@ import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.GtasksService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.service.TaskService;
@ -37,7 +37,7 @@ public class GtasksLegacyMigrator {
@Autowired GtasksListService gtasksListService;
@Autowired GtasksPreferenceService gtasksPreferenceService;
private final GtasksService gtasksService;
private final GtasksInvoker gtasksService;
private final GtasksListService listService;
private final TaskLists allLists;
@ -45,7 +45,7 @@ public class GtasksLegacyMigrator {
AstridDependencyInjector.initialize();
}
public GtasksLegacyMigrator(GtasksService service,GtasksListService listService, TaskLists allLists) {
public GtasksLegacyMigrator(GtasksInvoker service,GtasksListService listService, TaskLists allLists) {
DependencyInjectionService.getInstance().inject(this);
this.gtasksService = service;
this.listService = listService;
@ -76,7 +76,7 @@ public class GtasksLegacyMigrator {
defaultListId = list.getId();
}
Tasks allTasks = gtasksService.getAllGtasksFromListId(list.getId(), false, false);
Tasks allTasks = gtasksService.getAllGtasksFromListId(list.getId(), false, false, 0);
List<com.google.api.services.tasks.model.Task> tasksItems = allTasks.getItems();
if (tasksItems != null) {

@ -51,7 +51,7 @@ import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.api.CreateRequest;
import com.todoroo.astrid.gtasks.api.GoogleTasksException;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.MoveListRequest;
import com.todoroo.astrid.gtasks.api.MoveRequest;
import com.todoroo.astrid.gtasks.api.PushRequest;
@ -75,9 +75,9 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
@Autowired private GtasksTaskListUpdater gtasksTaskListUpdater;
/** google task service fields */
private GtasksService taskService = null;
private GtasksInvoker taskService = null;
public GtasksService getGtasksService() {
public GtasksInvoker getGtasksService() {
return taskService;
}
@ -124,7 +124,7 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
authToken = GtasksTokenValidator.validateAuthToken(ContextManager.getContext(), authToken);
gtasksPreferenceService.setToken(authToken);
taskService = new GtasksService(authToken);
taskService = new GtasksInvoker(authToken);
performSync();
} catch (IllegalStateException e) {
// occurs when application was closed
@ -342,7 +342,7 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
String listId = dashboard.getValue(GtasksList.REMOTE_ID);
if(Constants.DEBUG)
Log.e("gtasks-debug", "ACTION: getTasks, " + listId);
List<com.google.api.services.tasks.model.Task> remoteTasks = taskService.getAllGtasksFromListId(listId, includeDeleted, includeHidden).getItems();
List<com.google.api.services.tasks.model.Task> remoteTasks = taskService.getAllGtasksFromListId(listId, includeDeleted, includeHidden, 0).getItems();
addRemoteTasksToList(remoteTasks, listId, list);
} catch (Exception e) {
handleException("read-remotes", e, false);

@ -9,7 +9,6 @@ import android.text.TextUtils;
import com.todoroo.andlib.data.DatabaseDao.ModelUpdateListener;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
@ -21,16 +20,15 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksSyncMetadata;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.api.CreateRequest;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.MoveRequest;
import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.utility.Flags;
public final class GtasksSyncOnSaveService {
public final class GtasksSyncService {
@Autowired MetadataService metadataService;
@Autowired MetadataDao metadataDao;
@ -39,7 +37,7 @@ public final class GtasksSyncOnSaveService {
@Autowired GtasksPreferenceService gtasksPreferenceService;
@Autowired GtasksTaskListUpdater gtasksTaskListUpdater;
public GtasksSyncOnSaveService() {
public GtasksSyncService() {
DependencyInjectionService.getInstance().inject(this);
}
@ -75,13 +73,14 @@ public final class GtasksSyncOnSaveService {
continue;
}
try {
if (syncOnSaveEnabled() && !gtasksPreferenceService.isOngoing()) {
if (!gtasksPreferenceService.isOngoing()) {
GtasksInvoker invoker = new GtasksInvoker(gtasksPreferenceService.getToken());
if (op instanceof TaskPushOp) {
TaskPushOp taskPush = (TaskPushOp)op;
pushTaskOnSave(taskPush.model, taskPush.model.getSetValues());
pushTaskOnSave(taskPush.model, taskPush.model.getSetValues(), invoker, true);
} else if (op instanceof MoveOp) {
MoveOp move = (MoveOp)op;
pushMetadataOnSave(move.metadata);
pushMetadataOnSave(move.metadata, invoker);
}
}
} catch (IOException e){
@ -93,7 +92,7 @@ public final class GtasksSyncOnSaveService {
taskDao.addListener(new ModelUpdateListener<Task>() {
public void onModelUpdated(final Task model) {
if (!syncOnSaveEnabled())
if(Flags.checkAndClear(Flags.GTASKS_SUPPRESS_SYNC))
return;
if (gtasksPreferenceService.isOngoing()) //Don't try and sync changes that occur during a normal sync
return;
@ -102,8 +101,6 @@ public final class GtasksSyncOnSaveService {
return;
if (!checkValuesForProperties(setValues, TASK_PROPERTIES)) //None of the properties we sync were updated
return;
if(Flags.checkAndClear(Flags.GTASKS_SUPPRESS_SYNC))
return;
operationQueue.offer(new TaskPushOp((Task)model.clone()));
}
@ -133,7 +130,7 @@ public final class GtasksSyncOnSaveService {
public void triggerMoveForMetadata(final Metadata metadata) {
if (!syncOnSaveEnabled())
if (Flags.checkAndClear(Flags.GTASKS_SUPPRESS_SYNC))
return;
if (!metadata.getValue(Metadata.KEY).equals(GtasksMetadata.METADATA_KEY)) //Don't care about non-gtasks metadata
return;
@ -141,8 +138,6 @@ public final class GtasksSyncOnSaveService {
return;
if (!checkForToken())
return;
if (Flags.checkAndClear(Flags.GTASKS_SUPPRESS_SYNC))
return;
operationQueue.offer(new MoveOp(metadata));
}
@ -150,23 +145,18 @@ public final class GtasksSyncOnSaveService {
/**
* Synchronize with server when data changes
*/
private void pushTaskOnSave(Task task, ContentValues values) throws IOException {
public void pushTaskOnSave(Task task, ContentValues values, GtasksInvoker invoker, boolean sleep) throws IOException {
if (sleep)
AndroidUtilities.sleepDeep(1000L); //Wait for metadata to be saved
Metadata gtasksMetadata = gtasksMetadataService.getTaskMetadata(task.getId());
com.google.api.services.tasks.model.Task remoteModel = null;
boolean newlyCreated = false;
//Initialize the gtasks api service
String token = gtasksPreferenceService.getToken();
token = GtasksTokenValidator.validateAuthToken(ContextManager.getContext(), token);
gtasksPreferenceService.setToken(token);
GtasksService gtasksService = new GtasksService(token);
String remoteId = null;
String listId = Preferences.getStringValue(GtasksPreferenceService.PREF_DEFAULT_LIST);
if (listId == null) {
listId = gtasksService.getGtaskList("@default").getId(); //$NON-NLS-1$
listId = "@default"; //$NON-NLS-1$
Preferences.setString(GtasksPreferenceService.PREF_DEFAULT_LIST, listId);
}
@ -184,7 +174,7 @@ public final class GtasksSyncOnSaveService {
} else { //update case
remoteId = gtasksMetadata.getValue(GtasksMetadata.ID);
listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
remoteModel = gtasksService.getGtask(listId, remoteId);
remoteModel = invoker.getGtask(listId, remoteId);
}
//If task was newly created but without a title, don't sync--we're in the middle of
@ -205,7 +195,7 @@ public final class GtasksSyncOnSaveService {
if (values.containsKey(Task.NOTES.name)) {
remoteModel.setNotes(task.getValue(Task.NOTES));
}
if (values.containsKey(Task.DUE_DATE.name)) {
if (values.containsKey(Task.DUE_DATE.name) && task.hasDueDate()) {
remoteModel.setDue(GtasksApiUtilities.unixTimeToGtasksDueDate(task.getValue(Task.DUE_DATE)));
}
if (values.containsKey(Task.COMPLETION_DATE.name)) {
@ -219,85 +209,44 @@ public final class GtasksSyncOnSaveService {
}
if (!newlyCreated) {
gtasksService.updateGtask(listId, remoteModel);
invoker.updateGtask(listId, remoteModel);
} else {
String parent = gtasksMetadataService.getRemoteParentId(gtasksMetadata);
String priorSibling = gtasksMetadataService.getRemoteSiblingId(listId, gtasksMetadata);
try { //Make sure the parent task exists on the target list
if (parent != null) {
com.google.api.services.tasks.model.Task remoteParent = gtasksService.getGtask(listId, parent);
if (remoteParent == null || (remoteParent.getDeleted() != null && remoteParent.getDeleted().booleanValue()))
parent = null;
}
} catch (IOException e) {
parent = null;
}
try {
if (priorSibling != null) {
com.google.api.services.tasks.model.Task remoteSibling = gtasksService.getGtask(listId, priorSibling);
if (remoteSibling == null || (remoteSibling.getDeleted() != null && remoteSibling.getDeleted().booleanValue()))
priorSibling = null;
}
} catch (IOException e) {
priorSibling = null;
}
com.google.api.services.tasks.model.Task created = gtasksService.createGtask(listId, remoteModel, parent, priorSibling);
CreateRequest create = new CreateRequest(invoker, listId, remoteModel, parent, priorSibling);
com.google.api.services.tasks.model.Task created = create.executePush();
if (created != null) {
//Update the metadata for the newly created task
gtasksMetadata.setValue(GtasksMetadata.ID, created.getId());
gtasksMetadata.setValue(GtasksMetadata.LIST_ID, listId);
metadataService.save(gtasksMetadata);
} else return;
}
task.setValue(Task.MODIFICATION_DATE, DateUtilities.now());
GtasksSyncMetadata.set(metadataDao, task.getId(), GtasksSyncMetadata.LAST_SYNC, DateUtilities.now());
gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now());
metadataService.save(gtasksMetadata);
Flags.set(Flags.GTASKS_SUPPRESS_SYNC);
taskDao.saveExisting(task);
}
private void pushMetadataOnSave(Metadata model) throws IOException {
public void pushMetadataOnSave(Metadata model, GtasksInvoker invoker) throws IOException {
AndroidUtilities.sleepDeep(1000L);
//Initialize the gtasks api service
String token = gtasksPreferenceService.getToken();
token = GtasksTokenValidator.validateAuthToken(ContextManager.getContext(), token);
gtasksPreferenceService.setToken(token);
GtasksService gtasksService = new GtasksService(token);
String taskId = model.getValue(GtasksMetadata.ID);
String listId = model.getValue(GtasksMetadata.LIST_ID);
String parent = gtasksMetadataService.getRemoteParentId(model);
String priorSibling = gtasksMetadataService.getRemoteSiblingId(listId, model);
try { //Make sure the parent task exists on the target list
if (parent != null) {
com.google.api.services.tasks.model.Task remoteParent = gtasksService.getGtask(listId, parent);
if (remoteParent == null || (remoteParent.getDeleted() != null && remoteParent.getDeleted().booleanValue()))
parent = null;
}
} catch (IOException e) {
parent = null;
}
try {
if (priorSibling != null) {
com.google.api.services.tasks.model.Task remoteSibling = gtasksService.getGtask(listId, priorSibling);
if (remoteSibling == null || (remoteSibling.getDeleted() != null && remoteSibling.getDeleted().booleanValue()))
priorSibling = null;
}
} catch (IOException e) {
priorSibling = null;
}
MoveRequest move = new MoveRequest(gtasksService, taskId, listId, parent, priorSibling);
move.push();
MoveRequest move = new MoveRequest(invoker, taskId, listId, parent, priorSibling);
com.google.api.services.tasks.model.Task result = move.push();
// Update order metadata from result
if (result != null) {
model.setValue(GtasksMetadata.GTASKS_ORDER, Long.parseLong(result.getPosition()));
Flags.set(Flags.GTASKS_SUPPRESS_SYNC);
metadataDao.saveExisting(model);
}
private boolean syncOnSaveEnabled() {
return Preferences.getBoolean(gtasksPreferenceService.getSyncOnSaveKey(), false);
}
private boolean checkForToken() {

@ -0,0 +1,274 @@
package com.todoroo.astrid.gtasks.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.json.JSONException;
import android.text.TextUtils;
import com.google.api.services.tasks.model.Tasks;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.StoreObjectDao;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksList;
import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.api.GoogleTasksException;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.SyncV2Service.SyncResultCallback;
import com.todoroo.astrid.service.SyncV2Service.SyncV2Provider;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.utility.Flags;
public class GtasksSyncV2Provider extends SyncV2Provider {
@Autowired TaskService taskService;
@Autowired StoreObjectDao storeObjectDao;
@Autowired GtasksPreferenceService gtasksPreferenceService;
@Autowired GtasksSyncService gtasksSyncService;
@Autowired GtasksListService gtasksListService;
@Autowired GtasksMetadataService gtasksMetadataService;
@Autowired GtasksTaskListUpdater gtasksTaskListUpdater;
static {
AstridDependencyInjector.initialize();
}
public GtasksSyncV2Provider() {
DependencyInjectionService.getInstance().inject(this);
}
@Override
public String getName() {
return ContextManager.getString(R.string.gtasks_GPr_header);
}
@Override
public boolean isActive() {
return gtasksPreferenceService.isLoggedIn();
}
@Override
public void synchronizeActiveTasks(boolean manual, final SyncResultCallback callback) {
callback.started();
callback.incrementMax(100);
new Thread(new Runnable() {
public void run() {
callback.incrementProgress(50);
String authToken = getValidatedAuthToken();
final GtasksInvoker invoker = new GtasksInvoker(authToken);
try {
gtasksListService.updateLists(invoker.allGtaskLists());
} catch (IOException e) {
// error updating lists
} finally {
callback.incrementMax(25);
}
StoreObject[] lists = gtasksListService.getLists();
final AtomicInteger finisher = new AtomicInteger(lists.length);
pushUpdated(invoker, callback);
for (final StoreObject list : lists) {
new Thread(new Runnable() {
@Override
public void run() {
synchronizeListHelper(list, invoker, callback);
if (finisher.decrementAndGet() == 0) {
callback.finished();
}
}
}).start();
}
}
}).start();
}
private void pushUpdated(GtasksInvoker invoker, SyncResultCallback callback) {
TodorooCursor<Task> queued = taskService.query(Query.select(Task.PROPERTIES).join(Join.left(Metadata.TABLE, Task.ID.eq(Metadata.TASK))).where(
Criterion.or(
Criterion.and(MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
Task.MODIFICATION_DATE.gt(GtasksMetadata.LAST_SYNC)),
Metadata.KEY.isNull())));
callback.incrementMax(queued.getCount() * 10);
try {
Task task = new Task();
for (queued.moveToFirst(); !queued.isAfterLast(); queued.moveToNext()) {
task.readFromCursor(queued);
try {
gtasksSyncService.pushTaskOnSave(task, task.getMergedValues(), invoker, false);
} catch (IOException e) {
// Eh
} finally {
callback.incrementProgress(10);
}
}
}
finally {
queued.close();
}
}
@Override
public void synchronizeList(Object list, boolean manual, final SyncResultCallback callback) {
if (!(list instanceof StoreObject))
return;
final StoreObject gtasksList = (StoreObject) list;
if (!GtasksList.TYPE.equals(gtasksList.getValue(StoreObject.TYPE)))
return;
callback.started();
callback.incrementMax(100);
new Thread(new Runnable() {
public void run() {
callback.incrementProgress(50);
try {
String authToken = getValidatedAuthToken();
callback.incrementProgress(25);
final GtasksInvoker service = new GtasksInvoker(authToken);
synchronizeListHelper(gtasksList, service, callback);
} finally {
callback.incrementProgress(25);
callback.finished();
}
}
}).start();
}
private String getValidatedAuthToken() {
String authToken = gtasksPreferenceService.getToken();
try {
authToken = GtasksTokenValidator.validateAuthToken(ContextManager.getContext(), authToken);
if (authToken != null)
gtasksPreferenceService.setToken(authToken);
} catch (GoogleTasksException e) {
authToken = null;
}
return authToken;
}
private void synchronizeListHelper(StoreObject list, GtasksInvoker invoker, SyncResultCallback callback) {
// Do stuff
String listId = list.getValue(GtasksList.REMOTE_ID);
long lastSyncDate;
if (list.containsNonNullValue(GtasksList.LAST_SYNC)) {
lastSyncDate = list.getValue(GtasksList.LAST_SYNC);
} else {
lastSyncDate = 0;
}
boolean includeDeletedAndHidden = lastSyncDate != 0;
try {
Tasks taskList = invoker.getAllGtasksFromListId(listId, includeDeletedAndHidden, includeDeletedAndHidden, lastSyncDate);
List<com.google.api.services.tasks.model.Task> tasks = taskList.getItems();
if (tasks != null) {
callback.incrementMax(tasks.size() * 10);
for (com.google.api.services.tasks.model.Task t : tasks) {
GtasksTaskContainer container = parseRemoteTask(t, listId);
gtasksMetadataService.findLocalMatch(container);
container.gtaskMetadata.setValue(GtasksMetadata.GTASKS_ORDER, Long.parseLong(t.getPosition()));
container.gtaskMetadata.setValue(GtasksMetadata.PARENT_TASK, gtasksMetadataService.localIdForGtasksId(t.getParent()));
container.gtaskMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now());
write(container);
callback.incrementProgress(10);
}
list.setValue(GtasksList.LAST_SYNC, DateUtilities.now());
storeObjectDao.persist(list);
gtasksTaskListUpdater.correctOrderAndIndentForList(listId);
}
} catch (IOException e) {
// Stuff
}
}
/** Create a task container for the given remote task
* @throws JSONException */
private GtasksTaskContainer parseRemoteTask(com.google.api.services.tasks.model.Task remoteTask, String listId) {
Task task = new Task();
ArrayList<Metadata> metadata = new ArrayList<Metadata>();
task.setValue(Task.TITLE, remoteTask.getTitle());
task.setValue(Task.CREATION_DATE, DateUtilities.now());
task.setValue(Task.COMPLETION_DATE, GtasksApiUtilities.gtasksCompletedTimeToUnixTime(remoteTask.getCompleted(), 0));
if (remoteTask.getDeleted() == null || !remoteTask.getDeleted().booleanValue())
task.setValue(Task.DELETION_DATE, 0L);
else if (remoteTask.getDeleted().booleanValue())
task.setValue(Task.DELETION_DATE, DateUtilities.now());
if (remoteTask.getHidden() != null && remoteTask.getHidden().booleanValue())
task.setValue(Task.DELETION_DATE, DateUtilities.now());
long dueDate = GtasksApiUtilities.gtasksDueTimeToUnixTime(remoteTask.getDue(), 0);
long createdDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, dueDate);
task.setValue(Task.DUE_DATE, createdDate);
task.setValue(Task.NOTES, remoteTask.getNotes());
Metadata gtasksMetadata = GtasksMetadata.createEmptyMetadata(AbstractModel.NO_ID);
gtasksMetadata.setValue(GtasksMetadata.ID, remoteTask.getId());
gtasksMetadata.setValue(GtasksMetadata.LIST_ID, listId);
GtasksTaskContainer container = new GtasksTaskContainer(task, metadata,
gtasksMetadata);
return container;
}
private void write(GtasksTaskContainer task) throws IOException {
// merge astrid dates with google dates
if(task.task.isSaved()) {
Task local = PluginServices.getTaskService().fetchById(task.task.getId(), Task.DUE_DATE, Task.COMPLETION_DATE);
mergeDates(task.task, local);
if(task.task.isCompleted() && !local.isCompleted())
StatisticsService.reportEvent(StatisticsConstants.GTASKS_TASK_COMPLETED);
} else { // Set default reminders for remotely created tasks
TaskDao.setDefaultReminders(task.task);
}
if (!TextUtils.isEmpty(task.task.getValue(Task.TITLE))) {
Flags.set(Flags.GTASKS_SUPPRESS_SYNC);
gtasksMetadataService.saveTaskAndMetadata(task);
}
}
private void mergeDates(Task remote, Task local) {
if(remote.hasDueDate() && local.hasDueTime()) {
Date newDate = new Date(remote.getValue(Task.DUE_DATE));
Date oldDate = new Date(local.getValue(Task.DUE_DATE));
newDate.setHours(oldDate.getHours());
newDate.setMinutes(oldDate.getMinutes());
newDate.setSeconds(oldDate.getSeconds());
long setDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME,
newDate.getTime());
remote.setValue(Task.DUE_DATE, setDate);
}
}
}

@ -3,9 +3,10 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:astrid="http://schemas.android.com/apk/res/com.timsu.astrid"
android:layout_width="fill_parent"
android:layout_height="52dip"
android:layout_height="70dip"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- importance -->
@ -28,64 +29,61 @@
<RelativeLayout android:id="@+id/rowBody"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_height="fill_parent"
android:background="@android:drawable/list_selector_background"
android:paddingTop="1dip"
android:paddingLeft="5dip"
android:paddingBottom="1dip">
<!-- completion area -->
<View android:id="@+id/completeArea"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_alignParentRight="true"/>
<!-- completion check-box -->
<CheckBox android:id="@+id/completeBox"
android:layout_width="wrap_content"
android:layout_height="22dip"
<CheckBox
android:id="@+id/completeBox"
android:layout_width="45dip"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="3dip"
android:layout_gravity="top"
android:paddingBottom="2dip"
android:layout_marginLeft="10dip"
android:button="@drawable/btn_check" />
<!-- assignee photo -->
<greendroid.widget.AsyncImageView
android:id="@+id/picture"
android:layout_width="35dip"
android:layout_height="35dip"
android:layout_marginLeft="10dip"
astrid:defaultSrc="@drawable/icn_default_person_image"
android:scaleType="fitCenter"
android:visibility="gone" />
<LinearLayout android:id="@+id/task_row"
<LinearLayout
android:id="@+id/task_row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:paddingLeft="5dip"
android:paddingRight="32dip"
android:orientation="horizontal">
android:layout_height="fill_parent"
android:layout_alignTop="@id/completeBox"
android:layout_toRightOf="@id/completeBox"
android:orientation="horizontal"
android:paddingLeft="5dip" >
<!-- task name -->
<TextView android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100"
style="@style/TextAppearance.TAd_ItemTitle"/>
<!-- assignee photo -->
<greendroid.widget.AsyncImageView android:id="@+id/picture"
android:layout_width="35dip"
<TextView
android:id="@+id/title"
style="@style/TextAppearance.TAd_ItemTitle"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dip"
android:scaleType="fitCenter"
astrid:defaultSrc="@drawable/icn_default_person_image"
android:visibility="gone"/>
</LinearLayout>
android:layout_weight="100"
android:gravity="center_vertical"
android:maxLines="2" />
<!-- due date -->
<TextView android:id="@+id/dueDate"
<TextView
android:id="@+id/dueDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/task_row"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:paddingRight="5dip"
android:singleLine="true"/>
android:layout_marginRight="4dip"
android:gravity="center_vertical|right" />
</LinearLayout>
<!-- details line 1 -->
<TextView android:id="@+id/details1"

@ -3,7 +3,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100">
android:layout_weight="100"
style="@style/Content">
<!-- No Tasks label -->
<TextView android:id="@android:id/empty"

@ -313,9 +313,6 @@
<string name="gtasks_GPr_interval_key">gtasks_sync_freq</string>
<string name="gtasks_GPr_sync_on_save_key">gtasks_sync_on_save</string>
<!-- ========================================================== SHARING == -->
<string name="actfm_APr_interval_key">actfm_sync_freq</string>

@ -88,10 +88,6 @@
<!-- GTasks Preferences Title -->
<string name="gtasks_GPr_header">Google Tasks (Beta!)</string>
<string name="gtasks_GPr_sync_on_save">Sync on Save</string>
<string name="gtasks_GPr_sync_on_save_summary">Sync individual tasks as they are saved</string>
<!-- ================================================ Synchronization == -->
<!-- title for notification tray when synchronizing -->

@ -22,11 +22,6 @@
android:entryValues="@array/sync_SPr_interval_values"
android:title="@string/sync_SPr_interval_title" />
<com.todoroo.astrid.ui.MultilineCheckboxPreference
android:key="@string/gtasks_GPr_sync_on_save_key"
android:title="@string/gtasks_GPr_sync_on_save"
android:summary="@string/gtasks_GPr_sync_on_save_summary" />
</PreferenceCategory>
<PreferenceCategory

@ -10,7 +10,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.TextView;
import com.commonsware.cwac.tlv.TouchListView;
import com.timsu.astrid.R;
@ -71,8 +70,6 @@ public class DraggableTaskListActivity extends TaskListActivity {
sqlQueryTemplate.set(SortHelper.adjustQueryForFlagsAndSort(filter.sqlQuery,
sortFlags, sortSort));
((TextView)getView().findViewById(R.id.listLabel)).setText(filter.title);
// perform query
TodorooCursor<Task> currentCursor = taskService.fetchFiltered(
sqlQueryTemplate.get(), null, getProperties());
@ -114,6 +111,11 @@ public class DraggableTaskListActivity extends TaskListActivity {
applyListenersToRowBody = true;
}
@Override
protected ViewHolder getTagFromCheckBox(View v) {
return (ViewHolder)((View)v.getParent()).getTag();
}
@Override
public synchronized void setFieldContentsAndVisibility(View view) {
super.setFieldContentsAndVisibility(view);

@ -211,7 +211,7 @@ public class TaskListActivity extends ListFragment implements OnScrollListener,
private final TaskListContextMenuExtensionLoader contextMenuExtensionLoader = new TaskListContextMenuExtensionLoader();
private SyncResultCallback syncResultCallback;
protected SyncResultCallback syncResultCallback;
private VoiceInputAssistant voiceInputAssistant;
// --- fragment handling variables

@ -894,7 +894,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
int[] location = new int[2];
v.getLocationOnScreen(location);
ViewHolder viewHolder = (ViewHolder)((View)v.getParent()).getTag();
ViewHolder viewHolder = getTagFromCheckBox(v);
if(Math.abs(location[1] + lastTouchYRawY.getLeft() - lastTouchYRawY.getRight()) > 10) {
viewHolder.completeBox.setChecked(!viewHolder.completeBox.isChecked());
@ -911,6 +911,10 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
}
};
protected ViewHolder getTagFromCheckBox(View v) {
return (ViewHolder)((View)v.getParent()).getTag();
}
private final class QuickActionListener implements OnQuickActionClickListener {
private final HashMap<Integer, TaskAction> positionActionMap =
new HashMap<Integer, TaskAction>(2);

@ -37,7 +37,7 @@ public class Database extends AbstractDatabase {
* Database version number. This variable must be updated when database
* tables are updated, as it determines whether a database needs updating.
*/
public static final int VERSION = 18;
public static final int VERSION = 19;
/**
* Database name (must be unique)
@ -232,6 +232,14 @@ public class Database extends AbstractDatabase {
} catch (SQLiteException e) {
Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e);
}
case 18: try {
database.execSQL("ALTER TABLE " + Metadata.TABLE.name + " ADD " +
Metadata.VALUE6.accept(visitor, null));
database.execSQL("ALTER TABLE " + Metadata.TABLE.name + " ADD " +
Metadata.VALUE7.accept(visitor, null));
} catch (SQLiteException e) {
Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e);
}
return true;
}

@ -22,7 +22,7 @@ import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.sync.GtasksSyncOnSaveService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.service.abtesting.ABOptions;
import com.todoroo.astrid.service.abtesting.FeatureFlipper;
@ -93,7 +93,7 @@ public class AstridDependencyInjector extends AbstractDependencyInjector {
injectables.put("gtasksListService", GtasksListService.class);
injectables.put("gtasksMetadataService", GtasksMetadataService.class);
injectables.put("gtasksTaskListUpdater", GtasksTaskListUpdater.class);
injectables.put("gtasksSyncOnSaveService", GtasksSyncOnSaveService.class);
injectables.put("gtasksSyncService", GtasksSyncService.class);
// AB testing
injectables.put("abChooser", ABChooser.class);

@ -37,7 +37,7 @@ import com.todoroo.astrid.backup.BackupService;
import com.todoroo.astrid.backup.TasksXmlImporter;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncOnSaveService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.reminders.ReminderStartupReceiver;
@ -83,7 +83,7 @@ public class StartupService {
@Autowired ActFmPreferenceService actFmPreferenceService;
@Autowired GtasksSyncOnSaveService gtasksSyncOnSaveService;
@Autowired GtasksSyncService gtasksSyncService;
@Autowired FeatureFlipper featureFlipper;
@ -198,7 +198,7 @@ public class StartupService {
BackupService.scheduleService(context);
actFmSyncService.initialize();
gtasksSyncOnSaveService.initialize();
gtasksSyncService.initialize();
// get and display update messages
if (finalLatestVersion != 0)

@ -5,6 +5,7 @@ import java.util.Collections;
import java.util.List;
import com.todoroo.astrid.actfm.sync.ActFmSyncV2Provider;
import com.todoroo.astrid.gtasks.sync.GtasksSyncV2Provider;
/**
* SyncV2Service is a simplified synchronization interface for supporting
@ -77,7 +78,8 @@ public class SyncV2Service {
* for responding to sync requests through this new API.
*/
private final SyncV2Provider[] providers = new SyncV2Provider[] {
new ActFmSyncV2Provider()
new ActFmSyncV2Provider(),
new GtasksSyncV2Provider()
};
/**

Loading…
Cancel
Save