Sorts mimetypes together in the cards

Change-Id: I1247874e4fb671551d9b0554960a566a5a5d6b0d
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index 1a4051e..2b2f032 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -131,8 +131,10 @@
     private boolean mIsExpanded = false;
     private int mCollapsedEntriesCount;
     private ExpandingEntryCardViewListener mListener;
-    private List<Entry> mEntries;
-    private List<View> mEntryViews;
+    private List<List<Entry>> mEntries;
+    private int mNumEntries = 0;
+    private boolean mAllEntriesInflated = false;
+    private List<List<View>> mEntryViews;
     private LinearLayout mEntriesViewGroup;
     private final Drawable mCollapseArrowDrawable;
     private final Drawable mExpandArrowDrawable;
@@ -179,21 +181,31 @@
      *
      * @param entries The Entry list to display.
      */
-    public void initialize(List<Entry> entries, int numInitialVisibleEntries,
+    public void initialize(List<List<Entry>> entries, int numInitialVisibleEntries,
             boolean isExpanded, ExpandingEntryCardViewListener listener) {
         LayoutInflater layoutInflater = LayoutInflater.from(getContext());
         mIsExpanded = isExpanded;
+        mEntryViews = new ArrayList<List<View>>(entries.size());
         mEntries = entries;
-        mEntryViews = new ArrayList<View>(entries.size());
-        mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, entries.size());
+        for (List<Entry> entryList : mEntries) {
+            mNumEntries += entryList.size();
+            mEntryViews.add(new ArrayList<View>());
+        }
+        mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, mNumEntries);
+        // Only show the head of each entry list if the initial visible number falls between the
+        // number of lists and the total number of entries
+        if (mCollapsedEntriesCount > mEntries.size()) {
+            mCollapsedEntriesCount = mEntries.size();
+        }
         mListener = listener;
 
         if (mIsExpanded) {
             updateExpandCollapseButton(getCollapseButtonText());
+            inflateAllEntries(layoutInflater);
         } else {
             updateExpandCollapseButton(getExpandButtonText());
+            inflateInitialEntries(layoutInflater);
         }
-        inflateViewsIfNeeded(layoutInflater);
         insertEntriesIntoViewGroup();
         applyColor();
     }
