session-android/src/org/thoughtcrime/securesms/ConversationListItem.java
Moxie Marlinspike fa5e993191 Weird NPE
2012-12-01 16:02:55 -08:00

192 lines
6.7 KiB
Java

/**
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.provider.Contacts.Intents;
import android.provider.ContactsContract.QuickContact;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.QuickContactBadge;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import java.util.Set;
/**
* A view that displays the element in a list of multiple conversation threads.
* Used by SecureSMS's ListActivity via a ConversationListAdapter.
*
* @author Moxie Marlinspike
*/
public class ConversationListItem extends RelativeLayout {
private Context context;
private Set<Long> selectedThreads;
private Recipients recipients;
private long threadId;
private TextView subjectView;
private TextView fromView;
private TextView dateView;
private CheckBox checkbox;
private ImageView contactPhotoImage;
private QuickContactBadge contactPhotoBadge;
public ConversationListItem(Context context, Set<Long> selectedThreads) {
super(context);
LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
li.inflate(R.layout.conversation_list_item_view, this, true);
this.context = context;
this.selectedThreads = selectedThreads;
this.subjectView = (TextView)findViewById(R.id.subject);
this.fromView = (TextView)findViewById(R.id.from);
this.dateView = (TextView)findViewById(R.id.date);
this.checkbox = (CheckBox)findViewById(R.id.checkbox);
this.contactPhotoBadge = (QuickContactBadge)findViewById(R.id.contact_photo_badge);
this.contactPhotoImage = (ImageView)findViewById(R.id.contact_photo_image);
initializeContactWidgetVisibility();
intializeListeners();
}
public ConversationListItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void set(ThreadRecord thread, boolean batchMode) {
this.recipients = thread.getRecipients();
this.threadId = thread.getThreadId();
this.fromView.setText(formatFrom(recipients, thread.getCount(), thread.isRead()));
if (thread.isKeyExchange())
this.subjectView.setText(R.string.ConversationListItem_key_exchange_message,
TextView.BufferType.SPANNABLE);
else
this.subjectView.setText(thread.getBody(), TextView.BufferType.SPANNABLE);
if (thread.getEmphasis())
((Spannable)this.subjectView.getText()).setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, this.subjectView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
if (thread.getDate() > 0)
this.dateView.setText(DateUtils.getRelativeTimeSpanString(getContext(), thread.getDate(), false));
if (selectedThreads != null)
this.checkbox.setChecked(selectedThreads.contains(threadId));
if (batchMode) checkbox.setVisibility(View.VISIBLE);
else checkbox.setVisibility(View.GONE);
setContactPhoto(this.recipients.getPrimaryRecipient());
}
private void intializeListeners() {
checkbox.setOnCheckedChangeListener(new CheckedChangedListener());
}
private void initializeContactWidgetVisibility() {
if (isBadgeEnabled()) {
contactPhotoBadge.setVisibility(View.VISIBLE);
contactPhotoImage.setVisibility(View.GONE);
} else {
contactPhotoBadge.setVisibility(View.GONE);
contactPhotoImage.setVisibility(View.VISIBLE);
}
}
private void setContactPhoto(final Recipient recipient) {
if (recipient == null) return;
if (isBadgeEnabled()) {
contactPhotoBadge.setImageBitmap(recipient.getContactPhoto());
contactPhotoBadge.assignContactFromPhone(recipient.getNumber(), true);
} else {
contactPhotoImage.setImageBitmap(recipient.getContactPhoto());
contactPhotoImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (recipient.getContactUri() != null) {
QuickContact.showQuickContact(context, contactPhotoImage, recipient.getContactUri(), QuickContact.MODE_LARGE, null);
} else {
Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, Uri.fromParts("tel", recipient.getNumber(), null));
context.startActivity(intent);
}
}
});
}
}
private boolean isBadgeEnabled() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}
private CharSequence formatFrom(Recipients from, long count, boolean read) {
SpannableStringBuilder builder = new SpannableStringBuilder(from.toShortString());
if (count > 0) {
builder.append(" " + count);
builder.setSpan(new ForegroundColorSpan(Color.parseColor("#66333333")),
from.toShortString().length(), builder.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
if (!read) {
builder.setSpan(new StyleSpan(Typeface.BOLD), 0, builder.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
return builder;
}
public Recipients getRecipients() {
return recipients;
}
public long getThreadId() {
return threadId;
}
private class CheckedChangedListener implements CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) selectedThreads.add(threadId);
else selectedThreads.remove(threadId);
}
}
}