2012-09-27 00:37:25 -04:00
|
|
|
package com.fsck.k9.fragment;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
import java.text.DateFormat;
|
2010-07-13 17:49:28 -04:00
|
|
|
import java.util.ArrayList;
|
2012-10-22 21:01:50 -04:00
|
|
|
import java.util.Arrays;
|
2010-07-13 17:49:28 -04:00
|
|
|
import java.util.Collections;
|
2010-09-21 18:12:45 -04:00
|
|
|
import java.util.Comparator;
|
2012-10-16 09:46:40 -04:00
|
|
|
import java.util.Date;
|
2010-09-21 18:12:45 -04:00
|
|
|
import java.util.EnumMap;
|
2012-10-17 23:15:40 -04:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.LinkedList;
|
2010-07-13 17:49:28 -04:00
|
|
|
import java.util.List;
|
2010-09-21 18:12:45 -04:00
|
|
|
import java.util.Map;
|
2012-09-25 18:46:30 -04:00
|
|
|
import java.util.concurrent.Future;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
import android.app.Activity;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
2012-05-16 14:35:55 -04:00
|
|
|
import android.content.SharedPreferences.Editor;
|
2012-10-16 09:46:40 -04:00
|
|
|
import android.database.Cursor;
|
2011-04-26 10:49:25 -04:00
|
|
|
import android.graphics.Color;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.graphics.Typeface;
|
|
|
|
import android.graphics.drawable.Drawable;
|
2012-10-05 21:41:32 -04:00
|
|
|
import android.net.ConnectivityManager;
|
|
|
|
import android.net.NetworkInfo;
|
2012-10-16 09:46:40 -04:00
|
|
|
import android.net.Uri;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.os.Bundle;
|
2012-09-04 18:35:43 -04:00
|
|
|
import android.os.Handler;
|
2012-10-05 21:41:32 -04:00
|
|
|
import android.support.v4.app.DialogFragment;
|
2012-10-17 23:15:40 -04:00
|
|
|
import android.support.v4.app.LoaderManager;
|
2012-10-16 09:46:40 -04:00
|
|
|
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
|
|
|
import android.support.v4.content.CursorLoader;
|
|
|
|
import android.support.v4.content.Loader;
|
|
|
|
import android.support.v4.widget.CursorAdapter;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.text.Spannable;
|
2010-08-30 10:37:34 -04:00
|
|
|
import android.text.SpannableStringBuilder;
|
2011-11-09 23:09:54 -05:00
|
|
|
import android.text.style.AbsoluteSizeSpan;
|
2011-04-26 10:49:25 -04:00
|
|
|
import android.text.style.ForegroundColorSpan;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.util.Log;
|
2012-10-16 09:46:40 -04:00
|
|
|
import android.util.SparseBooleanArray;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.util.TypedValue;
|
2012-10-05 21:41:32 -04:00
|
|
|
import android.view.ContextMenu;
|
2012-09-24 12:11:34 -04:00
|
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
2012-09-27 00:12:01 -04:00
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.MotionEvent;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.widget.AdapterView;
|
2012-09-24 12:11:34 -04:00
|
|
|
import android.widget.AdapterView.AdapterContextMenuInfo;
|
2012-08-24 23:47:23 -04:00
|
|
|
import android.widget.AdapterView.OnItemClickListener;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.widget.ListView;
|
|
|
|
import android.widget.ProgressBar;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
import com.actionbarsherlock.app.SherlockFragment;
|
2012-07-19 16:39:30 -04:00
|
|
|
import com.actionbarsherlock.view.ActionMode;
|
2012-07-16 09:22:42 -04:00
|
|
|
import com.actionbarsherlock.view.Menu;
|
2012-07-19 16:39:30 -04:00
|
|
|
import com.actionbarsherlock.view.MenuInflater;
|
2012-07-16 09:22:42 -04:00
|
|
|
import com.actionbarsherlock.view.MenuItem;
|
|
|
|
import com.actionbarsherlock.view.Window;
|
2010-07-13 17:49:28 -04:00
|
|
|
import com.fsck.k9.Account;
|
2012-04-08 22:29:08 -04:00
|
|
|
import com.fsck.k9.Account.SortType;
|
2010-07-13 17:49:28 -04:00
|
|
|
import com.fsck.k9.AccountStats;
|
|
|
|
import com.fsck.k9.FontSizes;
|
|
|
|
import com.fsck.k9.K9;
|
|
|
|
import com.fsck.k9.Preferences;
|
|
|
|
import com.fsck.k9.R;
|
2012-10-05 21:41:32 -04:00
|
|
|
import com.fsck.k9.activity.ActivityListener;
|
|
|
|
import com.fsck.k9.activity.ChooseFolder;
|
|
|
|
import com.fsck.k9.activity.FolderInfoHolder;
|
|
|
|
import com.fsck.k9.activity.MessageInfoHolder;
|
|
|
|
import com.fsck.k9.activity.MessageReference;
|
2010-07-13 17:49:28 -04:00
|
|
|
import com.fsck.k9.controller.MessagingController;
|
2012-10-17 23:15:40 -04:00
|
|
|
import com.fsck.k9.fragment.ConfirmationDialogFragment;
|
2012-10-05 21:41:32 -04:00
|
|
|
import com.fsck.k9.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
|
2010-10-03 06:56:16 -04:00
|
|
|
import com.fsck.k9.helper.MessageHelper;
|
2012-10-17 23:15:40 -04:00
|
|
|
import com.fsck.k9.helper.MergeCursorWithUniqueId;
|
2012-10-16 09:46:40 -04:00
|
|
|
import com.fsck.k9.helper.StringUtils;
|
2010-07-13 17:49:28 -04:00
|
|
|
import com.fsck.k9.helper.Utility;
|
2012-10-16 09:46:40 -04:00
|
|
|
import com.fsck.k9.mail.Address;
|
2010-07-13 17:49:28 -04:00
|
|
|
import com.fsck.k9.mail.Flag;
|
|
|
|
import com.fsck.k9.mail.Folder;
|
|
|
|
import com.fsck.k9.mail.Message;
|
2012-10-16 09:46:40 -04:00
|
|
|
import com.fsck.k9.mail.MessagingException;
|
|
|
|
import com.fsck.k9.mail.Folder.OpenMode;
|
2010-07-13 17:49:28 -04:00
|
|
|
import com.fsck.k9.mail.store.LocalStore;
|
|
|
|
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
2012-10-16 09:46:40 -04:00
|
|
|
import com.fsck.k9.provider.EmailProvider;
|
|
|
|
import com.fsck.k9.provider.EmailProvider.MessageColumns;
|
2012-10-17 23:15:40 -04:00
|
|
|
import com.fsck.k9.provider.EmailProvider.SpecialColumns;
|
2012-10-13 15:07:28 -04:00
|
|
|
import com.fsck.k9.search.ConditionsTreeNode;
|
|
|
|
import com.fsck.k9.search.LocalSearch;
|
|
|
|
import com.fsck.k9.search.SearchSpecification;
|
|
|
|
import com.fsck.k9.search.SearchSpecification.SearchCondition;
|
2012-09-12 04:18:07 -04:00
|
|
|
import com.handmark.pulltorefresh.library.PullToRefreshBase;
|
|
|
|
import com.handmark.pulltorefresh.library.PullToRefreshListView;
|
2010-12-28 04:11:10 -05:00
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
public class MessageListFragment extends SherlockFragment implements OnItemClickListener,
|
2012-10-16 09:46:40 -04:00
|
|
|
ConfirmationDialogFragmentListener, LoaderCallbacks<Cursor> {
|
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
private static final String[] THREADED_PROJECTION = {
|
2012-10-16 09:46:40 -04:00
|
|
|
MessageColumns.ID,
|
|
|
|
MessageColumns.UID,
|
|
|
|
MessageColumns.INTERNAL_DATE,
|
|
|
|
MessageColumns.SUBJECT,
|
|
|
|
MessageColumns.DATE,
|
|
|
|
MessageColumns.SENDER_LIST,
|
|
|
|
MessageColumns.TO_LIST,
|
|
|
|
MessageColumns.CC_LIST,
|
|
|
|
MessageColumns.FLAGS,
|
|
|
|
MessageColumns.ATTACHMENT_COUNT,
|
|
|
|
MessageColumns.FOLDER_ID,
|
|
|
|
MessageColumns.PREVIEW,
|
|
|
|
MessageColumns.THREAD_ROOT,
|
2012-10-17 23:15:40 -04:00
|
|
|
MessageColumns.THREAD_PARENT,
|
2012-10-22 21:01:50 -04:00
|
|
|
SpecialColumns.ACCOUNT_UUID,
|
|
|
|
|
|
|
|
MessageColumns.THREAD_COUNT,
|
2012-10-16 09:46:40 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
private static final int ID_COLUMN = 0;
|
|
|
|
private static final int UID_COLUMN = 1;
|
|
|
|
private static final int INTERNAL_DATE_COLUMN = 2;
|
|
|
|
private static final int SUBJECT_COLUMN = 3;
|
|
|
|
private static final int DATE_COLUMN = 4;
|
|
|
|
private static final int SENDER_LIST_COLUMN = 5;
|
|
|
|
private static final int TO_LIST_COLUMN = 6;
|
|
|
|
private static final int CC_LIST_COLUMN = 7;
|
|
|
|
private static final int FLAGS_COLUMN = 8;
|
|
|
|
private static final int ATTACHMENT_COUNT_COLUMN = 9;
|
|
|
|
private static final int FOLDER_ID_COLUMN = 10;
|
|
|
|
private static final int PREVIEW_COLUMN = 11;
|
|
|
|
private static final int THREAD_ROOT_COLUMN = 12;
|
|
|
|
private static final int THREAD_PARENT_COLUMN = 13;
|
2012-10-17 23:15:40 -04:00
|
|
|
private static final int ACCOUNT_UUID_COLUMN = 14;
|
2012-10-22 21:01:50 -04:00
|
|
|
private static final int THREAD_COUNT_COLUMN = 15;
|
|
|
|
|
|
|
|
private static final String[] PROJECTION = Arrays.copyOf(THREADED_PROJECTION,
|
|
|
|
THREAD_COUNT_COLUMN);
|
2012-10-16 09:46:40 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
public static MessageListFragment newInstance(LocalSearch search, boolean threadedList,
|
|
|
|
boolean remoteSearch) {
|
2012-10-05 21:41:32 -04:00
|
|
|
MessageListFragment fragment = new MessageListFragment();
|
|
|
|
Bundle args = new Bundle();
|
2012-10-13 15:07:28 -04:00
|
|
|
args.putParcelable(ARG_SEARCH, search);
|
2012-10-22 21:01:50 -04:00
|
|
|
args.putBoolean(ARG_THREADED_LIST, threadedList);
|
2012-10-05 21:41:32 -04:00
|
|
|
args.putBoolean(ARG_REMOTE_SEARCH, remoteSearch);
|
|
|
|
fragment.setArguments(args);
|
|
|
|
return fragment;
|
|
|
|
}
|
|
|
|
|
2010-09-21 18:12:45 -04:00
|
|
|
/**
|
|
|
|
* Reverses the result of a {@link Comparator}.
|
2010-10-03 20:01:59 -04:00
|
|
|
*
|
2010-09-21 18:12:45 -04:00
|
|
|
* @param <T>
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class ReverseComparator<T> implements Comparator<T> {
|
2010-09-21 18:12:45 -04:00
|
|
|
private Comparator<T> mDelegate;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param delegate
|
|
|
|
* Never <code>null</code>.
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public ReverseComparator(final Comparator<T> delegate) {
|
2010-09-21 18:12:45 -04:00
|
|
|
mDelegate = delegate;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(final T object1, final T object2) {
|
2010-09-21 18:12:45 -04:00
|
|
|
// arg1 & 2 are mixed up, this is done on purpose
|
|
|
|
return mDelegate.compare(object2, object1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Chains comparator to find a non-0 result.
|
2010-10-03 20:01:59 -04:00
|
|
|
*
|
2010-09-21 18:12:45 -04:00
|
|
|
* @param <T>
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class ComparatorChain<T> implements Comparator<T> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
private List<Comparator<T>> mChain;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param chain
|
|
|
|
* Comparator chain. Never <code>null</code>.
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public ComparatorChain(final List<Comparator<T>> chain) {
|
2010-09-21 18:12:45 -04:00
|
|
|
mChain = chain;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(T object1, T object2) {
|
2010-09-21 18:12:45 -04:00
|
|
|
int result = 0;
|
2011-02-06 17:09:48 -05:00
|
|
|
for (final Comparator<T> comparator : mChain) {
|
2010-09-21 18:12:45 -04:00
|
|
|
result = comparator.compare(object1, object2);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (result != 0) {
|
2010-09-21 18:12:45 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2010-10-03 20:01:59 -04:00
|
|
|
|
2010-09-21 18:12:45 -04:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class AttachmentComparator implements Comparator<MessageInfoHolder> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(MessageInfoHolder object1, MessageInfoHolder object2) {
|
2010-11-26 23:02:56 -05:00
|
|
|
return (object1.message.hasAttachments() ? 0 : 1) - (object2.message.hasAttachments() ? 0 : 1);
|
2010-09-21 18:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class FlaggedComparator implements Comparator<MessageInfoHolder> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(MessageInfoHolder object1, MessageInfoHolder object2) {
|
2010-09-21 18:12:45 -04:00
|
|
|
return (object1.flagged ? 0 : 1) - (object2.flagged ? 0 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class UnreadComparator implements Comparator<MessageInfoHolder> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(MessageInfoHolder object1, MessageInfoHolder object2) {
|
2010-09-21 18:12:45 -04:00
|
|
|
return (object1.read ? 1 : 0) - (object2.read ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class SenderComparator implements Comparator<MessageInfoHolder> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(MessageInfoHolder object1, MessageInfoHolder object2) {
|
2012-03-05 15:04:34 -05:00
|
|
|
if (object1.compareCounterparty == null) {
|
|
|
|
return (object2.compareCounterparty == null ? 0 : 1);
|
|
|
|
} else if (object2.compareCounterparty == null) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return object1.compareCounterparty.toLowerCase().compareTo(object2.compareCounterparty.toLowerCase());
|
|
|
|
}
|
2010-09-21 18:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class DateComparator implements Comparator<MessageInfoHolder> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(MessageInfoHolder object1, MessageInfoHolder object2) {
|
2012-03-05 15:04:34 -05:00
|
|
|
if (object1.compareDate == null) {
|
|
|
|
return (object2.compareDate == null ? 0 : 1);
|
|
|
|
} else if (object2.compareDate == null) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return object1.compareDate.compareTo(object2.compareDate);
|
|
|
|
}
|
2010-09-21 18:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-03-11 18:48:56 -04:00
|
|
|
public static class ArrivalComparator implements Comparator<MessageInfoHolder> {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compare(MessageInfoHolder object1, MessageInfoHolder object2) {
|
|
|
|
return object1.compareArrival.compareTo(object2.compareArrival);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public static class SubjectComparator implements Comparator<MessageInfoHolder> {
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int compare(MessageInfoHolder arg0, MessageInfoHolder arg1) {
|
2010-09-21 18:12:45 -04:00
|
|
|
// XXX doesn't respect the Comparator contract since it alters the compared object
|
2011-02-06 17:09:48 -05:00
|
|
|
if (arg0.compareSubject == null) {
|
2010-11-26 23:03:06 -05:00
|
|
|
arg0.compareSubject = Utility.stripSubject(arg0.message.getSubject());
|
2010-09-21 18:12:45 -04:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (arg1.compareSubject == null) {
|
2010-11-26 23:03:06 -05:00
|
|
|
arg1.compareSubject = Utility.stripSubject(arg1.message.getSubject());
|
2010-09-21 18:12:45 -04:00
|
|
|
}
|
|
|
|
return arg0.compareSubject.compareToIgnoreCase(arg1.compareSubject);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
|
|
|
|
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
|
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
private static final String ARG_SEARCH = "searchObject";
|
2012-10-22 21:01:50 -04:00
|
|
|
private static final String ARG_THREADED_LIST = "threadedList";
|
2012-10-13 15:07:28 -04:00
|
|
|
private static final String ARG_REMOTE_SEARCH = "remoteSearch";
|
2012-10-05 21:41:32 -04:00
|
|
|
private static final String STATE_LIST_POSITION = "listPosition";
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2010-09-21 18:12:45 -04:00
|
|
|
/**
|
2012-04-08 17:17:06 -04:00
|
|
|
* Maps a {@link SortType} to a {@link Comparator} implementation.
|
2010-09-21 18:12:45 -04:00
|
|
|
*/
|
2012-04-08 17:17:06 -04:00
|
|
|
private static final Map<SortType, Comparator<MessageInfoHolder>> SORT_COMPARATORS;
|
2010-09-21 18:12:45 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
static {
|
2010-09-21 18:12:45 -04:00
|
|
|
// fill the mapping at class time loading
|
|
|
|
|
2012-04-08 17:17:06 -04:00
|
|
|
final Map<SortType, Comparator<MessageInfoHolder>> map = new EnumMap<SortType, Comparator<MessageInfoHolder>>(SortType.class);
|
|
|
|
map.put(SortType.SORT_ATTACHMENT, new AttachmentComparator());
|
|
|
|
map.put(SortType.SORT_DATE, new DateComparator());
|
|
|
|
map.put(SortType.SORT_ARRIVAL, new ArrivalComparator());
|
|
|
|
map.put(SortType.SORT_FLAGGED, new FlaggedComparator());
|
|
|
|
map.put(SortType.SORT_SENDER, new SenderComparator());
|
|
|
|
map.put(SortType.SORT_SUBJECT, new SubjectComparator());
|
|
|
|
map.put(SortType.SORT_UNREAD, new UnreadComparator());
|
2010-09-21 18:12:45 -04:00
|
|
|
|
|
|
|
// make it immutable to prevent accidental alteration (content is immutable already)
|
|
|
|
SORT_COMPARATORS = Collections.unmodifiableMap(map);
|
|
|
|
}
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
private ListView mListView;
|
2012-09-12 04:18:07 -04:00
|
|
|
private PullToRefreshListView mPullToRefreshView;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2010-11-04 22:59:26 -04:00
|
|
|
private int mPreviewLines = 0;
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
private MessageListAdapter mAdapter;
|
2011-02-19 22:50:50 -05:00
|
|
|
private View mFooterView;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
private FolderInfoHolder mCurrentFolder;
|
|
|
|
|
|
|
|
private LayoutInflater mInflater;
|
|
|
|
|
|
|
|
private MessagingController mController;
|
|
|
|
|
|
|
|
private Account mAccount;
|
2012-10-17 23:15:40 -04:00
|
|
|
private String[] mAccountUuids;
|
2010-07-13 17:49:28 -04:00
|
|
|
private int mUnreadMessageCount = 0;
|
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
private Map<Integer, Cursor> mCursors = new HashMap<Integer, Cursor>();
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
/**
|
|
|
|
* Stores the name of the folder that we want to open as soon as possible
|
|
|
|
* after load.
|
|
|
|
*/
|
|
|
|
private String mFolderName;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If we're doing a search, this contains the query string.
|
|
|
|
*/
|
2012-03-05 15:04:34 -05:00
|
|
|
private boolean mRemoteSearch = false;
|
2012-09-25 18:46:30 -04:00
|
|
|
private Future mRemoteSearchFuture = null;
|
2012-10-16 14:57:47 -04:00
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
private String mTitle;
|
2012-10-13 15:07:28 -04:00
|
|
|
private LocalSearch mSearch = null;
|
|
|
|
private boolean mSingleAccountMode;
|
|
|
|
private boolean mSingleFolderMode;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
private MessageListHandler mHandler = new MessageListHandler();
|
|
|
|
|
2012-04-08 22:29:08 -04:00
|
|
|
private SortType mSortType = SortType.SORT_DATE;
|
|
|
|
private boolean mSortAscending = true;
|
|
|
|
private boolean mSortDateAscending = false;
|
2012-09-24 19:11:21 -04:00
|
|
|
private boolean mSenderAboveSubject = false;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
private int mSelectedCount = 0;
|
2012-10-16 09:46:40 -04:00
|
|
|
private SparseBooleanArray mSelected;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
private FontSizes mFontSizes = K9.getFontSizes();
|
|
|
|
|
2012-07-16 09:22:42 -04:00
|
|
|
private MenuItem mRefreshMenuItem;
|
2012-07-19 16:39:30 -04:00
|
|
|
private ActionMode mActionMode;
|
2012-08-02 10:00:28 -04:00
|
|
|
private View mActionBarProgressView;
|
2010-07-13 17:49:28 -04:00
|
|
|
private Bundle mState = null;
|
|
|
|
|
2012-09-29 17:12:01 -04:00
|
|
|
private Boolean mHasConnectivity;
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* Relevant messages for the current context when we have to remember the
|
|
|
|
* chosen messages between user interactions (eg. Selecting a folder for
|
|
|
|
* move operation)
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private Message[] mActiveMessages;
|
2011-06-04 16:57:03 -04:00
|
|
|
|
2010-10-05 02:04:28 -04:00
|
|
|
/* package visibility for faster inner class access */
|
2012-10-05 21:41:32 -04:00
|
|
|
MessageHelper mMessageHelper;
|
2010-10-03 06:56:16 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private ActionModeCallback mActionModeCallback = new ActionModeCallback();
|
2010-11-13 16:40:56 -05:00
|
|
|
|
2012-08-24 23:47:23 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private MessageListFragmentListener mFragmentListener;
|
2012-09-13 00:27:58 -04:00
|
|
|
|
2010-11-13 16:40:56 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private DateFormat mTimeFormat;
|
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
private boolean mThreadedList;
|
2012-10-08 16:51:29 -04:00
|
|
|
|
2010-11-13 16:40:56 -05:00
|
|
|
|
2012-10-09 22:30:19 -04:00
|
|
|
private Context mContext;
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private final ActivityListener mListener = new MessageListActivityListener();
|
2012-10-09 22:30:19 -04:00
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
private Preferences mPreferences;
|
|
|
|
|
2012-09-04 18:51:04 -04:00
|
|
|
/**
|
2012-09-04 21:50:02 -04:00
|
|
|
* 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>
|
2012-09-04 18:51:04 -04:00
|
|
|
*/
|
2012-09-04 18:35:43 -04:00
|
|
|
class MessageListHandler extends Handler {
|
2012-10-16 09:46:40 -04:00
|
|
|
private static final int ACTION_SORT_MESSAGES = 1;
|
|
|
|
private static final int ACTION_FOLDER_LOADING = 2;
|
|
|
|
private static final int ACTION_REFRESH_TITLE = 3;
|
|
|
|
private static final int ACTION_PROGRESS = 4;
|
2012-09-04 18:35:43 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
public void sortMessages() {
|
|
|
|
android.os.Message msg = android.os.Message.obtain(this, ACTION_SORT_MESSAGES);
|
|
|
|
sendMessage(msg);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
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);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-03-05 15:04:34 -05:00
|
|
|
public void updateFooter(final String message, final boolean showProgress) {
|
2012-10-05 21:41:32 -04:00
|
|
|
//TODO: use message
|
|
|
|
post(new Runnable() {
|
2012-03-05 15:04:34 -05:00
|
|
|
@Override
|
|
|
|
public void run() {
|
2012-10-05 21:41:32 -04:00
|
|
|
updateFooter(message, showProgress);
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
@Override
|
|
|
|
public void handleMessage(android.os.Message msg) {
|
|
|
|
switch (msg.what) {
|
|
|
|
case ACTION_SORT_MESSAGES: {
|
2012-09-04 18:51:04 -04:00
|
|
|
mAdapter.sortMessages();
|
2012-09-04 18:35:43 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ACTION_FOLDER_LOADING: {
|
|
|
|
String folder = (String) msg.obj;
|
|
|
|
boolean loading = (msg.arg1 == 1);
|
2012-10-05 21:41:32 -04:00
|
|
|
MessageListFragment.this.folderLoading(folder, loading);
|
2012-09-04 18:35:43 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ACTION_REFRESH_TITLE: {
|
2012-10-05 21:41:32 -04:00
|
|
|
MessageListFragment.this.refreshTitle();
|
2012-09-04 18:35:43 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ACTION_PROGRESS: {
|
|
|
|
boolean progress = (msg.arg1 == 1);
|
2012-10-05 21:41:32 -04:00
|
|
|
MessageListFragment.this.progress(progress);
|
2012-09-04 18:35:43 -04:00
|
|
|
break;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-04 18:35:43 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
/**
|
|
|
|
* @return The comparator to use to display messages in an ordered
|
|
|
|
* fashion. Never <code>null</code>.
|
|
|
|
*/
|
|
|
|
protected Comparator<MessageInfoHolder> getComparator() {
|
|
|
|
final List<Comparator<MessageInfoHolder>> chain = new ArrayList<Comparator<MessageInfoHolder>>(2 /* we add 2 comparators at most */);
|
|
|
|
|
|
|
|
{
|
|
|
|
// add the specified comparator
|
|
|
|
final Comparator<MessageInfoHolder> comparator = SORT_COMPARATORS.get(mSortType);
|
|
|
|
if (mSortAscending) {
|
|
|
|
chain.add(comparator);
|
|
|
|
} else {
|
|
|
|
chain.add(new ReverseComparator<MessageInfoHolder>(comparator));
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
{
|
|
|
|
// add the date comparator if not already specified
|
|
|
|
if (mSortType != SortType.SORT_DATE && mSortType != SortType.SORT_ARRIVAL) {
|
|
|
|
final Comparator<MessageInfoHolder> comparator = SORT_COMPARATORS.get(SortType.SORT_DATE);
|
|
|
|
if (mSortDateAscending) {
|
|
|
|
chain.add(comparator);
|
|
|
|
} else {
|
|
|
|
chain.add(new ReverseComparator<MessageInfoHolder>(comparator));
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-09-04 18:35:43 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
// build the comparator chain
|
|
|
|
final Comparator<MessageInfoHolder> chainComparator = new ComparatorChain<MessageInfoHolder>(chain);
|
|
|
|
|
|
|
|
return chainComparator;
|
2012-09-04 18:35:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
private void folderLoading(String folder, boolean loading) {
|
|
|
|
if (mCurrentFolder != null && mCurrentFolder.name.equals(folder)) {
|
|
|
|
mCurrentFolder.loading = loading;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-09-04 18:35:43 -04:00
|
|
|
updateFooterView();
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
private void refreshTitle() {
|
|
|
|
setWindowTitle();
|
2012-03-05 15:04:34 -05:00
|
|
|
if (!mRemoteSearch) {
|
|
|
|
setWindowProgress();
|
|
|
|
}
|
2012-09-04 18:35:43 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
private void setWindowProgress() {
|
|
|
|
int level = Window.PROGRESS_END;
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (mCurrentFolder != null && mCurrentFolder.loading && mListener.getFolderTotal() > 0) {
|
|
|
|
int divisor = mListener.getFolderTotal();
|
2012-09-04 18:35:43 -04:00
|
|
|
if (divisor != 0) {
|
2012-10-16 09:46:40 -04:00
|
|
|
level = (Window.PROGRESS_END / divisor) * (mListener.getFolderCompleted()) ;
|
2012-09-04 18:35:43 -04:00
|
|
|
if (level > Window.PROGRESS_END) {
|
|
|
|
level = Window.PROGRESS_END;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setMessageListProgress(level);
|
2012-09-04 18:35:43 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
private void setWindowTitle() {
|
2012-07-17 09:17:29 -04:00
|
|
|
// regular folder content display
|
2012-10-13 15:07:28 -04:00
|
|
|
if (mSingleFolderMode) {
|
2012-10-05 21:41:32 -04:00
|
|
|
Activity activity = getActivity();
|
|
|
|
String displayName = FolderInfoHolder.getDisplayName(activity, mAccount,
|
2012-08-24 21:48:43 -04:00
|
|
|
mFolderName);
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setMessageListTitle(displayName);
|
2012-07-17 09:17:29 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
String operation = mListener.getOperation(activity, getTimeFormat()).trim();
|
2012-08-28 14:20:46 -04:00
|
|
|
if (operation.length() < 1) {
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setMessageListSubTitle(mAccount.getEmail());
|
2012-08-28 14:20:46 -04:00
|
|
|
} else {
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setMessageListSubTitle(operation);
|
2012-08-28 14:20:46 -04:00
|
|
|
}
|
2012-10-13 15:07:28 -04:00
|
|
|
} else {
|
2012-09-06 18:46:58 -04:00
|
|
|
// query result display. This may be for a search folder as opposed to a user-initiated search.
|
2012-09-04 18:35:43 -04:00
|
|
|
if (mTitle != null) {
|
2012-09-06 18:46:58 -04:00
|
|
|
// This was a search folder; the search folder has overridden our title.
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setMessageListTitle(mTitle);
|
2012-09-04 18:35:43 -04:00
|
|
|
} else {
|
2012-09-06 18:46:58 -04:00
|
|
|
// This is a search result; set it to the default search result line.
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setMessageListTitle(getString(R.string.search_results));
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-10-05 21:41:32 -04:00
|
|
|
|
|
|
|
mFragmentListener.setMessageListSubTitle(null);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-08-27 14:19:09 -04:00
|
|
|
|
|
|
|
// set unread count
|
|
|
|
if (mUnreadMessageCount == 0) {
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setUnreadCount(0);
|
2012-08-27 14:19:09 -04:00
|
|
|
} else {
|
2012-10-13 15:07:28 -04:00
|
|
|
if (!mSingleFolderMode && mTitle == null) {
|
|
|
|
// The unread message count is easily confused
|
2012-09-06 18:46:58 -04:00
|
|
|
// with total number of messages in the search result, so let's hide it.
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setUnreadCount(0);
|
2012-09-06 18:46:58 -04:00
|
|
|
} else {
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.setUnreadCount(mUnreadMessageCount);
|
2012-09-06 18:46:58 -04:00
|
|
|
}
|
2012-08-27 14:19:09 -04:00
|
|
|
}
|
2012-09-04 18:35:43 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private void setupFormats() {
|
2012-10-09 22:30:19 -04:00
|
|
|
mTimeFormat = android.text.format.DateFormat.getTimeFormat(mContext);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
private DateFormat getTimeFormat() {
|
|
|
|
return mTimeFormat;
|
|
|
|
}
|
|
|
|
|
2012-09-04 18:35:43 -04:00
|
|
|
private void progress(final boolean progress) {
|
2012-07-16 09:22:42 -04:00
|
|
|
// Make sure we don't try this before the menu is initialized
|
|
|
|
// this could happen while the activity is initialized.
|
2012-09-12 04:18:07 -04:00
|
|
|
if (mRefreshMenuItem != null) {
|
|
|
|
if (progress) {
|
|
|
|
mRefreshMenuItem.setActionView(mActionBarProgressView);
|
|
|
|
} else {
|
|
|
|
mRefreshMenuItem.setActionView(null);
|
|
|
|
}
|
2012-07-16 09:22:42 -04:00
|
|
|
}
|
|
|
|
|
2012-09-12 04:18:07 -04:00
|
|
|
if (mPullToRefreshView != null && !progress) {
|
|
|
|
mPullToRefreshView.onRefreshComplete();
|
2012-07-16 09:22:42 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2011-02-28 16:55:34 -05:00
|
|
|
|
2010-08-03 01:46:35 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
2011-04-30 23:34:17 -04:00
|
|
|
if (view == mFooterView) {
|
2012-03-05 15:04:34 -05:00
|
|
|
if (mCurrentFolder != null && !mRemoteSearch) {
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.loadMoreMessages(mAccount, mFolderName, null);
|
|
|
|
} /*else if (mRemoteSearch && mAdapter.mExtraSearchResults != null && mAdapter.mExtraSearchResults.size() > 0 && mSearchAccount != null) {
|
2012-03-05 15:04:34 -05:00
|
|
|
int numResults = mAdapter.mExtraSearchResults.size();
|
2012-10-05 21:41:32 -04:00
|
|
|
Context appContext = getActivity().getApplicationContext();
|
|
|
|
Account account = Preferences.getPreferences(appContext).getAccount(mSearchAccount);
|
2012-03-05 15:04:34 -05:00
|
|
|
if (account == null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
updateFooter("", false);
|
2012-03-05 15:04:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-10-13 15:07:28 -04:00
|
|
|
int limit = mAccount.getRemoteSearchNumResults();
|
2012-03-05 15:04:34 -05:00
|
|
|
List<Message> toProcess = mAdapter.mExtraSearchResults;
|
|
|
|
if (limit > 0 && numResults > limit) {
|
|
|
|
toProcess = toProcess.subList(0, limit);
|
|
|
|
mAdapter.mExtraSearchResults = mAdapter.mExtraSearchResults.subList(limit, mAdapter.mExtraSearchResults.size());
|
|
|
|
} else {
|
|
|
|
mAdapter.mExtraSearchResults = null;
|
2012-10-16 09:46:40 -04:00
|
|
|
updateFooter("", false);
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
2012-10-16 14:57:47 -04:00
|
|
|
mController.loadSearchResults(mAccount, mCurrentFolder.name, toProcess, mListener);
|
2012-10-16 09:46:40 -04:00
|
|
|
}*/
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (mSelectedCount > 0) {
|
2012-10-16 09:46:40 -04:00
|
|
|
toggleMessageSelect(position);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2012-10-17 23:15:40 -04:00
|
|
|
Account account = getAccountFromCursor(cursor);
|
|
|
|
|
|
|
|
long folderId = cursor.getLong(FOLDER_ID_COLUMN);
|
|
|
|
String folderName = getFolderNameById(account, folderId);
|
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
if (mThreadedList && cursor.getInt(THREAD_COUNT_COLUMN) > 1) {
|
|
|
|
long rootId = cursor.getLong(THREAD_ROOT_COLUMN);
|
|
|
|
mFragmentListener.showThread(account, folderName, rootId);
|
|
|
|
} else {
|
|
|
|
MessageReference ref = new MessageReference();
|
|
|
|
ref.accountUuid = account.getUuid();
|
|
|
|
ref.folderName = folderName;
|
|
|
|
ref.uid = cursor.getString(UID_COLUMN);
|
|
|
|
onOpenMessage(ref);
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
@Override
|
|
|
|
public void onAttach(Activity activity) {
|
|
|
|
super.onAttach(activity);
|
|
|
|
|
2012-10-09 22:30:19 -04:00
|
|
|
mContext = activity.getApplicationContext();
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
try {
|
|
|
|
mFragmentListener = (MessageListFragmentListener) activity;
|
|
|
|
} catch (ClassCastException e) {
|
|
|
|
throw new ClassCastException(activity.getClass() +
|
|
|
|
" must implement MessageListFragmentListener");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
2010-07-13 17:49:28 -04:00
|
|
|
super.onCreate(savedInstanceState);
|
2010-08-30 10:37:34 -04:00
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
mPreferences = Preferences.getPreferences(getActivity().getApplicationContext());
|
2012-10-05 21:41:32 -04:00
|
|
|
mController = MessagingController.getInstance(getActivity().getApplication());
|
2012-08-02 10:00:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mPreviewLines = K9.messageListPreviewLines();
|
2012-07-20 14:36:34 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
decodeArguments();
|
|
|
|
}
|
2012-09-12 04:18:07 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
@Override
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
Bundle savedInstanceState) {
|
2011-11-06 17:37:49 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mInflater = inflater;
|
2011-11-06 17:37:49 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
View view = inflater.inflate(R.layout.message_list_fragment, container, false);
|
Fix gesture detection
This commit addresses 2 issues:
1) Before, a general GestureDetector was registered on the highest level in K9Activity
This resulted in EVERY inherited activity to have a useless, unused gesture detector.
But more than that, in MessageList, a second GestureDetector was assigned to the ListView.
On every fling gesture, both detectors called the onSwipe() methods,
which technically did the following:
- The one directly assigned to the ListView would work corectly by mapping the
(local) event coordinates to the right entry in the ListView
- The global one worked on screen coordinates, so the onSwipe() method would
likely select the wrong ListView entry (system menu bar offset).
- For some reason this "worked" fine, and only the correct entry was selected,
despite two detectors used.
2) The gesture detection for the MessageView caused problems when the message
itself was scrollable, i.e. wide HTML mails. A fling gesture inside the WebView
would scroll the message, but also switch the message.
This commit fixes all those by doing the following:
- Don't register the GestureDetector in K9Activity, instead make the member variable
accessible by subclasses.
- In the subclasses that need a detector register it
- In K9Activity.dispatchTouchEvent() check for mGestureDetector being null
- For MessageList:
* Remove the duplicate gesture detector assigned to the ListView
* in the handleSwipe() methods: calclulate pixel offset of the ListView to make
it work using the global screen coordinates
- For MessageView: Limit sensitive area to the message header, to prevent interference
with the WebView scrolling
- Respect current behavior:
* Force-enable gestures for the MessageList
* Respect user setting in MessageView
- Make sure that after a successful swipe gesture, any pending action is cancelled, to
prevent unwanted things to happen (such as expanding the header after changing
the message, or a context menu popping up in the MessageList).
See http://code.google.com/p/android/issues/detail?id=8497
2012-04-30 19:56:06 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mActionBarProgressView = inflater.inflate(R.layout.actionbar_indeterminate_progress_actionview, null);
|
2012-09-20 16:50:56 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mPullToRefreshView = (PullToRefreshListView) view.findViewById(R.id.message_list);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
initializeLayout();
|
|
|
|
mListView.setVerticalFadingEdgeEnabled(false);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
return view;
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
@Override
|
|
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
|
|
super.onActivityCreated(savedInstanceState);
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mMessageHelper = MessageHelper.getInstance(getActivity());
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
initializeMessageList();
|
2012-10-16 09:46:40 -04:00
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
LoaderManager loaderManager = getLoaderManager();
|
|
|
|
for (int i = 0, len = mAccountUuids.length; i < len; i++) {
|
|
|
|
loaderManager.initLoader(i, null, this);
|
|
|
|
}
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
2011-12-05 12:16:43 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private void decodeArguments() {
|
|
|
|
Bundle args = getArguments();
|
2011-11-06 17:37:49 -05:00
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
mThreadedList = args.getBoolean(ARG_THREADED_LIST, false);
|
2012-10-05 21:41:32 -04:00
|
|
|
mRemoteSearch = args.getBoolean(ARG_REMOTE_SEARCH, false);
|
2012-10-13 15:07:28 -04:00
|
|
|
mSearch = args.getParcelable(ARG_SEARCH);
|
2012-10-22 12:10:47 -04:00
|
|
|
mTitle = mSearch.getName();
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
String[] accountUuids = mSearch.getAccountUuids();
|
2011-11-06 17:37:49 -05:00
|
|
|
|
2012-10-16 14:57:47 -04:00
|
|
|
mSingleAccountMode = false;
|
2012-10-17 23:15:40 -04:00
|
|
|
if (accountUuids.length == 1 && !accountUuids[0].equals(SearchSpecification.ALL_ACCOUNTS)) {
|
2012-10-16 14:57:47 -04:00
|
|
|
mSingleAccountMode = true;
|
2012-10-17 23:15:40 -04:00
|
|
|
mAccount = mPreferences.getAccount(accountUuids[0]);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-10-05 21:41:32 -04:00
|
|
|
|
2012-10-16 14:57:47 -04:00
|
|
|
mSingleFolderMode = false;
|
|
|
|
if (mSingleAccountMode && (mSearch.getFolderNames().size() == 1)) {
|
|
|
|
mSingleFolderMode = true;
|
|
|
|
mFolderName = mSearch.getFolderNames().get(0);
|
|
|
|
mCurrentFolder = getFolder(mFolderName, mAccount);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-10-17 23:15:40 -04:00
|
|
|
|
|
|
|
if (mSingleAccountMode) {
|
|
|
|
mAccountUuids = new String[] { mAccount.getUuid() };
|
|
|
|
} else {
|
|
|
|
if (accountUuids.length == 1 &&
|
|
|
|
accountUuids[0].equals(SearchSpecification.ALL_ACCOUNTS)) {
|
|
|
|
|
|
|
|
Account[] accounts = mPreferences.getAccounts();
|
|
|
|
|
|
|
|
mAccountUuids = new String[accounts.length];
|
|
|
|
for (int i = 0, len = accounts.length; i < len; i++) {
|
|
|
|
mAccountUuids[i] = accounts[i].getUuid();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mAccountUuids = accountUuids;
|
|
|
|
}
|
|
|
|
}
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private void initializeMessageList() {
|
2010-07-13 17:49:28 -04:00
|
|
|
mAdapter = new MessageListAdapter();
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (mFolderName != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
mCurrentFolder = getFolder(mFolderName, mAccount);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
// Hide "Load up to x more" footer for search views
|
2012-10-16 14:57:47 -04:00
|
|
|
mFooterView.setVisibility((!mSingleFolderMode) ? View.GONE : View.VISIBLE);
|
2011-12-30 20:22:31 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
mController = MessagingController.getInstance(getActivity().getApplication());
|
2010-07-13 17:49:28 -04:00
|
|
|
mListView.setAdapter(mAdapter);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private FolderInfoHolder getFolder(String folder, Account account) {
|
|
|
|
LocalFolder local_folder = null;
|
|
|
|
try {
|
|
|
|
LocalStore localStore = account.getLocalStore();
|
|
|
|
local_folder = localStore.getFolder(folder);
|
|
|
|
return new FolderInfoHolder(mContext, local_folder, account);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(K9.LOG_TAG, "getFolder(" + folder + ") goes boom: ", e);
|
|
|
|
return null;
|
|
|
|
} finally {
|
|
|
|
if (local_folder != null) {
|
|
|
|
local_folder.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
private String getFolderNameById(Account account, long folderId) {
|
|
|
|
try {
|
|
|
|
LocalStore localStore = account.getLocalStore();
|
|
|
|
LocalFolder localFolder = localStore.getFolderById(folderId);
|
|
|
|
localFolder.open(OpenMode.READ_ONLY);
|
|
|
|
return localFolder.getName();
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(K9.LOG_TAG, "getFolderNameById() failed.", e);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onPause() {
|
2010-07-13 17:49:28 -04:00
|
|
|
super.onPause();
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.removeListener(mListener);
|
2010-07-13 17:49:28 -04:00
|
|
|
saveListState();
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void saveListState() {
|
2010-07-13 17:49:28 -04:00
|
|
|
mState = new Bundle();
|
2012-10-05 21:41:32 -04:00
|
|
|
mState.putInt(STATE_LIST_POSITION, mListView.getSelectedItemPosition());
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void restoreListState() {
|
|
|
|
if (mState == null) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
int pos = mState.getInt(STATE_LIST_POSITION, ListView.INVALID_POSITION);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (pos >= mListView.getCount()) {
|
2010-07-13 17:49:28 -04:00
|
|
|
pos = mListView.getCount() - 1;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (pos == ListView.INVALID_POSITION) {
|
2010-07-13 17:49:28 -04:00
|
|
|
mListView.setSelected(false);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2010-07-13 17:49:28 -04:00
|
|
|
mListView.setSelection(pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* On resume we refresh messages for the folder that is currently open.
|
|
|
|
* This guarantees that things like unread message count and read status
|
|
|
|
* are updated.
|
|
|
|
*/
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onResume() {
|
2010-07-13 17:49:28 -04:00
|
|
|
super.onResume();
|
2011-04-12 08:16:22 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
setupFormats();
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
Context appContext = getActivity().getApplicationContext();
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-09-24 19:11:21 -04:00
|
|
|
mSenderAboveSubject = K9.messageListSenderAboveSubject();
|
2010-11-13 16:40:56 -05:00
|
|
|
|
2012-09-29 17:12:01 -04:00
|
|
|
// Check if we have connectivity. Cache the value.
|
|
|
|
if (mHasConnectivity == null) {
|
2012-10-05 21:41:32 -04:00
|
|
|
final ConnectivityManager connectivityManager =
|
|
|
|
(ConnectivityManager) getActivity().getApplication().getSystemService(
|
|
|
|
Context.CONNECTIVITY_SERVICE);
|
|
|
|
final NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
|
|
|
|
if (netInfo != null && netInfo.getState() == NetworkInfo.State.CONNECTED) {
|
|
|
|
mHasConnectivity = true;
|
|
|
|
} else {
|
|
|
|
mHasConnectivity = false;
|
|
|
|
}
|
2012-09-29 17:12:01 -04:00
|
|
|
}
|
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
if (mSingleFolderMode) {
|
2012-10-16 14:57:47 -04:00
|
|
|
if (!mAccount.allowRemoteSearch()) {
|
|
|
|
mPullToRefreshView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>() {
|
|
|
|
@Override
|
|
|
|
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
|
|
|
checkMail();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// TODO this has to go! find better remote search integration
|
|
|
|
} else {
|
2012-10-13 15:07:28 -04:00
|
|
|
mPullToRefreshView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>() {
|
|
|
|
@Override
|
|
|
|
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
|
|
|
mPullToRefreshView.onRefreshComplete();
|
|
|
|
onRemoteSearchRequested();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
mPullToRefreshView.setPullLabel(getString(R.string.pull_to_refresh_remote_search_from_local_search_pull));
|
|
|
|
mPullToRefreshView.setReleaseLabel(getString(R.string.pull_to_refresh_remote_search_from_local_search_release));
|
2012-10-16 14:57:47 -04:00
|
|
|
}
|
2012-09-12 04:18:07 -04:00
|
|
|
} else {
|
|
|
|
mPullToRefreshView.setMode(PullToRefreshBase.Mode.DISABLED);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.addListener(mListener);
|
2012-01-20 14:55:04 -05:00
|
|
|
|
2012-03-05 15:04:34 -05:00
|
|
|
//Cancel pending new mail notifications when we open an account
|
2012-01-20 17:32:12 -05:00
|
|
|
Account[] accountsWithNotification;
|
2012-05-15 02:09:28 -04:00
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
Account account = mAccount;
|
2012-05-15 02:09:28 -04:00
|
|
|
|
|
|
|
if (account != null) {
|
|
|
|
accountsWithNotification = new Account[] { account };
|
|
|
|
mSortType = account.getSortType();
|
|
|
|
mSortAscending = account.isSortAscending(mSortType);
|
|
|
|
mSortDateAscending = account.isSortAscending(SortType.SORT_DATE);
|
2012-01-20 14:55:04 -05:00
|
|
|
} else {
|
2012-10-17 23:15:40 -04:00
|
|
|
accountsWithNotification = mPreferences.getAccounts();
|
2012-05-15 02:09:28 -04:00
|
|
|
mSortType = K9.getSortType();
|
2012-04-12 22:12:22 -04:00
|
|
|
mSortAscending = K9.isSortAscending(mSortType);
|
|
|
|
mSortDateAscending = K9.isSortAscending(SortType.SORT_DATE);
|
2012-01-20 14:55:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Account accountWithNotification : accountsWithNotification) {
|
2012-10-05 21:41:32 -04:00
|
|
|
mController.notifyAccountCancel(appContext, accountWithNotification);
|
2010-10-23 11:19:56 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-03-05 15:04:34 -05:00
|
|
|
if (mAccount != null && mFolderName != null && !mRemoteSearch) {
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.getFolderUnreadMessageCount(mAccount, mFolderName, mListener);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-09-04 19:02:05 -04:00
|
|
|
refreshTitle();
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-09-04 19:02:05 -04:00
|
|
|
|
2012-07-16 09:22:42 -04:00
|
|
|
private void initializeLayout() {
|
2012-09-12 04:18:07 -04:00
|
|
|
mListView = mPullToRefreshView.getRefreshableView();
|
2012-09-10 09:52:36 -04:00
|
|
|
mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
|
2010-07-13 17:49:28 -04:00
|
|
|
mListView.setLongClickable(true);
|
|
|
|
mListView.setFastScrollEnabled(true);
|
2011-07-19 10:37:19 -04:00
|
|
|
mListView.setScrollingCacheEnabled(false);
|
2010-07-13 17:49:28 -04:00
|
|
|
mListView.setOnItemClickListener(this);
|
2011-02-19 22:50:50 -05:00
|
|
|
mListView.addFooterView(getFooterView(mListView));
|
2012-10-16 09:46:40 -04:00
|
|
|
//mListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
registerForContextMenu(mListView);
|
2012-07-16 09:22:42 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onOpenMessage(MessageReference reference) {
|
|
|
|
mFragmentListener.openMessage(reference);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
public void onCompose() {
|
2012-10-13 15:07:28 -04:00
|
|
|
if (!mSingleAccountMode) {
|
2010-07-13 17:49:28 -04:00
|
|
|
/*
|
|
|
|
* If we have a query string, we don't have an account to let
|
|
|
|
* compose start the default action.
|
|
|
|
*/
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.onCompose(null);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2012-10-05 21:41:32 -04:00
|
|
|
mFragmentListener.onCompose(mAccount);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
public void onReply(Message message) {
|
|
|
|
mFragmentListener.onReply(message);
|
2012-08-21 10:42:45 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
public void onReplyAll(Message message) {
|
|
|
|
mFragmentListener.onReplyAll(message);
|
2012-08-21 10:42:45 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
public void onForward(Message message) {
|
|
|
|
mFragmentListener.onForward(message);
|
2012-08-21 10:42:45 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
public void onResendMessage(Message message) {
|
|
|
|
mFragmentListener.onResendMessage(message);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
public void changeSort(SortType sortType) {
|
|
|
|
Boolean sortAscending = (mSortType == sortType) ? !mSortAscending : null;
|
|
|
|
changeSort(sortType, sortAscending);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-09-22 12:40:46 -04:00
|
|
|
/**
|
|
|
|
* User has requested a remote search. Setup the bundle and start the intent.
|
|
|
|
*/
|
2012-10-13 15:07:28 -04:00
|
|
|
public void onRemoteSearchRequested() {
|
2012-10-05 21:41:32 -04:00
|
|
|
String searchAccount;
|
|
|
|
String searchFolder;
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
searchAccount = mAccount.getUuid();
|
|
|
|
searchFolder = mCurrentFolder.name;
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
mFragmentListener.remoteSearch(searchAccount, searchFolder, mSearch.getRemoteSearchArguments());
|
2012-05-16 14:33:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change the sort type and sort order used for the message list.
|
|
|
|
*
|
|
|
|
* @param sortType
|
|
|
|
* Specifies which field to use for sorting the message list.
|
|
|
|
* @param sortAscending
|
|
|
|
* Specifies the sort order. If this argument is {@code null} the default search order
|
|
|
|
* for the sort type is used.
|
|
|
|
*/
|
|
|
|
// FIXME: Don't save the changes in the UI thread
|
|
|
|
private void changeSort(SortType sortType, Boolean sortAscending) {
|
|
|
|
mSortType = sortType;
|
2012-05-15 02:09:28 -04:00
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
Account account = mAccount;
|
2012-05-15 02:09:28 -04:00
|
|
|
|
2012-05-16 14:33:36 -04:00
|
|
|
if (account != null) {
|
|
|
|
account.setSortType(mSortType);
|
|
|
|
|
|
|
|
if (sortAscending == null) {
|
2012-05-15 02:09:28 -04:00
|
|
|
mSortAscending = account.isSortAscending(mSortType);
|
2012-04-12 22:12:22 -04:00
|
|
|
} else {
|
2012-05-16 14:33:36 -04:00
|
|
|
mSortAscending = sortAscending;
|
|
|
|
}
|
|
|
|
account.setSortAscending(mSortType, mSortAscending);
|
|
|
|
mSortDateAscending = account.isSortAscending(SortType.SORT_DATE);
|
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
account.save(mPreferences);
|
2012-05-16 14:33:36 -04:00
|
|
|
} else {
|
|
|
|
K9.setSortType(mSortType);
|
2012-05-16 14:35:55 -04:00
|
|
|
|
2012-05-16 14:33:36 -04:00
|
|
|
if (sortAscending == null) {
|
|
|
|
mSortAscending = K9.isSortAscending(mSortType);
|
|
|
|
} else {
|
|
|
|
mSortAscending = sortAscending;
|
2012-04-11 01:08:49 -04:00
|
|
|
}
|
2012-05-16 14:33:36 -04:00
|
|
|
K9.setSortAscending(mSortType, mSortAscending);
|
|
|
|
mSortDateAscending = K9.isSortAscending(SortType.SORT_DATE);
|
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
Editor editor = mPreferences.getPreferences().edit();
|
2012-05-16 14:33:36 -04:00
|
|
|
K9.save(editor);
|
|
|
|
editor.commit();
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-05-16 14:33:36 -04:00
|
|
|
|
|
|
|
reSort();
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void reSort() {
|
2012-04-08 22:29:08 -04:00
|
|
|
int toastString = mSortType.getToast(mSortAscending);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
Toast toast = Toast.makeText(getActivity(), toastString, Toast.LENGTH_SHORT);
|
2010-07-13 17:49:28 -04:00
|
|
|
toast.show();
|
|
|
|
|
2012-09-04 19:02:05 -04:00
|
|
|
mAdapter.sortMessages();
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
public void onCycleSort() {
|
2012-04-08 17:17:06 -04:00
|
|
|
SortType[] sorts = SortType.values();
|
2010-07-13 17:49:28 -04:00
|
|
|
int curIndex = 0;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
for (int i = 0; i < sorts.length; i++) {
|
2012-04-08 22:29:08 -04:00
|
|
|
if (sorts[i] == mSortType) {
|
2010-07-13 17:49:28 -04:00
|
|
|
curIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
curIndex++;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (curIndex == sorts.length) {
|
2010-07-13 17:49:28 -04:00
|
|
|
curIndex = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
changeSort(sorts[curIndex]);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onDelete(Message message) {
|
|
|
|
onDelete(new Message[] { message });
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onDelete(Message[] messages) {
|
|
|
|
mController.deleteMessages(messages, null);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2012-10-05 21:41:32 -04:00
|
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
if (resultCode != Activity.RESULT_OK) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
2011-06-04 16:57:03 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
switch (requestCode) {
|
|
|
|
case ACTIVITY_CHOOSE_FOLDER_MOVE:
|
|
|
|
case ACTIVITY_CHOOSE_FOLDER_COPY: {
|
2011-06-04 16:57:03 -04:00
|
|
|
if (data == null) {
|
2011-02-06 17:09:48 -05:00
|
|
|
return;
|
2011-06-04 16:57:03 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
final String destFolderName = data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER);
|
2012-10-16 09:46:40 -04:00
|
|
|
final Message[] messages = mActiveMessages;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
if (destFolderName != null) {
|
|
|
|
|
|
|
|
mActiveMessages = null; // don't need it any more
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
final Account account = messages[0].getFolder().getAccount();
|
2011-02-06 17:09:48 -05:00
|
|
|
account.setLastSelectedFolderName(destFolderName);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
switch (requestCode) {
|
|
|
|
case ACTIVITY_CHOOSE_FOLDER_MOVE:
|
2012-10-16 09:46:40 -04:00
|
|
|
move(messages, destFolderName);
|
2011-02-06 17:09:48 -05:00
|
|
|
break;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
case ACTIVITY_CHOOSE_FOLDER_COPY:
|
2012-10-16 09:46:40 -04:00
|
|
|
copy(messages, destFolderName);
|
2011-02-06 17:09:48 -05:00
|
|
|
break;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
break;
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
public void onExpunge() {
|
|
|
|
if (mCurrentFolder != null) {
|
|
|
|
onExpunge(mAccount, mCurrentFolder.name);
|
|
|
|
}
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void onExpunge(final Account account, String folderName) {
|
2010-07-13 17:49:28 -04:00
|
|
|
mController.expunge(account, folderName, null);
|
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private void showDialog(int dialogId) {
|
|
|
|
DialogFragment fragment;
|
|
|
|
switch (dialogId) {
|
|
|
|
case R.id.dialog_confirm_spam: {
|
|
|
|
String title = getString(R.string.dialog_confirm_spam_title);
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
int selectionSize = mActiveMessages.length;
|
2012-10-05 21:41:32 -04:00
|
|
|
String message = getResources().getQuantityString(
|
|
|
|
R.plurals.dialog_confirm_spam_message, selectionSize,
|
|
|
|
Integer.valueOf(selectionSize));
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
String confirmText = getString(R.string.dialog_confirm_spam_confirm_button);
|
|
|
|
String cancelText = getString(R.string.dialog_confirm_spam_cancel_button);
|
|
|
|
|
|
|
|
fragment = ConfirmationDialogFragment.newInstance(dialogId, title, message,
|
|
|
|
confirmText, cancelText);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
throw new RuntimeException("Called showDialog(int) with unknown dialog id.");
|
2011-06-06 19:15:04 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-07-20 10:13:35 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
fragment.setTargetFragment(this, dialogId);
|
|
|
|
fragment.show(getFragmentManager(), getDialogTag(dialogId));
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
private String getDialogTag(int dialogId) {
|
|
|
|
return String.format("dialog-%d", dialogId);
|
2012-09-25 18:46:30 -04:00
|
|
|
}
|
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
2010-07-13 17:49:28 -04:00
|
|
|
int itemId = item.getItemId();
|
2011-02-06 17:09:48 -05:00
|
|
|
switch (itemId) {
|
|
|
|
case R.id.set_sort_date: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_DATE);
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
2012-03-11 18:48:56 -04:00
|
|
|
case R.id.set_sort_arrival: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_ARRIVAL);
|
2012-03-11 18:48:56 -04:00
|
|
|
return true;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
case R.id.set_sort_subject: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_SUBJECT);
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.set_sort_sender: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_SENDER);
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.set_sort_flag: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_FLAGGED);
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.set_sort_unread: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_UNREAD);
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.set_sort_attach: {
|
2012-04-08 17:17:06 -04:00
|
|
|
changeSort(SortType.SORT_ATTACHMENT);
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
2012-09-14 22:24:49 -04:00
|
|
|
case R.id.select_all: {
|
2012-10-16 09:46:40 -04:00
|
|
|
selectAll();
|
2012-09-14 22:24:49 -04:00
|
|
|
return true;
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
if (!mSingleAccountMode) {
|
2010-07-13 17:49:28 -04:00
|
|
|
// None of the options after this point are "safe" for search results
|
|
|
|
//TODO: This is not true for "unread" and "starred" searches in regular folders
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
switch (itemId) {
|
|
|
|
case R.id.send_messages: {
|
2012-10-05 21:41:32 -04:00
|
|
|
onSendPendingMessages();
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.expunge: {
|
|
|
|
if (mCurrentFolder != null) {
|
|
|
|
onExpunge(mAccount, mCurrentFolder.name);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
2012-10-05 21:41:32 -04:00
|
|
|
|
|
|
|
public void onSendPendingMessages() {
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.sendPendingMessages(mAccount, null);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
|
2012-09-24 12:11:34 -04:00
|
|
|
@Override
|
|
|
|
public boolean onContextItemSelected(android.view.MenuItem item) {
|
|
|
|
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
2012-10-16 09:46:40 -04:00
|
|
|
int adapterPosition = listViewToAdapterPosition(info.position);
|
|
|
|
Message message = getMessageAtPosition(adapterPosition);
|
2012-09-24 12:11:34 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
switch (item.getItemId()) {
|
|
|
|
case R.id.reply: {
|
|
|
|
onReply(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.reply_all: {
|
|
|
|
onReplyAll(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.forward: {
|
|
|
|
onForward(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.send_again: {
|
|
|
|
onResendMessage(message);
|
|
|
|
mSelectedCount = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.same_sender: {
|
|
|
|
Cursor cursor = (Cursor) mAdapter.getItem(adapterPosition);
|
|
|
|
String senderAddress = getSenderAddressFromCursor(cursor);
|
|
|
|
if (senderAddress != null) {
|
|
|
|
mFragmentListener.showMoreFromSameSender(senderAddress);
|
2012-09-24 12:11:34 -04:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.delete: {
|
|
|
|
onDelete(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.mark_as_read: {
|
|
|
|
setFlag(message, Flag.SEEN, true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.mark_as_unread: {
|
|
|
|
setFlag(message, Flag.SEEN, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.flag: {
|
|
|
|
setFlag(message, Flag.FLAGGED, true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.unflag: {
|
|
|
|
setFlag(message, Flag.FLAGGED, false);
|
|
|
|
break;
|
2012-09-24 12:11:34 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
// only if the account supports this
|
|
|
|
case R.id.archive: {
|
|
|
|
onArchive(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.spam: {
|
|
|
|
onSpam(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.move: {
|
|
|
|
onMove(message);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.copy: {
|
|
|
|
onCopy(message);
|
|
|
|
break;
|
|
|
|
}
|
2012-09-24 12:11:34 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String getSenderAddressFromCursor(Cursor cursor) {
|
|
|
|
String fromList = cursor.getString(SENDER_LIST_COLUMN);
|
|
|
|
Address[] fromAddrs = Address.unpack(fromList);
|
|
|
|
return (fromAddrs.length > 0) ? fromAddrs[0].getAddress() : null;
|
|
|
|
}
|
2012-09-24 12:11:34 -04:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
|
|
|
super.onCreateContextMenu(menu, v, menuInfo);
|
|
|
|
|
|
|
|
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
2012-10-16 09:46:40 -04:00
|
|
|
Cursor cursor = (Cursor) mListView.getItemAtPosition(info.position);
|
2012-09-24 12:11:34 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (cursor == null) {
|
2012-09-24 12:11:34 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
getActivity().getMenuInflater().inflate(R.menu.message_list_item_context, menu);
|
2012-09-24 12:11:34 -04:00
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
Account account = getAccountFromCursor(cursor);
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
String subject = cursor.getString(SUBJECT_COLUMN);
|
|
|
|
String flagList = cursor.getString(FLAGS_COLUMN);
|
|
|
|
String[] flags = flagList.split(",");
|
|
|
|
boolean read = false;
|
|
|
|
boolean flagged = false;
|
|
|
|
for (int i = 0, len = flags.length; i < len; i++) {
|
|
|
|
try {
|
|
|
|
switch (Flag.valueOf(flags[i])) {
|
|
|
|
case SEEN: {
|
|
|
|
read = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FLAGGED: {
|
|
|
|
flagged = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
// We don't care about the other flags
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) { /* ignore */ }
|
|
|
|
}
|
|
|
|
|
|
|
|
menu.setHeaderTitle(subject);
|
2012-09-24 12:11:34 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (read) {
|
2012-10-02 13:59:08 -04:00
|
|
|
menu.findItem(R.id.mark_as_read).setVisible(false);
|
|
|
|
} else {
|
|
|
|
menu.findItem(R.id.mark_as_unread).setVisible(false);
|
2012-09-24 12:11:34 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (flagged) {
|
2012-10-02 13:59:08 -04:00
|
|
|
menu.findItem(R.id.flag).setVisible(false);
|
|
|
|
} else {
|
|
|
|
menu.findItem(R.id.unflag).setVisible(false);
|
2012-09-24 12:11:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!mController.isCopyCapable(account)) {
|
|
|
|
menu.findItem(R.id.copy).setVisible(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mController.isMoveCapable(account)) {
|
|
|
|
menu.findItem(R.id.move).setVisible(false);
|
|
|
|
menu.findItem(R.id.archive).setVisible(false);
|
|
|
|
menu.findItem(R.id.spam).setVisible(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!account.hasArchiveFolder()) {
|
|
|
|
menu.findItem(R.id.archive).setVisible(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!account.hasSpamFolder()) {
|
|
|
|
menu.findItem(R.id.spam).setVisible(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-09-20 16:50:56 -04:00
|
|
|
public void onSwipeRightToLeft(final MotionEvent e1, final MotionEvent e2) {
|
|
|
|
// Handle right-to-left as an un-select
|
|
|
|
handleSwipe(e1, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onSwipeLeftToRight(final MotionEvent e1, final MotionEvent e2) {
|
|
|
|
// Handle left-to-right as a select.
|
|
|
|
handleSwipe(e1, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle a select or unselect swipe event
|
|
|
|
* @param downMotion Event that started the swipe
|
|
|
|
* @param selected true if this was an attempt to select (i.e. left to right).
|
|
|
|
*/
|
|
|
|
private void handleSwipe(final MotionEvent downMotion, final boolean selected) {
|
|
|
|
int[] listPosition = new int[2];
|
|
|
|
mListView.getLocationOnScreen(listPosition);
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
int listX = (int) downMotion.getRawX() - listPosition[0];
|
|
|
|
int listY = (int) downMotion.getRawY() - listPosition[1];
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
int listViewPosition = mListView.pointToPosition(listX, listY);
|
|
|
|
|
|
|
|
toggleMessageSelect(listViewPosition);
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private int listViewToAdapterPosition(int position) {
|
|
|
|
if (position > 0 && position <= mAdapter.getCount()) {
|
|
|
|
return position - 1;
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
return AdapterView.INVALID_POSITION;
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
class MessageListActivityListener extends ActivityListener {
|
|
|
|
@Override
|
|
|
|
public void remoteSearchFailed(Account acct, String folder, final String err) {
|
|
|
|
//TODO: Better error handling
|
|
|
|
mHandler.post(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
Toast.makeText(getActivity(), err, Toast.LENGTH_LONG).show();
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
});
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void remoteSearchStarted(Account acct, String folder) {
|
|
|
|
mHandler.progress(true);
|
|
|
|
mHandler.updateFooter(mContext.getString(R.string.remote_search_sending_query), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void remoteSearchFinished(Account acct, String folder, int numResults, List<Message> extraResults) {
|
|
|
|
mHandler.progress(false);
|
|
|
|
if (extraResults != null && extraResults.size() > 0) {
|
|
|
|
mHandler.updateFooter(String.format(mContext.getString(R.string.load_more_messages_fmt), acct.getRemoteSearchNumResults()), false);
|
|
|
|
} else {
|
|
|
|
mHandler.updateFooter("", false);
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
mFragmentListener.setMessageListProgress(Window.PROGRESS_END);
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void remoteSearchServerQueryComplete(Account account, String folderName, int numResults) {
|
|
|
|
mHandler.progress(true);
|
|
|
|
if (account != null && account.getRemoteSearchNumResults() != 0 && numResults > account.getRemoteSearchNumResults()) {
|
|
|
|
mHandler.updateFooter(mContext.getString(R.string.remote_search_downloading_limited, account.getRemoteSearchNumResults(), numResults), true);
|
|
|
|
} else {
|
|
|
|
mHandler.updateFooter(mContext.getString(R.string.remote_search_downloading, numResults), true);
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
mFragmentListener.setMessageListProgress(Window.PROGRESS_START);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void informUserOfStatus() {
|
|
|
|
mHandler.refreshTitle();
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void synchronizeMailboxStarted(Account account, String folder) {
|
|
|
|
if (updateForMe(account, folder)) {
|
2012-03-05 15:04:34 -05:00
|
|
|
mHandler.progress(true);
|
2012-10-16 09:46:40 -04:00
|
|
|
mHandler.folderLoading(folder, true);
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
super.synchronizeMailboxStarted(account, folder);
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void synchronizeMailboxFinished(Account account, String folder,
|
|
|
|
int totalMessagesInMailbox, int numNewMessages) {
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (updateForMe(account, folder)) {
|
2012-03-05 15:04:34 -05:00
|
|
|
mHandler.progress(false);
|
2012-10-16 09:46:40 -04:00
|
|
|
mHandler.folderLoading(folder, false);
|
|
|
|
mHandler.sortMessages();
|
2012-03-05 15:04:34 -05:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
super.synchronizeMailboxFinished(account, folder, totalMessagesInMailbox, numNewMessages);
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void synchronizeMailboxFailed(Account account, String folder, String message) {
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (updateForMe(account, folder)) {
|
|
|
|
mHandler.progress(false);
|
|
|
|
mHandler.folderLoading(folder, false);
|
|
|
|
mHandler.sortMessages();
|
2010-07-13 19:59:14 -04:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
super.synchronizeMailboxFailed(account, folder, message);
|
|
|
|
}
|
2010-07-13 19:59:14 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void searchStats(AccountStats stats) {
|
|
|
|
mUnreadMessageCount = stats.unreadMessageCount;
|
|
|
|
super.searchStats(stats);
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void folderStatusChanged(Account account, String folder, int unreadMessageCount) {
|
|
|
|
if (updateForMe(account, folder)) {
|
|
|
|
mUnreadMessageCount = unreadMessageCount;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
super.folderStatusChanged(account, folder, unreadMessageCount);
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private boolean updateForMe(Account account, String folder) {
|
2012-10-16 14:57:47 -04:00
|
|
|
//FIXME
|
2012-10-16 09:46:40 -04:00
|
|
|
return ((account.equals(mAccount) && folder.equals(mFolderName)));
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2012-09-04 19:31:09 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
class MessageListAdapter extends CursorAdapter {
|
2012-09-04 19:31:09 -04:00
|
|
|
|
2010-07-13 17:49:28 -04:00
|
|
|
private Drawable mAttachmentIcon;
|
2012-08-20 22:09:34 -04:00
|
|
|
private Drawable mForwardedIcon;
|
2010-07-13 17:49:28 -04:00
|
|
|
private Drawable mAnsweredIcon;
|
2012-08-20 22:09:34 -04:00
|
|
|
private Drawable mForwardedAnsweredIcon;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
MessageListAdapter() {
|
2012-10-16 09:46:40 -04:00
|
|
|
super(getActivity(), null, 0);
|
2011-01-17 12:25:00 -05:00
|
|
|
mAttachmentIcon = getResources().getDrawable(R.drawable.ic_email_attachment_small);
|
|
|
|
mAnsweredIcon = getResources().getDrawable(R.drawable.ic_email_answered_small);
|
2012-08-20 22:09:34 -04:00
|
|
|
mForwardedIcon = getResources().getDrawable(R.drawable.ic_email_forwarded_small);
|
2012-08-30 11:47:58 -04:00
|
|
|
mForwardedAnsweredIcon = getResources().getDrawable(R.drawable.ic_email_forwarded_answered_small);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
/**
|
|
|
|
* Set the selection state for all messages at once.
|
|
|
|
* @param selected Selection state to set.
|
|
|
|
*/
|
|
|
|
public void setSelectionForAllMesages(final boolean selected) {
|
|
|
|
//TODO: implement
|
|
|
|
|
|
|
|
//notifyDataSetChanged();
|
2010-10-08 01:34:33 -04:00
|
|
|
}
|
2012-09-04 19:31:09 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
public void sortMessages() {
|
|
|
|
//TODO: implement
|
2012-09-04 21:02:22 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
//notifyDataSetChanged();
|
2012-09-04 21:02:22 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private String recipientSigil(boolean toMe, boolean ccMe) {
|
|
|
|
if (toMe) {
|
|
|
|
return getString(R.string.messagelist_sent_to_me_sigil);
|
|
|
|
} else if (ccMe) {
|
|
|
|
return getString(R.string.messagelist_sent_cc_me_sigil);
|
2012-09-04 21:02:22 -04:00
|
|
|
} else {
|
2012-10-16 09:46:40 -04:00
|
|
|
return "";
|
2012-09-04 21:02:22 -04:00
|
|
|
}
|
2010-10-08 01:34:33 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
|
|
|
View view = mInflater.inflate(R.layout.message_list_item, parent, false);
|
|
|
|
view.setId(R.layout.message_list_item);
|
|
|
|
|
|
|
|
MessageViewHolder holder = new MessageViewHolder();
|
|
|
|
holder.date = (TextView) view.findViewById(R.id.date);
|
|
|
|
holder.chip = view.findViewById(R.id.chip);
|
|
|
|
holder.preview = (TextView) view.findViewById(R.id.preview);
|
|
|
|
|
|
|
|
if (mSenderAboveSubject) {
|
|
|
|
holder.from = (TextView) view.findViewById(R.id.subject);
|
|
|
|
holder.from.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageListSender());
|
|
|
|
} else {
|
|
|
|
holder.subject = (TextView) view.findViewById(R.id.subject);
|
|
|
|
holder.subject.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageListSubject());
|
2012-09-04 18:51:04 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
holder.date.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageListDate());
|
2012-09-04 18:51:04 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
holder.preview.setLines(mPreviewLines);
|
|
|
|
holder.preview.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageListPreview());
|
|
|
|
holder.threadCount = (TextView) view.findViewById(R.id.thread_count);
|
2012-09-04 18:51:04 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
view.setTag(holder);
|
2012-09-09 17:09:35 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
return view;
|
2012-09-09 17:09:35 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
@Override
|
|
|
|
public void bindView(View view, Context context, Cursor cursor) {
|
2012-10-17 23:15:40 -04:00
|
|
|
Account account = getAccountFromCursor(cursor);
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
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 = mMessageHelper.toMe(account, fromAddrs);
|
|
|
|
boolean toMe = mMessageHelper.toMe(account, toAddrs);
|
|
|
|
boolean ccMe = mMessageHelper.toMe(account, ccAddrs);
|
|
|
|
|
|
|
|
CharSequence displayName = mMessageHelper.getDisplayName(account, fromAddrs, toAddrs);
|
|
|
|
|
|
|
|
Date sentDate = new Date(cursor.getLong(DATE_COLUMN));
|
|
|
|
String displayDate = mMessageHelper.formatDate(sentDate);
|
|
|
|
|
|
|
|
String preview = cursor.getString(PREVIEW_COLUMN);
|
|
|
|
if (preview == null) {
|
|
|
|
preview = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
String subject = cursor.getString(SUBJECT_COLUMN);
|
|
|
|
if (StringUtils.isNullOrEmpty(subject)) {
|
|
|
|
subject = getString(R.string.general_no_subject);
|
|
|
|
}
|
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
int threadCount = (mThreadedList) ? cursor.getInt(THREAD_COUNT_COLUMN) : 0;
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
String flagList = cursor.getString(FLAGS_COLUMN);
|
|
|
|
String[] flags = flagList.split(",");
|
|
|
|
boolean read = false;
|
|
|
|
boolean flagged = false;
|
|
|
|
boolean answered = false;
|
|
|
|
boolean forwarded = false;
|
|
|
|
for (int i = 0, len = flags.length; i < len; i++) {
|
|
|
|
try {
|
|
|
|
switch (Flag.valueOf(flags[i])) {
|
|
|
|
case SEEN: {
|
|
|
|
read = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FLAGGED: {
|
|
|
|
flagged = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ANSWERED: {
|
|
|
|
answered = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FORWARDED: {
|
|
|
|
forwarded = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
// We don't care about the other flags
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) { /* ignore */ }
|
2012-09-04 18:51:04 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
boolean hasAttachments = (cursor.getInt(ATTACHMENT_COUNT_COLUMN) > 0);
|
2012-09-04 18:51:04 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
MessageViewHolder holder = (MessageViewHolder) view.getTag();
|
2012-09-04 18:51:04 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
int maybeBoldTypeface = (read) ? Typeface.NORMAL : Typeface.BOLD;
|
2012-09-04 18:51:04 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
int adapterPosition = cursor.getPosition();
|
|
|
|
boolean selected = mSelected.get(adapterPosition, false);
|
2012-09-21 16:51:37 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (selected) {
|
|
|
|
holder.chip.setBackgroundDrawable(account.getCheckmarkChip().drawable());
|
|
|
|
} else {
|
|
|
|
holder.chip.setBackgroundDrawable(account.generateColorChip(read, toMe, ccMe,
|
|
|
|
fromMe, flagged).drawable());
|
2012-09-21 16:51:37 -04:00
|
|
|
}
|
2012-10-02 16:56:06 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
// Background indicator
|
2012-10-02 16:56:06 -04:00
|
|
|
if (K9.useBackgroundAsUnreadIndicator()) {
|
2012-10-16 09:46:40 -04:00
|
|
|
int res = (read) ? R.attr.messageListReadItemBackgroundColor :
|
2012-10-02 16:56:06 -04:00
|
|
|
R.attr.messageListUnreadItemBackgroundColor;
|
|
|
|
|
|
|
|
TypedValue outValue = new TypedValue();
|
2012-10-05 21:41:32 -04:00
|
|
|
getActivity().getTheme().resolveAttribute(res, outValue, true);
|
2012-10-02 16:56:06 -04:00
|
|
|
view.setBackgroundColor(outValue.data);
|
|
|
|
}
|
2010-08-03 03:46:31 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
// Thread count
|
2012-10-22 21:01:50 -04:00
|
|
|
if (threadCount > 1) {
|
2012-10-08 16:51:29 -04:00
|
|
|
holder.threadCount.setText(Integer.toString(threadCount));
|
|
|
|
holder.threadCount.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
holder.threadCount.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
CharSequence beforePreviewText = (mSenderAboveSubject) ? subject : displayName;
|
2012-10-08 16:51:29 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
String sigil = recipientSigil(toMe, ccMe);
|
2012-09-24 19:11:21 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
holder.preview.setText(
|
|
|
|
new SpannableStringBuilder(sigil)
|
|
|
|
.append(beforePreviewText)
|
|
|
|
.append(" ")
|
|
|
|
.append(preview), TextView.BufferType.SPANNABLE);
|
2010-10-21 16:48:45 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
Spannable str = (Spannable)holder.preview.getText();
|
2012-09-24 19:11:21 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
// Create a span section for the sender, and assign the correct font size and weight
|
|
|
|
int fontSize = (mSenderAboveSubject) ?
|
|
|
|
mFontSizes.getMessageListSubject():
|
|
|
|
mFontSizes.getMessageListSender();
|
2010-08-03 03:46:31 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
AbsoluteSizeSpan span = new AbsoluteSizeSpan(fontSize, true);
|
|
|
|
str.setSpan(span, 0, beforePreviewText.length() + 1,
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
2011-04-26 10:49:25 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
//TODO: make this part of the theme
|
|
|
|
int color = (K9.getK9Theme() == K9.THEME_LIGHT) ?
|
|
|
|
Color.rgb(105, 105, 105) :
|
|
|
|
Color.rgb(160, 160, 160);
|
2012-09-10 09:50:07 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
// Set span (color) for preview message
|
|
|
|
str.setSpan(new ForegroundColorSpan(color), beforePreviewText.length() + 1,
|
|
|
|
str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
2012-09-24 19:11:21 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
Drawable statusHolder = null;
|
|
|
|
if (forwarded && answered) {
|
|
|
|
statusHolder = mForwardedAnsweredIcon;
|
|
|
|
} else if (answered) {
|
|
|
|
statusHolder = mAnsweredIcon;
|
|
|
|
} else if (forwarded) {
|
|
|
|
statusHolder = mForwardedIcon;
|
|
|
|
}
|
2012-09-24 19:11:21 -04:00
|
|
|
|
|
|
|
if (holder.from != null ) {
|
|
|
|
holder.from.setTypeface(null, maybeBoldTypeface);
|
|
|
|
if (mSenderAboveSubject) {
|
|
|
|
holder.from.setCompoundDrawablesWithIntrinsicBounds(
|
2012-10-16 09:46:40 -04:00
|
|
|
statusHolder, // left
|
2012-09-24 19:11:21 -04:00
|
|
|
null, // top
|
2012-10-16 09:46:40 -04:00
|
|
|
hasAttachments ? mAttachmentIcon : null, // right
|
2012-09-24 19:11:21 -04:00
|
|
|
null); // bottom
|
2010-10-21 16:48:45 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
holder.from.setText(displayName);
|
2012-09-24 19:11:21 -04:00
|
|
|
} else {
|
2012-10-16 09:46:40 -04:00
|
|
|
holder.from.setText(new SpannableStringBuilder(sigil).append(displayName));
|
2012-09-24 19:11:21 -04:00
|
|
|
}
|
2010-08-03 03:46:31 -04:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:11:21 -04:00
|
|
|
if (holder.subject != null ) {
|
|
|
|
if (!mSenderAboveSubject) {
|
|
|
|
holder.subject.setCompoundDrawablesWithIntrinsicBounds(
|
2012-10-16 09:46:40 -04:00
|
|
|
statusHolder, // left
|
2012-09-24 19:11:21 -04:00
|
|
|
null, // top
|
2012-10-16 09:46:40 -04:00
|
|
|
hasAttachments ? mAttachmentIcon : null, // right
|
2012-09-24 19:11:21 -04:00
|
|
|
null); // bottom
|
|
|
|
}
|
2012-08-20 22:09:34 -04:00
|
|
|
|
2012-09-24 19:11:21 -04:00
|
|
|
holder.subject.setTypeface(null, maybeBoldTypeface);
|
|
|
|
holder.subject.setText(subject);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
holder.date.setText(displayDate);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
class MessageViewHolder {
|
2010-07-13 17:49:28 -04:00
|
|
|
public TextView subject;
|
|
|
|
public TextView preview;
|
|
|
|
public TextView from;
|
|
|
|
public TextView time;
|
|
|
|
public TextView date;
|
|
|
|
public View chip;
|
2012-10-08 16:51:29 -04:00
|
|
|
public TextView threadCount;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-02-19 22:50:50 -05:00
|
|
|
|
|
|
|
private View getFooterView(ViewGroup parent) {
|
|
|
|
if (mFooterView == null) {
|
|
|
|
mFooterView = mInflater.inflate(R.layout.message_list_item_footer, parent, false);
|
|
|
|
mFooterView.setId(R.layout.message_list_item_footer);
|
|
|
|
FooterViewHolder holder = new FooterViewHolder();
|
|
|
|
holder.progress = (ProgressBar) mFooterView.findViewById(R.id.message_list_progress);
|
|
|
|
holder.progress.setIndeterminate(true);
|
|
|
|
holder.main = (TextView) mFooterView.findViewById(R.id.main_text);
|
|
|
|
mFooterView.setTag(holder);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mFooterView;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateFooterView() {
|
|
|
|
if (mCurrentFolder != null && mAccount != null) {
|
|
|
|
if (mCurrentFolder.loading) {
|
2012-03-05 15:04:34 -05:00
|
|
|
final boolean showProgress = true;
|
2012-10-09 22:30:19 -04:00
|
|
|
updateFooter(mContext.getString(R.string.status_loading_more), showProgress);
|
2011-02-19 22:50:50 -05:00
|
|
|
} else {
|
2012-03-05 15:04:34 -05:00
|
|
|
String message;
|
2011-02-19 22:50:50 -05:00
|
|
|
if (!mCurrentFolder.lastCheckFailed) {
|
|
|
|
if (mAccount.getDisplayCount() == 0) {
|
2012-10-09 22:30:19 -04:00
|
|
|
message = mContext.getString(R.string.message_list_load_more_messages_action);
|
2011-02-19 22:50:50 -05:00
|
|
|
} else {
|
2012-10-09 22:30:19 -04:00
|
|
|
message = String.format(mContext.getString(R.string.load_more_messages_fmt), mAccount.getDisplayCount());
|
2011-02-19 22:50:50 -05:00
|
|
|
}
|
|
|
|
} else {
|
2012-10-09 22:30:19 -04:00
|
|
|
message = mContext.getString(R.string.status_loading_more_failed);
|
2011-02-19 22:50:50 -05:00
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
final boolean showProgress = false;
|
|
|
|
updateFooter(message, showProgress);
|
2011-02-19 22:50:50 -05:00
|
|
|
}
|
|
|
|
} else {
|
2012-03-05 15:04:34 -05:00
|
|
|
final boolean showProgress = false;
|
|
|
|
updateFooter(null, showProgress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateFooter(final String text, final boolean progressVisible) {
|
|
|
|
FooterViewHolder holder = (FooterViewHolder) mFooterView.getTag();
|
|
|
|
|
|
|
|
holder.progress.setVisibility(progressVisible ? ProgressBar.VISIBLE : ProgressBar.INVISIBLE);
|
|
|
|
if (text != null) {
|
|
|
|
holder.main.setText(text);
|
|
|
|
}
|
|
|
|
if (progressVisible || holder.main.getText().length() > 0) {
|
|
|
|
holder.main.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
holder.main.setVisibility(View.GONE);
|
2011-02-19 22:50:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
static class FooterViewHolder {
|
2010-07-13 17:49:28 -04:00
|
|
|
public ProgressBar progress;
|
|
|
|
public TextView main;
|
|
|
|
}
|
|
|
|
|
2012-09-09 17:09:35 -04:00
|
|
|
/**
|
2012-09-17 22:05:13 -04:00
|
|
|
* Set selection state for all messages.
|
|
|
|
*
|
|
|
|
* @param selected
|
|
|
|
* If {@code true} all messages get selected. Otherwise, all messages get deselected and
|
|
|
|
* action mode is finished.
|
2012-09-09 17:09:35 -04:00
|
|
|
*/
|
2012-09-17 22:05:13 -04:00
|
|
|
private void setSelectionState(boolean selected) {
|
|
|
|
if (selected) {
|
2012-09-09 17:09:35 -04:00
|
|
|
mSelectedCount = mAdapter.getCount();
|
2012-10-16 09:46:40 -04:00
|
|
|
for (int i = 0, end = mSelectedCount; i < end; i++) {
|
|
|
|
mSelected.put(i, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mActionMode == null) {
|
|
|
|
mActionMode = getSherlockActivity().startActionMode(mActionModeCallback);
|
|
|
|
}
|
|
|
|
computeBatchDirection();
|
2012-09-13 00:41:04 -04:00
|
|
|
updateActionModeTitle();
|
2012-09-13 00:27:58 -04:00
|
|
|
computeSelectAllVisibility();
|
2012-09-09 17:09:35 -04:00
|
|
|
} else {
|
2012-10-16 09:46:40 -04:00
|
|
|
mSelected.clear();
|
2012-09-09 17:09:35 -04:00
|
|
|
mSelectedCount = 0;
|
2012-09-17 22:05:13 -04:00
|
|
|
if (mActionMode != null) {
|
|
|
|
mActionMode.finish();
|
2012-10-16 09:46:40 -04:00
|
|
|
mActionMode = null;
|
2012-09-17 22:05:13 -04:00
|
|
|
}
|
2012-07-25 16:20:01 -04:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
mAdapter.notifyDataSetChanged();
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private void toggleMessageSelect(int listViewPosition) {
|
|
|
|
int adapterPosition = listViewToAdapterPosition(listViewPosition);
|
|
|
|
if (adapterPosition == AdapterView.INVALID_POSITION) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean selected = mSelected.get(adapterPosition, false);
|
|
|
|
mSelected.put(adapterPosition, !selected);
|
|
|
|
|
2012-09-11 18:45:16 -04:00
|
|
|
if (mActionMode != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
if (mSelectedCount == 1 && selected) {
|
2012-09-11 18:45:16 -04:00
|
|
|
mActionMode.finish();
|
2012-10-16 09:46:40 -04:00
|
|
|
mActionMode = null;
|
2012-09-11 18:45:16 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2012-10-05 21:41:32 -04:00
|
|
|
mActionMode = getSherlockActivity().startActionMode(mActionModeCallback);
|
2012-09-13 18:34:25 -04:00
|
|
|
}
|
2012-09-11 18:45:16 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
if (selected) {
|
2012-09-13 00:27:58 -04:00
|
|
|
mSelectedCount -= 1;
|
|
|
|
} else {
|
|
|
|
mSelectedCount += 1;
|
|
|
|
}
|
2012-09-13 18:34:25 -04:00
|
|
|
|
|
|
|
computeBatchDirection();
|
2012-09-13 00:41:04 -04:00
|
|
|
updateActionModeTitle();
|
2012-07-20 13:30:23 -04:00
|
|
|
|
2012-09-10 09:50:07 -04:00
|
|
|
// make sure the onPrepareActionMode is called
|
|
|
|
mActionMode.invalidate();
|
2012-09-13 00:27:58 -04:00
|
|
|
|
|
|
|
computeSelectAllVisibility();
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
mAdapter.notifyDataSetChanged();
|
2012-09-13 00:27:58 -04:00
|
|
|
}
|
|
|
|
|
2012-09-13 00:41:04 -04:00
|
|
|
private void updateActionModeTitle() {
|
|
|
|
mActionMode.setTitle(String.format(getString(R.string.actionbar_selected), mSelectedCount));
|
|
|
|
}
|
|
|
|
|
2012-09-13 00:27:58 -04:00
|
|
|
private void computeSelectAllVisibility() {
|
|
|
|
mActionModeCallback.showSelectAll(mSelectedCount != mAdapter.getCount());
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-09-13 18:34:25 -04:00
|
|
|
private void computeBatchDirection() {
|
|
|
|
boolean isBatchFlag = false;
|
|
|
|
boolean isBatchRead = false;
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
/*
|
2012-09-13 18:34:25 -04:00
|
|
|
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
|
|
|
if (holder.selected) {
|
|
|
|
if (!holder.flagged) {
|
|
|
|
isBatchFlag = true;
|
|
|
|
}
|
|
|
|
if (!holder.read) {
|
|
|
|
isBatchRead = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isBatchFlag && isBatchRead) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
*/
|
|
|
|
//TODO: implement
|
2012-09-13 18:34:25 -04:00
|
|
|
|
|
|
|
mActionModeCallback.showMarkAsRead(isBatchRead);
|
|
|
|
mActionModeCallback.showFlag(isBatchFlag);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private void setFlag(Message message, final Flag flag, final boolean newState) {
|
|
|
|
setFlag(new Message[] { message }, flag, newState);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setFlag(Message[] messages, final Flag flag, final boolean newState) {
|
|
|
|
if (messages.length == 0) {
|
2011-06-04 16:57:03 -04:00
|
|
|
return;
|
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
mController.setFlag(messages, flag, newState);
|
2012-10-05 21:41:32 -04:00
|
|
|
|
|
|
|
computeBatchDirection();
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onMove(Message message) {
|
|
|
|
onMove(new Message[] { message });
|
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* Display the message move activity.
|
2011-06-13 19:49:06 -04:00
|
|
|
*
|
2011-06-04 16:57:03 -04:00
|
|
|
* @param holders
|
|
|
|
* Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onMove(Message[] messages) {
|
|
|
|
if (!checkCopyOrMovePossible(messages, FolderOperation.MOVE)) {
|
2011-06-04 16:57:03 -04:00
|
|
|
return;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
final Folder folder = messages.length == 1 ? messages[0].getFolder() : mCurrentFolder.folder;
|
|
|
|
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, folder, messages);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onCopy(Message message) {
|
|
|
|
onCopy(new Message[] { message });
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* Display the message copy activity.
|
2011-06-13 19:49:06 -04:00
|
|
|
*
|
2011-06-04 16:57:03 -04:00
|
|
|
* @param holders
|
|
|
|
* Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onCopy(Message[] messages) {
|
|
|
|
if (!checkCopyOrMovePossible(messages, FolderOperation.COPY)) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
final Folder folder = messages.length == 1 ? messages[0].getFolder() : mCurrentFolder.folder;
|
|
|
|
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, folder, messages);
|
2011-06-04 16:57:03 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* Helper method to manage the invocation of
|
|
|
|
* {@link #startActivityForResult(Intent, int)} for a folder operation
|
|
|
|
* ({@link ChooseFolder} activity), while saving a list of associated
|
|
|
|
* messages.
|
|
|
|
*
|
|
|
|
* @param requestCode
|
|
|
|
* If >= 0, this code will be returned in onActivityResult() when
|
|
|
|
* the activity exits.
|
|
|
|
* @param folder
|
|
|
|
* Never {@code null}.
|
|
|
|
* @param holders
|
|
|
|
* Messages to be affected by the folder operation. Never
|
|
|
|
* {@code null}.
|
|
|
|
* @see #startActivityForResult(Intent, int)
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void displayFolderChoice(final int requestCode, final Folder folder, final Message[] messages) {
|
2012-10-05 21:41:32 -04:00
|
|
|
final Intent intent = new Intent(getActivity(), ChooseFolder.class);
|
2011-06-04 16:57:03 -04:00
|
|
|
intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, folder.getAccount().getUuid());
|
2010-07-13 17:49:28 -04:00
|
|
|
intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, folder.getName());
|
|
|
|
intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, folder.getAccount().getLastSelectedFolderName());
|
2011-06-04 16:57:03 -04:00
|
|
|
// remember the selected messages for #onActivityResult
|
2012-10-16 09:46:40 -04:00
|
|
|
mActiveMessages = messages;
|
2011-06-04 16:57:03 -04:00
|
|
|
startActivityForResult(intent, requestCode);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onArchive(final Message message) {
|
|
|
|
onArchive(new Message[] { message });
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onArchive(final Message[] messages) {
|
|
|
|
final String folderName = messages[0].getFolder().getAccount().getArchiveFolderName();
|
2011-06-04 16:57:03 -04:00
|
|
|
if (K9.FOLDER_NONE.equalsIgnoreCase(folderName)) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
|
|
|
}
|
2011-06-04 16:57:03 -04:00
|
|
|
// TODO one should separate messages by account and call move afterwards
|
|
|
|
// (because each account might have a specific Archive folder name)
|
2012-10-16 09:46:40 -04:00
|
|
|
move(messages, folderName);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onSpam(Message message) {
|
|
|
|
onSpam(new Message[] { message });
|
2011-06-04 16:57:03 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* @param holders
|
|
|
|
* Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onSpam(Message[] messages) {
|
2011-06-04 16:57:03 -04:00
|
|
|
if (K9.confirmSpam()) {
|
|
|
|
// remember the message selection for #onCreateDialog(int)
|
2012-10-16 09:46:40 -04:00
|
|
|
mActiveMessages = messages;
|
2011-06-04 16:57:03 -04:00
|
|
|
showDialog(R.id.dialog_confirm_spam);
|
|
|
|
} else {
|
2012-10-16 09:46:40 -04:00
|
|
|
onSpamConfirmed(messages);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* @param holders
|
|
|
|
* Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void onSpamConfirmed(Message[] messages) {
|
|
|
|
final String folderName = messages[0].getFolder().getAccount().getSpamFolderName();
|
2011-02-06 17:09:48 -05:00
|
|
|
if (K9.FOLDER_NONE.equalsIgnoreCase(folderName)) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
|
|
|
}
|
2011-06-04 16:57:03 -04:00
|
|
|
// TODO one should separate messages by account and call move afterwards
|
|
|
|
// (because each account might have a specific Spam folder name)
|
2012-10-16 09:46:40 -04:00
|
|
|
move(messages, folderName);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
private static enum FolderOperation {
|
|
|
|
COPY, MOVE
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* Display an Toast message if any message isn't synchronized
|
2011-06-13 19:49:06 -04:00
|
|
|
*
|
2011-06-04 16:57:03 -04:00
|
|
|
* @param holders
|
|
|
|
* Never <code>null</code>.
|
2011-06-04 17:17:47 -04:00
|
|
|
* @param operation
|
|
|
|
* Never {@code null}.
|
2011-06-13 19:49:06 -04:00
|
|
|
*
|
2011-06-04 16:57:03 -04:00
|
|
|
* @return <code>true</code> if operation is possible
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private boolean checkCopyOrMovePossible(final Message[] messages, final FolderOperation operation) {
|
|
|
|
if (messages.length == 0) {
|
2011-06-04 16:57:03 -04:00
|
|
|
return false;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
boolean first = true;
|
2012-10-16 09:46:40 -04:00
|
|
|
for (final Message message : messages) {
|
2011-06-04 16:57:03 -04:00
|
|
|
if (first) {
|
|
|
|
first = false;
|
|
|
|
// account check
|
|
|
|
final Account account = message.getFolder().getAccount();
|
2012-10-16 09:46:40 -04:00
|
|
|
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(account)) ||
|
|
|
|
(operation == FolderOperation.COPY && !mController.isCopyCapable(account))) {
|
2011-06-04 16:57:03 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// message check
|
2012-10-16 09:46:40 -04:00
|
|
|
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(message)) ||
|
|
|
|
(operation == FolderOperation.COPY && !mController.isCopyCapable(message))) {
|
2012-10-05 21:41:32 -04:00
|
|
|
final Toast toast = Toast.makeText(getActivity(), R.string.move_copy_cannot_copy_unsynced_message,
|
2011-06-13 19:49:06 -04:00
|
|
|
Toast.LENGTH_LONG);
|
2011-06-04 16:57:03 -04:00
|
|
|
toast.show();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* Copy the specified messages to the specified folder.
|
|
|
|
*
|
|
|
|
* @param holders Never {@code null}.
|
|
|
|
* @param destination Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void copy(Message[] messages, final String destination) {
|
|
|
|
copyOrMove(messages, destination, FolderOperation.COPY);
|
2011-06-04 16:57:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Move the specified messages to the specified folder.
|
|
|
|
*
|
|
|
|
* @param holders Never {@code null}.
|
|
|
|
* @param destination Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void move(Message[] messages, final String destination) {
|
|
|
|
copyOrMove(messages, destination, FolderOperation.MOVE);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
/**
|
|
|
|
* The underlying implementation for {@link #copy(List, String)} and
|
|
|
|
* {@link #move(List, String)}. This method was added mainly because those 2
|
|
|
|
* methods share common behavior.
|
2011-06-13 19:49:06 -04:00
|
|
|
*
|
2012-09-04 19:02:05 -04:00
|
|
|
* Note: Must be called from the UI thread!
|
|
|
|
*
|
2011-06-04 16:57:03 -04:00
|
|
|
* @param holders
|
|
|
|
* Never {@code null}.
|
|
|
|
* @param destination
|
|
|
|
* Never {@code null}.
|
|
|
|
* @param operation
|
|
|
|
* Never {@code null}.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
private void copyOrMove(Message[] messages, final String destination, final FolderOperation operation) {
|
2011-06-04 16:57:03 -04:00
|
|
|
if (K9.FOLDER_NONE.equalsIgnoreCase(destination)) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-04 16:57:03 -04:00
|
|
|
boolean first = true;
|
|
|
|
Account account = null;
|
|
|
|
String folderName = null;
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
List<Message> outMessages = new ArrayList<Message>();
|
2011-06-04 16:57:03 -04:00
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
for (Message message : messages) {
|
2011-06-04 16:57:03 -04:00
|
|
|
if (first) {
|
|
|
|
first = false;
|
|
|
|
folderName = message.getFolder().getName();
|
|
|
|
account = message.getFolder().getAccount();
|
|
|
|
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(account)) || (operation == FolderOperation.COPY && !mController.isCopyCapable(account))) {
|
|
|
|
// account is not copy/move capable
|
|
|
|
return;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2011-06-04 16:57:03 -04:00
|
|
|
} else if (!account.equals(message.getFolder().getAccount())
|
2011-06-13 19:49:06 -04:00
|
|
|
|| !folderName.equals(message.getFolder().getName())) {
|
2011-06-04 16:57:03 -04:00
|
|
|
// make sure all messages come from the same account/folder?
|
|
|
|
return;
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2011-06-04 16:57:03 -04:00
|
|
|
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(message)) || (operation == FolderOperation.COPY && !mController.isCopyCapable(message))) {
|
2012-10-05 21:41:32 -04:00
|
|
|
final Toast toast = Toast.makeText(getActivity(), R.string.move_copy_cannot_copy_unsynced_message,
|
2011-06-13 19:49:06 -04:00
|
|
|
Toast.LENGTH_LONG);
|
2011-06-04 16:57:03 -04:00
|
|
|
toast.show();
|
|
|
|
|
|
|
|
// XXX return meaningful error value?
|
|
|
|
|
|
|
|
// message isn't synchronized
|
|
|
|
return;
|
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
outMessages.add(message);
|
2011-06-04 16:57:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (operation == FolderOperation.MOVE) {
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.moveMessages(account, folderName, outMessages.toArray(new Message[outMessages.size()]), destination,
|
2011-06-13 19:49:06 -04:00
|
|
|
null);
|
2011-06-04 16:57:03 -04:00
|
|
|
} else {
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.copyMessages(account, folderName, outMessages.toArray(new Message[outMessages.size()]), destination,
|
2011-06-13 19:49:06 -04:00
|
|
|
null);
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
}
|
2010-11-13 16:40:56 -05:00
|
|
|
|
2012-05-15 02:09:28 -04:00
|
|
|
/**
|
|
|
|
* Return the currently "open" account if available.
|
|
|
|
*
|
|
|
|
* @param prefs
|
|
|
|
* A {@link Preferences} instance that might be used to retrieve the current
|
|
|
|
* {@link Account}.
|
|
|
|
*
|
|
|
|
* @return The {@code Account} all displayed messages belong to.
|
|
|
|
*/
|
2012-10-16 14:57:47 -04:00
|
|
|
//TODO: remove
|
2012-10-13 15:07:28 -04:00
|
|
|
/*private Account getCurrentAccount(Preferences prefs) {
|
2012-05-15 02:09:28 -04:00
|
|
|
Account account = null;
|
|
|
|
if (mQueryString != null && !mIntegrate && mAccountUuids != null &&
|
|
|
|
mAccountUuids.length == 1) {
|
|
|
|
String uuid = mAccountUuids[0];
|
|
|
|
account = prefs.getAccount(uuid);
|
|
|
|
} else if (mAccount != null) {
|
|
|
|
account = mAccount;
|
|
|
|
}
|
|
|
|
|
|
|
|
return account;
|
2012-10-13 15:07:28 -04:00
|
|
|
}*/
|
2012-07-16 09:22:42 -04:00
|
|
|
|
2012-07-19 16:39:30 -04:00
|
|
|
|
2012-09-13 00:27:58 -04:00
|
|
|
class ActionModeCallback implements ActionMode.Callback {
|
|
|
|
private MenuItem mSelectAll;
|
2012-09-13 18:34:25 -04:00
|
|
|
private MenuItem mMarkAsRead;
|
|
|
|
private MenuItem mMarkAsUnread;
|
|
|
|
private MenuItem mFlag;
|
|
|
|
private MenuItem mUnflag;
|
2012-07-19 16:39:30 -04:00
|
|
|
|
2012-09-10 09:50:07 -04:00
|
|
|
@Override
|
|
|
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
2012-09-13 00:27:58 -04:00
|
|
|
mSelectAll = menu.findItem(R.id.select_all);
|
2012-09-13 18:34:25 -04:00
|
|
|
mMarkAsRead = menu.findItem(R.id.mark_as_read);
|
|
|
|
mMarkAsUnread = menu.findItem(R.id.mark_as_unread);
|
|
|
|
mFlag = menu.findItem(R.id.flag);
|
|
|
|
mUnflag = menu.findItem(R.id.unflag);
|
2012-08-21 10:42:45 -04:00
|
|
|
|
2012-10-13 15:07:28 -04:00
|
|
|
// we don't support cross account actions atm
|
|
|
|
if (!mSingleAccountMode) {
|
2012-09-10 09:50:07 -04:00
|
|
|
// show all
|
|
|
|
menu.findItem(R.id.move).setVisible(true);
|
|
|
|
menu.findItem(R.id.archive).setVisible(true);
|
|
|
|
menu.findItem(R.id.spam).setVisible(true);
|
|
|
|
menu.findItem(R.id.copy).setVisible(true);
|
|
|
|
|
|
|
|
// hide uncapable
|
|
|
|
/*
|
|
|
|
* TODO think of a better way then looping over all
|
|
|
|
* messages.
|
|
|
|
*/
|
2012-10-16 09:46:40 -04:00
|
|
|
Message[] messages = getCheckedMessages();
|
2012-09-10 09:50:07 -04:00
|
|
|
Account account;
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
for (Message message : messages) {
|
|
|
|
account = message.getFolder().getAccount();
|
2012-09-10 09:50:07 -04:00
|
|
|
setContextCapabilities(account, menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroyActionMode(ActionMode mode) {
|
|
|
|
mActionMode = null;
|
2012-09-13 00:27:58 -04:00
|
|
|
mSelectAll = null;
|
2012-09-13 18:34:25 -04:00
|
|
|
mMarkAsRead = null;
|
|
|
|
mMarkAsUnread = null;
|
|
|
|
mFlag = null;
|
|
|
|
mUnflag = null;
|
2012-10-16 09:46:40 -04:00
|
|
|
setSelectionState(false);
|
2012-09-10 09:50:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
|
|
|
MenuInflater inflater = mode.getMenuInflater();
|
|
|
|
inflater.inflate(R.menu.message_list_context, menu);
|
|
|
|
|
|
|
|
// check capabilities
|
2012-10-13 15:07:28 -04:00
|
|
|
setContextCapabilities(mAccount, menu);
|
2012-09-10 09:50:07 -04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disables menu options based on if the account supports it or not.
|
|
|
|
* It also checks the controller and for now the 'mode' the messagelist
|
|
|
|
* is operation in ( query or not ).
|
|
|
|
*
|
|
|
|
* @param mAccount Account to check capabilities of.
|
|
|
|
* @param menu Menu to adapt.
|
|
|
|
*/
|
|
|
|
private void setContextCapabilities(Account mAccount, Menu menu) {
|
|
|
|
/*
|
|
|
|
* TODO get rid of this when we finally split the messagelist into
|
|
|
|
* a folder content display and a search result display
|
|
|
|
*/
|
2012-10-13 15:07:28 -04:00
|
|
|
if (!mSingleAccountMode) {
|
2012-09-10 09:50:07 -04:00
|
|
|
menu.findItem(R.id.move).setVisible(false);
|
|
|
|
menu.findItem(R.id.copy).setVisible(false);
|
|
|
|
|
|
|
|
menu.findItem(R.id.archive).setVisible(false);
|
|
|
|
menu.findItem(R.id.spam).setVisible(false);
|
|
|
|
|
2012-10-16 14:57:47 -04:00
|
|
|
} else {
|
|
|
|
// hide unsupported
|
|
|
|
if (!mController.isCopyCapable(mAccount)) {
|
|
|
|
menu.findItem(R.id.copy).setVisible(false);
|
|
|
|
}
|
2012-09-10 09:50:07 -04:00
|
|
|
|
2012-10-16 14:57:47 -04:00
|
|
|
if (!mController.isMoveCapable(mAccount)) {
|
|
|
|
menu.findItem(R.id.move).setVisible(false);
|
|
|
|
menu.findItem(R.id.archive).setVisible(false);
|
|
|
|
menu.findItem(R.id.spam).setVisible(false);
|
|
|
|
}
|
2012-09-10 09:50:07 -04:00
|
|
|
|
2012-10-16 14:57:47 -04:00
|
|
|
if (!mAccount.hasArchiveFolder()) {
|
|
|
|
menu.findItem(R.id.archive).setVisible(false);
|
|
|
|
}
|
2012-09-10 09:50:07 -04:00
|
|
|
|
2012-10-16 14:57:47 -04:00
|
|
|
if (!mAccount.hasSpamFolder()) {
|
|
|
|
menu.findItem(R.id.spam).setVisible(false);
|
|
|
|
}
|
2012-09-10 09:50:07 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-13 00:27:58 -04:00
|
|
|
public void showSelectAll(boolean show) {
|
|
|
|
if (mActionMode != null) {
|
|
|
|
mSelectAll.setVisible(show);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-13 18:34:25 -04:00
|
|
|
public void showMarkAsRead(boolean show) {
|
|
|
|
if (mActionMode != null) {
|
|
|
|
mMarkAsRead.setVisible(show);
|
|
|
|
mMarkAsUnread.setVisible(!show);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void showFlag(boolean show) {
|
|
|
|
if (mActionMode != null) {
|
|
|
|
mFlag.setVisible(show);
|
|
|
|
mUnflag.setVisible(!show);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-10 09:50:07 -04:00
|
|
|
@Override
|
|
|
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message[] messages = getCheckedMessages();
|
2012-09-10 09:50:07 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* In the following we assume that we can't move or copy
|
|
|
|
* mails to the same folder. Also that spam isn't available if we are
|
|
|
|
* in the spam folder,same for archive.
|
|
|
|
*
|
|
|
|
* This is the case currently so safe assumption.
|
|
|
|
*/
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case R.id.delete: {
|
2012-10-16 09:46:40 -04:00
|
|
|
onDelete(messages);
|
|
|
|
|
|
|
|
//FIXME
|
2012-09-10 09:50:07 -04:00
|
|
|
mSelectedCount = 0;
|
|
|
|
break;
|
|
|
|
}
|
2012-09-13 18:34:25 -04:00
|
|
|
case R.id.mark_as_read: {
|
2012-10-16 09:46:40 -04:00
|
|
|
setFlag(messages, Flag.SEEN, true);
|
2012-09-13 18:34:25 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.mark_as_unread: {
|
2012-10-16 09:46:40 -04:00
|
|
|
setFlag(messages, Flag.SEEN, false);
|
2012-09-10 09:50:07 -04:00
|
|
|
break;
|
|
|
|
}
|
2012-09-13 18:34:25 -04:00
|
|
|
case R.id.flag: {
|
2012-10-16 09:46:40 -04:00
|
|
|
setFlag(messages, Flag.FLAGGED, true);
|
2012-09-13 18:34:25 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.unflag: {
|
2012-10-16 09:46:40 -04:00
|
|
|
setFlag(messages, Flag.FLAGGED, false);
|
2012-09-10 09:50:07 -04:00
|
|
|
break;
|
|
|
|
}
|
2012-09-13 00:27:58 -04:00
|
|
|
case R.id.select_all: {
|
2012-10-16 09:46:40 -04:00
|
|
|
selectAll();
|
2012-09-13 00:27:58 -04:00
|
|
|
break;
|
|
|
|
}
|
2012-09-10 09:50:07 -04:00
|
|
|
|
|
|
|
// only if the account supports this
|
|
|
|
case R.id.archive: {
|
2012-10-16 09:46:40 -04:00
|
|
|
onArchive(messages);
|
2012-09-10 09:50:07 -04:00
|
|
|
mSelectedCount = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.spam: {
|
2012-10-16 09:46:40 -04:00
|
|
|
onSpam(messages);
|
2012-09-10 09:50:07 -04:00
|
|
|
mSelectedCount = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.move: {
|
2012-10-16 09:46:40 -04:00
|
|
|
onMove(messages);
|
2012-09-10 09:50:07 -04:00
|
|
|
mSelectedCount = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.copy: {
|
2012-10-16 09:46:40 -04:00
|
|
|
onCopy(messages);
|
2012-09-10 09:50:07 -04:00
|
|
|
mSelectedCount = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mSelectedCount == 0) {
|
|
|
|
mActionMode.finish();
|
|
|
|
}
|
2012-07-20 09:20:32 -04:00
|
|
|
|
2012-09-10 09:50:07 -04:00
|
|
|
return true;
|
|
|
|
}
|
2012-09-13 18:34:25 -04:00
|
|
|
}
|
2012-09-12 20:58:44 -04:00
|
|
|
|
2012-10-05 21:41:32 -04:00
|
|
|
@Override
|
|
|
|
public void doPositiveClick(int dialogId) {
|
|
|
|
switch (dialogId) {
|
|
|
|
case R.id.dialog_confirm_spam: {
|
|
|
|
onSpamConfirmed(mActiveMessages);
|
|
|
|
// No further need for this reference
|
|
|
|
mActiveMessages = null;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void doNegativeClick(int dialogId) {
|
|
|
|
switch (dialogId) {
|
|
|
|
case R.id.dialog_confirm_spam: {
|
|
|
|
// No further need for this reference
|
|
|
|
mActiveMessages = null;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void dialogCancelled(int dialogId) {
|
|
|
|
doNegativeClick(dialogId);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void checkMail() {
|
2012-10-16 09:46:40 -04:00
|
|
|
mController.synchronizeMailbox(mAccount, mFolderName, mListener, null);
|
|
|
|
mController.sendPendingMessages(mAccount, mListener);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* We need to do some special clean up when leaving a remote search result screen. If no remote search is
|
|
|
|
* in progress, this method does nothing special.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onStop() {
|
|
|
|
// If we represent a remote search, then kill that before going back.
|
2012-10-13 15:07:28 -04:00
|
|
|
if (isRemoteSearch() && mRemoteSearchFuture != null) {
|
2012-10-05 21:41:32 -04:00
|
|
|
try {
|
|
|
|
Log.i(K9.LOG_TAG, "Remote search in progress, attempting to abort...");
|
|
|
|
// Canceling the future stops any message fetches in progress.
|
|
|
|
final boolean cancelSuccess = mRemoteSearchFuture.cancel(true); // mayInterruptIfRunning = true
|
|
|
|
if (!cancelSuccess) {
|
|
|
|
Log.e(K9.LOG_TAG, "Could not cancel remote search future.");
|
|
|
|
}
|
|
|
|
// Closing the folder will kill off the connection if we're mid-search.
|
2012-10-13 15:07:28 -04:00
|
|
|
final Account searchAccount = mAccount;
|
|
|
|
final Folder remoteFolder = mCurrentFolder.folder;
|
2012-10-05 21:41:32 -04:00
|
|
|
remoteFolder.close();
|
|
|
|
// Send a remoteSearchFinished() message for good measure.
|
2012-10-16 14:57:47 -04:00
|
|
|
//mAdapter.mListener.remoteSearchFinished(searchAccount, mCurrentFolder.name, 0, null);
|
2012-10-05 21:41:32 -04:00
|
|
|
} catch (Exception e) {
|
|
|
|
// Since the user is going back, log and squash any exceptions.
|
|
|
|
Log.e(K9.LOG_TAG, "Could not abort remote search before going back", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
super.onStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArrayList<MessageReference> getMessageReferences() {
|
|
|
|
ArrayList<MessageReference> messageRefs = new ArrayList<MessageReference>();
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
/*
|
2012-10-05 21:41:32 -04:00
|
|
|
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
|
|
|
MessageReference ref = holder.message.makeMessageReference();
|
|
|
|
messageRefs.add(ref);
|
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
*/
|
|
|
|
//TODO: implement
|
2012-10-05 21:41:32 -04:00
|
|
|
|
|
|
|
return messageRefs;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void selectAll() {
|
|
|
|
setSelectionState(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onMoveUp() {
|
|
|
|
int currentPosition = mListView.getSelectedItemPosition();
|
|
|
|
if (currentPosition == AdapterView.INVALID_POSITION || mListView.isInTouchMode()) {
|
|
|
|
currentPosition = mListView.getFirstVisiblePosition();
|
|
|
|
}
|
|
|
|
if (currentPosition > 0) {
|
|
|
|
mListView.setSelection(currentPosition - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onMoveDown() {
|
|
|
|
int currentPosition = mListView.getSelectedItemPosition();
|
|
|
|
if (currentPosition == AdapterView.INVALID_POSITION || mListView.isInTouchMode()) {
|
|
|
|
currentPosition = mListView.getFirstVisiblePosition();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentPosition < mListView.getCount()) {
|
|
|
|
mListView.setSelection(currentPosition + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface MessageListFragmentListener {
|
|
|
|
void setMessageListProgress(int level);
|
2012-10-08 16:51:29 -04:00
|
|
|
void showThread(Account account, String folderName, long rootId);
|
2012-10-05 21:41:32 -04:00
|
|
|
void remoteSearch(String searchAccount, String searchFolder, String queryString);
|
|
|
|
void showMoreFromSameSender(String senderAddress);
|
|
|
|
void onResendMessage(Message message);
|
|
|
|
void onForward(Message message);
|
|
|
|
void onReply(Message message);
|
|
|
|
void onReplyAll(Message message);
|
|
|
|
void openMessage(MessageReference messageReference);
|
|
|
|
void setMessageListTitle(String title);
|
|
|
|
void setMessageListSubTitle(String subTitle);
|
|
|
|
void setUnreadCount(int unread);
|
|
|
|
void onCompose(Account account);
|
|
|
|
boolean startSearch(Account account, String folderName);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onReverseSort() {
|
|
|
|
changeSort(mSortType);
|
|
|
|
}
|
|
|
|
|
2012-10-16 09:46:40 -04:00
|
|
|
private Message getSelectedMessage() {
|
|
|
|
int listViewPosition = mListView.getSelectedItemPosition();
|
|
|
|
int adapterPosition = listViewToAdapterPosition(listViewPosition);
|
|
|
|
|
|
|
|
return getMessageAtPosition(adapterPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Message getMessageAtPosition(int adapterPosition) {
|
|
|
|
if (adapterPosition == AdapterView.INVALID_POSITION) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor cursor = (Cursor) mAdapter.getItem(adapterPosition);
|
|
|
|
String uid = cursor.getString(UID_COLUMN);
|
|
|
|
|
|
|
|
//TODO: get account and folder from cursor
|
|
|
|
Folder folder = mCurrentFolder.folder;
|
|
|
|
|
|
|
|
try {
|
|
|
|
return folder.getMessage(uid);
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
Log.e(K9.LOG_TAG, "Something went wrong while fetching a message", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Message[] getCheckedMessages() {
|
|
|
|
Message[] messages = new Message[mSelectedCount];
|
|
|
|
int out = 0;
|
|
|
|
for (int position = 0, end = mAdapter.getCount(); position < end; position++) {
|
|
|
|
if (mSelected.get(position, false)) {
|
|
|
|
messages[out++] = getMessageAtPosition(position);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return messages;
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onDelete() {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message message = getSelectedMessage();
|
2012-10-05 21:41:32 -04:00
|
|
|
if (message != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
onDelete(new Message[] { message });
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void toggleMessageSelect() {
|
2012-10-16 09:46:40 -04:00
|
|
|
toggleMessageSelect(mListView.getSelectedItemPosition());
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onToggleFlag() {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message message = getSelectedMessage();
|
2012-10-05 21:41:32 -04:00
|
|
|
if (message != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
setFlag(message, Flag.FLAGGED, !message.isSet(Flag.FLAGGED));
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onMove() {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message message = getSelectedMessage();
|
2012-10-05 21:41:32 -04:00
|
|
|
if (message != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
onMove(message);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onArchive() {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message message = getSelectedMessage();
|
2012-10-05 21:41:32 -04:00
|
|
|
if (message != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
onArchive(message);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onCopy() {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message message = getSelectedMessage();
|
2012-10-05 21:41:32 -04:00
|
|
|
if (message != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
onCopy(message);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onToggleRead() {
|
2012-10-16 09:46:40 -04:00
|
|
|
Message message = getSelectedMessage();
|
2012-10-05 21:41:32 -04:00
|
|
|
if (message != null) {
|
2012-10-16 09:46:40 -04:00
|
|
|
setFlag(message, Flag.SEEN, !message.isSet(Flag.SEEN));
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isSearchQuery() {
|
2012-10-13 15:07:28 -04:00
|
|
|
return (mSearch.getRemoteSearchArguments() != null || !mSingleAccountMode);
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isOutbox() {
|
|
|
|
return (mFolderName != null && mFolderName.equals(mAccount.getOutboxFolderName()));
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isErrorFolder() {
|
|
|
|
return K9.ERROR_FOLDER_NAME.equals(mFolderName);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isRemoteFolder() {
|
|
|
|
if (isSearchQuery() || isOutbox() || isErrorFolder()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mController.isMoveCapable(mAccount)) {
|
|
|
|
// For POP3 accounts only the Inbox is a remote folder.
|
|
|
|
return (mFolderName != null && !mFolderName.equals(mAccount.getInboxFolderName()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isAccountExpungeCapable() {
|
|
|
|
try {
|
|
|
|
return (mAccount != null && mAccount.getRemoteStore().isExpungeCapable());
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onRemoteSearch() {
|
|
|
|
// Remote search is useless without the network.
|
|
|
|
if (mHasConnectivity) {
|
2012-10-13 15:07:28 -04:00
|
|
|
onRemoteSearchRequested();
|
2012-10-05 21:41:32 -04:00
|
|
|
} else {
|
|
|
|
Toast.makeText(getActivity(), getText(R.string.remote_search_unavailable_no_network),
|
|
|
|
Toast.LENGTH_SHORT).show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isRemoteSearch() {
|
|
|
|
return mRemoteSearch;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isRemoteSearchAllowed() {
|
2012-10-13 15:07:28 -04:00
|
|
|
if (!isSearchQuery() || mRemoteSearch || !mSingleFolderMode) {
|
2012-10-05 21:41:32 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean allowRemoteSearch = false;
|
2012-10-13 15:07:28 -04:00
|
|
|
final Account searchAccount = mAccount;
|
2012-10-05 21:41:32 -04:00
|
|
|
if (searchAccount != null) {
|
|
|
|
allowRemoteSearch = searchAccount.allowRemoteSearch();
|
|
|
|
}
|
|
|
|
|
|
|
|
return allowRemoteSearch;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean onSearchRequested() {
|
|
|
|
String folderName = (mCurrentFolder != null) ? mCurrentFolder.name : null;
|
|
|
|
return mFragmentListener.startSearch(mAccount, folderName);
|
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
2012-10-17 23:15:40 -04:00
|
|
|
String accountUuid = mAccountUuids[id];
|
|
|
|
Account account = mPreferences.getAccount(accountUuid);
|
2012-10-16 09:46:40 -04:00
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
Uri uri;
|
|
|
|
String[] projection;
|
|
|
|
if (mThreadedList) {
|
|
|
|
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/messages/threaded");
|
|
|
|
projection = THREADED_PROJECTION;
|
|
|
|
} else {
|
|
|
|
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/messages");
|
|
|
|
projection = PROJECTION;
|
|
|
|
}
|
2012-10-16 09:46:40 -04:00
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
StringBuilder query = new StringBuilder();
|
|
|
|
List<String> queryArgs = new ArrayList<String>();
|
|
|
|
buildQuery(account, mSearch.getConditions(), query, queryArgs);
|
|
|
|
|
|
|
|
String selection = query.toString();
|
|
|
|
String[] selectionArgs = queryArgs.toArray(new String[0]);
|
|
|
|
|
2012-10-22 21:01:50 -04:00
|
|
|
return new CursorLoader(getActivity(), uri, projection, selection, selectionArgs,
|
2012-10-17 23:15:40 -04:00
|
|
|
MessageColumns.DATE + " DESC");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void buildQuery(Account account, ConditionsTreeNode node, StringBuilder query,
|
|
|
|
List<String> selectionArgs) {
|
|
|
|
|
2012-10-21 13:18:57 -04:00
|
|
|
if (node == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
if (node.mLeft == null && node.mRight == null) {
|
|
|
|
SearchCondition condition = node.mCondition;
|
|
|
|
switch (condition.field) {
|
|
|
|
case FOLDER: {
|
|
|
|
String folderName;
|
|
|
|
//TODO: Fix the search condition used by the Unified Inbox
|
|
|
|
if (LocalSearch.GENERIC_INBOX_NAME.equals(condition.value) ||
|
|
|
|
"1".equals(condition.value)) {
|
|
|
|
folderName = account.getInboxFolderName();
|
|
|
|
} else {
|
|
|
|
folderName = condition.value;
|
|
|
|
}
|
|
|
|
long folderId = getFolderId(account, folderName);
|
|
|
|
query.append("folder_id = ?");
|
|
|
|
selectionArgs.add(Long.toString(folderId));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
query.append(condition.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
query.append("(");
|
|
|
|
buildQuery(account, node.mLeft, query, selectionArgs);
|
|
|
|
query.append(") ");
|
|
|
|
query.append(node.mValue.name());
|
|
|
|
query.append(" (");
|
|
|
|
buildQuery(account, node.mRight, query, selectionArgs);
|
|
|
|
query.append(")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private long getFolderId(Account account, String folderName) {
|
2012-10-16 09:46:40 -04:00
|
|
|
long folderId = 0;
|
|
|
|
try {
|
2012-10-17 23:15:40 -04:00
|
|
|
LocalFolder folder = (LocalFolder) getFolder(folderName, account).folder;
|
2012-10-16 09:46:40 -04:00
|
|
|
folder.open(OpenMode.READ_ONLY);
|
|
|
|
folderId = folder.getId();
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
//FIXME
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
|
2012-10-17 23:15:40 -04:00
|
|
|
return folderId;
|
2012-10-16 09:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
2012-10-17 23:15:40 -04:00
|
|
|
mCursors.put(loader.getId(), data);
|
|
|
|
|
|
|
|
List<Integer> list = new LinkedList<Integer>(mCursors.keySet());
|
|
|
|
Collections.sort(list);
|
|
|
|
List<Cursor> cursors = new ArrayList<Cursor>(list.size());
|
|
|
|
for (Integer id : list) {
|
|
|
|
cursors.add(mCursors.get(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
MergeCursorWithUniqueId cursor = new MergeCursorWithUniqueId(cursors);
|
|
|
|
|
|
|
|
mSelected = new SparseBooleanArray(cursor.getCount());
|
|
|
|
//TODO: use the (stable) IDs as index and reuse the old mSelected
|
|
|
|
mAdapter.swapCursor(cursor);
|
2012-10-16 09:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLoaderReset(Loader<Cursor> loader) {
|
|
|
|
mSelected = null;
|
|
|
|
mAdapter.swapCursor(null);
|
|
|
|
}
|
2012-10-17 23:15:40 -04:00
|
|
|
|
|
|
|
private Account getAccountFromCursor(Cursor cursor) {
|
|
|
|
String accountUuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
|
|
|
return mPreferences.getAccount(accountUuid);
|
|
|
|
}
|
2012-10-05 21:41:32 -04:00
|
|
|
}
|