Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2199372 authored by Flavio Lerda's avatar Flavio Lerda
Browse files

Small clean-up of stream items utility class.

We do not need a way to add a set of stream items to a container: we now
use a ListView.

Do not set the listener in the helper method: we can just do that in the
adapter itself.

Bug: 5119353
Change-Id: Id647ddc358f82b5fee8628b06645412e48712229
parent 6c00230c
Loading
Loading
Loading
Loading
+9 −28
Original line number Diff line number Diff line
@@ -249,36 +249,15 @@ public class ContactDetailDisplayUtils {
        }
    }

    /**
     * Displays the social stream items under the given layout.
     */
    public static void showSocialStreamItems(LayoutInflater inflater, Context context,
            Result contactData, LinearLayout streamContainer, View.OnClickListener listener) {
        if (streamContainer != null) {
            streamContainer.removeAllViews();
            List<StreamItemEntry> streamItems = contactData.getStreamItems();
            for (StreamItemEntry streamItem : streamItems) {
                addStreamItemToContainer(inflater, context, streamItem, streamContainer, listener);
            }
        }
    }

    public static View addStreamItemToContainer(LayoutInflater inflater, Context context,
            StreamItemEntry streamItem, LinearLayout streamContainer,
            View.OnClickListener listener) {
    /** Creates the view that represents a stream item. */
    public static View createStreamItemView(LayoutInflater inflater, Context context,
            StreamItemEntry streamItem, LinearLayout parent) {
        View oneColumnView = inflater.inflate(R.layout.stream_item_one_column,
                streamContainer, false);
                parent, false);
        ViewGroup contentBox = (ViewGroup) oneColumnView.findViewById(R.id.stream_item_content);
        int internalPadding = context.getResources().getDimensionPixelSize(
                R.dimen.detail_update_section_internal_padding);

        // Add the listener only if there is an action and corresponding URI.
        if (streamItem.getAction() != null && streamItem.getActionUri() != null) {
            contentBox.setTag(streamItem);
            contentBox.setOnClickListener(listener);
            contentBox.setFocusable(true);
        }

        // TODO: This is not the correct layout for a stream item with photos.  Photos should be
        // displayed first, then the update text either to the right of the final image (if there
        // are an odd number of images) or below the last row of images (if there are an even
@@ -335,8 +314,8 @@ public class ContactDetailDisplayUtils {
            }
        }

        if (streamContainer != null) {
            streamContainer.addView(oneColumnView);
        if (parent != null) {
            parent.addView(oneColumnView);
        }

        return oneColumnView;
@@ -358,7 +337,9 @@ public class ContactDetailDisplayUtils {
        } else {
            commentsView.setVisibility(View.GONE);
        }
        if (parent != null) {
            parent.addView(textUpdate);
        }
        return textUpdate;
    }

+19 −4
Original line number Diff line number Diff line
@@ -66,16 +66,31 @@ public class ContactDetailUpdatesFragment extends ListFragment
        @Override
        public void onClick(View view) {
            StreamItemEntry streamItemEntry = (StreamItemEntry) view.getTag();
            if (streamItemEntry == null) {
                // Ignore if this item does not have a stream item associated with it.
                return;
            }
            String actionUri = streamItemEntry.getActionUri();
            if (actionUri == null) {
                // Ignore if this item does not have a URI.
                return;
            }
            // Parse the URI.
            Uri uri;
            try {
                uri = Uri.parse(streamItemEntry.getActionUri());
                uri = Uri.parse(actionUri);
            } catch (Throwable throwable) {
                // This may fail if the URI is invalid: instead of failing, just ignore it.
                Log.e(TAG, "invalid URI for stream item #" + streamItemEntry.getId() + ": "
                        + streamItemEntry.getActionUri());
                        + actionUri);
                return;
            }
            String action = streamItemEntry.getAction();
            if (action == null) {
                // Ignore if this item does not have an action.
                return;
            }
            Intent streamItemIntent = new Intent(streamItemEntry.getAction(), uri);
            startActivity(streamItemIntent);
            startActivity(new Intent(action, uri));
        }
    };

