Merge "Fix title when account screen is opened from group." into ub-contactsdialer-h-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 18e8e92..13d2f61 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -172,8 +172,14 @@
<!-- Toast shown after two contacts have been linked by a user action. [CHAR LIMIT=NONE] -->
<string name="contactsJoinedMessage">Contacts linked</string>
- <!-- Toast shown after contact deleted when no display name is given. [CHAR LIMIT=20]-->
- <string name="contact_deleted_named_toast"><xliff:g id="name">%s</xliff:g> deleted</string>
+ <!-- Toast shown with names after user selected contacts are deleted by user action. [CHAR LIMIT=30] -->
+ <string name="contacts_deleted_one_named_toast"><xliff:g id="name">%1$s</xliff:g> deleted</string>
+
+ <!-- Toast shown with names after user selected contacts are deleted by user action. [CHAR LIMIT=30] -->
+ <string name="contacts_deleted_two_named_toast"><xliff:g id="name">%1$s</xliff:g> and <xliff:g id="name">%2$s</xliff:g> deleted</string>
+
+ <!-- Toast shown with names after user selected contacts are deleted by user action. [CHAR LIMIT=30] -->
+ <string name="contacts_deleted_many_named_toast"><xliff:g id="name">%1$s</xliff:g>, <xliff:g id="name">%2$s</xliff:g>, <xliff:g id="name">%3$s</xliff:g>... deleted</string>
<!-- Toast shown after contacts that the user has selected are deleted by a user action. [CHAR LIMIT=30] -->
<plurals name="contacts_deleted_toast">
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 2e98932..1dcc838 100755
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -119,6 +119,7 @@
public static final String EXTRA_CONTACT_IDS = "contactIds";
public static final String EXTRA_STARRED_FLAG = "starred";
public static final String EXTRA_DISPLAY_NAME = "extraDisplayName";
+ public static final String EXTRA_DISPLAY_NAME_ARRAY = "extraDisplayNameArray";
public static final String ACTION_SET_SUPER_PRIMARY = "setSuperPrimary";
public static final String ACTION_CLEAR_PRIMARY = "clearPrimary";
@@ -1148,10 +1149,11 @@
* Creates an intent that can be sent to this service to delete multiple contacts.
*/
public static Intent createDeleteMultipleContactsIntent(Context context,
- long[] contactIds) {
+ long[] contactIds, final String[] names) {
Intent serviceIntent = new Intent(context, ContactSaveService.class);
serviceIntent.setAction(ContactSaveService.ACTION_DELETE_MULTIPLE_CONTACTS);
serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_IDS, contactIds);
+ serviceIntent.putExtra(ContactSaveService.EXTRA_DISPLAY_NAME_ARRAY, names);
return serviceIntent;
}
@@ -1175,8 +1177,22 @@
final Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
getContentResolver().delete(contactUri, null, null);
}
- final String deleteToastMessage = getResources().getQuantityString(R.plurals
- .contacts_deleted_toast, contactIds.length);
+ final String[] names = intent.getStringArrayExtra(
+ ContactSaveService.EXTRA_DISPLAY_NAME_ARRAY);
+ final String deleteToastMessage;
+ if (names.length == 0) {
+ deleteToastMessage = getResources().getQuantityString(
+ R.plurals.contacts_deleted_toast, contactIds.length);
+ } else if (names.length == 1) {
+ deleteToastMessage = getResources().getString(
+ R.string.contacts_deleted_one_named_toast, names);
+ } else if (names.length == 2) {
+ deleteToastMessage = getResources().getString(
+ R.string.contacts_deleted_two_named_toast, names);
+ } else {
+ deleteToastMessage = getResources().getString(
+ R.string.contacts_deleted_many_named_toast, names);
+ }
mMainHandler.post(new Runnable() {
@Override
public void run() {
diff --git a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
index 7396bbd..5b71c48 100644
--- a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
@@ -39,6 +39,8 @@
private Cursor mCursor;
private MaterialPalette mMaterialPalette;
private boolean mIsUserProfile;
+ private boolean mHasWritableAccount;
+ private int mWritableAccountPosition;
/**
* The contact data loader listener.
@@ -61,10 +63,11 @@
}
mCursor = cursor;
mIsUserProfile = ((PickRawContactLoader) loader).isUserProfile();
- if (mCursor.getCount() == 1) {
- loadEditor();
- } else {
+ setHasWritableAccount();
+ if (mCursor.getCount() > 1 && mHasWritableAccount) {
showDialog();
+ } else {
+ loadEditor();
}
}
@@ -142,17 +145,17 @@
}
/**
- * Starts the editor for the first (only) raw contact in the cursor.
+ * Starts the editor for the only writable raw contact in the cursor if one exists. Otherwise,
+ * the editor is started normally and handles creation of a new writable raw contact.
*/
private void loadEditor() {
final Intent intent;
- if (isSingleWritableAccount()) {
- mCursor.moveToFirst();
+ if (mHasWritableAccount) {
+ mCursor.moveToPosition(mWritableAccountPosition);
final long rawContactId = mCursor.getLong(PickRawContactLoader.RAW_CONTACT_ID);
intent = getIntentForRawContact(rawContactId);
-
} else {
- // If it's a single read-only raw contact, we'll want to let the editor create
+ // If the contact has only read-only raw contacts, we'll want to let the editor create
// the writable raw contact for it.
intent = EditorIntents.createEditContactIntent(this, mUri, mMaterialPalette, -1);
intent.setClass(this, ContactEditorActivity.class);
@@ -164,19 +167,21 @@
}
/**
- * @return true if there is only one raw contact in the contact and it is from a writable
- * account.
+ * Determines if this contact has a writable account.
*/
- private boolean isSingleWritableAccount() {
- if (mCursor.getCount() != 1) {
- return false;
+ private void setHasWritableAccount() {
+ mCursor.moveToPosition(-1);
+ while (mCursor.moveToNext()) {
+ final String accountType = mCursor.getString(PickRawContactLoader.ACCOUNT_TYPE);
+ final String dataSet = mCursor.getString(PickRawContactLoader.DATA_SET);
+ final AccountType account = AccountTypeManager.getInstance(this)
+ .getAccountType(accountType, dataSet);
+ if (account.areContactsWritable()) {
+ mHasWritableAccount = true;
+ mWritableAccountPosition = mCursor.getPosition();
+ return;
+ }
}
- mCursor.moveToFirst();
- final String accountType = mCursor.getString(PickRawContactLoader.ACCOUNT_TYPE);
- final String dataSet = mCursor.getString(PickRawContactLoader.DATA_SET);
- final AccountType account = AccountTypeManager.getInstance(this)
- .getAccountType(accountType, dataSet);
- return account.areContactsWritable();
}
/**
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index a6d48b4..455d9ae 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -21,6 +21,7 @@
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -75,6 +76,8 @@
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.common.util.MaterialColorMapUtils;
import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
@@ -980,19 +983,11 @@
}
/**
- * Whether the contact being edited spans multiple raw contacts.
- * The may also span multiple accounts.
- */
- private boolean isEditingMultipleRawContacts() {
- return mState.size() > 1;
- }
-
- /**
- * Whether the contact being edited is composed of a single read-only raw contact
+ * Whether the contact being edited is composed of read-only raw contacts
* aggregated with a newly created writable raw contact.
*/
private boolean isEditingReadOnlyRawContactWithNewContact() {
- return mHasNewContact && mState.size() == 2;
+ return mHasNewContact && mState.size() > 1;
}
/**
@@ -1015,19 +1010,6 @@
}
/**
- * We allow unlinking only if there is more than one raw contact, it is not a user-profile,
- * and unlinking won't result in an empty contact. For the empty contact case, we only guard
- * against this when there is a single read-only contact in the aggregate. If the user
- * has joined >1 read-only contacts together, we allow them to unlink it, even if they have
- * never added their own information and unlinking will create a name only contact.
- */
- private boolean canUnlinkRawContacts() {
- return isEditingMultipleRawContacts()
- && !isEditingUserProfile()
- && !isEditingReadOnlyRawContactWithNewContact();
- }
-
- /**
* Determines if changes were made in the editor that need to be saved, while taking into
* account that name changes are not real for read-only contacts.
* See go/editing-read-only-contacts
@@ -1060,7 +1042,7 @@
* name fields as the original.
*/
private boolean structuredNamesAreEqual(ValuesDelta before, ValuesDelta after) {
- if (before == null && after == null) return true;
+ if (before == after) return true;
if (before == null || after == null) return false;
final ContentValues original = before.getBefore();
final ContentValues pending = after.getAfter();
@@ -1377,7 +1359,7 @@
}
editorView.setState(mState, getMaterialPalette(), mViewIdGenerator,
mHasNewContact, mIsUserProfile, mAccountWithDataSet,
- mRawContactIdToDisplayAlone, isEditingReadOnlyRawContactWithNewContact());
+ mRawContactIdToDisplayAlone);
// Set up the photo widget
editorView.setPhotoListener(this);
@@ -1510,6 +1492,28 @@
onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri, /* joinContactId */ null);
}
+
+ private String getNameToDisplay(Uri contactUri) {
+ final ContentResolver resolver = mContext.getContentResolver();
+ final Cursor cursor = resolver.query(contactUri, new String[]{
+ ContactsContract.Contacts.DISPLAY_NAME,
+ ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE}, null, null, null);
+ try {
+ if (cursor.moveToFirst()) {
+ final String displayName = cursor.getString(0);
+ final String displayNameAlt = cursor.getString(1);
+ cursor.close();
+ return ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
+ new ContactsPreferences(mContext));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return null;
+ }
+
+
@Override
public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
Uri contactLookupUri, Long joinContactId) {
@@ -1523,8 +1527,7 @@
.show();
break;
default:
- final String displayName = getContent().getNameEditorView()
- .getDisplayName();
+ final String displayName = getNameToDisplay(contactLookupUri);
final String toastMessage;
if (!TextUtils.isEmpty(displayName)) {
toastMessage = getResources().getString(
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index 038a8de..1b37dab 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -206,7 +206,6 @@
private RawContactDeltaList mRawContactDeltas;
private RawContactDelta mCurrentRawContactDelta;
private long mRawContactIdToDisplayAlone = -1;
- private boolean mIsEditingReadOnlyRawContactWithNewContact;
private Map<String, KindSectionData> mKindSectionDataMap = new HashMap<>();
private Set<String> mSortedMimetypes = new TreeSet<>(new MimeTypeComparator());
@@ -429,11 +428,10 @@
public void setState(RawContactDeltaList rawContactDeltas,
MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
boolean hasNewContact, boolean isUserProfile, AccountWithDataSet primaryAccount,
- long rawContactIdToDisplayAlone, boolean isEditingReadOnlyRawContactWithNewContact) {
+ long rawContactIdToDisplayAlone) {
mRawContactDeltas = rawContactDeltas;
mRawContactIdToDisplayAlone = rawContactIdToDisplayAlone;
- mIsEditingReadOnlyRawContactWithNewContact = isEditingReadOnlyRawContactWithNewContact;
mKindSectionViewMap.clear();
mKindSectionViews.removeAllViews();
diff --git a/src/com/android/contacts/interactions/ContactDeletionInteraction.java b/src/com/android/contacts/interactions/ContactDeletionInteraction.java
index ec500f3..9b3d0f8 100644
--- a/src/com/android/contacts/interactions/ContactDeletionInteraction.java
+++ b/src/com/android/contacts/interactions/ContactDeletionInteraction.java
@@ -40,6 +40,8 @@
import com.android.contacts.R;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.common.util.ContactDisplayUtils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
@@ -67,6 +69,7 @@
Entity.CONTACT_ID, // 3
Entity.LOOKUP_KEY, // 4
Entity.DISPLAY_NAME, // 5
+ Entity.DISPLAY_NAME_ALTERNATIVE, // 6
};
private static final int COLUMN_INDEX_RAW_CONTACT_ID = 0;
@@ -75,10 +78,12 @@
private static final int COLUMN_INDEX_CONTACT_ID = 3;
private static final int COLUMN_INDEX_LOOKUP_KEY = 4;
private static final int COLUMN_INDEX_DISPLAY_NAME = 5;
+ private static final int COLUMN_INDEX_DISPLAY_NAME_ALT = 6;
private boolean mActive;
private Uri mContactUri;
private String mDisplayName;
+ private String mDisplayNameAlt;
private boolean mFinishActivityWhenDone;
private Context mContext;
private AlertDialog mDialog;
@@ -252,6 +257,7 @@
contactId = cursor.getLong(COLUMN_INDEX_CONTACT_ID);
lookupKey = cursor.getString(COLUMN_INDEX_LOOKUP_KEY);
mDisplayName = cursor.getString(COLUMN_INDEX_DISPLAY_NAME);
+ mDisplayNameAlt = cursor.getString(COLUMN_INDEX_DISPLAY_NAME_ALT);
AccountType type = accountTypes.getAccountType(accountType, dataSet);
boolean writable = type == null || type.areContactsWritable();
if (writable) {
@@ -343,12 +349,14 @@
getActivity().setResult(RESULT_CODE_DELETED);
getActivity().finish();
final String deleteToastMessage;
- if (mDisplayName == null) {
+ final String name = ContactDisplayUtils.getPreferredDisplayName(mDisplayName,
+ mDisplayNameAlt, new ContactsPreferences(mContext));
+ if (TextUtils.isEmpty(name)) {
deleteToastMessage = getResources().getQuantityString(
R.plurals.contacts_deleted_toast, /* quantity */ 1);
} else {
deleteToastMessage = getResources().getString(
- R.string.contact_deleted_named_toast, mDisplayName);
+ R.string.contacts_deleted_one_named_toast, name);
}
Toast.makeText(mContext, deleteToastMessage, Toast.LENGTH_LONG).show();
}
diff --git a/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java b/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
index ff0d978..b63eacd 100644
--- a/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
+++ b/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
@@ -16,6 +16,8 @@
package com.android.contacts.interactions;
+import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.common.util.ContactDisplayUtils;
import com.google.common.collect.Sets;
import com.android.contacts.ContactSaveService;
@@ -64,12 +66,16 @@
RawContacts.ACCOUNT_TYPE,
RawContacts.DATA_SET,
RawContacts.CONTACT_ID,
+ RawContacts.DISPLAY_NAME_PRIMARY,
+ RawContacts.DISPLAY_NAME_ALTERNATIVE
};
private static final int COLUMN_INDEX_RAW_CONTACT_ID = 0;
private static final int COLUMN_INDEX_ACCOUNT_TYPE = 1;
private static final int COLUMN_INDEX_DATA_SET = 2;
private static final int COLUMN_INDEX_CONTACT_ID = 3;
+ private static final int COLUMN_INDEX_DISPLAY_NAME = 4;
+ private static final int COLUMN_INDEX_DISPLAY_NAME_ALT = 5;
private boolean mIsLoaderActive;
private TreeSet<Long> mContactIds;
@@ -193,6 +199,9 @@
final HashSet<Long> readOnlyRawContacts = Sets.newHashSet();
final HashSet<Long> writableRawContacts = Sets.newHashSet();
final HashSet<Long> contactIds = Sets.newHashSet();
+ final HashSet<String> names = Sets.newHashSet();
+
+ final ContactsPreferences contactsPreferences = new ContactsPreferences(mContext);
AccountTypeManager accountTypes = AccountTypeManager.getInstance(getActivity());
cursor.moveToPosition(-1);
@@ -201,6 +210,12 @@
final String accountType = cursor.getString(COLUMN_INDEX_ACCOUNT_TYPE);
final String dataSet = cursor.getString(COLUMN_INDEX_DATA_SET);
final long contactId = cursor.getLong(COLUMN_INDEX_CONTACT_ID);
+ final String displayName = cursor.getString(COLUMN_INDEX_DISPLAY_NAME);
+ final String displayNameAlt = cursor.getString(COLUMN_INDEX_DISPLAY_NAME_ALT);
+
+ names.add(ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
+ contactsPreferences));
+
contactIds.add(contactId);
final AccountType type = accountTypes.getAccountType(accountType, dataSet);
boolean writable = type == null || type.areContactsWritable();
@@ -237,7 +252,8 @@
contactIdArray[i] = contactIdObjectArray[i];
}
- showDialog(messageId, positiveButtonId, contactIdArray);
+ final String[] namesArray = names.toArray(new String[names.size()]);
+ showDialog(messageId, positiveButtonId, contactIdArray, namesArray);
// We don't want onLoadFinished() calls any more, which may come when the database is
// updating.
@@ -248,7 +264,8 @@
public void onLoaderReset(Loader<Cursor> loader) {
}
- private void showDialog(int messageId, int positiveButtonId, final long[] contactIds) {
+ private void showDialog(int messageId, int positiveButtonId, final long[] contactIds,
+ final String[] namesArray) {
mDialog = new AlertDialog.Builder(getActivity())
.setIconAttribute(android.R.attr.alertDialogIcon)
.setMessage(messageId)
@@ -257,7 +274,7 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
- doDeleteContact(contactIds);
+ doDeleteContact(contactIds, namesArray);
}
}
)
@@ -289,9 +306,9 @@
}
}
- protected void doDeleteContact(long[] contactIds) {
+ protected void doDeleteContact(long[] contactIds, final String[] names) {
mContext.startService(ContactSaveService.createDeleteMultipleContactsIntent(mContext,
- contactIds));
+ contactIds, names));
mListener.onDeletionFinished();
}