1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.messaging.ui.contact;
17 
18 import android.content.Context;
19 import android.database.Cursor;
20 import android.net.Uri;
21 import android.provider.ContactsContract.CommonDataKinds.Phone;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.View.OnClickListener;
25 import android.widget.ImageView;
26 import android.widget.LinearLayout;
27 import android.widget.TextView;
28 
29 import com.android.ex.chips.RecipientEntry;
30 import com.android.messaging.R;
31 import com.android.messaging.datamodel.DataModel;
32 import com.android.messaging.datamodel.data.ContactListItemData;
33 import com.android.messaging.datamodel.data.ParticipantData;
34 import com.android.messaging.ui.ContactIconView;
35 import com.android.messaging.util.Assert;
36 import com.android.messaging.util.AvatarUriUtil;
37 import com.google.common.annotations.VisibleForTesting;
38 
39 /**
40  * The view for a single entry in a contact list.
41  */
42 public class ContactListItemView extends LinearLayout implements OnClickListener {
43     public interface HostInterface {
onContactListItemClicked(ContactListItemData item, ContactListItemView view)44         void onContactListItemClicked(ContactListItemData item, ContactListItemView view);
isContactSelected(ContactListItemData item)45         boolean isContactSelected(ContactListItemData item);
46     }
47 
48     @VisibleForTesting
49     final ContactListItemData mData;
50     private TextView mContactNameTextView;
51     private TextView mContactDetailsTextView;
52     private TextView mContactDetailTypeTextView;
53     private TextView mAlphabetHeaderTextView;
54     private ContactIconView mContactIconView;
55     private ImageView mContactCheckmarkView;
56     private ImageView mWorkProfileIcon;
57     private HostInterface mHostInterface;
58     private boolean mShouldShowAlphabetHeader;
59 
ContactListItemView(final Context context, final AttributeSet attrs)60     public ContactListItemView(final Context context, final AttributeSet attrs) {
61         super(context, attrs);
62         mData = DataModel.get().createContactListItemData();
63     }
64 
65     @Override
onFinishInflate()66     protected void onFinishInflate () {
67         mContactNameTextView = (TextView) findViewById(R.id.contact_name);
68         mContactDetailsTextView = (TextView) findViewById(R.id.contact_details);
69         mContactDetailTypeTextView = (TextView) findViewById(R.id.contact_detail_type);
70         mAlphabetHeaderTextView = (TextView) findViewById(R.id.alphabet_header);
71         mContactIconView = (ContactIconView) findViewById(R.id.contact_icon);
72         mContactCheckmarkView = (ImageView) findViewById(R.id.contact_checkmark);
73         mWorkProfileIcon = (ImageView) findViewById(R.id.work_profile_icon);
74     }
75 
76     /**
77      * Fills in the data associated with this view by binding to a contact cursor provided by
78      * ContactUtil.
79      * @param cursor the contact cursor.
80      * @param hostInterface host interface to this view.
81      * @param shouldShowAlphabetHeader whether an alphabetical header should shown on the side
82      *        of this view. If {@code headerLabel} is empty, we will still leave space for it.
83      * @param headerLabel the alphabetical header on the side of this view, if it should be shown.
84      */
bind(final Cursor cursor, final HostInterface hostInterface, final boolean shouldShowAlphabetHeader, final String headerLabel)85     public void bind(final Cursor cursor, final HostInterface hostInterface,
86             final boolean shouldShowAlphabetHeader, final String headerLabel) {
87         mData.bind(cursor, headerLabel);
88         mHostInterface = hostInterface;
89         mShouldShowAlphabetHeader = shouldShowAlphabetHeader;
90         setOnClickListener(this);
91         updateViewAppearance();
92     }
93 
94     /**
95      * Binds a RecipientEntry. This is used by the chips text view's dropdown layout.
96      * @param recipientEntry the source RecipientEntry provided by ContactDropdownLayouter, which
97      *        was in turn directly from one of the existing chips, or from filtered results
98      *        generated by ContactRecipientAdapter.
99      * @param styledName display name where the portion that matches the search text is bold.
100      * @param styledDestination number where the portion that matches the search text is bold.
101      * @param hostInterface host interface to this view.
102      * @param isSingleRecipient whether this item is shown as the only line item in the single
103      *        recipient drop down from the chips view. If this is the case, we always show the
104      *        contact avatar even if it's not a first-level entry.
105      * @param isWorkContact whether the contact is in managed profile.
106      */
bind(final RecipientEntry recipientEntry, final CharSequence styledName, final CharSequence styledDestination, final HostInterface hostInterface, final boolean isSingleRecipient, final boolean isWorkContact)107     public void bind(final RecipientEntry recipientEntry, final CharSequence styledName,
108             final CharSequence styledDestination, final HostInterface hostInterface,
109             final boolean isSingleRecipient, final boolean isWorkContact) {
110         mData.bind(recipientEntry, styledName, styledDestination, isSingleRecipient, isWorkContact);
111         mHostInterface = hostInterface;
112         mShouldShowAlphabetHeader = false;
113         updateViewAppearance();
114     }
115 
updateViewAppearance()116     private void updateViewAppearance() {
117         mContactNameTextView.setText(mData.getDisplayName());
118         mContactDetailsTextView.setText(mData.getDestination());
119         mContactDetailTypeTextView.setText(Phone.getTypeLabel(getResources(),
120                 mData.getDestinationType(), mData.getDestinationLabel()));
121         final RecipientEntry recipientEntry = mData.getRecipientEntry();
122         final String destinationString = String.valueOf(mData.getDestination());
123         if (mData.getIsSimpleContactItem()) {
124             // This is a special number-with-avatar type of contact (for unknown contact chips
125             // and for direct "send to destination" item). In this case, make sure we only show
126             // the display name (phone number) and the avatar and hide everything else.
127             final Uri avatarUri = AvatarUriUtil.createAvatarUri(
128                     ParticipantData.getFromRecipientEntry(recipientEntry));
129             mContactIconView.setImageResourceUri(avatarUri, mData.getContactId(),
130                     mData.getLookupKey(), destinationString);
131             mContactIconView.setVisibility(VISIBLE);
132             mContactCheckmarkView.setVisibility(GONE);
133             mContactDetailTypeTextView.setVisibility(GONE);
134             mContactDetailsTextView.setVisibility(GONE);
135             mContactNameTextView.setVisibility(VISIBLE);
136         } else if (mData.getIsFirstLevel()) {
137             final Uri avatarUri = AvatarUriUtil.createAvatarUri(
138                     ParticipantData.getFromRecipientEntry(recipientEntry));
139             mContactIconView.setImageResourceUri(avatarUri, mData.getContactId(),
140                     mData.getLookupKey(), destinationString);
141             mContactIconView.setVisibility(VISIBLE);
142             mContactNameTextView.setVisibility(VISIBLE);
143             final boolean isSelected = mHostInterface.isContactSelected(mData);
144             setSelected(isSelected);
145             mContactCheckmarkView.setVisibility(isSelected ? VISIBLE : GONE);
146             mContactDetailsTextView.setVisibility(VISIBLE);
147             mContactDetailTypeTextView.setVisibility(VISIBLE);
148         } else {
149             mContactIconView.setImageResourceUri(null);
150             mContactIconView.setVisibility(INVISIBLE);
151             mContactNameTextView.setVisibility(GONE);
152             final boolean isSelected = mHostInterface.isContactSelected(mData);
153             setSelected(isSelected);
154             mContactCheckmarkView.setVisibility(isSelected ? VISIBLE : GONE);
155             mContactDetailsTextView.setVisibility(VISIBLE);
156             mContactDetailTypeTextView.setVisibility(VISIBLE);
157         }
158         if (mData.getIsWorkContact()) {
159             mWorkProfileIcon.setVisibility(VISIBLE);
160         } else {
161             mWorkProfileIcon.setVisibility(GONE);
162         }
163         if (mShouldShowAlphabetHeader) {
164             mAlphabetHeaderTextView.setVisibility(VISIBLE);
165             mAlphabetHeaderTextView.setText(mData.getAlphabetHeader());
166         } else {
167             mAlphabetHeaderTextView.setVisibility(GONE);
168         }
169     }
170 
171     /**
172      * {@inheritDoc} from OnClickListener
173      */
174     @Override
onClick(final View v)175     public void onClick(final View v) {
176         Assert.isTrue(v == this);
177         Assert.isTrue(mHostInterface != null);
178         mHostInterface.onContactListItemClicked(mData, this);
179     }
180 
setImageClickHandlerDisabled(final boolean isHandlerDisabled)181     public void setImageClickHandlerDisabled(final boolean isHandlerDisabled) {
182         mContactIconView.setImageClickHandlerDisabled(isHandlerDisabled);
183     }
184 }
185