Add comments to items in Updates tab.

Bug: 5095383
Change-Id: I87311bc37446fe83bf47aa554774a9a056f3a251
diff --git a/res/layout/stream_item_text.xml b/res/layout/stream_item_text.xml
index 601dfb9..4c44100 100644
--- a/res/layout/stream_item_text.xml
+++ b/res/layout/stream_item_text.xml
@@ -25,9 +25,22 @@
         android:textSize="16sp"
         android:textColor="@color/social_update_text_color" />
 
-    <TextView android:id="@+id/stream_item_attribution"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="@color/social_update_attribution_color"/>
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView android:id="@+id/stream_item_attribution"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="@color/social_update_attribution_color" />
+
+        <TextView android:id="@+id/stream_item_comments"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="4dip"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="@color/social_update_comments_color" />
+    </LinearLayout>
+
 </LinearLayout>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 325d2e7..b6b3f31 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -35,6 +35,8 @@
 
     <color name="social_update_attribution_color">#ff777777</color>
 
+    <color name="social_update_comments_color">#ff777777</color>
+
     <!-- Color used for the letter in the A-Z section header -->
     <color name="section_header_text_color">#ff999999</color>
 
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index e9d75ef..d8ba995 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -25,6 +25,7 @@
 import com.android.contacts.util.ContactBadgeUtil;
 import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.util.StreamItemPhotoEntry;
+import com.google.common.annotations.VisibleForTesting;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -327,14 +328,22 @@
         streamContainer.addView(oneColumnView);
     }
 
-    private static View addStreamItemText(LayoutInflater inflater, Context context,
+    @VisibleForTesting
+    static View addStreamItemText(LayoutInflater inflater, Context context,
             StreamItemEntry streamItem, ViewGroup parent) {
         View textUpdate = inflater.inflate(R.layout.stream_item_text, parent, false);
         TextView htmlView = (TextView) textUpdate.findViewById(R.id.stream_item_html);
         TextView attributionView = (TextView) textUpdate.findViewById(
                 R.id.stream_item_attribution);
+        TextView commentsView = (TextView) textUpdate.findViewById(R.id.stream_item_comments);
         htmlView.setText(Html.fromHtml(streamItem.getText()));
         attributionView.setText(ContactBadgeUtil.getSocialDate(streamItem, context));
+        if (streamItem.getComments() != null) {
+            commentsView.setText(Html.fromHtml(streamItem.getComments()));
+            commentsView.setVisibility(View.VISIBLE);
+        } else {
+            commentsView.setVisibility(View.GONE);
+        }
         parent.addView(textUpdate);
         return textUpdate;
     }
diff --git a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
new file mode 100644
index 0000000..f9b33e0
--- /dev/null
+++ b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.detail;
+
+import com.android.contacts.R;
+import com.android.contacts.util.StreamItemEntry;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Html;
+import android.text.Spanned;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Unit tests for {@link ContactDetailDisplayUtils}.
+ */
+@SmallTest
+public class ContactDetailDisplayUtilsTest extends AndroidTestCase {
+    private static final String TEST_STREAM_ITEM_TEXT = "text";
+
+    private ViewGroup mParent;
+    private LayoutInflater mLayoutInflater;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mParent = new LinearLayout(getContext());
+        mLayoutInflater =
+                (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testAddStreamItemText_IncludesComments() {
+        StreamItemEntry streamItem = getTestBuilder().setComment("1 comment").build();
+        View streamItemView = addStreamItemText(streamItem);
+        assertHasText(streamItemView, R.id.stream_item_comments, "1 comment");
+    }
+
+    public void testAddStreamItemText_IncludesHtmlComments() {
+        StreamItemEntry streamItem = getTestBuilder().setComment("1 <b>comment</b>").build();
+        View streamItemView = addStreamItemText(streamItem);
+        assertHasHtmlText(streamItemView, R.id.stream_item_comments, "1 <b>comment<b>");
+    }
+
+    public void testAddStreamItemText_NoComments() {
+        StreamItemEntry streamItem = getTestBuilder().setComment(null).build();
+        View streamItemView = addStreamItemText(streamItem);
+        assertGone(streamItemView, R.id.stream_item_comments);
+    }
+
+    /**
+     * Calls {@link ContactDetailDisplayUtils#addStreamItemText(LayoutInflater, Context,
+     * StreamItemEntry, ViewGroup)} with the default parameters and the given stream item.
+     */
+    private View addStreamItemText(StreamItemEntry streamItem) {
+        return ContactDetailDisplayUtils.addStreamItemText(
+                mLayoutInflater, getContext(), streamItem, mParent);
+    }
+
+    /** Checks that the given id corresponds to a visible text view with the expected text. */
+    private void assertHasText(View parent, int textViewId, String expectedText) {
+        TextView textView = (TextView) parent.findViewById(textViewId);
+        assertNotNull(textView);
+        assertEquals(View.VISIBLE, textView.getVisibility());
+        assertEquals(expectedText, textView.getText().toString());
+    }
+
+    /** Checks that the given id corresponds to a visible text view with the expected HTML. */
+    private void assertHasHtmlText(View parent, int textViewId, String expectedHtml) {
+        TextView textView = (TextView) parent.findViewById(textViewId);
+        assertNotNull(textView);
+        assertEquals(View.VISIBLE, textView.getVisibility());
+        assertSpannableEquals(Html.fromHtml(expectedHtml), textView.getText());
+    }
+
+    /**
+     * Asserts that a char sequence is actually a {@link Spanned} matching the one expected.
+     */
+    private void assertSpannableEquals(Spanned expected, CharSequence actualCharSequence) {
+        assertEquals(expected.toString(), actualCharSequence.toString());
+        assertTrue(actualCharSequence instanceof Spanned);
+        Spanned actual = (Spanned) actualCharSequence;
+        assertEquals(Html.toHtml(expected), Html.toHtml(actual));
+    }
+
+    /** Checks that the given id corresponds to a gone view. */
+    private void assertGone(View parent, int textId) {
+        View view = parent.findViewById(textId);
+        assertNotNull(view);
+        assertEquals(View.GONE, view.getVisibility());
+    }
+
+    private static class StreamItemEntryBuilder {
+        private long mId;
+        private String mText;
+        private String mComment;
+        private long mTimestamp;
+        private String mAction;
+        private String mActionUri;
+        private String mResPackage;
+        private int mIconRes;
+        private int mLabelRes;
+
+        public StreamItemEntryBuilder() {}
+
+        public StreamItemEntryBuilder setText(String text) {
+            mText = text;
+            return this;
+        }
+
+        public StreamItemEntryBuilder setComment(String comment) {
+            mComment = comment;
+            return this;
+        }
+
+        public StreamItemEntry build() {
+            return new StreamItemEntry(mId, mText, mComment, mTimestamp, mAction, mActionUri,
+                    mResPackage, mIconRes, mLabelRes);
+        }
+    }
+
+    private StreamItemEntryBuilder getTestBuilder() {
+        return new StreamItemEntryBuilder().setText(TEST_STREAM_ITEM_TEXT);
+    }
+}