+13 −2
Original line number Diff line number Diff line
@@ -74,8 +74,19 @@ public class StreamItemAdapter extends BaseAdapter {
        if (position == 0) {
            return mInflater.inflate(R.layout.updates_header_contact, null);
        }
        return ContactDetailDisplayUtils.addStreamItemToContainer(
                mInflater, mContext, (StreamItemEntry) getItem(position), null, mListener);
        StreamItemEntry streamItem = (StreamItemEntry) getItem(position);
        View view = ContactDetailDisplayUtils.createStreamItemView(
                mInflater, mContext, streamItem, null);
        if (streamItem.getAction() != null && streamItem.getActionUri() != null) {
            view.setTag(streamItem);
            view.setFocusable(true);
            view.setOnClickListener(mListener);
        } else {
            view.setTag(null);
            view.setFocusable(false);
            view.setOnClickListener(null);
        }
        return view;
    }

    @Override
+2 −143
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.contacts.detail;

import com.android.contacts.R;
import com.android.contacts.util.StreamItemEntry;
import com.android.contacts.util.StreamItemEntryBuilder;

import android.content.Context;
import android.test.AndroidTestCase;
@@ -27,7 +28,6 @@ import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
@@ -37,14 +37,11 @@ import android.widget.TextView;
public class ContactDetailDisplayUtilsTest extends AndroidTestCase {
    private static final String TEST_STREAM_ITEM_TEXT = "text";

