Pick from aggregate contacts when adding to a group (1/2)
* Searching for new group members happens on the standard
contact seletion activity now so we remove the separate
search menu item and the old SuggestedMemberListAdapter
used by the autocomplete text view.
* When a new group member is selected, we add all the raw
contacts in the selected contact that are owned by the
group account owner to the group.
* Also use the same unknown name string "(No name)" on the
the new group member picker that is used on the other
contact lists.
Bug 28720761
Bug 28716004
Bug 28707265
Bug 18641067
Change-Id: I152bf1caf6652aa474f8f2915248ee19fb5fccf8
diff --git a/res/layout/group_member_suggestion.xml b/res/layout/group_member_suggestion.xml
deleted file mode 100644
index 4fe8d20..0000000
--- a/res/layout/group_member_suggestion.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2011, The Android Open Source Project
-**
-** 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.
-*/
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="48dip"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:background="?android:attr/selectableItemBackground">
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_vertical"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/text1"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="8dip"
- android:paddingStart="8dip"
- android:singleLine="true"
- android:ellipsize="end"/>
-
- <TextView android:id="@+id/text2"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="8dip"
- android:paddingStart="8dip"
- android:singleLine="true"
- android:ellipsize="end" />
-
- </LinearLayout>
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="48dip"
- android:layout_height="48dip"
- android:cropToPadding="true"
- android:scaleType="centerCrop" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/view_group.xml b/res/menu/view_group.xml
index 2fc36be..cf945fd 100644
--- a/res/menu/view_group.xml
+++ b/res/menu/view_group.xml
@@ -24,11 +24,6 @@
contacts:showAsAction="ifRoom" />
<item
- android:id="@+id/menu_search"
- android:icon="@drawable/ic_ab_search"
- android:title="@string/menu_search" />
-
- <item
android:id="@+id/menu_rename_group"
android:title="@string/menu_renameGroup"/>
diff --git a/src/com/android/contacts/GroupMemberLoader.java b/src/com/android/contacts/GroupMemberLoader.java
index 0c1d01e..8bc7d04 100644
--- a/src/com/android/contacts/GroupMemberLoader.java
+++ b/src/com/android/contacts/GroupMemberLoader.java
@@ -54,14 +54,6 @@
private final long mGroupId;
- /**
- * @return GroupMemberLoader object which can be used in group editor.
- */
- public static GroupMemberLoader constructLoaderForGroupEditorQuery(
- Context context, long groupId) {
- return new GroupMemberLoader(context, groupId, GroupEditorQuery.PROJECTION);
- }
-
private GroupMemberLoader(Context context, long groupId, String[] projection) {
super(context);
mGroupId = groupId;
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index 80a4acb..6e2746d 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -139,10 +139,9 @@
.inflate(R.layout.custom_action_bar, null);
mSearchView = (SearchView) mSearchViewContainer.findViewById(R.id.search_view);
- // Postal address group member,and legacy pickers don't support search, so just show
+ // Postal address pickers (and legacy pickers) don't support search, so just show
// "HomeAsUp" button and title.
if (mRequest.getActionCode() == ContactsRequest.ACTION_PICK_POSTAL ||
- mRequest.getActionCode() == ContactsRequest.ACTION_PICK_GROUP_MEMBERS ||
mRequest.isLegacyCompatibilityMode()) {
mSearchView.setVisibility(View.GONE);
if (actionBar != null) {
@@ -359,9 +358,9 @@
case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: {
final AccountWithDataSet account = getIntent().getParcelableExtra(
UiIntentActions.GROUP_ACCOUNT_WITH_DATA_SET);
- final ArrayList<String> rawContactIds = getIntent().getStringArrayListExtra(
- UiIntentActions.GROUP_RAW_CONTACT_IDS);
- mListFragment = GroupMemberPickerFragment.newInstance(account, rawContactIds);
+ final ArrayList<String> contactIds = getIntent().getStringArrayListExtra(
+ UiIntentActions.GROUP_CONTACT_IDS);
+ mListFragment = GroupMemberPickerFragment.newInstance(account, contactIds);
break;
}
@@ -483,8 +482,10 @@
private final class GroupMemberPickerListener implements GroupMemberPickerFragment.Listener {
@Override
- public void onGroupMemberClicked(Uri uri) {
- returnPickerResult(uri);
+ public void onGroupMemberClicked(long contactId) {
+ final Intent intent = new Intent();
+ intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, contactId);
+ returnPickerResult(intent);
}
}
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index f41972e..f1242d6 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -17,29 +17,23 @@
import android.accounts.Account;
import android.app.FragmentManager;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.CursorLoader;
+import android.content.Context;
import android.content.Intent;
-import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Intents;
+import android.provider.ContactsContract.RawContacts;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AutoCompleteTextView;
import android.widget.Toast;
import com.android.contacts.AppCompatContactsActivity;
import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupMemberLoader;
-import com.android.contacts.GroupMemberLoader.GroupEditorQuery;
import com.android.contacts.R;
import com.android.contacts.common.editor.SelectAccountDialogFragment;
import com.android.contacts.common.logging.ListEvent;
@@ -53,9 +47,6 @@
import com.android.contacts.group.GroupMembersListFragment;
import com.android.contacts.group.GroupMetadata;
import com.android.contacts.group.GroupNameEditDialogFragment;
-import com.android.contacts.group.Member;
-import com.android.contacts.group.SuggestedMemberListAdapter;
-import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
import com.android.contacts.interactions.GroupDeletionDialogFragment;
import com.android.contacts.list.ContactsRequest;
import com.android.contacts.list.MultiSelectContactsListFragment;
@@ -85,8 +76,6 @@
private static final String TAG_SELECT_ACCOUNT_DIALOG = "selectAccountDialog";
private static final String TAG_GROUP_NAME_EDIT_DIALOG = "groupNameEditDialog";
- private static final int LOADER_GROUP_MEMBERS = 0;
-
private static final String ACTION_DELETE_GROUP = "deleteGroup";
private static final String ACTION_CREATE_GROUP = "createGroup";
private static final String ACTION_UPDATE_GROUP = "updateGroup";
@@ -95,35 +84,74 @@
private static final int RESULT_GROUP_ADD_MEMBER = 100;
- /** Loader callbacks for existing group members for the autocomplete text view. */
- private final LoaderCallbacks<Cursor> mGroupMemberCallbacks = new LoaderCallbacks<Cursor>() {
+ /**
+ * Starts an Intent to add the raw contacts for a given contact ID to a group.
+ * Only the raw contacts that belong to the specified account are added.
+ */
+ private static class AddGroupMembersAsyncTask extends AsyncTask<Void, Void, Intent> {
- @Override
- public CursorLoader onCreateLoader(int id, Bundle args) {
- return GroupMemberLoader.constructLoaderForGroupEditorQuery(
- GroupMembersActivity.this, mGroupMetadata.groupId);
+ private final Context mContext;
+ private final long mContactId;
+ private final long mGroupId;
+ private final String mAccountName;
+ private final String mAccountType;
+
+ AddGroupMembersAsyncTask(Context context, long contactId, long groupId, String accountName,
+ String accountType) {
+ mContext = context;
+ mContactId = contactId;
+ mGroupId = groupId;
+ mAccountName = accountName;
+ mAccountType = accountType;
}
@Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- final List<Member> members = new ArrayList<>();
- data.moveToPosition(-1);
- while (data.moveToNext()) {
- members.add(new Member(
- data.getLong(GroupEditorQuery.RAW_CONTACT_ID),
- data.getString(GroupEditorQuery.CONTACT_LOOKUP_KEY),
- data.getLong(GroupEditorQuery.CONTACT_ID),
- data.getString(GroupEditorQuery.CONTACT_DISPLAY_NAME_PRIMARY),
- data.getString(GroupEditorQuery.CONTACT_PHOTO_URI),
- data.getLong(GroupEditorQuery.CONTACT_PHOTO_ID)));
+ protected Intent doInBackground(Void... params) {
+ final long[] rawContactIdsToAdd = getRawContactIdsToAdd();
+ if (rawContactIdsToAdd.length == 0) {
+ return null;
}
+ return ContactSaveService.createGroupUpdateIntent(
+ mContext, mGroupId, /* newLabel */ null,
+ rawContactIdsToAdd, /* rawContactIdsToRemove */ null,
+ GroupMembersActivity.class, GroupMembersActivity.ACTION_ADD_TO_GROUP);
+ }
- bindAutocompleteGroupMembers(members);
+ // TODO(wjang): prune raw contacts that are already in the group; ContactSaveService will
+ // log a warning if the raw contact is already a member and keep going but it is not ideal.
+ private long[] getRawContactIdsToAdd() {
+ final Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon()
+ .appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccountName)
+ .appendQueryParameter(RawContacts.ACCOUNT_TYPE, mAccountType)
+ .build();
+ final String[] projection = new String[]{RawContacts._ID};
+ final String selection = RawContacts.CONTACT_ID + "=?";
+ final String[] selectionArgs = new String[1];
+ selectionArgs[0] = Long.toString(mContactId);
+ final Cursor cursor = mContext.getContentResolver().query(
+ rawContactUri, projection, selection, selectionArgs, null, null);
+ final long[] rawContactIds = new long[cursor.getCount()];
+ try {
+ int i = 0;
+ while (cursor.moveToNext()) {
+ rawContactIds[i] = cursor.getLong(0);
+ i++;
+ }
+ } finally {
+ cursor.close();
+ }
+ return rawContactIds;
}
@Override
- public void onLoaderReset(Loader<Cursor> loader) {}
- };
+ protected void onPostExecute(Intent intent) {
+ if (intent == null) {
+ Toast.makeText(mContext, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
+ } else {
+ mContext.startService(intent);
+ }
+ }
+ }
private ActionBarAdapter mActionBarAdapter;
@@ -131,8 +159,6 @@
private GroupMembersListFragment mMembersListFragment;
- private SuggestedMemberListAdapter mAutoCompleteAdapter;
-
private Uri mGroupUri;
private boolean mIsInsertAction;
@@ -198,8 +224,6 @@
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, mMembersListFragment, TAG_GROUP_MEMBERS)
.commit();
- } else {
- getLoaderManager().initLoader(LOADER_GROUP_MEMBERS, null, mGroupMemberCallbacks);
}
mMembersListFragment.setListener(this);
if (mGroupMetadata != null && mGroupMetadata.editable) {
@@ -311,25 +335,13 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
final boolean isSelectionMode = mActionBarAdapter.isSelectionMode();
- final boolean isSearchMode = mActionBarAdapter.isSearchMode();
-
final boolean isGroupEditable = mGroupMetadata != null && mGroupMetadata.editable;
final boolean isGroupReadOnly = mGroupMetadata != null && mGroupMetadata.readOnly;
- setVisible(menu, R.id.menu_add,
- isGroupEditable && !isSelectionMode && !isSearchMode);
-
- setVisible(menu, R.id.menu_search,
- isGroupEditable && !isSelectionMode && !isSearchMode);
-
- setVisible(menu, R.id.menu_rename_group,
- isGroupEditable && !isSelectionMode && !isSearchMode);
-
- setVisible(menu, R.id.menu_delete_group,
- !isGroupReadOnly && !isSelectionMode && !isSearchMode);
-
- setVisible(menu, R.id.menu_remove_from_group,
- isGroupEditable && isSelectionMode);
+ setVisible(menu, R.id.menu_add, isGroupEditable && !isSelectionMode);
+ setVisible(menu, R.id.menu_rename_group, isGroupEditable && !isSelectionMode);
+ setVisible(menu, R.id.menu_delete_group, !isGroupReadOnly && !isSelectionMode);
+ setVisible(menu, R.id.menu_remove_from_group, isGroupEditable && isSelectionMode);
return true;
}
@@ -353,17 +365,11 @@
intent.setType(ContactsContract.Groups.CONTENT_ITEM_TYPE);
intent.putExtra(UiIntentActions.GROUP_ACCOUNT_WITH_DATA_SET,
mGroupMetadata.createAccountWithDataSet());
- intent.putExtra(UiIntentActions.GROUP_RAW_CONTACT_IDS,
- getExistingGroupMemberRawContactIds());
+ intent.putExtra(UiIntentActions.GROUP_CONTACT_IDS,
+ getExistingGroupMemberContactIds());
startActivityForResult(intent, RESULT_GROUP_ADD_MEMBER);
return true;
}
- case R.id.menu_search: {
- if (mActionBarAdapter != null) {
- mActionBarAdapter.setSearchMode(true);
- }
- return true;
- }
case R.id.menu_rename_group: {
GroupNameEditDialogFragment.showUpdateDialog(
getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG, mGroupMetadata.groupName);
@@ -385,15 +391,15 @@
return super.onOptionsItemSelected(item);
}
- private ArrayList<String> getExistingGroupMemberRawContactIds() {
- final ArrayList<String> rawContactIds = new ArrayList<>();
+ private ArrayList<String> getExistingGroupMemberContactIds() {
+ final ArrayList<String> contactIds = new ArrayList<>();
final Cursor cursor = mMembersListFragment.getAdapter().getCursor(/* partition */ 0);
if (cursor != null && cursor.moveToFirst()) {
do {
- rawContactIds.add(cursor.getString(GroupMembersQuery.RAW_CONTACT_ID));
+ contactIds.add(cursor.getString(GroupMembersQuery.CONTACT_ID));
} while (cursor.moveToNext());
}
- return rawContactIds;
+ return contactIds;
}
private void deleteGroup() {
@@ -408,7 +414,6 @@
}
}
- // TODO(wjang): replace this with group events
private void logListEvent() {
Logger.logListEvent(
ListEvent.ActionType.REMOVE_LABEL,
@@ -446,30 +451,14 @@
}
}
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RESULT_GROUP_ADD_MEMBER && resultCode == RESULT_OK && data != null) {
- final Uri rawContactUri = data.getData();
- if (rawContactUri != null) {
- long rawContactId = -1;
- try {
- rawContactId = Long.parseLong(rawContactUri.getLastPathSegment());
- } catch (NumberFormatException ignored) {}
- if (rawContactId < 0) {
- Toast.makeText(this, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
- Log.w(TAG, "Failed to parse ID from pick group member result uri " +
- rawContactUri);
- return;
- }
- final long[] rawContactIdsToAdd = new long[1];
- rawContactIdsToAdd[0] = rawContactId;
- final Intent intent = ContactSaveService.createGroupUpdateIntent(
- GroupMembersActivity.this, mGroupMetadata.groupId, /* newLabel */ null,
- rawContactIdsToAdd, /* rawContactIdsToRemove */ null,
- GroupMembersActivity.class, GroupMembersActivity.ACTION_ADD_TO_GROUP);
- startService(intent);
- }
+ final long contactId = data.getLongExtra(
+ UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
+ new AddGroupMembersAsyncTask(this, contactId, mGroupMetadata.groupId,
+ mGroupMetadata.accountName, mGroupMetadata.accountType)
+ .execute();
}
}
@@ -512,11 +501,6 @@
@Override
public void onAction(int action) {
switch (action) {
- case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
- mActionBarAdapter.setSearchMode(true);
- invalidateOptionsMenu();
- showFabWithAnimation(/* showFabWithAnimation = */ false);
- break;
case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
if (mMembersListFragment != null) {
mMembersListFragment.displayCheckBoxes(true);
@@ -539,7 +523,7 @@
}
private void showFabWithAnimation(boolean showFab) {
- // TODO(wjang): b/28497108
+ // TODO: b/28497108
}
@Override
@@ -598,63 +582,12 @@
@Override
public void onGroupMetadataLoaded(GroupMetadata groupMetadata) {
mGroupMetadata = groupMetadata;
-
if (!mIsInsertAction) {
getSupportActionBar().setTitle(mGroupMetadata.groupName);
}
-
- bindAutocompleteTextView();
- getLoaderManager().initLoader(LOADER_GROUP_MEMBERS, null, mGroupMemberCallbacks);
-
invalidateOptionsMenu();
}
- private void bindAutocompleteTextView() {
- final AutoCompleteTextView autoCompleteTextView =
- (AutoCompleteTextView) mActionBarAdapter.getSearchView();
- if (autoCompleteTextView == null) return;
- mAutoCompleteAdapter = createAutocompleteAdapter();
- autoCompleteTextView.setAdapter(mAutoCompleteAdapter);
- autoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final SuggestedMember member = (SuggestedMember) view.getTag();
- if (member == null) {
- return;
- }
- final long[] rawContactIdsToAdd = new long[1];
- rawContactIdsToAdd[0] = member.getRawContactId();
- final Intent intent = ContactSaveService.createGroupUpdateIntent(
- GroupMembersActivity.this, mGroupMetadata.groupId, /* newLabel */ null,
- rawContactIdsToAdd, /* rawContactIdsToRemove */ null,
- GroupMembersActivity.class, ACTION_ADD_TO_GROUP);
- startService(intent);
-
- // Update the autocomplete adapter so the contact doesn't get suggested again
- mAutoCompleteAdapter.addNewMember(member.getContactId());
-
- // Clear out the text field
- autoCompleteTextView.setText("");
- }
- });
- }
-
- private SuggestedMemberListAdapter createAutocompleteAdapter() {
- final SuggestedMemberListAdapter adapter = new SuggestedMemberListAdapter(
- this, android.R.layout.simple_dropdown_item_1line);
- adapter.setContentResolver(this.getContentResolver());
- adapter.setAccountType(mGroupMetadata.accountType);
- adapter.setAccountName(mGroupMetadata.accountName);
- adapter.setDataSet(mGroupMetadata.dataSet);
- return adapter;
- }
-
- private void bindAutocompleteGroupMembers(List<Member> members) {
- if (mAutoCompleteAdapter != null) {
- mAutoCompleteAdapter.updateExistingMembersList(members);
- }
- }
-
@Override
public void onGroupMetadataLoadFailed() {
setResultCanceledAndFinish(R.string.groupLoadErrorToast);
diff --git a/src/com/android/contacts/group/GroupMembersListAdapter.java b/src/com/android/contacts/group/GroupMembersListAdapter.java
index 86e75b1..0f3ae8a 100644
--- a/src/com/android/contacts/group/GroupMembersListAdapter.java
+++ b/src/com/android/contacts/group/GroupMembersListAdapter.java
@@ -28,6 +28,7 @@
import android.view.ViewGroup;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
+import com.android.contacts.common.R;
import com.android.contacts.common.list.ContactListItemView;
import com.android.contacts.common.list.MultiSelectEntryContactListAdapter;
import com.android.contacts.common.preference.ContactsPreferences;
@@ -71,7 +72,7 @@
public GroupMembersListAdapter(Context context) {
super(context, GroupMembersQuery.RAW_CONTACT_ID);
- mUnknownNameText = context.getText(android.R.string.unknownName);
+ mUnknownNameText = context.getText(R.string.missing_name);
}
/** Sets the ID of the group whose members will be displayed. */
diff --git a/src/com/android/contacts/group/Member.java b/src/com/android/contacts/group/Member.java
deleted file mode 100644
index ad6f9b2..0000000
--- a/src/com/android/contacts/group/Member.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.contacts.group;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.ContactsContract.Contacts;
-
-import com.google.common.base.Objects;
-
-/** A member of the group currently being displayed to the user. */
-public class Member implements Parcelable {
-
- public static final Parcelable.Creator<Member> CREATOR = new Parcelable.Creator<Member>() {
- @Override
- public Member createFromParcel(Parcel in) {
- return new Member(in);
- }
-
- @Override
- public Member[] newArray(int size) {
- return new Member[size];
- }
- };
-
- private final long mRawContactId;
- private final long mContactId;
- private final Uri mLookupUri;
- private final String mDisplayName;
- private final Uri mPhotoUri;
- private final String mLookupKey;
- private final long mPhotoId;
-
- public Member(long rawContactId, String lookupKey, long contactId, String displayName,
- String photoUri, long photoId) {
- mRawContactId = rawContactId;
- mContactId = contactId;
- mLookupKey = lookupKey;
- mLookupUri = Contacts.getLookupUri(contactId, lookupKey);
- mDisplayName = displayName;
- mPhotoUri = (photoUri != null) ? Uri.parse(photoUri) : null;
- mPhotoId = photoId;
- }
-
- public long getRawContactId() {
- return mRawContactId;
- }
-
- public long getContactId() {
- return mContactId;
- }
-
- public Uri getLookupUri() {
- return mLookupUri;
- }
-
- public String getLookupKey() {
- return mLookupKey;
- }
-
- public String getDisplayName() {
- return mDisplayName;
- }
-
- public Uri getPhotoUri() {
- return mPhotoUri;
- }
-
- public long getPhotoId() {
- return mPhotoId;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object instanceof Member) {
- Member otherMember = (Member) object;
- return Objects.equal(mLookupUri, otherMember.getLookupUri());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mLookupUri == null ? 0 : mLookupUri.hashCode();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mRawContactId);
- dest.writeLong(mContactId);
- dest.writeParcelable(mLookupUri, flags);
- dest.writeString(mLookupKey);
- dest.writeString(mDisplayName);
- dest.writeParcelable(mPhotoUri, flags);
- dest.writeLong(mPhotoId);
- }
-
- private Member(Parcel in) {
- mRawContactId = in.readLong();
- mContactId = in.readLong();
- mLookupUri = in.readParcelable(getClass().getClassLoader());
- mLookupKey = in.readString();
- mDisplayName = in.readString();
- mPhotoUri = in.readParcelable(getClass().getClassLoader());
- mPhotoId = in.readLong();
- }
-}
\ No newline at end of file
diff --git a/src/com/android/contacts/group/SuggestedMemberListAdapter.java b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
deleted file mode 100644
index e2756c6..0000000
--- a/src/com/android/contacts/group/SuggestedMemberListAdapter.java
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.contacts.group;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.Contacts.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.RawContactsEntity;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.Filter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.contacts.R;
-import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This adapter provides suggested contacts that can be added to a group for an
- * {@link AutoCompleteTextView} within the group editor.
- */
-public class SuggestedMemberListAdapter extends ArrayAdapter<SuggestedMember> {
-
- private static final String[] PROJECTION_FILTERED_MEMBERS = new String[] {
- RawContacts._ID, // 0
- RawContacts.CONTACT_ID, // 1
- RawContacts.DISPLAY_NAME_PRIMARY // 2
- };
-
- private static final int RAW_CONTACT_ID_COLUMN_INDEX = 0;
- private static final int CONTACT_ID_COLUMN_INDEX = 1;
- private static final int DISPLAY_NAME_PRIMARY_COLUMN_INDEX = 2;
-
- private static final String[] PROJECTION_MEMBER_DATA = new String[] {
- RawContacts._ID, // 0
- RawContacts.CONTACT_ID, // 1
- Data.MIMETYPE, // 2
- Data.DATA1, // 3
- Photo.PHOTO, // 4
- };
-
- private static final int ID_INDEX = 0;
- private static final int MIMETYPE_COLUMN_INDEX = 2;
- private static final int DATA_COLUMN_INDEX = 3;
- private static final int PHOTO_COLUMN_INDEX = 4;
-
- private Filter mFilter;
- private ContentResolver mContentResolver;
- private LayoutInflater mInflater;
- private ContactPhotoManager mPhotoManager;
-
- private String mAccountType;
- private String mAccountName;
- private String mDataSet;
-
- // TODO: Make this a Map for better performance when we check if a new contact is in the list
- // or not
- private final List<Long> mExistingMemberContactIds = new ArrayList<Long>();
-
- private static final int SUGGESTIONS_LIMIT = 5;
-
- public SuggestedMemberListAdapter(Context context, int textViewResourceId) {
- super(context, textViewResourceId);
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mPhotoManager = ContactPhotoManager.getInstance(context);
- }
-
- public void setAccountType(String accountType) {
- mAccountType = accountType;
- }
-
- public void setAccountName(String accountName) {
- mAccountName = accountName;
- }
-
- public void setDataSet(String dataSet) {
- mDataSet = dataSet;
- }
-
- public void setContentResolver(ContentResolver resolver) {
- mContentResolver = resolver;
- }
-
- public void updateExistingMembersList(List<Member> list) {
- mExistingMemberContactIds.clear();
- for (Member member : list) {
- mExistingMemberContactIds.add(member.getContactId());
- }
- }
-
- public void addNewMember(long contactId) {
- mExistingMemberContactIds.add(contactId);
- }
-
- public void removeMember(long contactId) {
- if (mExistingMemberContactIds.contains(contactId)) {
- mExistingMemberContactIds.remove(contactId);
- }
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View result = convertView;
- if (result == null) {
- result = mInflater.inflate(R.layout.group_member_suggestion, parent, false);
- }
- // TODO: Use a viewholder
- SuggestedMember member = getItem(position);
- TextView text1 = (TextView) result.findViewById(R.id.text1);
- TextView text2 = (TextView) result.findViewById(R.id.text2);
- ImageView icon = (ImageView) result.findViewById(R.id.icon);
- text1.setText(member.getDisplayName());
- if (member.hasExtraInfo()) {
- text2.setText(member.getExtraInfo());
- } else {
- text2.setVisibility(View.GONE);
- }
- byte[] byteArray = member.getPhotoByteArray();
- if (byteArray == null) {
- final Uri contactLookupUri = RawContacts.getContactLookupUri(mContentResolver,
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, member.getContactId()));
- final String imageRequestIdentifier = contactLookupUri == null
- ? null : contactLookupUri.toString();
- GroupUtil.bindPhoto(mPhotoManager, icon, member.getPhotoId(),
- /* photoUri */ null, member.getDisplayName(), imageRequestIdentifier);
- } else {
- Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
- icon.setImageBitmap(frameBitmapInCircle(bitmap));
- }
- result.setTag(member);
- return result;
- }
-
- private static Bitmap frameBitmapInCircle(Bitmap input) {
- // Crop the image if not squared.
- final int targetDiameter = input.getWidth();
- final Bitmap scaled = Bitmap.createScaledBitmap(
- input, targetDiameter, targetDiameter, /* filter */ false);
- int inputWidth = scaled.getWidth();
- int inputHeight = scaled.getHeight();
- int targetX, targetY, targetSize;
- if (inputWidth >= inputHeight) {
- targetX = inputWidth / 2 - inputHeight / 2;
- targetY = 0;
- targetSize = inputHeight;
- } else {
- targetX = 0;
- targetY = inputHeight / 2 - inputWidth / 2;
- targetSize = inputWidth;
- }
-
- // Create an output bitmap and a canvas to draw on it.
- final Bitmap output = Bitmap.createBitmap(targetSize, targetSize, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(output);
-
- // Create a black paint to draw the mask.
- final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(Color.BLACK);
-
- // Draw a circle.
- canvas.drawCircle(targetDiameter / 2, targetDiameter / 2, targetDiameter / 2, paint);
-
- // Replace the black parts of the mask with the input image.
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
- canvas.drawBitmap(scaled, targetX /* left */, targetY /* top */, paint);
-
- return output;
- }
-
- @Override
- public Filter getFilter() {
- if (mFilter == null) {
- mFilter = new SuggestedMemberFilter();
- }
- return mFilter;
- }
-
- /**
- * This filter queries for raw contacts that match the given account name and account type,
- * as well as the search query.
- */
- public class SuggestedMemberFilter extends Filter {
-
- @Override
- protected FilterResults performFiltering(CharSequence prefix) {
- FilterResults results = new FilterResults();
- if (mContentResolver == null || TextUtils.isEmpty(prefix)) {
- return results;
- }
-
- // Create a list to store the suggested contacts (which will be alphabetically ordered),
- // but also keep a map of raw contact IDs to {@link SuggestedMember}s to make it easier
- // to add supplementary data to the contact (photo, phone, email) to the members based
- // on raw contact IDs after the second query is completed.
- List<SuggestedMember> suggestionsList = new ArrayList<SuggestedMember>();
- HashMap<Long, SuggestedMember> suggestionsMap = new HashMap<Long, SuggestedMember>();
-
- // First query for all the raw contacts that match the given search query
- // and have the same account name and type as specified in this adapter
- String searchQuery = prefix.toString() + "%";
- String accountClause = RawContacts.ACCOUNT_NAME + "=? AND " +
- RawContacts.ACCOUNT_TYPE + "=?";
- String[] args;
- if (mDataSet == null) {
- accountClause += " AND " + RawContacts.DATA_SET + " IS NULL";
- args = new String[] {mAccountName, mAccountType, searchQuery, searchQuery};
- } else {
- accountClause += " AND " + RawContacts.DATA_SET + "=?";
- args = new String[] {
- mAccountName, mAccountType, mDataSet, searchQuery, searchQuery
- };
- }
-
- Cursor cursor = mContentResolver.query(
- RawContacts.CONTENT_URI, PROJECTION_FILTERED_MEMBERS,
- accountClause + " AND (" +
- RawContacts.DISPLAY_NAME_PRIMARY + " LIKE ? OR " +
- RawContacts.DISPLAY_NAME_ALTERNATIVE + " LIKE ? )",
- args, RawContacts.DISPLAY_NAME_PRIMARY + " COLLATE LOCALIZED ASC");
-
- if (cursor == null) {
- return results;
- }
-
- // Read back the results from the cursor and filter out existing group members.
- // For valid suggestions, add them to the hash map of suggested members.
- try {
- cursor.moveToPosition(-1);
- while (cursor.moveToNext() && suggestionsMap.keySet().size() < SUGGESTIONS_LIMIT) {
- long rawContactId = cursor.getLong(RAW_CONTACT_ID_COLUMN_INDEX);
- long contactId = cursor.getLong(CONTACT_ID_COLUMN_INDEX);
- // Filter out contacts that have already been added to this group
- if (mExistingMemberContactIds.contains(contactId)) {
- continue;
- }
- // Otherwise, add the contact as a suggested new group member
- String displayName = cursor.getString(DISPLAY_NAME_PRIMARY_COLUMN_INDEX);
- SuggestedMember member = new SuggestedMember(rawContactId, displayName,
- contactId);
- // Store the member in the list of suggestions and add it to the hash map too.
- suggestionsList.add(member);
- suggestionsMap.put(rawContactId, member);
- }
- } finally {
- cursor.close();
- }
-
- int numSuggestions = suggestionsMap.keySet().size();
- if (numSuggestions == 0) {
- return results;
- }
-
- // Create a part of the selection string for the next query with the pattern (?, ?, ?)
- // where the number of comma-separated question marks represent the number of raw
- // contact IDs found in the previous query (while respective the SUGGESTION_LIMIT)
- final StringBuilder rawContactIdSelectionBuilder = new StringBuilder();
- final String[] questionMarks = new String[numSuggestions];
- Arrays.fill(questionMarks, "?");
- rawContactIdSelectionBuilder.append(RawContacts._ID + " IN (")
- .append(TextUtils.join(",", questionMarks))
- .append(")");
-
- // Construct the selection args based on the raw contact IDs we're interested in
- // (as well as the photo, email, and phone mimetypes)
- List<String> selectionArgs = new ArrayList<String>();
- selectionArgs.add(Photo.CONTENT_ITEM_TYPE);
- selectionArgs.add(Email.CONTENT_ITEM_TYPE);
- selectionArgs.add(Phone.CONTENT_ITEM_TYPE);
- for (Long rawContactId : suggestionsMap.keySet()) {
- selectionArgs.add(String.valueOf(rawContactId));
- }
-
- // Perform a second query to retrieve a photo and possibly a phone number or email
- // address for the suggested contact
- Cursor memberDataCursor = mContentResolver.query(
- RawContactsEntity.CONTENT_URI, PROJECTION_MEMBER_DATA,
- "(" + Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=? OR " + Data.MIMETYPE +
- "=?) AND " + rawContactIdSelectionBuilder.toString(),
- selectionArgs.toArray(new String[0]), null);
-
- if (memberDataCursor != null) {
- try {
- memberDataCursor.moveToPosition(-1);
- while (memberDataCursor.moveToNext()) {
- long rawContactId = memberDataCursor.getLong(RAW_CONTACT_ID_COLUMN_INDEX);
- SuggestedMember member = suggestionsMap.get(rawContactId);
- if (member == null) {
- continue;
- }
- String mimetype = memberDataCursor.getString(MIMETYPE_COLUMN_INDEX);
- if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) {
- // Set photo
- member.setPhotoId(memberDataCursor.getLong(ID_INDEX));
- byte[] bitmapArray = memberDataCursor.getBlob(PHOTO_COLUMN_INDEX);
- member.setPhotoByteArray(bitmapArray);
- } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype) ||
- Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
- // Set at most 1 extra piece of contact info that can be a phone number or
- // email
- if (!member.hasExtraInfo()) {
- String info = memberDataCursor.getString(DATA_COLUMN_INDEX);
- member.setExtraInfo(info);
- }
- }
- }
- } finally {
- memberDataCursor.close();
- }
- }
- results.values = suggestionsList;
- return results;
- }
-
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- @SuppressWarnings("unchecked")
- List<SuggestedMember> suggestionsList = (List<SuggestedMember>) results.values;
- if (suggestionsList == null) {
- return;
- }
-
- // Clear out the existing suggestions in this adapter
- clear();
-
- // Add all the suggested members to this adapter
- for (SuggestedMember member : suggestionsList) {
- add(member);
- }
-
- notifyDataSetChanged();
- }
- }
-
- /**
- * This represents a single contact that is a suggestion for the user to add to a group.
- */
- // TODO: Merge this with the {@link GroupEditorFragment} Member class once we can find the
- // lookup URI for this contact using the autocomplete filter queries
- public class SuggestedMember {
-
- private long mRawContactId;
- private long mContactId;
- private String mDisplayName;
-
- private String mExtraInfo;
- private byte[] mPhoto;
- private long mPhotoId;
-
- public SuggestedMember(long rawContactId, String displayName, long contactId) {
- mRawContactId = rawContactId;
- mDisplayName = displayName;
- mContactId = contactId;
- }
-
- public String getDisplayName() {
- return mDisplayName;
- }
-
- public String getExtraInfo() {
- return mExtraInfo;
- }
-
- public long getRawContactId() {
- return mRawContactId;
- }
-
- public long getContactId() {
- return mContactId;
- }
-
- public byte[] getPhotoByteArray() {
- return mPhoto;
- }
-
- public long getPhotoId() {
- return mPhotoId;
- }
-
- public boolean hasExtraInfo() {
- return mExtraInfo != null;
- }
-
- /**
- * Set a phone number or email to distinguish this contact
- */
- public void setExtraInfo(String info) {
- mExtraInfo = info;
- }
-
- public void setPhotoByteArray(byte[] photo) {
- mPhoto = photo;
- }
-
- public void setPhotoId(long photoId) {
- mPhotoId = photoId;
- }
-
- @Override
- public String toString() {
- return getDisplayName();
- }
- }
-}
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index ded72c2..4bd131e 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -97,7 +97,7 @@
request.setAccountWithDataSet(intent.<AccountWithDataSet> getParcelableExtra(
UiIntentActions.GROUP_ACCOUNT_WITH_DATA_SET));
request.setRawContactIds(intent.getStringArrayListExtra(
- UiIntentActions.GROUP_RAW_CONTACT_IDS));
+ UiIntentActions.GROUP_CONTACT_IDS));
}
} else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
String component = intent.getComponent().getClassName();
diff --git a/src/com/android/contacts/list/GroupMemberPickListAdapter.java b/src/com/android/contacts/list/GroupMemberPickListAdapter.java
deleted file mode 100644
index d25aafd..0000000
--- a/src/com/android/contacts/list/GroupMemberPickListAdapter.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * 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.android.contacts.list;
-
-import android.content.Context;
-import android.content.CursorLoader;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
-import com.android.contacts.common.list.ContactEntryListAdapter;
-import com.android.contacts.common.list.ContactListItemView;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.preference.ContactsPreferences;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Adapter for raw contacts owned by an account that are not already members of a given group.
- */
-public class GroupMemberPickListAdapter extends ContactEntryListAdapter {
-
- static class GroupMembersQuery {
-
- private static final String[] PROJECTION_PRIMARY = new String[] {
- Data.RAW_CONTACT_ID, // 0
- Data.CONTACT_ID, // 1
- Data.DISPLAY_NAME_PRIMARY, // 2
- // Dummy columns overwritten by the cursor wrapper
- Data.PHOTO_ID, // 3
- Data.LOOKUP_KEY // 4
- };
-
- private static final String[] PROJECTION_ALTERNATIVE = new String[] {
- Data.RAW_CONTACT_ID, // 0
- Data.CONTACT_ID, // 1
- Data.DISPLAY_NAME_ALTERNATIVE, // 2
- // Dummy columns overwritten by the cursor wrapper
- Data.PHOTO_ID, // 3
- Data.LOOKUP_KEY // 4
- };
-
- static final int RAW_CONTACT_ID = 0;
- static final int CONTACT_ID = 1;
- static final int CONTACT_DISPLAY_NAME = 2;
- // Provided by the cursor wrapper.
- static final int CONTACT_PHOTO_ID = 3;
- // Provided by the cursor wrapper.
- static final int CONTACT_LOOKUP_KEY = 4;
-
- private GroupMembersQuery() {
- }
- }
-
- private AccountWithDataSet mAccount;
- private final Set<String> mRawContactIds = new HashSet<>();
-
- private final CharSequence mUnknownNameText;
-
- public GroupMemberPickListAdapter(Context context) {
- super(context);
- mUnknownNameText = context.getText(android.R.string.unknownName);
- }
-
- public GroupMemberPickListAdapter setAccount(AccountWithDataSet account) {
- mAccount = account;
- return this;
- }
-
- public GroupMemberPickListAdapter setRawContactIds(ArrayList<String> rawContactIds) {
- mRawContactIds.clear();
- mRawContactIds.addAll(rawContactIds);
- return this;
- }
-
- @Override
- public String getContactDisplayName(int position) {
- final Cursor cursor = (Cursor) getItem(position);
- return cursor.getString(GroupMembersQuery.CONTACT_DISPLAY_NAME);
- }
-
- @Override
- public void configureLoader(CursorLoader loader, long directoryId) {
- final Uri uri = Data.CONTENT_URI.buildUpon()
- .appendQueryParameter(Data.VISIBLE_CONTACTS_ONLY, "true")
- .build();
- loader.setUri(uri);
- loader.setProjection(
- getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
- ? GroupMembersQuery.PROJECTION_PRIMARY
- : GroupMembersQuery.PROJECTION_ALTERNATIVE);
- loader.setSelection(getSelection());
- loader.setSelectionArgs(getSelectionArgs());
- loader.setSortOrder(getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY
- ? Data.SORT_KEY_PRIMARY : Data.SORT_KEY_ALTERNATIVE
- + " COLLATE LOCALIZED ASC");
- }
-
- private String getSelection() {
- // Select raw contacts by account
- String result = RawContacts.ACCOUNT_NAME + "=? AND " + RawContacts.ACCOUNT_TYPE + "=? AND "
- + Data.MIMETYPE + "=? AND ";
- if (TextUtils.isEmpty(mAccount.dataSet)) {
- result += Data.DATA_SET + " IS NULL";
- } else {
- result += Data.DATA_SET + "=?";
- }
- return result;
- }
-
- private String[] getSelectionArgs() {
- final ArrayList<String> result = new ArrayList<>();
- result.add(mAccount.name);
- result.add(mAccount.type);
- result.add(GroupMembership.CONTENT_ITEM_TYPE);
- if (!TextUtils.isEmpty(mAccount.dataSet)) result.add(mAccount.dataSet);
- return result.toArray(new String[0]);
- }
-
- public Uri getRawContactUri(int position) {
- final Cursor cursor = (Cursor) getItem(position);
- final long rawContactId = cursor.getLong(GroupMembersQuery.RAW_CONTACT_ID);
- return Data.CONTENT_URI.buildUpon()
- .appendPath(Long.toString(rawContactId))
- .build();
- }
-
- @Override
- protected ContactListItemView newView(Context context, int partition, Cursor cursor,
- int position, ViewGroup parent) {
- final ContactListItemView view =
- super.newView(context, partition, cursor, position, parent);
- view.setUnknownNameText(mUnknownNameText);
- return view;
- }
-
- @Override
- protected void bindView(View v, int partition, Cursor cursor, int position) {
- super.bindView(v, partition, cursor, position);
- final ContactListItemView view = (ContactListItemView) v;
- bindName(view, cursor);
- bindViewId(view, cursor, GroupMembersQuery.RAW_CONTACT_ID);
- bindPhoto(view, cursor);
- }
-
- private void bindName(ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, GroupMembersQuery.CONTACT_DISPLAY_NAME,
- getContactNameDisplayOrder());
- }
-
- private void bindPhoto(final ContactListItemView view, Cursor cursor) {
- final long photoId = cursor.isNull(GroupMembersQuery.CONTACT_PHOTO_ID)
- ? 0 : cursor.getLong(GroupMembersQuery.CONTACT_PHOTO_ID);
- final DefaultImageRequest imageRequest = photoId == 0
- ? getDefaultImageRequestFromCursor(cursor, GroupMembersQuery.CONTACT_DISPLAY_NAME,
- GroupMembersQuery.CONTACT_LOOKUP_KEY)
- : null;
- getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false, getCircularPhotos(),
- imageRequest);
- }
-}
diff --git a/src/com/android/contacts/list/GroupMemberPickerFragment.java b/src/com/android/contacts/list/GroupMemberPickerFragment.java
index edd5739..fb378e6 100644
--- a/src/com/android/contacts/list/GroupMemberPickerFragment.java
+++ b/src/com/android/contacts/list/GroupMemberPickerFragment.java
@@ -15,38 +15,29 @@
*/
package com.android.contacts.list;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.database.CursorWrapper;
-import android.net.Uri;
import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
import android.util.Log;
-import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.contacts.common.R;
import com.android.contacts.common.list.ContactEntryListFragment;
+import com.android.contacts.common.list.ContactListAdapter.ContactQuery;
+import com.android.contacts.common.list.ContactListFilter;
+import com.android.contacts.common.list.DefaultContactListAdapter;
import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.preference.ContactsPreferences;
-import com.android.contacts.list.GroupMemberPickListAdapter.GroupMembersQuery;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
/**
* Fragment containing raw contacts for a specified account that are not already in a group.
*/
public class GroupMemberPickerFragment extends
- ContactEntryListFragment<GroupMemberPickListAdapter> {
+ ContactEntryListFragment<DefaultContactListAdapter> {
public static final String TAG = "GroupMemberPicker";
@@ -56,13 +47,11 @@
private static final String ARG_ACCOUNT = "account";
private static final String ARG_RAW_CONTACT_IDS = "rawContactIds";
- private static final int LOADER_CONTACT_ENTITY = 0;
-
/** Callbacks for host of {@link GroupMemberPickerFragment}. */
public interface Listener {
/** Invoked when a potential group member is selected. */
- void onGroupMemberClicked(Uri uri);
+ void onGroupMemberClicked(long contactId);
}
/**
@@ -82,23 +71,14 @@
mIndex = new int[mCount];
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "FilterCursorWrapper starting size cursor=" + mCount + " photosMap="
- + (mContactPhotosMap == null ? 0 : mContactPhotosMap.size()));
+ Log.v(TAG, "FilterCursorWrapper starting cursor size is " + mCount);
}
- final Set<String> uniqueRawContactIds = new HashSet<String>();
-
for (int i = 0; i < mCount; i++) {
super.moveToPosition(i);
- final String rawContactId = getString(GroupMembersQuery.RAW_CONTACT_ID);
- if (!mRawContactIds.contains(rawContactId)
- && !uniqueRawContactIds.contains(rawContactId)) {
+ final String contactId = getString(ContactQuery.CONTACT_ID);
+ if (!mRawContactIds.contains(contactId)) {
mIndex[mPos++] = i;
- uniqueRawContactIds.add(rawContactId);
- }
- if (mRawContactIds.contains(rawContactId) && mContactPhotosMap != null) {
- final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
- mContactPhotosMap.remove(contactId);
}
}
mCount = mPos;
@@ -106,82 +86,11 @@
super.moveToFirst();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "FilterCursorWrapper ending size cursor=" + mCount + " photosMap="
- + (mContactPhotosMap == null ? 0 : mContactPhotosMap.size()));
+ Log.v(TAG, "FilterCursorWrapper ending cursor size is" + mCount);
}
}
@Override
- public int getColumnIndex(String columnName) {
- final int index = getColumnIndexForContactColumn(columnName);
- return index < 0 ? super.getColumnIndex(columnName) : index;
- }
-
- @Override
- public int getColumnIndexOrThrow(String columnName) {
- final int index = getColumnIndexForContactColumn(columnName);
- return index < 0 ? super.getColumnIndexOrThrow(columnName) : index;
- }
-
- private int getColumnIndexForContactColumn(String columnName) {
- if (Data.PHOTO_ID.equals(columnName)) {
- return GroupMembersQuery.CONTACT_PHOTO_ID;
- }
- if (Data.LOOKUP_KEY.equals(columnName)) {
- return GroupMembersQuery.CONTACT_LOOKUP_KEY;
- }
- return -1;
- }
-
- @Override
- public String[] getColumnNames() {
- final String displayNameColumnName =
- getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
- ? Data.DISPLAY_NAME_PRIMARY
- : Data.DISPLAY_NAME_ALTERNATIVE;
- return new String[] {
- Data._ID,
- Data.CONTACT_ID,
- displayNameColumnName,
- Data.PHOTO_ID,
- Data.LOOKUP_KEY,
- };
- }
-
- @Override
- public String getString(int columnIndex) {
- if (columnIndex == GroupMembersQuery.CONTACT_LOOKUP_KEY) {
- if (columnIndex == GroupMembersQuery.CONTACT_PHOTO_ID) {
- final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
- final Pair<Long,String> pair = getContactPhotoPair(contactId);
- if (pair != null) {
- return pair.second;
- }
- }
- return null;
- }
- return super.getString(columnIndex);
- }
-
- @Override
- public long getLong(int columnIndex) {
- if (columnIndex == GroupMembersQuery.CONTACT_PHOTO_ID) {
- final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
- final Pair<Long,String> pair = getContactPhotoPair(contactId);
- if (pair != null) {
- return pair.first;
- }
- return 0;
- }
- return super.getLong(columnIndex);
- }
-
- private Pair<Long,String> getContactPhotoPair(long contactId) {
- return mContactPhotosMap != null && mContactPhotosMap.containsKey(contactId)
- ? mContactPhotosMap.get(contactId) : null;
- }
-
- @Override
public boolean move(int offset) {
return moveToPosition(mPos + offset);
}
@@ -223,49 +132,15 @@
}
}
- private final LoaderCallbacks<Cursor> mContactsEntityCallbacks = new LoaderCallbacks<Cursor>() {
-
- private final String[] PROJECTION = new String[] {
- Data.CONTACT_ID,
- Data.PHOTO_ID,
- Data.LOOKUP_KEY
- };
-
- @Override
- public CursorLoader onCreateLoader(int id, Bundle args) {
- final CursorLoader loader = new CursorLoader(getActivity());
- loader.setUri(Data.CONTENT_URI);
- loader.setProjection(PROJECTION);
- return loader;
- }
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
- mContactPhotosMap = new HashMap<>();
- while (cursor.moveToNext()) {
- final long contactId = cursor.getLong(0);
- final Pair<Long, String> pair =
- new Pair(cursor.getLong(1), cursor.getString(2));
- mContactPhotosMap.put(contactId, pair);
- }
- GroupMemberPickerFragment.super.startLoading();
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {}
- };
-
private AccountWithDataSet mAccount;
private ArrayList<String> mRawContactIds;
- // Contact ID longs to Pairs of photo ID and contact lookup keys
- private Map<Long, Pair<Long,String>> mContactPhotosMap;
-
private Listener mListener;
public static GroupMemberPickerFragment newInstance(AccountWithDataSet account,
- ArrayList<String> rawContactids) {
+ ArrayList<String> rawContactIds) {
final Bundle args = new Bundle();
args.putParcelable(ARG_ACCOUNT, account);
- args.putStringArrayList(ARG_RAW_CONTACT_IDS, rawContactids);
+ args.putStringArrayList(ARG_RAW_CONTACT_IDS, rawContactIds);
final GroupMemberPickerFragment fragment = new GroupMemberPickerFragment();
fragment.setArguments(args);
@@ -273,15 +148,15 @@
}
public GroupMemberPickerFragment() {
- setQuickContactEnabled(false);
setPhotoLoaderEnabled(true);
+ setSectionHeaderDisplayEnabled(false);
setVisibleScrollbarEnabled(true);
+
setHasOptionsMenu(true);
}
@Override
public void onCreate(Bundle savedState) {
- super.onCreate(savedState);
if (savedState == null) {
mAccount = getArguments().getParcelable(ARG_ACCOUNT);
mRawContactIds = getArguments().getStringArrayList(ARG_RAW_CONTACT_IDS);
@@ -289,6 +164,7 @@
mAccount = savedState.getParcelable(KEY_ACCOUNT);
mRawContactIds = savedState.getStringArrayList(KEY_RAW_CONTACT_IDS);
}
+ super.onCreate(savedState);
}
@Override
@@ -298,15 +174,6 @@
outState.putStringArrayList(KEY_RAW_CONTACT_IDS, mRawContactIds);
}
- @Override
- protected void startLoading() {
- if (mContactPhotosMap == null) {
- getLoaderManager().restartLoader(LOADER_CONTACT_ENTITY, null, mContactsEntityCallbacks);
- } else {
- super.startLoading();
- }
- }
-
public void setListener(Listener listener) {
mListener = listener;
}
@@ -324,24 +191,22 @@
}
@Override
- protected GroupMemberPickListAdapter createListAdapter() {
- final GroupMemberPickListAdapter adapter = new GroupMemberPickListAdapter(getActivity());
+ protected DefaultContactListAdapter createListAdapter() {
+ final DefaultContactListAdapter adapter = new DefaultContactListAdapter(getActivity());
+ adapter.setFilter(ContactListFilter.createGroupMembersFilter(
+ mAccount.type, mAccount.name, mAccount.dataSet));
+ adapter.setSectionHeaderDisplayEnabled(true);
adapter.setDisplayPhotos(true);
return adapter;
}
@Override
- protected void configureAdapter() {
- super.configureAdapter();
- getAdapter().setAccount(mAccount);
- getAdapter().setRawContactIds(mRawContactIds);
- getAdapter().setEmptyListEnabled(true);
- }
-
- @Override
protected void onItemClick(int position, long id) {
if (mListener != null) {
- mListener.onGroupMemberClicked(getAdapter().getRawContactUri(position));
+ final long contactId = getAdapter().getContactId(position);
+ if (contactId > 0) {
+ mListener.onGroupMemberClicked(contactId);
+ }
}
}
}
diff --git a/src/com/android/contacts/list/UiIntentActions.java b/src/com/android/contacts/list/UiIntentActions.java
index 31e5ade..571d56f 100644
--- a/src/com/android/contacts/list/UiIntentActions.java
+++ b/src/com/android/contacts/list/UiIntentActions.java
@@ -40,16 +40,16 @@
public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
/**
- * The account used to filter potential raw contact groups members.
+ * The account used to filter potential new group members.
*/
public static final String GROUP_ACCOUNT_WITH_DATA_SET =
"com.android.contacts.extra.GROUP_ACCOUNT_WITH_DATA_SET";
/**
- * The raw contact IDs for existing group members.
+ * The contact IDs for existing group members.
*/
- public static final String GROUP_RAW_CONTACT_IDS =
- "com.android.contacts.extra.GROUP_RAW_CONTACT_IDS";
+ public static final String GROUP_CONTACT_IDS =
+ "com.android.contacts.extra.GROUP_CONTACT_IDS";
/**
* The action for the all contacts list tab.