diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index 498c34a9b..bf6a56298 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -235,6 +235,7 @@ + diff --git a/astrid/astrid.launch b/astrid/astrid.launch index 18a0852f5..63d8c0eae 100644 --- a/astrid/astrid.launch +++ b/astrid/astrid.launch @@ -5,8 +5,8 @@ - - + + diff --git a/astrid/libs/todoroo-g.jar b/astrid/libs/todoroo-g.jar index fb9d883e7..a415f05d4 100644 Binary files a/astrid/libs/todoroo-g.jar and b/astrid/libs/todoroo-g.jar differ diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksBackgroundService.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksBackgroundService.java new file mode 100644 index 000000000..fec6661c3 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksBackgroundService.java @@ -0,0 +1,37 @@ +package com.todoroo.astrid.gtasks; + +import com.flurry.android.FlurryAgent; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.astrid.gtasks.sync.GtasksSyncProvider; +import com.todoroo.astrid.sync.SyncBackgroundService; +import com.todoroo.astrid.sync.SyncProvider; +import com.todoroo.astrid.sync.SyncProviderUtilities; +import com.todoroo.astrid.utility.Constants; + +public class GtasksBackgroundService extends SyncBackgroundService { + + @Autowired private GtasksPreferenceService gtasksPreferenceService; + + @Override + protected SyncProvider getSyncProvider() { + return new GtasksSyncProvider(); + } + + @Override + protected SyncProviderUtilities getSyncUtilities() { + return gtasksPreferenceService; + } + + @Override + public void onCreate() { + super.onCreate(); + FlurryAgent.onStartSession(this, Constants.FLURRY_KEY); + } + + @Override + public void onDestroy() { + FlurryAgent.onEndSession(this); + super.onDestroy(); + } + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java index 6e90695fb..5396ea374 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java @@ -58,7 +58,6 @@ public class GtasksListService { return LIST_NOT_FOUND; } - @SuppressWarnings("nls") public void updateLists(GoogleTaskListInfo[] remoteLists) { readLists(); for(int i = 0; i < remoteLists.length; i++) { diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java index bb17a7e9d..889968ca3 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java @@ -3,6 +3,7 @@ package com.todoroo.astrid.gtasks; import com.timsu.astrid.R; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.astrid.gtasks.sync.GtasksSyncProvider; import com.todoroo.astrid.sync.SyncProviderPreferences; import com.todoroo.astrid.sync.SyncProviderUtilities; @@ -29,12 +30,12 @@ public class GtasksPreferences extends SyncProviderPreferences { @Override public void startSync() { - // + new GtasksSyncProvider().synchronize(this); } @Override public void logOut() { - // + new GtasksSyncProvider().signOut(); } @Override diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksSyncActionExposer.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksSyncActionExposer.java index 645c2fd85..717bc0235 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksSyncActionExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksSyncActionExposer.java @@ -14,6 +14,7 @@ import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.SyncAction; +import com.todoroo.astrid.sync.SyncBackgroundService; /** * Exposes sync action @@ -32,10 +33,9 @@ public class GtasksSyncActionExposer extends BroadcastReceiver { if(!gtasksPreferenceService.isLoggedIn()) return; - // TODO - Intent syncIntent = new Intent(intent.getAction(), null, - context, GtasksSyncActionExposer.class); - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, syncIntent, 0); + Intent syncIntent = new Intent(SyncBackgroundService.SYNC_ACTION, null, + context, GtasksBackgroundService.class); + PendingIntent pendingIntent = PendingIntent.getService(context, 0, syncIntent, PendingIntent.FLAG_UPDATE_CURRENT); SyncAction syncAction = new SyncAction(context.getString(R.string.gtasks_GPr_header), pendingIntent); diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java index 25ac58dd1..d454ac789 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java @@ -29,9 +29,11 @@ import com.todoroo.andlib.service.ExceptionService; import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DialogUtilities; +import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.StoreObject; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.gtasks.GtasksBackgroundService; import com.todoroo.astrid.gtasks.GtasksList; import com.todoroo.astrid.gtasks.GtasksListService; import com.todoroo.astrid.gtasks.GtasksMetadata; @@ -39,15 +41,14 @@ import com.todoroo.astrid.gtasks.GtasksMetadataService; import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.GtasksPreferences; import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; -import com.todoroo.astrid.producteev.ProducteevBackgroundService; -import com.todoroo.astrid.producteev.ProducteevLoginActivity; -import com.todoroo.astrid.producteev.ProducteevUtilities; import com.todoroo.astrid.producteev.api.ApiServiceException; import com.todoroo.astrid.service.AstridDependencyInjector; +import com.todoroo.astrid.sync.SyncBackgroundService; import com.todoroo.astrid.sync.SyncContainer; import com.todoroo.astrid.sync.SyncProvider; import com.todoroo.astrid.utility.Constants; -import com.todoroo.andlib.utility.Preferences; +import com.todoroo.gtasks.GoogleConnectionManager; +import com.todoroo.gtasks.GoogleLoginException; import com.todoroo.gtasks.GoogleTaskService; import com.todoroo.gtasks.GoogleTaskService.ConvenientTaskCreator; import com.todoroo.gtasks.GoogleTaskTask; @@ -79,7 +80,6 @@ public class GtasksSyncProvider extends SyncProvider { private final HashMap> listActions = new HashMap>(); - static { AstridDependencyInjector.initialize(); } @@ -90,6 +90,8 @@ public class GtasksSyncProvider extends SyncProvider { public GtasksSyncProvider() { super(); DependencyInjectionService.getInstance().inject(this); + // TODO? + gtasksPreferenceService.stopOngoing(); } // ---------------------------------------------------------------------- @@ -155,24 +157,15 @@ public class GtasksSyncProvider extends SyncProvider { try { String authToken = gtasksPreferenceService.getToken(); - String email = "tasktest@todoroo.com"; // TODO - String password = "tasktest0000"; - - taskService = new GoogleTaskService(email, password); - - // check if we have a token & it works - if(authToken != null) { - - taskService.getTaskView(); - performSync(); + final GoogleConnectionManager connectionManager; + if(authToken == null) { + connectionManager = logInHelper(); } else { - if (email == null && password == null) { - // we can't do anything, user is not logged in - } else { - //authToken = null; // TODO set up auth token - performSync(); - } + connectionManager = new GoogleConnectionManager(authToken); } + + taskService = new GoogleTaskService(connectionManager); + performSync(); } catch (IllegalStateException e) { // occurs when application was closed } catch (Exception e) { @@ -182,25 +175,39 @@ public class GtasksSyncProvider extends SyncProvider { } } + private GoogleConnectionManager logInHelper() throws GoogleLoginException, + IOException { + // TODO get email and password or something? + String email = "tasktest@todoroo.com"; + String password = "tasktest0000"; + GoogleConnectionManager connectionManager = new GoogleConnectionManager(email, password); + connectionManager.authenticate(true); + gtasksPreferenceService.setToken(connectionManager.getToken()); + return connectionManager; + } + /** * If user isn't already signed in, show sign in dialog. Else perform sync. */ @Override protected void initiateManual(Activity activity) { String authToken = gtasksPreferenceService.getToken(); - ProducteevUtilities.INSTANCE.stopOngoing(); + gtasksPreferenceService.stopOngoing(); // check if we have a token & it works if(authToken == null) { - // display login-activity - Intent intent = new Intent(activity, ProducteevLoginActivity.class); - activity.startActivityForResult(intent, 0); - } else { - activity.startService(new Intent(ProducteevBackgroundService.SYNC_ACTION, null, - activity, ProducteevBackgroundService.class)); + try { + logInHelper(); + } catch (Exception e) { + handleException("auth", e, true); + } } + + activity.startService(new Intent(SyncBackgroundService.SYNC_ACTION, null, + activity, GtasksBackgroundService.class)); } + // ---------------------------------------------------------------------- // ----------------------------------------------------- synchronization! // ---------------------------------------------------------------------- @@ -227,15 +234,8 @@ public class GtasksSyncProvider extends SyncProvider { } taskService.executeActions(getTasksActions.toArray(new GetTasksAction[getTasksActions.size()])); for(GetTasksAction action : getTasksActions) { - List remoteTasksInList = action.getGoogleTasks(); - for(GoogleTaskTask remoteTask : remoteTasksInList) { - GtasksTaskContainer remote = parseRemoteTask(remoteTask); - // update reminder flags for incoming remote tasks to prevent annoying - if(remote.task.hasDueDate() && remote.task.getValue(Task.DUE_DATE) < DateUtilities.now()) - remote.task.setFlag(Task.REMINDER_FLAGS, Task.NOTIFY_AFTER_DEADLINE, false); - gtasksMetadataService.findLocalMatch(remote); - remoteTasks.add(remote); - } + List list = action.getGoogleTasks(); + readTasksIntoRemoteTasks(list, remoteTasks); } SyncData syncData = populateSyncData(remoteTasks); @@ -255,6 +255,51 @@ public class GtasksSyncProvider extends SyncProvider { } } + private void readTasksIntoRemoteTasks(List list, + ArrayList remoteTasks) { + + int order = 0; + HashMap parents = new HashMap(); + HashMap indentation = new HashMap(); + HashMap parentToPriorSiblingMap = new HashMap(); + + for(GoogleTaskTask remoteTask : list) { + GtasksTaskContainer container = parseRemoteTask(remoteTask); + String id = remoteTask.getId(); + + // update parents, prior sibling + for(String child : remoteTask.getChild_ids()) + parents.put(child, id); + String parent = parents.get(id); // can be null, which means top level task + if(parentToPriorSiblingMap.containsKey(parent)) + container.priorSiblingId = parentToPriorSiblingMap.get(parent); + parentToPriorSiblingMap.put(parent, id); + + // update order, indent + container.gtaskMetadata.setValue(GtasksMetadata.ORDER, order++); + int indent = findIndentation(parents, indentation, id); + indentation.put(id, indent); + container.gtaskMetadata.setValue(GtasksMetadata.INDENT, indent); + + // update reminder flags for incoming remote tasks to prevent annoying + if(container.task.hasDueDate() && container.task.getValue(Task.DUE_DATE) < DateUtilities.now()) + container.task.setFlag(Task.REMINDER_FLAGS, Task.NOTIFY_AFTER_DEADLINE, false); + gtasksMetadataService.findLocalMatch(container); + remoteTasks.add(container); + } + } + + private int findIndentation(HashMap parents, + HashMap indentation, String task) { + if(indentation.containsKey(task)) + return indentation.get(task); + + if(!parents.containsKey(task)) + return 0; + + return findIndentation(parents, indentation, parents.get(task)) + 1; + } + // ---------------------------------------------------------------------- // ------------------------------------------------------------ sync data // ---------------------------------------------------------------------- @@ -299,6 +344,7 @@ public class GtasksSyncProvider extends SyncProvider { ConvenientTaskCreator createdTask; try { createdTask = taskService.createTask(list, local.task.getValue(Task.TITLE)); + createdTask.parentId(local.parentId); } catch (JSONException e) { throw new RuntimeException(e); } @@ -329,12 +375,10 @@ public class GtasksSyncProvider extends SyncProvider { // moving between lists if(remote != null && !idList.equals(remote.gtaskMetadata.getValue(GtasksMetadata.LIST_ID))) { - a.moveTask(idTask, idList, remote.gtaskMetadata.getValue(GtasksMetadata.LIST_ID), null); + batch(a.moveTask(idTask, idList, remote.gtaskMetadata.getValue(GtasksMetadata.LIST_ID), null)); } // other properties - if(shouldTransmit(local, Task.TITLE, remote)) - ((TaskModifier)builder).name(local.task.getValue(Task.TITLE)); if(shouldTransmit(local, Task.DUE_DATE, remote)) builder.taskDate(local.task.getValue(Task.DUE_DATE)); if(shouldTransmit(local, Task.COMPLETION_DATE, remote)) @@ -344,11 +388,15 @@ public class GtasksSyncProvider extends SyncProvider { if(shouldTransmit(local, Task.NOTES, remote)) builder.notes(local.task.getValue(Task.NOTES)); + // moving within a list + if(remote == null || local.parentId != remote.parentId || local.priorSiblingId != remote.priorSiblingId) { + batch(local.gtaskMetadata.getValue(GtasksMetadata.LIST_ID), + l.move(idTask, local.parentId, local.priorSiblingId)); + } + } catch (JSONException e) { throw new GoogleTasksException(e); } - - // TODO indentation } /** Create a task container for the given RtmTaskSeries @@ -363,16 +411,15 @@ public class GtasksSyncProvider extends SyncProvider { task.setValue(Task.DELETION_DATE, remoteTask.isDeleted() ? DateUtilities.now() : 0); long dueDate = remoteTask.getTask_date(); - task.setValue(Task.DUE_DATE, task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, dueDate)); + task.setValue(Task.DUE_DATE, task.createDueDate(Task.URGENCY_SPECIFIC_DAY, dueDate)); task.setValue(Task.NOTES, remoteTask.getNotes()); Metadata gtasksMetadata = GtasksMetadata.createEmptyMetadata(AbstractModel.NO_ID); gtasksMetadata.setValue(GtasksMetadata.LIST_ID, remoteTask.getList_id()); - // TODO gtasksMetadata.setValue(GtasksMetadata.INDENT, remoteTask.???); GtasksTaskContainer container = new GtasksTaskContainer(task, metadata, gtasksMetadata); - + // TODO indent return container; } @@ -406,10 +453,15 @@ public class GtasksSyncProvider extends SyncProvider { @Override protected void push(GtasksTaskContainer local, GtasksTaskContainer remote) throws IOException { try { - TaskModifier modifyTask = l.modifyTask(remote.gtaskMetadata.getValue(GtasksMetadata.ID)); + String id = local.gtaskMetadata.getValue(GtasksMetadata.ID); + TaskModifier modifyTask = l.modifyTask(id); updateTaskHelper(local, remote, modifyTask); + + if(shouldTransmit(local, Task.TITLE, remote)) + modifyTask.name(local.task.getValue(Task.TITLE)); ListAction action = modifyTask.done(); batch(local.gtaskMetadata.getValue(GtasksMetadata.LIST_ID), action); + } catch (JSONException e) { throw new GoogleTasksException(e); } @@ -422,6 +474,11 @@ public class GtasksSyncProvider extends SyncProvider { listActions.get(list).add(action); } + /** add action to batch */ + private void batch(Action action) { + actions.add(action); + } + // ---------------------------------------------------------------------- // --------------------------------------------------------- read / write // ---------------------------------------------------------------------- diff --git a/astrid/rmilk-src/org/weloveastrid/rmilk/MilkUtilities.java b/astrid/rmilk-src/org/weloveastrid/rmilk/MilkUtilities.java index a1018a939..dbdbd6d96 100644 --- a/astrid/rmilk-src/org/weloveastrid/rmilk/MilkUtilities.java +++ b/astrid/rmilk-src/org/weloveastrid/rmilk/MilkUtilities.java @@ -9,6 +9,7 @@ import android.content.SharedPreferences.Editor; import com.timsu.astrid.R; import com.todoroo.andlib.service.ContextManager; +import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.sync.SyncProviderUtilities; /** @@ -27,23 +28,26 @@ public class MilkUtilities extends SyncProviderUtilities { public static final MilkUtilities INSTANCE = new MilkUtilities(); + private static final String EXPORTED_PREFS_CHECKED = IDENTIFIER + "-prefscheck"; + // --- utilities boilerplate private MilkUtilities() { // if no token is set, see if astrid has exported one - if(getToken() == null) { + if(getToken() == null && !Preferences.getBoolean(EXPORTED_PREFS_CHECKED, false)) { try { Context astridContext = ContextManager.getContext().createPackageContext("com.timsu.astrid", 0); SharedPreferences sharedPreferences = astridContext.getSharedPreferences("rtm", 0); + Editor editor = getPrefs().edit(); if(sharedPreferences != null) { String token = sharedPreferences.getString("rmilk_token", null); long lastSyncDate = sharedPreferences.getLong("rmilk_last_sync", 0); - Editor editor = getPrefs().edit(); editor.putString(getIdentifier() + PREF_TOKEN, token); editor.putLong(getIdentifier() + PREF_LAST_SYNC, lastSyncDate); - editor.commit(); } + editor.putBoolean(EXPORTED_PREFS_CHECKED, true); + editor.commit(); } catch (Exception e) { // too bad }