From c8c170ed7bf9713c11969db4273780ae9541dd36 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Thu, 5 Apr 2012 18:49:47 -0700 Subject: [PATCH 01/13] First draft of contact picking --- .../astrid/actfm/EditPeopleControlSet.java | 42 +++++++++++++++++-- astrid/res/values/strings-core.xml | 2 + .../astrid/activity/TaskEditFragment.java | 7 ++-- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java index 8db6b7c99..272f5f08b 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java @@ -15,7 +15,10 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.database.Cursor; import android.graphics.Color; +import android.net.Uri; +import android.provider.ContactsContract; import android.support.v4.app.Fragment; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -45,6 +48,7 @@ import com.todoroo.andlib.service.ExceptionService; 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.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; @@ -112,6 +116,8 @@ public class EditPeopleControlSet extends PopupControlSet { private boolean loadedUI = false; + private boolean dontClearAssignedCustom = false; + private final List listeners = new LinkedList(); public interface AssignedChangedListener { @@ -175,7 +181,9 @@ public class EditPeopleControlSet extends PopupControlSet { @Override public void readFromTask(Task sourceTask) { setTask(sourceTask); - assignedCustom.setText(""); //$NON-NLS-1$ + if (!dontClearAssignedCustom) + assignedCustom.setText(""); //$NON-NLS-1$ + dontClearAssignedCustom = false; setUpData(task, null); } @@ -531,6 +539,14 @@ public class EditPeopleControlSet extends PopupControlSet { sharedWithDialog.show(); } }); + + assignedCustom.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); + fragment.startActivityForResult(intent, TaskEditFragment.REQUEST_CODE_CONTACT); + } + }); } // --- events @@ -811,9 +827,29 @@ public class EditPeopleControlSet extends PopupControlSet { // clear user values & reset them to trigger a save task.clearValue(Task.USER_ID); task.clearValue(Task.USER); - } - else if (requestCode == loginRequestCode) + } else if (requestCode == loginRequestCode) { makePrivateTask(); + } else if (requestCode == TaskEditFragment.REQUEST_CODE_CONTACT && resultCode == Activity.RESULT_OK) { + Uri contactData = data.getData(); + String contactId = contactData.getLastPathSegment(); + String[] args = { contactId }; + String[] projection = { ContactsContract.CommonDataKinds.Email.DATA }; + String selection = ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?"; //$NON-NLS-1$ + Cursor c = activity.managedQuery(ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, selection, args, null); + if (c.getCount() > 0) { + c.moveToFirst(); + int emailIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA); + String email = c.getString(emailIndex); + if (!TextUtils.isEmpty(email)) { + assignedCustom.setText(email); + dontClearAssignedCustom = true; + } else { + DialogUtilities.okDialog(activity, activity.getString(R.string.TEA_contact_error), null); + } + } else { + DialogUtilities.okDialog(activity, activity.getString(R.string.TEA_contact_error), null); + } + } } @Override diff --git a/astrid/res/values/strings-core.xml b/astrid/res/values/strings-core.xml index 15b4074b9..4142dc5a3 100644 --- a/astrid/res/values/strings-core.xml +++ b/astrid/res/values/strings-core.xml @@ -450,6 +450,8 @@ I can do more when connected to the Internet. Please check your connection. + Sorry! We couldn\'t find an email address for the selected contact. + diff --git a/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java b/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java index f213c8d15..49b9de922 100755 --- a/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java @@ -149,6 +149,7 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { public static final int REQUEST_LOG_IN = 0; private static final int REQUEST_VOICE_RECOG = 10; + public static final int REQUEST_CODE_CONTACT = 20; // --- menu codes @@ -1058,11 +1059,9 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { public void onActivityResult(int requestCode, int resultCode, Intent data) { if (taskRabbitControl != null && taskRabbitControl.activityResult(requestCode, resultCode, data)) { return; - } - else if (editNotes != null && editNotes.activityResult(requestCode, resultCode, data)) { + } else if (editNotes != null && editNotes.activityResult(requestCode, resultCode, data)) { return; - } - else if (requestCode == REQUEST_VOICE_RECOG + } else if (requestCode == REQUEST_VOICE_RECOG && resultCode == Activity.RESULT_OK) { // handle the result of voice recognition, put it into the // appropiate textfield From 626845809351317c23fa350bfcb13e288c39d813 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Wed, 15 Feb 2012 15:09:54 -0800 Subject: [PATCH 02/13] Cherry-pick astrid user loading commit --- api/src/com/todoroo/astrid/data/User.java | 15 -------- .../astrid/actfm/EditPeopleControlSet.java | 37 +++++++++++++++++-- .../astrid/actfm/sync/ActFmDataService.java | 26 +++++++++++++ .../astrid/actfm/sync/ActFmSyncService.java | 31 ++++++++++++++++ .../actfm/sync/ActFmSyncV2Provider.java | 34 ++++++++++++++++- .../src/com/todoroo/astrid/dao/Database.java | 6 ++- .../src/com/todoroo/astrid/dao/UserDao.java | 17 +++++++++ .../service/AstridDependencyInjector.java | 2 + 8 files changed, 146 insertions(+), 22 deletions(-) create mode 100644 astrid/src/com/todoroo/astrid/dao/UserDao.java 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); From a7bff3f9ec538231a5d4ad260c489a248ddc7406 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Fri, 6 Apr 2012 11:16:36 -0700 Subject: [PATCH 03/13] Fixed change from merge in Database upgrade --- astrid/src/com/todoroo/astrid/dao/Database.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/astrid/src/com/todoroo/astrid/dao/Database.java b/astrid/src/com/todoroo/astrid/dao/Database.java index 38081a237..71915080f 100644 --- a/astrid/src/com/todoroo/astrid/dao/Database.java +++ b/astrid/src/com/todoroo/astrid/dao/Database.java @@ -38,7 +38,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 = 22; + public static final int VERSION = 23; /** * Database name (must be unique) @@ -295,9 +295,6 @@ public class Database extends AbstractDatabase { 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)); @@ -306,6 +303,12 @@ public class Database extends AbstractDatabase { catch (SQLiteException e) { Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e); } + case 22: try { + database.execSQL(createTableSql(visitor, User.TABLE.name, User.PROPERTIES)); + onCreateTables(); + } catch (SQLiteException e) { + Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e); + } return true; } From 1e3006bde799aad64b473e5270de3dac59484da1 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Fri, 6 Apr 2012 12:41:29 -0700 Subject: [PATCH 04/13] More improvements to contact picking --- .../astrid/actfm/EditPeopleControlSet.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java index 5d7cb5d78..9d3aa772e 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java @@ -864,14 +864,27 @@ public class EditPeopleControlSet extends PopupControlSet { String[] args = { contactId }; String[] projection = { ContactsContract.CommonDataKinds.Email.DATA }; String selection = ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?"; //$NON-NLS-1$ - Cursor c = activity.managedQuery(ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, selection, args, null); - if (c.getCount() > 0) { - c.moveToFirst(); - int emailIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA); - String email = c.getString(emailIndex); + Cursor emailCursor = activity.managedQuery(ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, selection, args, null); + if (emailCursor.getCount() > 0) { + emailCursor.moveToFirst(); + int emailIndex = emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA); + String email = emailCursor.getString(emailIndex); if (!TextUtils.isEmpty(email)) { + String[] nameProjection = { ContactsContract.Contacts.DISPLAY_NAME }; + Cursor nameCursor = activity.managedQuery(contactData, nameProjection, null, null, null); + if (nameCursor.getCount() > 0) { + nameCursor.moveToFirst(); + int nameIndex = nameCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); + String name = nameCursor.getString(nameIndex); + if (!TextUtils.isEmpty(name)) { + StringBuilder fullName = new StringBuilder(); + fullName.append(name).append(" <").append(email).append('>'); //$NON-NLS-1$ + email = fullName.toString(); + } + } assignedCustom.setText(email); dontClearAssignedCustom = true; + dialog.dismiss(); } else { DialogUtilities.okDialog(activity, activity.getString(R.string.TEA_contact_error), null); } From 6168534e0a61ca1fe4f8b0db1ddeef4ebfa02fa6 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Fri, 6 Apr 2012 13:12:36 -0700 Subject: [PATCH 05/13] Better size for assigned picker rows --- .../todoroo/astrid/actfm/EditPeopleControlSet.java | 14 +++++++------- astrid/res/layout/assigned_adapter_row.xml | 10 +++++----- astrid/res/layout/control_set_assigned.xml | 1 - astrid/res/values/styles.xml | 4 ++++ 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java index 9d3aa772e..a4a001732 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java @@ -569,13 +569,13 @@ public class EditPeopleControlSet extends PopupControlSet { } }); - assignedCustom.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); - fragment.startActivityForResult(intent, TaskEditFragment.REQUEST_CODE_CONTACT); - } - }); +// assignedCustom.setOnClickListener(new OnClickListener() { +// @Override +// public void onClick(View v) { +// Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); +// fragment.startActivityForResult(intent, TaskEditFragment.REQUEST_CODE_CONTACT); +// } +// }); } // --- events diff --git a/astrid/res/layout/assigned_adapter_row.xml b/astrid/res/layout/assigned_adapter_row.xml index 95dbffd16..a8644ccda 100644 --- a/astrid/res/layout/assigned_adapter_row.xml +++ b/astrid/res/layout/assigned_adapter_row.xml @@ -2,12 +2,12 @@ - diff --git a/astrid/res/values/styles.xml b/astrid/res/values/styles.xml index 2cdf5d88f..5c99490fa 100644 --- a/astrid/res/values/styles.xml +++ b/astrid/res/values/styles.xml @@ -288,6 +288,10 @@ + + + + diff --git a/astrid/src/com/commonsware/cwac/merge/MergeAdapter.java b/astrid/src/com/commonsware/cwac/merge/MergeAdapter.java new file mode 100644 index 000000000..846299d17 --- /dev/null +++ b/astrid/src/com/commonsware/cwac/merge/MergeAdapter.java @@ -0,0 +1,379 @@ +/*** + Copyright (c) 2008-2009 CommonsWare, LLC + Portions (c) 2009 Google, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain + a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.commonsware.cwac.merge; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListAdapter; +import android.widget.SectionIndexer; +import java.util.ArrayList; +import java.util.List; +import com.commonsware.cwac.sacklist.SackOfViewsAdapter; + +/** + * Adapter that merges multiple child adapters and views + * into a single contiguous whole. + * + * Adapters used as pieces within MergeAdapter must + * have view type IDs monotonically increasing from 0. Ideally, + * adapters also have distinct ranges for their row ids, as + * returned by getItemId(). + * + */ +public class MergeAdapter extends BaseAdapter implements SectionIndexer { + protected ArrayList pieces=new ArrayList(); + + /** + * Stock constructor, simply chaining to the superclass. + */ + public MergeAdapter() { + super(); + } + + /** + * Adds a new adapter to the roster of things to appear + * in the aggregate list. + * @param adapter Source for row views for this section + */ + public void addAdapter(ListAdapter adapter) { + pieces.add(adapter); + adapter.registerDataSetObserver(new CascadeDataSetObserver()); + } + + /** + * Adds a new View to the roster of things to appear + * in the aggregate list. + * @param view Single view to add + */ + public void addView(View view) { + addView(view, false); + } + + /** + * Adds a new View to the roster of things to appear + * in the aggregate list. + * @param view Single view to add + * @param enabled false if views are disabled, true if enabled + */ + public void addView(View view, boolean enabled) { + ArrayList list=new ArrayList(1); + + list.add(view); + + addViews(list, enabled); + } + + /** + * Adds a list of views to the roster of things to appear + * in the aggregate list. + * @param views List of views to add + */ + public void addViews(List views) { + addViews(views, false); + } + + /** + * Adds a list of views to the roster of things to appear + * in the aggregate list. + * @param views List of views to add + * @param enabled false if views are disabled, true if enabled + */ + public void addViews(List views, boolean enabled) { + if (enabled) { + addAdapter(new EnabledSackAdapter(views)); + } + else { + addAdapter(new SackOfViewsAdapter(views)); + } + } + + /** + * Get the data item associated with the specified + * position in the data set. + * @param position Position of the item whose data we want + */ + @Override + public Object getItem(int position) { + for (ListAdapter piece : pieces) { + int size=piece.getCount(); + + if (position sections=new ArrayList(); + + for (ListAdapter piece : pieces) { + if (piece instanceof SectionIndexer) { + Object[] curSections=((SectionIndexer)piece).getSections(); + + if (curSections!=null) { + for (Object section : curSections) { + sections.add(section); + } + } + } + } + + if (sections.size()==0) { + return(null); + } + + return(sections.toArray(new Object[0])); + } + + private static class EnabledSackAdapter extends SackOfViewsAdapter { + public EnabledSackAdapter(List views) { + super(views); + } + + @Override + public boolean areAllItemsEnabled() { + return(true); + } + + @Override + public boolean isEnabled(int position) { + return(true); + } + } + + private class CascadeDataSetObserver extends DataSetObserver { + @Override + public void onChanged() { + notifyDataSetChanged(); + } + + @Override + public void onInvalidated() { + notifyDataSetInvalidated(); + } + } +} \ No newline at end of file diff --git a/astrid/src/com/commonsware/cwac/merge/MergeSpinnerAdapter.java b/astrid/src/com/commonsware/cwac/merge/MergeSpinnerAdapter.java new file mode 100644 index 000000000..b1f059add --- /dev/null +++ b/astrid/src/com/commonsware/cwac/merge/MergeSpinnerAdapter.java @@ -0,0 +1,102 @@ +package com.commonsware.cwac.merge; + +import java.util.List; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListAdapter; +import android.widget.SpinnerAdapter; + +/** + * Adapter that merges multiple child adapters into a single + * contiguous whole to be consumed by a Spinner. + * + * Adapters used as pieces within MergeSpinnerAdapter must + * have view type IDs monotonically increasing from 0. + * Ideally, adapters also have distinct ranges for their row + * ids, as returned by getItemId(). + * + * All Adapters used as pieces within MergeSpinnerAdapter + * must be properly-configured implementations of + * SpinnerAdapter (e.g., ArrayAdapter, CursorAdapter). + */ +public class MergeSpinnerAdapter extends MergeAdapter { + /** + * Stock constructor, simply chaining to the superclass. + */ + public MergeSpinnerAdapter() { + super(); + } + + /* + * Returns the drop-down View for a given position, by + * iterating over the pieces. Assumes that all pieces are + * implementations of SpinnerAdapter. + * + * @see android.widget.BaseAdapter#getDropDownView(int, + * android.view.View, android.view.ViewGroup) + */ + public View getDropDownView(int position, View convertView, + ViewGroup parent) { + for (ListAdapter piece : pieces) { + int size=piece.getCount(); + + if (position views) { + throw new RuntimeException("Not supported with MergeSpinnerAdapter"); + } + + /** + * Adds a list of views to the roster of things to appear + * in the aggregate list. + * + * @param views + * List of views to add + * @param enabled + * false if views are disabled, true if enabled + */ + public void addViews(List views, boolean enabled) { + throw new RuntimeException("Not supported with MergeSpinnerAdapter"); + } +} From 85efa99f2b6a4fe0856fa7a7ed8d64a97268d7ff Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Fri, 6 Apr 2012 16:54:07 -0700 Subject: [PATCH 11/13] Better plus button in the people picker --- astrid/res/drawable/btn_add.xml | 23 +++++++++++++++++++++ astrid/res/drawable/btn_add_normal.png | Bin 0 -> 3192 bytes astrid/res/drawable/btn_add_pressed.png | Bin 0 -> 3177 bytes astrid/res/layout/control_set_assigned.xml | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 astrid/res/drawable/btn_add.xml create mode 100644 astrid/res/drawable/btn_add_normal.png create mode 100644 astrid/res/drawable/btn_add_pressed.png diff --git a/astrid/res/drawable/btn_add.xml b/astrid/res/drawable/btn_add.xml new file mode 100644 index 000000000..eb597adab --- /dev/null +++ b/astrid/res/drawable/btn_add.xml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/astrid/res/drawable/btn_add_normal.png b/astrid/res/drawable/btn_add_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..56cf1c7b2f6b551516c251c7b628931e06016a74 GIT binary patch literal 3192 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 literal 0 HcmV?d00001 diff --git a/astrid/res/drawable/btn_add_pressed.png b/astrid/res/drawable/btn_add_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..25e764d8f39f0a4d008b155d793bd504cab31b84 GIT binary patch literal 3177 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