diff --git a/api/src/com/todoroo/astrid/data/User.java b/api/src/com/todoroo/astrid/data/User.java index 308f94e38..0d6d6e2cc 100644 --- a/api/src/com/todoroo/astrid/data/User.java +++ b/api/src/com/todoroo/astrid/data/User.java @@ -53,18 +53,6 @@ public final class User extends RemoteModel { public static final StringProperty PICTURE = new StringProperty( TABLE, "picture"); - /** User picture thumbnail */ - public static final StringProperty THUMB = new StringProperty( - TABLE, "thumb"); - - /** User last activity string */ - public static final StringProperty LAST_ACTIVITY = new StringProperty( - TABLE, "lastActivity"); - - /** User last activity date */ - public static final LongProperty LAST_ACTIVITY_DATE = new LongProperty( - TABLE, "lastActivityDate"); - /** Remote id */ public static final LongProperty REMOTE_ID = new LongProperty( TABLE, REMOTE_ID_PROPERTY_NAME); @@ -81,9 +69,6 @@ public final class User extends RemoteModel { defaultValues.put(NAME.name, ""); defaultValues.put(EMAIL.name, ""); defaultValues.put(PICTURE.name, ""); - defaultValues.put(THUMB.name, ""); - defaultValues.put(LAST_ACTIVITY.name, ""); - defaultValues.put(LAST_ACTIVITY_DATE.name, 0); } @Override diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java index 272f5f08b..5d7cb5d78 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java @@ -45,13 +45,17 @@ import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.ExceptionService; +import com.todoroo.andlib.sql.Order; +import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.DialogUtilities; import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.actfm.sync.ActFmSyncService; import com.todoroo.astrid.activity.TaskEditFragment; +import com.todoroo.astrid.dao.UserDao; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.data.User; import com.todoroo.astrid.helper.AsyncImageView; import com.todoroo.astrid.service.AstridDependencyInjector; import com.todoroo.astrid.service.MetadataService; @@ -78,6 +82,8 @@ public class EditPeopleControlSet extends PopupControlSet { @Autowired TaskService taskService; + @Autowired UserDao userDao; + @Autowired MetadataService metadataService; @Autowired ExceptionService exceptionService; @@ -352,13 +358,15 @@ public class EditPeopleControlSet extends PopupControlSet { myself.put("id", Task.USER_ID_SELF); sharedPeople.add(0, myself); - boolean hasTags = t.getTransitory(TaskService.TRANS_TAGS) != null && - ((HashSet)t.getTransitory(TaskService.TRANS_TAGS)).size() > 0; - if (actFmPreferenceService.isLoggedIn() && hasTags) { + boolean hasTags = t.getTransitory("tags") != null && + ((HashSet)t.getTransitory("tags")).size() > 0; + boolean addUnassigned = actFmPreferenceService.isLoggedIn() && hasTags; + if (addUnassigned) { JSONObject unassigned = new JSONObject(); unassigned.put("id", Task.USER_ID_UNASSIGNED); sharedPeople.add(1, unassigned); } + addAstridFriends(sharedPeople); // de-duplicate by user id and/or email listValues.clear(); @@ -420,7 +428,7 @@ public class EditPeopleControlSet extends PopupControlSet { for (AssignedChangedListener l : listeners) { if (l.shouldShowTaskRabbit()) { taskRabbitUser = new AssignedToUser(activity.getString(R.string.actfm_EPA_task_rabbit), new JSONObject().put("default_picture", R.drawable.task_rabbit_image)); - listValues.add(taskRabbitUser); + listValues.add(addUnassigned ? 2 : 1, taskRabbitUser); if(l.didPostToTaskRabbit()){ assignedIndex = listValues.size()-1; } @@ -443,6 +451,27 @@ public class EditPeopleControlSet extends PopupControlSet { }); } + private void addAstridFriends(ArrayList sharedPeople) { + TodorooCursor users = userDao.query(Query.select(User.PROPERTIES).orderBy(Order.asc(User.NAME))); + try { + User user = new User(); + for (users.moveToFirst(); !users.isAfterLast(); users.moveToNext()) { + user.readFromCursor(users); + JSONObject userJson = new JSONObject(); + try { + ActFmSyncService.JsonHelper.jsonFromUser(userJson, user); + sharedPeople.add(userJson); + } catch (JSONException e) { + // Ignored + } + } + } finally { + users.close(); + } + } + + + private class AssignedUserAdapter extends ArrayAdapter { public AssignedUserAdapter(Context context, ArrayList people) { diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java index 49b9168b8..1621a5ac1 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java @@ -22,9 +22,11 @@ import com.todoroo.andlib.sql.Query; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; +import com.todoroo.astrid.dao.UserDao; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.data.User; import com.todoroo.astrid.notes.NoteMetadata; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.TagDataService; @@ -46,6 +48,8 @@ public final class ActFmDataService { @Autowired TaskDao taskDao; + @Autowired UserDao userDao; + @Autowired MetadataService metadataService; @Autowired ActFmPreferenceService actFmPreferenceService; @@ -198,4 +202,26 @@ public final class ActFmDataService { } } + /** + * Save / Merge JSON user + * @param userObject + * @throws JSONException + */ + @SuppressWarnings("nls") + public void saveUserData(JSONObject userObject) throws JSONException { + TodorooCursor cursor = userDao.query(Query.select(User.PROPERTIES).where( + User.REMOTE_ID.eq(userObject.get("id")))); + try { + cursor.moveToFirst(); + User user = new User(); + if (!cursor.isAfterLast()) { + user.readFromCursor(cursor); + } + ActFmSyncService.JsonHelper.userFromJson(userObject, user); + userDao.persist(user); + + } finally { + cursor.close(); + } + } } diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java index 74960799a..abc57acbc 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java @@ -59,6 +59,7 @@ import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.TaskApiDao; import com.todoroo.astrid.data.Update; +import com.todoroo.astrid.data.User; import com.todoroo.astrid.helper.ImageDiskCache; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.StatisticsConstants; @@ -727,6 +728,22 @@ public final class ActFmSyncService { return result.optInt("time", 0); } + public int fetchUsers(int serverTime) throws JSONException, IOException { + if (!checkForToken()) + return 0; + + JSONObject result = actFmInvoker.invoke("user_list", + "token", token, "modified_after", serverTime); + JSONArray users = result.getJSONArray("list"); + for (int i = 0; i < users.length(); i++) { + JSONObject userObject = users.getJSONObject(i); + actFmDataService.saveUserData(userObject); + } + + return result.optInt("time", 0); + } + + /** * Fetch active tasks asynchronously * @param manual @@ -1134,6 +1151,20 @@ public final class ActFmSyncService { return item.optLong(key, 0) * 1000L; } + public static void userFromJson(JSONObject json, User model) throws JSONException { + model.setValue(User.REMOTE_ID, json.getLong("id")); + model.setValue(User.NAME, json.optString("name")); + model.setValue(User.EMAIL, json.optString("email")); + model.setValue(User.PICTURE, json.optString("picture")); + } + + public static void jsonFromUser(JSONObject json, User model) throws JSONException { + json.put("id", model.getValue(User.REMOTE_ID)); + json.put("name", model.getValue(User.NAME)); + json.put("email", model.getValue(User.EMAIL)); + json.put("picture", model.getValue(User.PICTURE)); + } + public static void updateFromJson(JSONObject json, Update model) throws JSONException { model.setValue(Update.REMOTE_ID, json.getLong("id")); readUser(json.getJSONObject("user"), model, Update.USER_ID, Update.USER); diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java index 3912c4107..9a316dca3 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java @@ -103,6 +103,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider { private static final String LAST_TAG_FETCH_TIME = "actfm_lastTag"; //$NON-NLS-1$ + private static final String LAST_USERS_FETCH_TIME = "actfm_lastUsers"; //$NON-NLS-1$ + // --- synchronize active tasks @Override @@ -112,12 +114,15 @@ public class ActFmSyncV2Provider extends SyncV2Provider { new Thread(new Runnable() { public void run() { callback.started(); - callback.incrementMax(100); + callback.incrementMax(120); - final AtomicInteger finisher = new AtomicInteger(2); + final AtomicInteger finisher = new AtomicInteger(3); actFmPreferenceService.recordSyncStart(); + + startUsersFetcher(callback, finisher); + startTagFetcher(callback, finisher); actFmSyncService.waitUntilEmpty(); @@ -128,6 +133,31 @@ public class ActFmSyncV2Provider extends SyncV2Provider { }).start(); } + /** fetch changes to users/friends */ + private void startUsersFetcher(final SyncResultCallback callback, + final AtomicInteger finisher) { + new Thread(new Runnable() { + @Override + public void run() { + int time = Preferences.getInt(LAST_USERS_FETCH_TIME, 0); + try { + time = actFmSyncService.fetchUsers(time); + Preferences.setInt(LAST_USERS_FETCH_TIME, time); + } catch (JSONException e) { + handler.handleException("actfm-sync", e, e.toString()); //$NON-NLS-1$ + } catch (IOException e) { + handler.handleException("actfm-sync", e, e.toString()); //$NON-NLS-1$ + } finally { + callback.incrementProgress(20); + if(finisher.decrementAndGet() == 0) { + actFmPreferenceService.recordSuccessfulSync(); + callback.finished(); + } + } + } + }).start(); + } + /** fetch changes to tags */ private void startTagFetcher(final SyncResultCallback callback, final AtomicInteger finisher) { diff --git a/astrid/src/com/todoroo/astrid/dao/Database.java b/astrid/src/com/todoroo/astrid/dao/Database.java index fc46c89e5..38081a237 100644 --- a/astrid/src/com/todoroo/astrid/dao/Database.java +++ b/astrid/src/com/todoroo/astrid/dao/Database.java @@ -18,6 +18,7 @@ import com.todoroo.astrid.data.StoreObject; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Update; +import com.todoroo.astrid.data.User; import com.todoroo.astrid.provider.Astrid2TaskProvider; import com.todoroo.astrid.provider.Astrid3ContentProvider; import com.todoroo.astrid.widget.TasksWidget; @@ -54,6 +55,7 @@ public class Database extends AbstractDatabase { StoreObject.TABLE, TagData.TABLE, Update.TABLE, + User.TABLE }; // --- listeners @@ -289,11 +291,13 @@ public class Database extends AbstractDatabase { database.execSQL(changeZeroes); onCreateTables(); - } catch (SQLiteException e) { Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e); } case 21: try { + database.execSQL(createTableSql(visitor, User.TABLE.name, User.PROPERTIES)); + onCreateTables(); + for(Property property : new Property[] { Update.OTHER_USER_ID, Update.OTHER_USER }) database.execSQL("ALTER TABLE " + Update.TABLE.name + " ADD " + property.accept(visitor, null)); diff --git a/astrid/src/com/todoroo/astrid/dao/UserDao.java b/astrid/src/com/todoroo/astrid/dao/UserDao.java new file mode 100644 index 000000000..972ec7b20 --- /dev/null +++ b/astrid/src/com/todoroo/astrid/dao/UserDao.java @@ -0,0 +1,17 @@ +package com.todoroo.astrid.dao; + +import com.todoroo.andlib.data.DatabaseDao; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.astrid.data.User; + +public class UserDao extends DatabaseDao { + @Autowired Database database; + + @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="UR_UNINIT_READ") + public UserDao() { + super(User.class); + DependencyInjectionService.getInstance().inject(this); + setDatabase(database); + } +} diff --git a/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java b/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java index d462eeb38..403823427 100644 --- a/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java +++ b/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java @@ -18,6 +18,7 @@ import com.todoroo.astrid.dao.StoreObjectDao; import com.todoroo.astrid.dao.TagDataDao; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.UpdateDao; +import com.todoroo.astrid.dao.UserDao; import com.todoroo.astrid.gtasks.GtasksListService; import com.todoroo.astrid.gtasks.GtasksMetadataService; import com.todoroo.astrid.gtasks.GtasksPreferenceService; @@ -66,6 +67,7 @@ public class AstridDependencyInjector extends AbstractDependencyInjector { injectables.put("tagDataDao", TagDataDao.class); injectables.put("storeObjectDao", StoreObjectDao.class); injectables.put("updateDao", UpdateDao.class); + injectables.put("userDao", UserDao.class); // com.todoroo.astrid.service injectables.put("taskService", TaskService.class);