@@ -229,17 +241,21 @@
 
     private void insertEntriesIntoViewGroup() {
         mEntriesViewGroup.removeAllViews();
-        for (int i = 0; i < mCollapsedEntriesCount; ++i) {
-            addEntry(mEntryViews.get(i));
-        }
+
         if (mIsExpanded) {
-            for (int i = mCollapsedEntriesCount; i < mEntryViews.size(); ++i) {
-                addEntry(mEntryViews.get(i));
+            for (List<View> viewList : mEntryViews) {
+                for (View view : viewList) {
+                    addEntry(view);
+                }
+            }
+        } else {
+            for (int i = 0; i < mCollapsedEntriesCount; i++) {
+                addEntry(mEntryViews.get(i).get(0));
             }
         }
 
         removeView(mExpandCollapseButton);
-        if (mCollapsedEntriesCount < mEntries.size()
+        if (mCollapsedEntriesCount < mNumEntries
                 && mExpandCollapseButton.getParent() == null) {
             addView(mExpandCollapseButton, -1);
         }
@@ -290,16 +306,37 @@
     }
 
     /**
-     * Lazily inflate the number of views currently needed, and bind data from
-     * mEntries into these views.
+     * Inflates the initial entries to be shown.
      */
-    private void inflateViewsIfNeeded(LayoutInflater layoutInflater) {
-        final int viewsToInflate = mIsExpanded ?  mEntries.size() : mCollapsedEntriesCount;
-        for (int i = mEntryViews.size(); i < viewsToInflate; i++) {
-            mEntryViews.add(createEntryView(layoutInflater, mEntries.get(i)));
+    private void inflateInitialEntries(LayoutInflater layoutInflater) {
+        // If the number of collapsed entries equals total entries, inflate all
+        if (mCollapsedEntriesCount == mNumEntries) {
+            inflateAllEntries(layoutInflater);
+        } else {
+            // Otherwise inflate the top entry from each list
+            for (int i = 0; i < mCollapsedEntriesCount; i++) {
+                mEntryViews.get(i).add(createEntryView(layoutInflater, mEntries.get(i).get(0)));
+            }
         }
     }
 
+    /**
+     * Inflates all entries.
+     */
+    private void inflateAllEntries(LayoutInflater layoutInflater) {
+        if (mAllEntriesInflated) {
+            return;
+        }
+        for (int i = 0; i < mEntries.size(); i++) {
+            List<Entry> entryList = mEntries.get(i);
+            List<View> viewList = mEntryViews.get(i);
+            for (int j = viewList.size(); j < entryList.size(); j++) {
+                viewList.add(createEntryView(layoutInflater, entryList.get(j)));
+            }
+        }
+        mAllEntriesInflated = true;
+    }
+
     public void setColorAndFilter(int color, ColorFilter colorFilter) {
         mThemeColor = color;
         mThemeColorFilter = colorFilter;
@@ -323,10 +360,12 @@
 
             // Entry icons
             if (mEntries != null) {
-                for (Entry entry : mEntries) {
-                    Drawable icon = entry.getIcon();
-                    if (icon != null) {
-                        icon.setColorFilter(mThemeColorFilter);
+                for (List<Entry> entryList : mEntries) {
+                    for (Entry entry : entryList) {
+                        Drawable icon = entry.getIcon();
+                        if (icon != null) {
+                            icon.setColorFilter(mThemeColorFilter);
+                        }
                     }
                 }
             }
@@ -412,7 +451,7 @@
 
         mIsExpanded = true;
         // In order to insert new entries, we may need to inflate them for the first time
-        inflateViewsIfNeeded(LayoutInflater.from(getContext()));
+        inflateAllEntries(LayoutInflater.from(getContext()));
         insertEntriesIntoViewGroup();
         updateExpandCollapseButton(getCollapseButtonText());
 
@@ -447,7 +486,7 @@
         if (mCollapsedEntriesCount == 0) {
             return 0;
         }
-        final View bottomCollapsedView = mEntryViews.get(mCollapsedEntriesCount - 1);
+        final View bottomCollapsedView = mEntryViews.get(mCollapsedEntriesCount - 1).get(0);
         return bottomCollapsedView.getTop() + bottomCollapsedView.getHeight();
     }
 
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index bc7dc1f..bd5336e 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -60,6 +60,7 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.DisplayNameSources;
 import android.provider.ContactsContract.DataUsageFeedback;
 import android.provider.ContactsContract.QuickContact;
@@ -781,46 +782,21 @@
     private void populateContactAndAboutCard() {
         Trace.beginSection("bind contact card");
 
-        final List<Entry> contactCardEntries = new ArrayList<>();
-        final List<Entry> aboutCardEntries = new ArrayList<>();
+        final List<List<Entry>> contactCardEntries = new ArrayList<>();
+        final List<List<Entry>> aboutCardEntries = new ArrayList<>();
 
-        int topContactIndex = 0;
         for (int i = 0; i < mDataItemsList.size(); ++i) {
             final List<DataItem> dataItemsByMimeType = mDataItemsList.get(i);
             final DataItem topDataItem = dataItemsByMimeType.get(0);
             if (ABOUT_CARD_MIMETYPES.contains(topDataItem.getMimeType())) {
-                aboutCardEntries.addAll(dataItemsToEntries(mDataItemsList.get(i)));
+                List<Entry> aboutEntries = dataItemsToEntries(mDataItemsList.get(i));
+                if (aboutEntries.size() > 0) {
+                    aboutCardEntries.add(aboutEntries);
+                }
             } else {
-                // Add most used to the top of the contact card
-                final Entry topEntry = dataItemToEntry(topDataItem);
-                if (topEntry != null) {
-                    contactCardEntries.add(topContactIndex++, dataItemToEntry(topDataItem));
-                }
-                // TODO merge SMS into secondary action
-                if (topDataItem instanceof PhoneDataItem) {
-                    final PhoneDataItem phone = (PhoneDataItem) topDataItem;
-                    Intent smsIntent = null;
-                    if (mSmsComponent != null) {
-                        smsIntent = new Intent(Intent.ACTION_SENDTO,
-                                Uri.fromParts(CallUtil.SCHEME_SMSTO, phone.getNumber(), null));
-                        smsIntent.setComponent(mSmsComponent);
-                    }
-                    final int dataId = phone.getId() > Integer.MAX_VALUE ?
-                            -1 : (int) phone.getId();
-                    contactCardEntries.add(topContactIndex++,
-                            new Entry(dataId,
-                                    getResources().getDrawable(R.drawable.ic_message_24dp),
-                                    getResources().getString(R.string.send_message),
-                                    /* subHeader = */ null,
-                                    /* text = */ phone.buildDataString(
-                                            this, topDataItem.getDataKind()),
-                                            smsIntent,
-                                            /* isEditable = */ false));
-                }
-                // Add the rest of the entries to the bottom of the card
-                if (dataItemsByMimeType.size() > 1) {
-                    contactCardEntries.addAll(dataItemsToEntries(
-                            dataItemsByMimeType.subList(1, dataItemsByMimeType.size())));
+                List<Entry> contactEntries = dataItemsToEntries(mDataItemsList.get(i));
+                if (contactEntries.size() > 0) {
+                    contactCardEntries.add(contactEntries);
                 }
             }
         }
@@ -1075,8 +1051,8 @@
             header = dataItem.buildDataStringForDisplay(this, kind);
             text = kind.typeColumn;
             intent = new Intent(Intent.ACTION_VIEW);
-            intent.setDataAndType(Uri.parse(dataItem.buildDataString(this, kind)),
-                    dataItem.getMimeType());
+            final Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, dataItem.getId());
+            intent.setDataAndType(uri, dataItem.getMimeType());
             icon = ResolveCache.getInstance(this).getIcon(dataItem.getMimeType(), intent);
         }
 
@@ -1107,6 +1083,26 @@
             if (entry != null) {
                 entries.add(entry);
             }
+            // TODO merge secondary intents
+            if (dataItem instanceof PhoneDataItem) {
+                final PhoneDataItem phone = (PhoneDataItem) dataItem;
+                Intent smsIntent = null;
+                if (mSmsComponent != null) {
+                    smsIntent = new Intent(Intent.ACTION_SENDTO,
+                            Uri.fromParts(CallUtil.SCHEME_SMSTO, phone.getNumber(), null));
+                    smsIntent.setComponent(mSmsComponent);
+                }
+                final int dataId = dataItem.getId() > Integer.MAX_VALUE ?
+                        -1 : (int) dataItem.getId();
+                entries.add(new Entry(dataId,
+                        getResources().getDrawable(R.drawable.ic_message_24dp),
+                        getResources().getString(R.string.send_message),
+                        /* subHeader = */ null,
+                        /* text = */ phone.buildDataString(this,
+                                dataItem.getDataKind()),
+                        smsIntent,
+                        /* isEditable = */ false));
+            }
         }
         return entries;
     }
@@ -1395,8 +1391,11 @@
             }
         });
 
+
+        List<List<Entry>> interactionsWrapper = new ArrayList<>();
+        interactionsWrapper.add(contactInteractionsToEntries(allInteractions));
         if (allInteractions.size() > 0) {
-            mRecentCard.initialize(contactInteractionsToEntries(allInteractions),
+            mRecentCard.initialize(interactionsWrapper,
                     /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN,
                     /* isExpanded = */ false, mExpandingEntryCardViewListener);
             mRecentCard.setVisibility(View.VISIBLE);