    private LinearLayout mParent;
    private LayoutInflater mLayoutInflater;
    private FakeOnClickListener mListener = new FakeOnClickListener();

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mParent = new LinearLayout(getContext());
        mLayoutInflater =
                (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
@@ -72,81 +69,6 @@ public class ContactDetailDisplayUtilsTest extends AndroidTestCase {
        assertGone(streamItemView, R.id.stream_item_comments);
    }

    public void testAddStreamItemToContainer_NoAction() {
        StreamItemEntry streamItem = getTestBuilder()
                .setAction(null)
                .setActionUri(null)
                .build();
        addStreamItemToContainer(streamItem, mListener);
        assertStreamItemNotClickable();
    }

    public void testAddStreamItemToContainer_WithActionButNoActionUri() {
        StreamItemEntry streamItem = getTestBuilder()
                .setAction("action")
                .setActionUri(null)
                .build();
        addStreamItemToContainer(streamItem, mListener);
        assertStreamItemNotClickable();
    }

    public void testAddStreamItemToContainer_WithActionUriButNoAction() {
        StreamItemEntry streamItem = getTestBuilder()
                .setAction(null)
                .setActionUri("http://www.google.com")
                .build();
        addStreamItemToContainer(streamItem, mListener);
        assertStreamItemNotClickable();
    }

    public void testAddStreamItemToContainer_WithActionAndActionUri() {
        StreamItemEntry streamItem = getTestBuilder()
                .setAction("action")
                .setActionUri("http://www.google.com")
                .build();
        addStreamItemToContainer(streamItem, mListener);
        assertStreamItemClickable();
        assertStreamItemHasOnClickListener();
        assertStreamItemHasTag(streamItem);
    }

    /** Checks that the stream item view is clickable. */
    private void assertStreamItemClickable() {
        View streamItemView = mParent.findViewById(R.id.stream_item_content);
        assertNotNull("should have a stream item", streamItemView);
        assertTrue("should be clickable", streamItemView.isClickable());
        assertTrue("should be focusable", streamItemView.isFocusable());
    }

    /** Asserts that there is a stream item but it is not clickable. */
    private void assertStreamItemNotClickable() {
        View streamItemView = mParent.findViewById(R.id.stream_item_content);
        assertNotNull("should have a stream item", streamItemView);
        assertFalse("should not be clickable", streamItemView.isClickable());
        assertFalse("should not be focusable", streamItemView.isFocusable());
    }

    /** Checks that the stream item view has a click listener. */
    private void assertStreamItemHasOnClickListener() {
        // Check that the on-click listener is invoked when clicked.
        View streamItemView = mParent.findViewById(R.id.stream_item_content);
        assertFalse("listener should have not been invoked yet", mListener.clicked);
        streamItemView.performClick();
        assertTrue("listener should have been invoked", mListener.clicked);
    }

    /** Checks that the stream item view has the given stream item as its tag. */
    private void assertStreamItemHasTag(StreamItemEntry streamItem) {
        // The view's tag should point to the stream item entry for this view.
        View streamItemView = mParent.findViewById(R.id.stream_item_content);
        Object tag = streamItemView.getTag();
        assertNotNull("should have a tag", tag);
        assertTrue("should be a StreamItemEntry", tag instanceof StreamItemEntry);
        StreamItemEntry streamItemTag = (StreamItemEntry) tag;
        // The streamItem itself should be in the tag.
        assertSame(streamItem, streamItemTag);
    }

    /** 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);
@@ -187,70 +109,7 @@ public class ContactDetailDisplayUtilsTest extends AndroidTestCase {
     */
    private View addStreamItemText(StreamItemEntry streamItem) {
        return ContactDetailDisplayUtils.addStreamItemText(
                mLayoutInflater, getContext(), streamItem, mParent);
    }

    /**
     * Calls {@link ContactDetailDisplayUtils#addStreamItemToContainer(LayoutInflater,
     * Context,StreamItemEntry, LinearLayout, android.view.View.OnClickListener)} with the default
     * parameters and the given stream item and listener.
     */
    private void addStreamItemToContainer(StreamItemEntry streamItem,
            View.OnClickListener listener) {
        ContactDetailDisplayUtils.addStreamItemToContainer(mLayoutInflater, getContext(),
                streamItem, mParent, listener);
    }

    /**
     * Simple fake implementation of {@link View.OnClickListener} which sets a member variable to
     * true when clicked.
     */
    private final class FakeOnClickListener implements View.OnClickListener {
        public boolean clicked = false;

        @Override
        public void onClick(View view) {
            clicked = true;
        }
    }

    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 StreamItemEntryBuilder setAction(String action) {
            mAction = action;
            return this;
        }

        public StreamItemEntryBuilder setActionUri(String actionUri) {
            mActionUri = actionUri;
            return this;
        }

        public StreamItemEntry build() {
            return new StreamItemEntry(mId, mText, mComment, mTimestamp, mAction, mActionUri,
                    mResPackage, mIconRes, mLabelRes);
        }
                mLayoutInflater, getContext(), streamItem, null);
    }

    private StreamItemEntryBuilder getTestBuilder() {
+173 −0
Original line number Diff line number Diff line
/*
 * 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.util.StreamItemEntry;
import com.android.contacts.util.StreamItemEntryBuilder;
import com.google.common.collect.Lists;

import android.content.Intent;
import android.test.AndroidTestCase;
import android.view.View;

import java.util.ArrayList;

/**
 * Unit tests for {@link StreamItemAdapter}.
 */
public class StreamItemAdapterTest extends AndroidTestCase {
    private StreamItemAdapter mAdapter;
    private FakeOnClickListener mListener;
    private View mView;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mListener = new FakeOnClickListener();
        mAdapter = new StreamItemAdapter(getContext(), mListener);
    }

    @Override
    protected void tearDown() throws Exception {
        mAdapter = null;
        mListener = null;
        super.tearDown();
    }

    public void testGetCount_Empty() {
        mAdapter.setStreamItems(createStreamItemList(0));
        // There is actually one view: the header.
        assertEquals(1, mAdapter.getCount());
    }

    public void testGetCount_NonEmpty() {
        mAdapter.setStreamItems(createStreamItemList(3));
        // There is one extra view: the header.
        assertEquals(4, mAdapter.getCount());
    }

    public void testGetView_WithAction() {
        StreamItemEntry streamItem = createStreamItemWithAction();
        mAdapter.setStreamItems(Lists.newArrayList(streamItem));
        mView = mAdapter.getView(1, null, null);
        assertStreamItemViewHasTag(streamItem);
        assertStreamItemViewHasOnClickListener();
        assertStreamItemViewFocusable();
    }

    public void testGetView_WithoutAction() {
        mAdapter.setStreamItems(Lists.newArrayList(createStreamItemWithoutAction()));
        mView = mAdapter.getView(1, null, null);
        assertStreamItemViewHasNoTag();
        assertStreamItemViewHasNoOnClickListener();
        assertStreamItemViewNotFocusable();
    }

    public void testGetView_Header() {
        // Just check that we can inflate it correctly.
        mView = mAdapter.getView(0, null, null);
    }

    /** Counter used by {@link #createStreamItemEntryBuilder()} to create unique builders. */
    private int mCreateStreamItemEntryBuilderCounter = 0;

    /** Returns a stream item builder with basic information in it. */
    private StreamItemEntryBuilder createStreamItemEntryBuilder() {
        return new StreamItemEntryBuilder().setText(
                "text #" + mCreateStreamItemEntryBuilderCounter++);
    }

    /** Returns a stream item with an action and action URI set. */
    private StreamItemEntry createStreamItemWithAction() {
        return createStreamItemEntryBuilder()
                .setAction(Intent.ACTION_VIEW)
                .setActionUri("http://www.google.com")
                .build();
    }

    /** Returns a stream item without an action and action URI set. */
    private StreamItemEntry createStreamItemWithoutAction() {
        return createStreamItemEntryBuilder()
                .setAction(null)
                .setActionUri(null)
                .build();
    }

    /** Creates a list containing the given number of {@link StreamItemEntry}s. */
    private ArrayList<StreamItemEntry> createStreamItemList(int count) {
        ArrayList<StreamItemEntry> list = Lists.newArrayList();
        for (int index = 0; index < count; ++index) {
            list.add(createStreamItemEntryBuilder().build());
        }
        return list;
    }

    /** Checks that the stream item view has a click listener. */
    private void assertStreamItemViewHasOnClickListener() {
        assertFalse("listener should have not been invoked yet", mListener.clicked);
        mView.performClick();
        assertTrue("listener should have been invoked", mListener.clicked);
    }

    /** Checks that the stream item view does not have a click listener. */
    private void assertStreamItemViewHasNoOnClickListener() {
        assertFalse("listener should have not been invoked yet", mListener.clicked);
        mView.performClick();
        assertFalse("listener should have not been invoked", mListener.clicked);
    }

    /** Checks that the stream item view is clickable. */
    private void assertStreamItemViewFocusable() {
        assertNotNull("should have a stream item", mView);
        assertTrue("should be focusable", mView.isFocusable());
    }

    /** Asserts that there is a stream item but it is not clickable. */
    private void assertStreamItemViewNotFocusable() {
        assertNotNull("should have a stream item", mView);
        assertFalse("should not be focusable", mView.isFocusable());
    }

    /** Checks that the stream item view has the given stream item as its tag. */
    private void assertStreamItemViewHasTag(StreamItemEntry streamItem) {
        Object tag = mView.getTag();
        assertNotNull("should have a tag", tag);
        assertTrue("should be a StreamItemEntry", tag instanceof StreamItemEntry);
        StreamItemEntry streamItemTag = (StreamItemEntry) tag;
        // The streamItem itself should be in the tag.
        assertSame(streamItem, streamItemTag);
    }

    /** Checks that the stream item view has the given stream item as its tag. */
    private void assertStreamItemViewHasNoTag() {
        Object tag = mView.getTag();
        assertNull("should not have a tag", tag);
    }

    /**
     * Simple fake implementation of {@link View.OnClickListener} which sets a member variable to
     * true when clicked.
     */
    private final class FakeOnClickListener implements View.OnClickListener {
        public boolean clicked = false;

        @Override
        public void onClick(View view) {
            clicked = true;
        }
    }
}
Loading