Merge "Delete group members one by one in edit mode"
diff --git a/res/menu/view_group.xml b/res/menu/view_group.xml
index cf945fd..69a4d85 100644
--- a/res/menu/view_group.xml
+++ b/res/menu/view_group.xml
@@ -24,6 +24,12 @@
contacts:showAsAction="ifRoom" />
<item
+ android:id="@+id/menu_edit_group"
+ android:icon="@drawable/ic_create_24dp"
+ android:title="@string/menu_editGroup"
+ contacts:showAsAction="ifRoom" />
+
+ <item
android:id="@+id/menu_rename_group"
android:title="@string/menu_renameGroup"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e735c58..44ad027 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -338,7 +338,7 @@
<string name="groupUpdatedToast">Label updated</string>
<!-- Toast displayed when contacts are removed from a label. [CHAR LIMIT=50] -->
- <string name="groupMembersRemovedToast">Removed contacts</string>
+ <string name="groupMembersRemovedToast">Removed from label</string>
<!-- Toast displayed when one or more contacts is added to a label. [CHAR LIMIT=50] -->
<string name="groupMembersAddedToast">Added to label</string>
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index e5c41ae..efedc2b 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -71,6 +71,7 @@
private static final String KEY_IS_INSERT_ACTION = "isInsertAction";
private static final String KEY_GROUP_URI = "groupUri";
private static final String KEY_GROUP_METADATA = "groupMetadata";
+ private static final String KEY_IS_EDIT_MODE = "editMode";
private static final String TAG_GROUP_MEMBERS = "groupMembers";
private static final String TAG_SELECT_ACCOUNT_DIALOG = "selectAccountDialog";
@@ -118,19 +119,21 @@
}
final long[] rawContactIdsToAdd;
final long[] rawContactIdsToRemove;
+ final String action;
if (mType == TYPE_ADD) {
rawContactIdsToAdd = rawContactIds;
rawContactIdsToRemove = null;
+ action = GroupMembersActivity.ACTION_ADD_TO_GROUP;
} else if (mType == TYPE_REMOVE) {
rawContactIdsToAdd = null;
rawContactIdsToRemove = rawContactIds;
+ action = GroupMembersActivity.ACTION_REMOVE_FROM_GROUP;
} else {
throw new IllegalStateException("Unrecognized type " + mType);
}
return ContactSaveService.createGroupUpdateIntent(
mContext, mGroupId, /* newLabel */ null, rawContactIdsToAdd,
- rawContactIdsToRemove, GroupMembersActivity.class,
- GroupMembersActivity.ACTION_ADD_TO_GROUP);
+ rawContactIdsToRemove, GroupMembersActivity.class, action);
}
// TODO(wjang): prune raw contacts that are already in the group; ContactSaveService will
@@ -177,12 +180,13 @@
private ActionBarAdapter mActionBarAdapter;
- private GroupMetadata mGroupMetadata;
-
private GroupMembersFragment mMembersFragment;
private Uri mGroupUri;
private boolean mIsInsertAction;
+ private boolean mIsEditMode;
+
+ private GroupMetadata mGroupMetadata;
@Override
public void onCreate(Bundle savedState) {
@@ -192,6 +196,7 @@
if (savedState != null) {
mGroupUri = savedState.getParcelable(KEY_GROUP_URI);
mIsInsertAction = savedState.getBoolean(KEY_IS_INSERT_ACTION);
+ mIsEditMode = savedState.getBoolean(KEY_IS_EDIT_MODE);
mGroupMetadata = savedState.getParcelable(KEY_GROUP_METADATA);
} else {
mGroupUri = getIntent().getData();
@@ -265,8 +270,9 @@
if (mActionBarAdapter != null) {
mActionBarAdapter.onSaveInstanceState(outState);
}
- outState.putBoolean(KEY_IS_INSERT_ACTION, mIsInsertAction);
outState.putParcelable(KEY_GROUP_URI, mGroupUri);
+ outState.putBoolean(KEY_IS_INSERT_ACTION, mIsInsertAction);
+ outState.putBoolean(KEY_IS_EDIT_MODE, mIsEditMode);
outState.putParcelable(KEY_GROUP_METADATA, mGroupMetadata);
}
@@ -293,14 +299,13 @@
super.onNewIntent(newIntent);
if (isDeleteAction(newIntent.getAction())) {
- Toast.makeText(this, R.string.groupDeletedToast, Toast.LENGTH_SHORT).show();
+ toast(R.string.groupDeletedToast);
setResult(RESULT_OK);
finish();
} else if (isSaveAction(newIntent.getAction())) {
final Uri groupUri = newIntent.getData();
if (groupUri == null) {
- Toast.makeText(this, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
- setResultCanceledAndFinish();
+ setResultCanceledAndFinish(R.string.groupSavedErrorToast);
return;
}
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Received group URI " + groupUri);
@@ -308,22 +313,14 @@
mGroupUri = groupUri;
mIsInsertAction = false;
- Toast.makeText(this, getToastMessageForSaveAction(newIntent.getAction()),
- Toast.LENGTH_SHORT).show();
+ toast(getToastMessageForSaveAction(newIntent.getAction()));
- mMembersFragment = GroupMembersFragment.newInstance(groupUri);
- mMembersFragment.setListener(this);
-
- final FragmentTransaction transaction = getFragmentManager().beginTransaction();
- addGroupsAndFiltersFragments(transaction);
- transaction.replace(R.id.fragment_container_inner, mMembersFragment, TAG_GROUP_MEMBERS)
- .commitAllowingStateLoss();
-
- if (mGroupMetadata != null && mGroupMetadata.editable) {
- mMembersFragment.setCheckBoxListListener(this);
+ // If we're editing the group, don't reload the fragment so the user can
+ // continue to remove group members one by one
+ if (!mIsEditMode && !ACTION_REMOVE_FROM_GROUP.equals(newIntent.getAction())) {
+ replaceGroupMembersFragment();
+ invalidateOptionsMenu();
}
-
- invalidateOptionsMenu();
}
}
@@ -346,6 +343,18 @@
throw new IllegalArgumentException("Unhanded contact save action " + action);
}
+ private void replaceGroupMembersFragment() {
+ mMembersFragment = GroupMembersFragment.newInstance(mGroupUri);
+ mMembersFragment.setListener(this);
+ final FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ addGroupsAndFiltersFragments(transaction);
+ transaction.replace(R.id.fragment_container_inner, mMembersFragment, TAG_GROUP_MEMBERS)
+ .commitAllowingStateLoss();
+ if (mGroupMetadata != null && mGroupMetadata.editable) {
+ mMembersFragment.setCheckBoxListListener(this);
+ }
+ }
+
@Override
protected void onGroupMenuItemClicked(long groupId) {
if (mGroupMetadata.groupId != groupId) {
@@ -392,7 +401,9 @@
setVisible(menu, R.id.menu_add, isGroupEditable && !isSelectionMode);
setVisible(menu, R.id.menu_rename_group, !isGroupReadOnly && !isSelectionMode);
setVisible(menu, R.id.menu_delete_group, !isGroupReadOnly && !isSelectionMode);
- setVisible(menu, R.id.menu_remove_from_group, isGroupEditable && isSelectionMode);
+ setVisible(menu, R.id.menu_edit_group, isGroupEditable && !mIsEditMode);
+ setVisible(menu, R.id.menu_remove_from_group, isGroupEditable && isSelectionMode &&
+ !mIsEditMode);
return true;
}
@@ -431,6 +442,15 @@
deleteGroup();
return true;
}
+ case R.id.menu_edit_group: {
+ if (mMembersFragment == null) {
+ return false;
+ }
+ mIsEditMode = true;
+ mActionBarAdapter.setSelectionMode(true);
+ mMembersFragment.displayDeleteButtons(true);
+ return true;
+ }
case R.id.menu_remove_from_group: {
if (mMembersFragment == null) {
return false;
@@ -482,6 +502,12 @@
mDrawer.closeDrawer(GravityCompat.START);
} else if (mIsInsertAction) {
finish();
+ } else if (mIsEditMode) {
+ mIsEditMode = false;
+ mActionBarAdapter.setSelectionMode(false);
+ if (mMembersFragment != null) {
+ mMembersFragment.displayDeleteButtons(false);
+ }
} else if (mActionBarAdapter.isSelectionMode()) {
mActionBarAdapter.setSelectionMode(false);
if (mMembersFragment != null) {
@@ -525,14 +551,18 @@
setResultCanceledAndFinish(-1);
}
- private void setResultCanceledAndFinish(int toastResId) {
- if (toastResId >= 0) {
- Toast.makeText(this, toastResId, Toast.LENGTH_SHORT).show();
- }
+ private void setResultCanceledAndFinish(int resId) {
+ toast(resId);
setResult(RESULT_CANCELED);
finish();
}
+ private void toast(int resId) {
+ if (resId >= 0) {
+ Toast.makeText(this, resId, Toast.LENGTH_SHORT).show();
+ }
+ }
+
// SelectAccountDialogFragment.Listener callbacks
@Override
@@ -554,7 +584,11 @@
switch (action) {
case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
if (mMembersFragment != null) {
- mMembersFragment.displayCheckBoxes(true);
+ if (mIsEditMode) {
+ mMembersFragment.displayDeleteButtons(true);
+ } else {
+ mMembersFragment.displayCheckBoxes(true);
+ }
}
invalidateOptionsMenu();
showFabWithAnimation(/* showFabWithAnimation = */ false);
@@ -562,7 +596,11 @@
case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
mActionBarAdapter.setSearchMode(false);
if (mMembersFragment != null) {
- mMembersFragment.displayCheckBoxes(false);
+ if (mIsEditMode) {
+ mMembersFragment.displayDeleteButtons(false);
+ } else {
+ mMembersFragment.displayCheckBoxes(false);
+ }
}
invalidateOptionsMenu();
showFabWithAnimation(/* showFabWithAnimation */ true);
@@ -661,4 +699,13 @@
intent.putExtra(QuickContactActivity.EXTRA_PREVIOUS_SCREEN_TYPE, ScreenType.LIST_GROUP);
startActivity(intent);
}
+
+ @Override
+ public void onGroupMemberListItemDeleted(int position, long contactId) {
+ final long[] contactIds = new long[1];
+ contactIds[0] = contactId;
+ new UpdateGroupMembersAsyncTask(UpdateGroupMembersAsyncTask.TYPE_REMOVE,
+ this, contactIds, mGroupMetadata.groupId, mGroupMetadata.accountName,
+ mGroupMetadata.accountType).execute();
+ }
}
diff --git a/src/com/android/contacts/group/GroupMembersAdapter.java b/src/com/android/contacts/group/GroupMembersAdapter.java
index a4d69cf..ae324a1 100644
--- a/src/com/android/contacts/group/GroupMembersAdapter.java
+++ b/src/com/android/contacts/group/GroupMembersAdapter.java
@@ -69,6 +69,7 @@
private final CharSequence mUnknownNameText;
private long mGroupId;
+ private boolean mDisplayDeleteButtons;
public GroupMembersAdapter(Context context) {
super(context, GroupMembersQuery.CONTACT_ID);
@@ -89,6 +90,21 @@
return Contacts.getLookupUri(contactId, lookupKey);
}
+ /** Returns the ID of the contact at the given position in the underlying cursor. */
+ public long getContactId(int position) {
+ final Cursor cursor = (Cursor) getItem(position);
+ return cursor.getLong(GroupMembersQuery.CONTACT_ID);
+ }
+
+ public void setDisplayDeleteButtons(boolean displayDeleteButtons) {
+ mDisplayDeleteButtons = displayDeleteButtons;
+ notifyDataSetChanged();
+ }
+
+ public boolean getDisplayDeleteButtons() {
+ return mDisplayDeleteButtons;
+ }
+
@Override
public void configureLoader(CursorLoader loader, long directoryId) {
loader.setUri(Data.CONTENT_URI.buildUpon()
@@ -143,6 +159,7 @@
bindSectionHeaderAndDivider(view, position);
bindName(view, cursor);
bindPhoto(view, cursor);
+ bindDeleteButton(view);
}
protected void bindSectionHeaderAndDivider(ContactListItemView view, int position) {
@@ -170,4 +187,12 @@
getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false, getCircularPhotos(),
imageRequest);
}
+
+ private void bindDeleteButton(final ContactListItemView view) {
+ if (mDisplayDeleteButtons) {
+ view.getDeleteImageButton();
+ } else {
+ view.hideDeleteImageButton();
+ }
+ }
}
diff --git a/src/com/android/contacts/group/GroupMembersFragment.java b/src/com/android/contacts/group/GroupMembersFragment.java
index c65bf49..7d98173 100644
--- a/src/com/android/contacts/group/GroupMembersFragment.java
+++ b/src/com/android/contacts/group/GroupMembersFragment.java
@@ -63,6 +63,9 @@
/** Invoked when a group member in the list is clicked. */
void onGroupMemberListItemClicked(int position, Uri contactLookupUri);
+
+ /** Invoked when a the delete button for a group member in the list is clicked. */
+ void onGroupMemberListItemDeleted(int position, long contactId);
}
/** Filters out duplicate contacts. */
@@ -209,6 +212,10 @@
mListener = listener;
}
+ public void displayDeleteButtons(boolean displayDeleteButtons) {
+ getAdapter().setDisplayDeleteButtons(displayDeleteButtons);
+ }
+
public ArrayList<String> getMemberContactIds() {
return new ArrayList<>(mGroupMemberContactIds);
}
@@ -328,8 +335,13 @@
return;
}
if (mListener != null) {
- final Uri contactLookupUri = getAdapter().getContactLookupUri(position);
- mListener.onGroupMemberListItemClicked(position, contactLookupUri);
+ if (getAdapter().getDisplayDeleteButtons()) {
+ final long contactId = getAdapter().getContactId(position);
+ mListener.onGroupMemberListItemDeleted(position, contactId);
+ } else {
+ final Uri contactLookupUri = getAdapter().getContactLookupUri(position);
+ mListener.onGroupMemberListItemClicked(position, contactLookupUri);
+ }
}
}
}