Dedupe same entries in the fasttrack action list.
Fixes b/2159633.
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index 1e3b8ad..622edbe 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -37,6 +37,7 @@
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.Im.ProviderNames;
+import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -424,4 +425,47 @@
public static boolean isGraphic(CharSequence str) {
return !TextUtils.isEmpty(str) && TextUtils.isGraphic(str);
}
+
+ /**
+ * Returns true if two objects are considered equal. Two null references are equal here.
+ */
+ public static boolean areObjectsEqual(Object a, Object b) {
+ return a == b || (a != null && a.equals(b));
+ }
+
+ /**
+ * Returns true if two data with mimetypes which represent values in contact entries are
+ * considered equal.
+ */
+ public static final boolean areDataEqual(Context context, CharSequence mimetype1,
+ CharSequence data1, CharSequence mimetype2, CharSequence data2) {
+ if (TextUtils.equals(Phone.CONTENT_ITEM_TYPE, mimetype1)
+ && TextUtils.equals(Phone.CONTENT_ITEM_TYPE, mimetype2)) {
+ if (data1 == data2) {
+ return true;
+ }
+ if (data1 == null || data2 == null) {
+ return false;
+ }
+ return PhoneNumberUtils.compare(context, data1.toString(), data2.toString());
+ } else {
+ if (mimetype1 == mimetype2 && data1 == data2) {
+ return true;
+ }
+ return TextUtils.equals(mimetype1, mimetype2) && TextUtils.equals(data1, data2);
+ }
+ }
+
+ /**
+ * Returns true if two {@link Intent}s are both null, or have the same action.
+ */
+ public static final boolean areIntentActionEqual(Intent a, Intent b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ return TextUtils.equals(a.getAction(), b.getAction());
+ }
}
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index 06296cc..a1aeca3 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -1026,39 +1026,19 @@
return false;
}
- if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)
- && Phone.CONTENT_ITEM_TYPE.equals(entry.mimetype)) {
- if (!PhoneNumberUtils.compare(this.context, data, entry.data)) {
- return false;
- }
- } else {
- if (!equals(data, entry.data)) {
- return false;
- }
+ if (!ContactsUtils.areDataEqual(context, mimetype, data, entry.mimetype, entry.data)) {
+ return false;
}
- if (!equals(mimetype, entry.mimetype)
- || !intentCollapsible(intent, entry.intent)
- || !intentCollapsible(secondaryIntent, entry.secondaryIntent)
+ if (!TextUtils.equals(mimetype, entry.mimetype)
+ || !ContactsUtils.areIntentActionEqual(intent, entry.intent)
+ || !ContactsUtils.areIntentActionEqual(secondaryIntent, entry.secondaryIntent)
|| actionIcon != entry.actionIcon) {
return false;
}
return true;
}
-
- private boolean equals(Object a, Object b) {
- return a==b || (a != null && a.equals(b));
- }
-
- private boolean intentCollapsible(Intent a, Intent b) {
- if (a == b) {
- return true;
- } else if ((a != null && b != null) && equals(a.getAction(), b.getAction())) {
- return true;
- }
- return false;
- }
}
/** Cache of the children views of a row */
diff --git a/src/com/android/contacts/ui/QuickContactWindow.java b/src/com/android/contacts/ui/QuickContactWindow.java
index e787987..f43c17e 100644
--- a/src/com/android/contacts/ui/QuickContactWindow.java
+++ b/src/com/android/contacts/ui/QuickContactWindow.java
@@ -16,6 +16,7 @@
package com.android.contacts.ui;
+import com.android.contacts.Collapser;
import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
import com.android.contacts.model.ContactsSource;
@@ -87,6 +88,7 @@
import android.widget.Toast;
import java.lang.ref.SoftReference;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -658,7 +660,7 @@
* Abstract definition of an action that could be performed, along with
* string description and icon.
*/
- private interface Action {
+ private interface Action extends Collapser.Collapsible<Action> {
public CharSequence getHeader();
public CharSequence getBody();
@@ -844,6 +846,39 @@
public Intent getIntent() {
return mIntent;
}
+
+ /** {@inheritDoc} */
+ public boolean collapseWith(Action other) {
+ if (!shouldCollapseWith(other)) {
+ return false;
+ }
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public boolean shouldCollapseWith(Action t) {
+ if (t == null) {
+ return false;
+ }
+ if (!(t instanceof DataAction)) {
+ Log.e(TAG, "t must be DataAction");
+ return false;
+ }
+ DataAction other = (DataAction)t;
+ if (!ContactsUtils.areObjectsEqual(mKind, other.mKind)) {
+ return false;
+ }
+ if (!ContactsUtils.areDataEqual(mContext, mMimeType, mBody, other.mMimeType,
+ other.mBody)) {
+ return false;
+ }
+ if (!TextUtils.equals(mMimeType, other.mMimeType)
+ || !ContactsUtils.areIntentActionEqual(mIntent, other.mIntent)
+ ) {
+ return false;
+ }
+ return true;
+ }
}
/**
@@ -895,6 +930,15 @@
return null;
}
+ /** {@inheritDoc} */
+ public boolean collapseWith(Action t) {
+ return false; // Never dup.
+ }
+
+ /** {@inheritDoc} */
+ public boolean shouldCollapseWith(Action t) {
+ return false; // Never dup.
+ }
}
/**
@@ -1039,7 +1083,7 @@
* Provide a strongly-typed {@link LinkedList} that holds a list of
* {@link Action} objects.
*/
- private class ActionList extends LinkedList<Action> {
+ private class ActionList extends ArrayList<Action> {
}
/**
@@ -1219,8 +1263,8 @@
}
/**
- * Inflate the in-track view for the action of the given MIME-type. Will use
- * the icon provided by the {@link DataKind}.
+ * Inflate the in-track view for the action of the given MIME-type, collapsing duplicate values.
+ * Will use the icon provided by the {@link DataKind}.
*/
private View inflateAction(String mimeType) {
final CheckableImageView view = (CheckableImageView)obtainView();
@@ -1228,6 +1272,9 @@
// Add direct intent if single child, otherwise flag for multiple
ActionList children = mActions.get(mimeType);
+ if (children.size() > 1) {
+ Collapser.collapseList(children);
+ }
Action firstInfo = children.get(0);
if (children.size() == 1) {
view.setTag(firstInfo);