1/* 2 * Copyright (C) 2007-2008 Esmertec AG. 3 * Copyright (C) 2007-2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.im.app; 19 20import android.app.Activity; 21import android.content.ContentResolver; 22import android.content.ContentUris; 23import android.content.Context; 24import android.content.res.Resources; 25import android.database.Cursor; 26import android.net.Uri; 27import android.text.Spannable; 28import android.text.SpannableString; 29import android.text.SpannableStringBuilder; 30import android.text.TextUtils; 31import android.text.style.RelativeSizeSpan; 32import android.text.style.UnderlineSpan; 33import android.util.AttributeSet; 34import android.view.View; 35import android.widget.ImageView; 36import android.widget.LinearLayout; 37import android.widget.TextView; 38import android.graphics.drawable.Drawable; 39 40import com.android.im.R; 41import com.android.im.plugin.BrandingResourceIDs; 42import com.android.im.provider.Imps; 43 44import java.text.DateFormat; 45import java.util.Calendar; 46 47public class ContactView extends LinearLayout { 48 static final String[] CONTACT_PROJECTION = { 49 Imps.Contacts._ID, 50 Imps.Contacts.PROVIDER, 51 Imps.Contacts.ACCOUNT, 52 Imps.Contacts.USERNAME, 53 Imps.Contacts.NICKNAME, 54 Imps.Contacts.TYPE, 55 Imps.Contacts.SUBSCRIPTION_TYPE, 56 Imps.Contacts.SUBSCRIPTION_STATUS, 57 Imps.Presence.PRESENCE_STATUS, 58 Imps.Presence.PRESENCE_CUSTOM_STATUS, 59 Imps.Chats.LAST_MESSAGE_DATE, 60 Imps.Chats.LAST_UNREAD_MESSAGE, 61 }; 62 63 static final int COLUMN_CONTACT_ID = 0; 64 static final int COLUMN_CONTACT_PROVIDER = 1; 65 static final int COLUMN_CONTACT_ACCOUNT = 2; 66 static final int COLUMN_CONTACT_USERNAME = 3; 67 static final int COLUMN_CONTACT_NICKNAME = 4; 68 static final int COLUMN_CONTACT_TYPE = 5; 69 static final int COLUMN_SUBSCRIPTION_TYPE = 6; 70 static final int COLUMN_SUBSCRIPTION_STATUS = 7; 71 static final int COLUMN_CONTACT_PRESENCE_STATUS = 8; 72 static final int COLUMN_CONTACT_CUSTOM_STATUS = 9; 73 static final int COLUMN_LAST_MESSAGE_DATE = 10; 74 static final int COLUMN_LAST_MESSAGE = 11; 75 76 //private ImageView mPresence; 77 private TextView mLine1; 78 private TextView mLine2; 79 private TextView mTimeStamp; 80 81 public ContactView(Context context, AttributeSet attrs) { 82 super(context, attrs); 83 } 84 85 @Override 86 protected void onFinishInflate() { 87 super.onFinishInflate(); 88 89 //mPresence = (ImageView) findViewById(R.id.presence); 90 mLine1 = (TextView) findViewById(R.id.line1); 91 mLine2 = (TextView) findViewById(R.id.line2); 92 mLine2.setCompoundDrawablePadding(5); 93 mTimeStamp = (TextView)findViewById(R.id.timestamp); 94 } 95 96 public void bind(Cursor cursor, String underLineText, boolean scrolling) { 97 bind(cursor, underLineText, true, scrolling); 98 } 99 100 public void bind(Cursor cursor, String underLineText, boolean showChatMsg, boolean scrolling) { 101 Resources r = getResources(); 102 long providerId = cursor.getLong(COLUMN_CONTACT_PROVIDER); 103 String username = cursor.getString(COLUMN_CONTACT_USERNAME); 104 String nickname = cursor.getString(COLUMN_CONTACT_NICKNAME); 105 int type = cursor.getInt(COLUMN_CONTACT_TYPE); 106 String statusText = cursor.getString(COLUMN_CONTACT_CUSTOM_STATUS); 107 String lastMsg = cursor.getString(COLUMN_LAST_MESSAGE); 108 109 boolean hasChat = !cursor.isNull(COLUMN_LAST_MESSAGE_DATE); 110 111 ImApp app = ImApp.getApplication((Activity)mContext); 112 BrandingResources brandingRes = app.getBrandingResource(providerId); 113 114 int presence = cursor.getInt(COLUMN_CONTACT_PRESENCE_STATUS); 115 int iconId = 0; 116 117 // status icon 118 119 if (Imps.Contacts.TYPE_GROUP == type) { 120 iconId = lastMsg == null ? R.drawable.group_chat : R.drawable.group_chat_new; 121 } else if (hasChat) { 122 iconId = lastMsg == null ? BrandingResourceIDs.DRAWABLE_READ_CHAT 123 : BrandingResourceIDs.DRAWABLE_UNREAD_CHAT; 124 } else { 125 iconId = PresenceUtils.getStatusIconId(presence); 126 } 127 128 //mPresence.setImageDrawable(brandingRes.getDrawable(iconId)); 129 Drawable presenceIcon = brandingRes.getDrawable(iconId); 130 131 // line1 132 CharSequence line1; 133 if (Imps.Contacts.TYPE_GROUP == type) { 134 ContentResolver resolver = getContext().getContentResolver(); 135 long id = cursor.getLong(ContactView.COLUMN_CONTACT_ID); 136 line1 = queryGroupMembers(resolver, id); 137 } else { 138 line1 = TextUtils.isEmpty(nickname) ? 139 ImpsAddressUtils.getDisplayableAddress(username) : nickname; 140 141 if (!TextUtils.isEmpty(underLineText)) { 142 // highlight/underline the word being searched 143 String lowercase = line1.toString().toLowerCase(); 144 int start = lowercase.indexOf(underLineText.toLowerCase()); 145 if (start >= 0) { 146 int end = start + underLineText.length(); 147 SpannableString str = new SpannableString(line1); 148 str.setSpan(new UnderlineSpan(), start, end, 149 Spannable.SPAN_INCLUSIVE_INCLUSIVE); 150 line1 = str; 151 } 152 } 153 154 if (Imps.Contacts.TYPE_TEMPORARY == type) { 155 // Add a mark at the front of name if it's only a temporary 156 // contact. 157 SpannableStringBuilder str = new SpannableStringBuilder( 158 r.getText(R.string.unknown_contact)); 159 str.setSpan(new RelativeSizeSpan(0.8f), 0, str.length(), 160 Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 161 str.append(line1); 162 line1 = str; 163 } 164 } 165 mLine1.setText(line1); 166 167 // time stamp 168 if (showChatMsg && hasChat) { 169 mTimeStamp.setVisibility(VISIBLE); 170 Calendar cal = Calendar.getInstance(); 171 cal.setTimeInMillis(cursor.getLong(COLUMN_LAST_MESSAGE_DATE)); 172 DateFormat formatter = DateFormat.getTimeInstance(DateFormat.SHORT); 173 mTimeStamp.setText(formatter.format(cal.getTime())); 174 } else { 175 mTimeStamp.setVisibility(GONE); 176 } 177 178 // line2 179 CharSequence line2 = null; 180 if (showChatMsg) { 181 line2 = lastMsg; 182 } 183 184 if (TextUtils.isEmpty(line2)){ 185 if (Imps.Contacts.TYPE_GROUP == type) { 186 // Show nothing in line2 if it's a group and don't 187 // have any unread message. 188 line2 = null; 189 } else { 190 // Show the custom status text if there's no new message. 191 line2 = statusText; 192 } 193 } 194 195 if (TextUtils.isEmpty(line2)) { 196 // Show a string of presence if there is neither new message nor 197 // custom status text. 198 line2 = brandingRes.getString(PresenceUtils.getStatusStringRes(presence)); 199 } 200 201 mLine2.setText(line2); 202 mLine2.setCompoundDrawablesWithIntrinsicBounds(null, null, presenceIcon, null); 203 204 205 View contactInfoPanel = findViewById(R.id.contactInfo); 206 if (hasChat && showChatMsg) { 207 contactInfoPanel.setBackgroundResource(R.drawable.bubble); 208 mLine1.setTextColor(r.getColor(R.color.chat_contact)); 209 } else { 210 contactInfoPanel.setBackgroundDrawable(null); 211 contactInfoPanel.setPadding(4, 0, 0, 0); 212 mLine1.setTextColor(r.getColor(R.color.nonchat_contact)); 213 } 214 } 215 216 private String queryGroupMembers(ContentResolver resolver, long groupId) { 217 String[] projection = { Imps.GroupMembers.NICKNAME }; 218 Uri uri = ContentUris.withAppendedId(Imps.GroupMembers.CONTENT_URI, groupId); 219 Cursor c = resolver.query(uri, projection, null, null, null); 220 StringBuilder buf = new StringBuilder(); 221 if(c != null) { 222 while(c.moveToNext()) { 223 buf.append(c.getString(0)); 224 if(!c.isLast()) { 225 buf.append(','); 226 } 227 } 228 c.close(); 229 } 230 return buf.toString(); 231 } 232} 233