Merge pull request #2347 from philipwhiuk/tidyUpMessageListFragment
Tidying up MessageListFragment
This commit is contained in:
commit
0763b09c83
7 changed files with 1295 additions and 1189 deletions
|
@ -0,0 +1,60 @@
|
|||
package com.fsck.k9.fragment;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.fsck.k9.provider.EmailProvider.MessageColumns;
|
||||
import com.fsck.k9.provider.EmailProvider.SpecialColumns;
|
||||
import com.fsck.k9.provider.EmailProvider.ThreadColumns;
|
||||
|
||||
|
||||
public final class MLFProjectionInfo {
|
||||
|
||||
static final String[] THREADED_PROJECTION = {
|
||||
MessageColumns.ID,
|
||||
MessageColumns.UID,
|
||||
MessageColumns.INTERNAL_DATE,
|
||||
MessageColumns.SUBJECT,
|
||||
MessageColumns.DATE,
|
||||
MessageColumns.SENDER_LIST,
|
||||
MessageColumns.TO_LIST,
|
||||
MessageColumns.CC_LIST,
|
||||
MessageColumns.READ,
|
||||
MessageColumns.FLAGGED,
|
||||
MessageColumns.ANSWERED,
|
||||
MessageColumns.FORWARDED,
|
||||
MessageColumns.ATTACHMENT_COUNT,
|
||||
MessageColumns.FOLDER_ID,
|
||||
MessageColumns.PREVIEW_TYPE,
|
||||
MessageColumns.PREVIEW,
|
||||
ThreadColumns.ROOT,
|
||||
SpecialColumns.ACCOUNT_UUID,
|
||||
SpecialColumns.FOLDER_NAME,
|
||||
|
||||
SpecialColumns.THREAD_COUNT,
|
||||
};
|
||||
|
||||
static final int ID_COLUMN = 0;
|
||||
static final int UID_COLUMN = 1;
|
||||
static final int INTERNAL_DATE_COLUMN = 2;
|
||||
static final int SUBJECT_COLUMN = 3;
|
||||
static final int DATE_COLUMN = 4;
|
||||
static final int SENDER_LIST_COLUMN = 5;
|
||||
static final int TO_LIST_COLUMN = 6;
|
||||
static final int CC_LIST_COLUMN = 7;
|
||||
static final int READ_COLUMN = 8;
|
||||
static final int FLAGGED_COLUMN = 9;
|
||||
static final int ANSWERED_COLUMN = 10;
|
||||
static final int FORWARDED_COLUMN = 11;
|
||||
static final int ATTACHMENT_COUNT_COLUMN = 12;
|
||||
static final int FOLDER_ID_COLUMN = 13;
|
||||
static final int PREVIEW_TYPE_COLUMN = 14;
|
||||
static final int PREVIEW_COLUMN = 15;
|
||||
static final int THREAD_ROOT_COLUMN = 16;
|
||||
static final int ACCOUNT_UUID_COLUMN = 17;
|
||||
static final int FOLDER_NAME_COLUMN = 18;
|
||||
static final int THREAD_COUNT_COLUMN = 19;
|
||||
|
||||
static final String[] PROJECTION = Arrays.copyOf(THREADED_PROJECTION,
|
||||
THREAD_COUNT_COLUMN);
|
||||
}
|
|
@ -0,0 +1,370 @@
|
|||
package com.fsck.k9.fragment;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.format.DateUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.FontSizes;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mailstore.DatabasePreviewType;
|
||||
import com.fsck.k9.ui.ContactBadge;
|
||||
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.ANSWERED_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.ATTACHMENT_COUNT_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.CC_LIST_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.DATE_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.FLAGGED_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.FOLDER_NAME_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.FORWARDED_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.PREVIEW_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.PREVIEW_TYPE_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.READ_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.SENDER_LIST_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.SUBJECT_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.THREAD_COUNT_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.TO_LIST_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.UID_COLUMN;
|
||||
|
||||
|
||||
public class MessageListAdapter extends CursorAdapter {
|
||||
|
||||
private final MessageListFragment fragment;
|
||||
private Drawable mAttachmentIcon;
|
||||
private Drawable mForwardedIcon;
|
||||
private Drawable mAnsweredIcon;
|
||||
private Drawable mForwardedAnsweredIcon;
|
||||
private FontSizes fontSizes = K9.getFontSizes();
|
||||
|
||||
MessageListAdapter(MessageListFragment fragment) {
|
||||
super(fragment.getActivity(), null, 0);
|
||||
this.fragment = fragment;
|
||||
mAttachmentIcon = fragment.getResources().getDrawable(R.drawable.ic_email_attachment_small);
|
||||
mAnsweredIcon = fragment.getResources().getDrawable(R.drawable.ic_email_answered_small);
|
||||
mForwardedIcon = fragment.getResources().getDrawable(R.drawable.ic_email_forwarded_small);
|
||||
mForwardedAnsweredIcon = fragment.getResources().getDrawable(R.drawable.ic_email_forwarded_answered_small);
|
||||
}
|
||||
|
||||
private String recipientSigil(boolean toMe, boolean ccMe) {
|
||||
if (toMe) {
|
||||
return fragment.getString(R.string.messagelist_sent_to_me_sigil);
|
||||
} else if (ccMe) {
|
||||
return fragment.getString(R.string.messagelist_sent_cc_me_sigil);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
View view = fragment.getLayoutInflater().inflate(R.layout.message_list_item, parent, false);
|
||||
|
||||
MessageViewHolder holder = new MessageViewHolder(fragment);
|
||||
holder.date = (TextView) view.findViewById(R.id.date);
|
||||
holder.chip = view.findViewById(R.id.chip);
|
||||
|
||||
|
||||
if (fragment.previewLines == 0 && fragment.contactsPictureLoader == null) {
|
||||
view.findViewById(R.id.preview).setVisibility(View.GONE);
|
||||
holder.preview = (TextView) view.findViewById(R.id.sender_compact);
|
||||
holder.flagged = (CheckBox) view.findViewById(R.id.flagged_center_right);
|
||||
view.findViewById(R.id.flagged_bottom_right).setVisibility(View.GONE);
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
view.findViewById(R.id.sender_compact).setVisibility(View.GONE);
|
||||
holder.preview = (TextView) view.findViewById(R.id.preview);
|
||||
holder.flagged = (CheckBox) view.findViewById(R.id.flagged_bottom_right);
|
||||
view.findViewById(R.id.flagged_center_right).setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
ContactBadge contactBadge =
|
||||
(ContactBadge) view.findViewById(R.id.contact_badge);
|
||||
if (fragment.contactsPictureLoader != null) {
|
||||
holder.contactBadge = contactBadge;
|
||||
} else {
|
||||
contactBadge.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (fragment.senderAboveSubject) {
|
||||
holder.from = (TextView) view.findViewById(R.id.subject);
|
||||
fontSizes.setViewTextSize(holder.from, fontSizes.getMessageListSender());
|
||||
|
||||
} else {
|
||||
holder.subject = (TextView) view.findViewById(R.id.subject);
|
||||
fontSizes.setViewTextSize(holder.subject, fontSizes.getMessageListSubject());
|
||||
|
||||
}
|
||||
|
||||
fontSizes.setViewTextSize(holder.date, fontSizes.getMessageListDate());
|
||||
|
||||
|
||||
// 1 preview line is needed even if it is set to 0, because subject is part of the same text view
|
||||
holder.preview.setLines(Math.max(fragment.previewLines,1));
|
||||
fontSizes.setViewTextSize(holder.preview, fontSizes.getMessageListPreview());
|
||||
holder.threadCount = (TextView) view.findViewById(R.id.thread_count);
|
||||
fontSizes.setViewTextSize(holder.threadCount, fontSizes.getMessageListSubject()); // thread count is next to subject
|
||||
view.findViewById(R.id.selected_checkbox_wrapper).setVisibility((fragment.checkboxes) ? View.VISIBLE : View.GONE);
|
||||
|
||||
holder.flagged.setVisibility(fragment.stars ? View.VISIBLE : View.GONE);
|
||||
holder.flagged.setOnClickListener(holder);
|
||||
|
||||
|
||||
holder.selected = (CheckBox) view.findViewById(R.id.selected_checkbox);
|
||||
holder.selected.setOnClickListener(holder);
|
||||
|
||||
|
||||
view.setTag(holder);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
Account account = fragment.getAccountFromCursor(cursor);
|
||||
|
||||
String fromList = cursor.getString(SENDER_LIST_COLUMN);
|
||||
String toList = cursor.getString(TO_LIST_COLUMN);
|
||||
String ccList = cursor.getString(CC_LIST_COLUMN);
|
||||
Address[] fromAddrs = Address.unpack(fromList);
|
||||
Address[] toAddrs = Address.unpack(toList);
|
||||
Address[] ccAddrs = Address.unpack(ccList);
|
||||
|
||||
boolean fromMe = fragment.messageHelper.toMe(account, fromAddrs);
|
||||
boolean toMe = fragment.messageHelper.toMe(account, toAddrs);
|
||||
boolean ccMe = fragment.messageHelper.toMe(account, ccAddrs);
|
||||
|
||||
CharSequence displayName = fragment.messageHelper.getDisplayName(account, fromAddrs, toAddrs);
|
||||
CharSequence displayDate = DateUtils.getRelativeTimeSpanString(context, cursor.getLong(DATE_COLUMN));
|
||||
|
||||
Address counterpartyAddress = fetchCounterPartyAddress(fromMe, toAddrs, ccAddrs, fromAddrs);
|
||||
|
||||
int threadCount = (fragment.showingThreadedList) ? cursor.getInt(THREAD_COUNT_COLUMN) : 0;
|
||||
|
||||
String subject = MlfUtils.buildSubject(cursor.getString(SUBJECT_COLUMN),
|
||||
fragment.getString(R.string.general_no_subject), threadCount);
|
||||
|
||||
boolean read = (cursor.getInt(READ_COLUMN) == 1);
|
||||
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
|
||||
boolean answered = (cursor.getInt(ANSWERED_COLUMN) == 1);
|
||||
boolean forwarded = (cursor.getInt(FORWARDED_COLUMN) == 1);
|
||||
|
||||
boolean hasAttachments = (cursor.getInt(ATTACHMENT_COUNT_COLUMN) > 0);
|
||||
|
||||
MessageViewHolder holder = (MessageViewHolder) view.getTag();
|
||||
|
||||
int maybeBoldTypeface = (read) ? Typeface.NORMAL : Typeface.BOLD;
|
||||
|
||||
long uniqueId = cursor.getLong(fragment.uniqueIdColumn);
|
||||
boolean selected = fragment.selected.contains(uniqueId);
|
||||
|
||||
holder.chip.setBackgroundColor(account.getChipColor());
|
||||
if (fragment.checkboxes) {
|
||||
holder.selected.setChecked(selected);
|
||||
}
|
||||
if (fragment.stars) {
|
||||
holder.flagged.setChecked(flagged);
|
||||
}
|
||||
holder.position = cursor.getPosition();
|
||||
if (holder.contactBadge != null) {
|
||||
updateContactBadge(holder, counterpartyAddress);
|
||||
}
|
||||
setBackgroundColor(view, selected, read);
|
||||
if (fragment.activeMessage != null) {
|
||||
changeBackgroundColorIfActiveMessage(cursor, account, view);
|
||||
}
|
||||
updateWithThreadCount(holder, threadCount);
|
||||
CharSequence beforePreviewText = (fragment.senderAboveSubject) ? subject : displayName;
|
||||
String sigil = recipientSigil(toMe, ccMe);
|
||||
SpannableStringBuilder messageStringBuilder = new SpannableStringBuilder(sigil)
|
||||
.append(beforePreviewText);
|
||||
if (fragment.previewLines > 0) {
|
||||
String preview = getPreview(cursor);
|
||||
messageStringBuilder.append(" ").append(preview);
|
||||
}
|
||||
holder.preview.setText(messageStringBuilder, TextView.BufferType.SPANNABLE);
|
||||
|
||||
formatPreviewText(holder.preview, beforePreviewText, sigil);
|
||||
|
||||
Drawable statusHolder = buildStatusHolder(forwarded, answered);
|
||||
|
||||
if (holder.from != null ) {
|
||||
holder.from.setTypeface(Typeface.create(holder.from.getTypeface(), maybeBoldTypeface));
|
||||
if (fragment.senderAboveSubject) {
|
||||
holder.from.setCompoundDrawablesWithIntrinsicBounds(
|
||||
statusHolder, // left
|
||||
null, // top
|
||||
hasAttachments ? mAttachmentIcon : null, // right
|
||||
null); // bottom
|
||||
|
||||
holder.from.setText(displayName);
|
||||
} else {
|
||||
holder.from.setText(new SpannableStringBuilder(sigil).append(displayName));
|
||||
}
|
||||
}
|
||||
if (holder.subject != null ) {
|
||||
if (!fragment.senderAboveSubject) {
|
||||
holder.subject.setCompoundDrawablesWithIntrinsicBounds(
|
||||
statusHolder, // left
|
||||
null, // top
|
||||
hasAttachments ? mAttachmentIcon : null, // right
|
||||
null); // bottom
|
||||
}
|
||||
|
||||
holder.subject.setTypeface(Typeface.create(holder.subject.getTypeface(), maybeBoldTypeface));
|
||||
holder.subject.setText(subject);
|
||||
}
|
||||
holder.date.setText(displayDate);
|
||||
}
|
||||
|
||||
private void formatPreviewText(TextView preview, CharSequence beforePreviewText, String sigil) {
|
||||
Spannable previewText = (Spannable)preview.getText();
|
||||
previewText.setSpan(buildSenderSpan(), 0, beforePreviewText.length() + sigil.length(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
int previewSpanColor = buildPreviewSpanColor();
|
||||
|
||||
// Set span (color) for preview message
|
||||
previewText.setSpan(new ForegroundColorSpan(previewSpanColor), beforePreviewText.length() + sigil.length(),
|
||||
previewText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a span section for the sender, and assign the correct font size and weight
|
||||
*/
|
||||
private AbsoluteSizeSpan buildSenderSpan() {
|
||||
int fontSize = (fragment.senderAboveSubject) ?
|
||||
fontSizes.getMessageListSubject():
|
||||
fontSizes.getMessageListSender();
|
||||
return new AbsoluteSizeSpan(fontSize, true);
|
||||
}
|
||||
|
||||
private Address fetchCounterPartyAddress(boolean fromMe, Address[] toAddrs, Address[] ccAddrs, Address[] fromAddrs) {
|
||||
if (fromMe) {
|
||||
if (toAddrs.length > 0) {
|
||||
return toAddrs[0];
|
||||
} else if (ccAddrs.length > 0) {
|
||||
return ccAddrs[0];
|
||||
}
|
||||
} else if (fromAddrs.length > 0) {
|
||||
return fromAddrs[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateContactBadge(MessageViewHolder holder, Address counterpartyAddress) {
|
||||
if (counterpartyAddress != null) {
|
||||
Utility.setContactForBadge(holder.contactBadge, counterpartyAddress);
|
||||
/*
|
||||
* At least in Android 2.2 a different background + padding is used when no
|
||||
* email address is available. ListView reuses the views but ContactBadge
|
||||
* doesn't reset the padding, so we do it ourselves.
|
||||
*/
|
||||
holder.contactBadge.setPadding(0, 0, 0, 0);
|
||||
fragment.contactsPictureLoader.loadContactPicture(counterpartyAddress, holder.contactBadge);
|
||||
} else {
|
||||
holder.contactBadge.assignContactUri(null);
|
||||
holder.contactBadge.setImageResource(R.drawable.ic_contact_picture);
|
||||
}
|
||||
}
|
||||
|
||||
private void changeBackgroundColorIfActiveMessage(Cursor cursor, Account account, View view) {
|
||||
String uid = cursor.getString(UID_COLUMN);
|
||||
String folderName = cursor.getString(FOLDER_NAME_COLUMN);
|
||||
|
||||
if (account.getUuid().equals(fragment.activeMessage.getAccountUuid()) &&
|
||||
folderName.equals(fragment.activeMessage.getFolderName()) &&
|
||||
uid.equals(fragment.activeMessage.getUid())) {
|
||||
int res = R.attr.messageListActiveItemBackgroundColor;
|
||||
|
||||
TypedValue outValue = new TypedValue();
|
||||
fragment.getActivity().getTheme().resolveAttribute(res, outValue, true);
|
||||
view.setBackgroundColor(outValue.data);
|
||||
}
|
||||
}
|
||||
|
||||
private int buildPreviewSpanColor() {
|
||||
//TODO: make this part of the theme
|
||||
return (K9.getK9Theme() == K9.Theme.LIGHT) ?
|
||||
Color.rgb(105, 105, 105) :
|
||||
Color.rgb(160, 160, 160);
|
||||
}
|
||||
|
||||
private Drawable buildStatusHolder(boolean forwarded, boolean answered) {
|
||||
if (forwarded && answered) {
|
||||
return mForwardedAnsweredIcon;
|
||||
} else if (answered) {
|
||||
return mAnsweredIcon;
|
||||
} else if (forwarded) {
|
||||
return mForwardedIcon;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setBackgroundColor(View view, boolean selected, boolean read) {
|
||||
if (selected || K9.useBackgroundAsUnreadIndicator()) {
|
||||
int res;
|
||||
if (selected) {
|
||||
res = R.attr.messageListSelectedBackgroundColor;
|
||||
} else if (read) {
|
||||
res = R.attr.messageListReadItemBackgroundColor;
|
||||
} else {
|
||||
res = R.attr.messageListUnreadItemBackgroundColor;
|
||||
}
|
||||
|
||||
TypedValue outValue = new TypedValue();
|
||||
fragment.getActivity().getTheme().resolveAttribute(res, outValue, true);
|
||||
view.setBackgroundColor(outValue.data);
|
||||
} else {
|
||||
view.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWithThreadCount(MessageViewHolder holder, int threadCount) {
|
||||
if (threadCount > 1) {
|
||||
holder.threadCount.setText(String.format("%d", threadCount));
|
||||
holder.threadCount.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.threadCount.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPreview(Cursor cursor) {
|
||||
String previewTypeString = cursor.getString(PREVIEW_TYPE_COLUMN);
|
||||
DatabasePreviewType previewType = DatabasePreviewType.fromDatabaseValue(previewTypeString);
|
||||
|
||||
switch (previewType) {
|
||||
case NONE:
|
||||
case ERROR: {
|
||||
return "";
|
||||
}
|
||||
case ENCRYPTED: {
|
||||
return fragment.getString(R.string.preview_encrypted);
|
||||
}
|
||||
case TEXT: {
|
||||
return cursor.getString(PREVIEW_COLUMN);
|
||||
}
|
||||
}
|
||||
|
||||
throw new AssertionError("Unknown preview type: " + previewType);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -2,9 +2,6 @@ package com.fsck.k9.fragment;
|
|||
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.fsck.k9.fragment.MessageListFragment;
|
||||
import com.fsck.k9.mail.Message;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -82,8 +79,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
int o1HasAttachment = (cursor1.getInt(MessageListFragment.ATTACHMENT_COUNT_COLUMN) > 0) ? 0 : 1;
|
||||
int o2HasAttachment = (cursor2.getInt(MessageListFragment.ATTACHMENT_COUNT_COLUMN) > 0) ? 0 : 1;
|
||||
int o1HasAttachment = (cursor1.getInt(MLFProjectionInfo.ATTACHMENT_COUNT_COLUMN) > 0) ? 0 : 1;
|
||||
int o2HasAttachment = (cursor2.getInt(MLFProjectionInfo.ATTACHMENT_COUNT_COLUMN) > 0) ? 0 : 1;
|
||||
return o1HasAttachment - o2HasAttachment;
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +89,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
int o1IsFlagged = (cursor1.getInt(MessageListFragment.FLAGGED_COLUMN) == 1) ? 0 : 1;
|
||||
int o2IsFlagged = (cursor2.getInt(MessageListFragment.FLAGGED_COLUMN) == 1) ? 0 : 1;
|
||||
int o1IsFlagged = (cursor1.getInt(MLFProjectionInfo.FLAGGED_COLUMN) == 1) ? 0 : 1;
|
||||
int o2IsFlagged = (cursor2.getInt(MLFProjectionInfo.FLAGGED_COLUMN) == 1) ? 0 : 1;
|
||||
return o1IsFlagged - o2IsFlagged;
|
||||
}
|
||||
}
|
||||
|
@ -102,8 +99,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
int o1IsUnread = cursor1.getInt(MessageListFragment.READ_COLUMN);
|
||||
int o2IsUnread = cursor2.getInt(MessageListFragment.READ_COLUMN);
|
||||
int o1IsUnread = cursor1.getInt(MLFProjectionInfo.READ_COLUMN);
|
||||
int o2IsUnread = cursor2.getInt(MLFProjectionInfo.READ_COLUMN);
|
||||
return o1IsUnread - o2IsUnread;
|
||||
}
|
||||
}
|
||||
|
@ -112,8 +109,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
long o1Date = cursor1.getLong(MessageListFragment.DATE_COLUMN);
|
||||
long o2Date = cursor2.getLong(MessageListFragment.DATE_COLUMN);
|
||||
long o1Date = cursor1.getLong(MLFProjectionInfo.DATE_COLUMN);
|
||||
long o2Date = cursor2.getLong(MLFProjectionInfo.DATE_COLUMN);
|
||||
if (o1Date < o2Date) {
|
||||
return -1;
|
||||
} else if (o1Date == o2Date) {
|
||||
|
@ -128,8 +125,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
long o1Date = cursor1.getLong(MessageListFragment.INTERNAL_DATE_COLUMN);
|
||||
long o2Date = cursor2.getLong(MessageListFragment.INTERNAL_DATE_COLUMN);
|
||||
long o1Date = cursor1.getLong(MLFProjectionInfo.INTERNAL_DATE_COLUMN);
|
||||
long o2Date = cursor2.getLong(MLFProjectionInfo.INTERNAL_DATE_COLUMN);
|
||||
if (o1Date == o2Date) {
|
||||
return 0;
|
||||
} else if (o1Date < o2Date) {
|
||||
|
@ -144,8 +141,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
String subject1 = cursor1.getString(MessageListFragment.SUBJECT_COLUMN);
|
||||
String subject2 = cursor2.getString(MessageListFragment.SUBJECT_COLUMN);
|
||||
String subject1 = cursor1.getString(MLFProjectionInfo.SUBJECT_COLUMN);
|
||||
String subject2 = cursor2.getString(MLFProjectionInfo.SUBJECT_COLUMN);
|
||||
|
||||
if (subject1 == null) {
|
||||
return (subject2 == null) ? 0 : -1;
|
||||
|
@ -161,8 +158,8 @@ public class MessageListFragmentComparators {
|
|||
|
||||
@Override
|
||||
public int compare(Cursor cursor1, Cursor cursor2) {
|
||||
String sender1 = MessageListFragment.getSenderAddressFromCursor(cursor1);
|
||||
String sender2 = MessageListFragment.getSenderAddressFromCursor(cursor2);
|
||||
String sender1 = MlfUtils.getSenderAddressFromCursor(cursor1);
|
||||
String sender2 = MlfUtils.getSenderAddressFromCursor(cursor2);
|
||||
|
||||
if (sender1 == null && sender2 == null) {
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
package com.fsck.k9.fragment;
|
||||
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fsck.k9.activity.MessageReference;
|
||||
|
||||
/**
|
||||
* This class is used to run operations that modify UI elements in the UI thread.
|
||||
*
|
||||
* <p>We are using convenience methods that add a {@link android.os.Message} instance or a
|
||||
* {@link Runnable} to the message queue.</p>
|
||||
*
|
||||
* <p><strong>Note:</strong> If you add a method to this class make sure you don't accidentally
|
||||
* perform the operation in the calling thread.</p>
|
||||
*/
|
||||
public class MessageListHandler extends Handler {
|
||||
private static final int ACTION_FOLDER_LOADING = 1;
|
||||
private static final int ACTION_REFRESH_TITLE = 2;
|
||||
private static final int ACTION_PROGRESS = 3;
|
||||
private static final int ACTION_REMOTE_SEARCH_FINISHED = 4;
|
||||
private static final int ACTION_GO_BACK = 5;
|
||||
private static final int ACTION_RESTORE_LIST_POSITION = 6;
|
||||
private static final int ACTION_OPEN_MESSAGE = 7;
|
||||
|
||||
private WeakReference<MessageListFragment> mFragment;
|
||||
|
||||
public MessageListHandler(MessageListFragment fragment) {
|
||||
mFragment = new WeakReference<>(fragment);
|
||||
}
|
||||
public void folderLoading(String folder, boolean loading) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_FOLDER_LOADING,
|
||||
(loading) ? 1 : 0, 0, folder);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void refreshTitle() {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_REFRESH_TITLE);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void progress(final boolean progress) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_PROGRESS,
|
||||
(progress) ? 1 : 0, 0);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void remoteSearchFinished() {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_REMOTE_SEARCH_FINISHED);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void updateFooter(final String message) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MessageListFragment fragment = mFragment.get();
|
||||
if (fragment != null) {
|
||||
fragment.updateFooter(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void goBack() {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_GO_BACK);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void restoreListPosition() {
|
||||
MessageListFragment fragment = mFragment.get();
|
||||
if (fragment != null) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_RESTORE_LIST_POSITION,
|
||||
fragment.savedListState);
|
||||
fragment.savedListState = null;
|
||||
sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void openMessage(MessageReference messageReference) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_OPEN_MESSAGE,
|
||||
messageReference);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
MessageListFragment fragment = mFragment.get();
|
||||
if (fragment == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The following messages don't need an attached activity.
|
||||
switch (msg.what) {
|
||||
case ACTION_REMOTE_SEARCH_FINISHED: {
|
||||
fragment.remoteSearchFinished();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Discard messages if the fragment isn't attached to an activity anymore.
|
||||
Activity activity = fragment.getActivity();
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.what) {
|
||||
case ACTION_FOLDER_LOADING: {
|
||||
String folder = (String) msg.obj;
|
||||
boolean loading = (msg.arg1 == 1);
|
||||
fragment.folderLoading(folder, loading);
|
||||
break;
|
||||
}
|
||||
case ACTION_REFRESH_TITLE: {
|
||||
fragment.updateTitle();
|
||||
break;
|
||||
}
|
||||
case ACTION_PROGRESS: {
|
||||
boolean progress = (msg.arg1 == 1);
|
||||
fragment.progress(progress);
|
||||
break;
|
||||
}
|
||||
case ACTION_GO_BACK: {
|
||||
fragment.fragmentListener.goBack();
|
||||
break;
|
||||
}
|
||||
case ACTION_RESTORE_LIST_POSITION: {
|
||||
fragment.listView.onRestoreInstanceState((Parcelable) msg.obj);
|
||||
break;
|
||||
}
|
||||
case ACTION_OPEN_MESSAGE: {
|
||||
MessageReference messageReference = (MessageReference) msg.obj;
|
||||
fragment.fragmentListener.openMessage(messageReference);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.fsck.k9.fragment;
|
||||
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.ui.ContactBadge;
|
||||
|
||||
|
||||
public class MessageViewHolder implements View.OnClickListener {
|
||||
private final MessageListFragment fragment;
|
||||
public TextView subject;
|
||||
public TextView preview;
|
||||
public TextView from;
|
||||
public TextView time;
|
||||
public TextView date;
|
||||
public View chip;
|
||||
public TextView threadCount;
|
||||
public CheckBox flagged;
|
||||
public CheckBox selected;
|
||||
public int position = -1;
|
||||
public ContactBadge contactBadge;
|
||||
|
||||
public MessageViewHolder(MessageListFragment fragment) {
|
||||
this.fragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (position != -1) {
|
||||
switch (view.getId()) {
|
||||
case R.id.selected_checkbox:
|
||||
fragment.toggleMessageSelectWithAdapterPosition(position);
|
||||
break;
|
||||
case R.id.flagged_bottom_right:
|
||||
case R.id.flagged_center_right:
|
||||
fragment.toggleMessageFlagWithAdapterPosition(position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
60
k9mail/src/main/java/com/fsck/k9/fragment/MlfUtils.java
Normal file
60
k9mail/src/main/java/com/fsck/k9/fragment/MlfUtils.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
package com.fsck.k9.fragment;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.activity.MessageReference;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mailstore.LocalFolder;
|
||||
import com.fsck.k9.mailstore.LocalStore;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.SENDER_LIST_COLUMN;
|
||||
|
||||
|
||||
public class MlfUtils {
|
||||
|
||||
static LocalFolder getOpenFolder(String folderName, Account account) throws MessagingException {
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
LocalFolder localFolder = localStore.getFolder(folderName);
|
||||
localFolder.open(Folder.OPEN_MODE_RO);
|
||||
return localFolder;
|
||||
}
|
||||
|
||||
static void setLastSelectedFolderName(Preferences preferences,
|
||||
List<MessageReference> messages, String destFolderName) {
|
||||
try {
|
||||
MessageReference firstMsg = messages.get(0);
|
||||
Account account = preferences.getAccount(firstMsg.getAccountUuid());
|
||||
LocalFolder firstMsgFolder = MlfUtils.getOpenFolder(firstMsg.getFolderName(), account);
|
||||
firstMsgFolder.setLastSelectedFolderName(destFolderName);
|
||||
} catch (MessagingException e) {
|
||||
Timber.e(e, "Error getting folder for setLastSelectedFolderName()");
|
||||
}
|
||||
}
|
||||
|
||||
static String getSenderAddressFromCursor(Cursor cursor) {
|
||||
String fromList = cursor.getString(SENDER_LIST_COLUMN);
|
||||
Address[] fromAddrs = Address.unpack(fromList);
|
||||
return (fromAddrs.length > 0) ? fromAddrs[0].getAddress() : null;
|
||||
}
|
||||
|
||||
static String buildSubject(String subjectFromCursor, String emptySubject, int threadCount) {
|
||||
String subject = subjectFromCursor;
|
||||
if (TextUtils.isEmpty(subject)) {
|
||||
return emptySubject;
|
||||
} else if (threadCount > 1) {
|
||||
// If this is a thread, strip the RE/FW from the subject. "Be like Outlook."
|
||||
return Utility.stripSubject(subject);
|
||||
}
|
||||
return subject;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue