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