mirror of
https://github.com/moparisthebest/k-9
synced 2024-12-26 09:38:52 -05:00
Merge branch 'MessageListAdapter_cleanup'
This commit is contained in:
commit
734e0d1920
@ -17,6 +17,7 @@ import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
@ -348,107 +349,112 @@ public class MessageList
|
||||
}
|
||||
}
|
||||
|
||||
class MessageListHandler {
|
||||
/**
|
||||
* @param messages Never {@code null}.
|
||||
* This class is used to run operations that modify UI elements in the UI thread.
|
||||
*
|
||||
* <p>We are using convenience methods that add a {@link android.os.Message} instance or a
|
||||
* {@link Runnable} to the message queue.</p>
|
||||
*
|
||||
* <p><strong>Note:</strong> If you add a method to this class make sure you don't accidentally
|
||||
* perform the operation in the calling thread.</p>
|
||||
*/
|
||||
public void removeMessages(final List<MessageInfoHolder> messages) {
|
||||
if (messages.isEmpty()) {
|
||||
return;
|
||||
class MessageListHandler extends Handler {
|
||||
private static final int ACTION_REMOVE_MESSAGE = 1;
|
||||
private static final int ACTION_RESET_UNREAD_COUNT = 2;
|
||||
private static final int ACTION_SORT_MESSAGES = 3;
|
||||
private static final int ACTION_FOLDER_LOADING = 4;
|
||||
private static final int ACTION_REFRESH_TITLE = 5;
|
||||
private static final int ACTION_PROGRESS = 6;
|
||||
|
||||
|
||||
public void removeMessage(MessageReference messageReference) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_REMOVE_MESSAGE,
|
||||
messageReference);
|
||||
sendMessage(msg);
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
|
||||
public void sortMessages() {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_SORT_MESSAGES);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void folderLoading(String folder, boolean loading) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_FOLDER_LOADING,
|
||||
(loading) ? 1 : 0, 0, folder);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void refreshTitle() {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_REFRESH_TITLE);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void progress(final boolean progress) {
|
||||
android.os.Message msg = android.os.Message.obtain(this, ACTION_PROGRESS,
|
||||
(progress) ? 1 : 0, 0);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void changeMessageUid(final MessageReference ref, final String newUid) {
|
||||
// Instead of explicitly creating a container to be able to pass both arguments in a
|
||||
// Message we post a Runnable to the message queue.
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (MessageInfoHolder message : messages) {
|
||||
if (message != null && (mFolderName == null || (
|
||||
message.folder != null &&
|
||||
message.folder.name.equals(mFolderName)))) {
|
||||
if (message.selected && mSelectedCount > 0) {
|
||||
mSelectedCount--;
|
||||
}
|
||||
mAdapter.messages.remove(message);
|
||||
}
|
||||
}
|
||||
resetUnreadCountOnThread();
|
||||
|
||||
mAdapter.notifyDataSetChanged();
|
||||
toggleBatchButtons();
|
||||
mAdapter.changeMessageUid(ref, newUid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messages Never {@code null}.
|
||||
*/
|
||||
public void addMessages(final List<MessageInfoHolder> messages) {
|
||||
if (messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final boolean wasEmpty = mAdapter.messages.isEmpty();
|
||||
runOnUiThread(new Runnable() {
|
||||
public void addOrUpdateMessages(final Account account, final String folderName,
|
||||
final List<Message> providedMessages, final boolean verifyAgainstSearch) {
|
||||
// We copy the message list because it's later modified by MessagingController
|
||||
final List<Message> messages = new ArrayList<Message>(providedMessages);
|
||||
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (final MessageInfoHolder message : messages) {
|
||||
if (mFolderName == null || (message.folder != null && message.folder.name.equals(mFolderName))) {
|
||||
int index;
|
||||
synchronized (mAdapter.messages) {
|
||||
index = Collections.binarySearch(mAdapter.messages, message, getComparator());
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
index = (index * -1) - 1;
|
||||
}
|
||||
|
||||
mAdapter.messages.add(index, message);
|
||||
}
|
||||
}
|
||||
|
||||
if (wasEmpty) {
|
||||
mListView.setSelection(0);
|
||||
}
|
||||
resetUnreadCountOnThread();
|
||||
|
||||
mAdapter.notifyDataSetChanged();
|
||||
mAdapter.addOrUpdateMessages(account, folderName, messages,
|
||||
verifyAgainstSearch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void resetUnreadCount() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resetUnreadCountOnThread();
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
switch (msg.what) {
|
||||
case ACTION_REMOVE_MESSAGE: {
|
||||
MessageReference messageReference = (MessageReference) msg.obj;
|
||||
mAdapter.removeMessage(messageReference);
|
||||
break;
|
||||
}
|
||||
});
|
||||
case ACTION_RESET_UNREAD_COUNT: {
|
||||
mAdapter.resetUnreadCount();
|
||||
break;
|
||||
}
|
||||
|
||||
private void resetUnreadCountOnThread() {
|
||||
if (mQueryString != null) {
|
||||
int unreadCount = 0;
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
unreadCount += holder.read ? 0 : 1;
|
||||
case ACTION_SORT_MESSAGES: {
|
||||
mAdapter.sortMessages();
|
||||
break;
|
||||
}
|
||||
case ACTION_FOLDER_LOADING: {
|
||||
String folder = (String) msg.obj;
|
||||
boolean loading = (msg.arg1 == 1);
|
||||
MessageList.this.folderLoading(folder, loading);
|
||||
break;
|
||||
}
|
||||
case ACTION_REFRESH_TITLE: {
|
||||
MessageList.this.refreshTitle();
|
||||
break;
|
||||
}
|
||||
case ACTION_PROGRESS: {
|
||||
boolean progress = (msg.arg1 == 1);
|
||||
MessageList.this.progress(progress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mUnreadMessageCount = unreadCount;
|
||||
refreshTitleOnThread();
|
||||
}
|
||||
}
|
||||
|
||||
private void sortMessages() {
|
||||
final Comparator<MessageInfoHolder> chainComparator = getComparator();
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mAdapter.messages) {
|
||||
Collections.sort(mAdapter.messages, chainComparator);
|
||||
}
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The comparator to use to display messages in an ordered
|
||||
* fashion. Never <code>null</code>.
|
||||
@ -484,27 +490,14 @@ public class MessageList
|
||||
return chainComparator;
|
||||
}
|
||||
|
||||
public void folderLoading(String folder, boolean loading) {
|
||||
private void folderLoading(String folder, boolean loading) {
|
||||
if (mCurrentFolder != null && mCurrentFolder.name.equals(folder)) {
|
||||
mCurrentFolder.loading = loading;
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override public void run() {
|
||||
updateFooterView();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshTitle() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshTitleOnThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshTitleOnThread() {
|
||||
setWindowTitle();
|
||||
setWindowProgress();
|
||||
}
|
||||
@ -549,15 +542,9 @@ public class MessageList
|
||||
}
|
||||
}
|
||||
|
||||
public void progress(final boolean progress) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
private void progress(final boolean progress) {
|
||||
showProgressIndicator(progress);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the message list that was used to open the {@link MessageView} for a message.
|
||||
@ -765,7 +752,7 @@ public class MessageList
|
||||
final ActivityState previousData = getLastNonConfigurationInstance();
|
||||
|
||||
if (previousData != null) {
|
||||
mAdapter.messages.addAll(previousData.messages);
|
||||
mAdapter.restoreMessages(previousData.messages);
|
||||
mActiveMessages = previousData.activeMessages;
|
||||
}
|
||||
}
|
||||
@ -843,7 +830,7 @@ public class MessageList
|
||||
mController.notifyAccountCancel(this, accountWithNotification);
|
||||
}
|
||||
|
||||
if (mAdapter.messages.isEmpty()) {
|
||||
if (mAdapter.isEmpty()) {
|
||||
if (mFolderName != null) {
|
||||
mController.listLocalMessages(mAccount, mFolderName, mAdapter.mListener);
|
||||
// Hide the archive button if we don't have an archive folder.
|
||||
@ -860,22 +847,21 @@ public class MessageList
|
||||
// reread the selected date format preference in case it has changed
|
||||
mMessageHelper.refresh();
|
||||
|
||||
mAdapter.markAllMessagesAsDirty();
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAdapter.markAllMessagesAsDirty();
|
||||
|
||||
if (mFolderName != null) {
|
||||
mController.listLocalMessagesSynchronous(mAccount, mFolderName, mAdapter.mListener);
|
||||
} else if (mQueryString != null) {
|
||||
mController.searchLocalMessagesSynchronous(mAccountUuids, mFolderNames, null, mQueryString, mIntegrate, mQueryFlags, mForbiddenFlags, mAdapter.mListener);
|
||||
}
|
||||
|
||||
|
||||
mAdapter.pruneDirtyMessages();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAdapter.pruneDirtyMessages();
|
||||
mAdapter.notifyDataSetChanged();
|
||||
restoreListState();
|
||||
}
|
||||
@ -889,9 +875,10 @@ public class MessageList
|
||||
if (mAccount != null && mFolderName != null) {
|
||||
mController.getFolderUnreadMessageCount(mAccount, mFolderName, mAdapter.mListener);
|
||||
}
|
||||
mHandler.refreshTitle();
|
||||
|
||||
refreshTitle();
|
||||
}
|
||||
|
||||
private void initializeLayout() {
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
@ -951,7 +938,7 @@ public class MessageList
|
||||
@Override
|
||||
public ActivityState onRetainNonConfigurationInstance() {
|
||||
final ActivityState state = new ActivityState();
|
||||
state.messages = mAdapter.messages;
|
||||
state.messages = mAdapter.getMessages();
|
||||
state.activeMessages = mActiveMessages;
|
||||
return state;
|
||||
}
|
||||
@ -1142,12 +1129,11 @@ public class MessageList
|
||||
// Need to get the list before the sort starts
|
||||
ArrayList<MessageReference> messageRefs = new ArrayList<MessageReference>();
|
||||
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
MessageReference ref = holder.message.makeMessageReference();
|
||||
messageRefs.add(ref);
|
||||
}
|
||||
}
|
||||
|
||||
MessageReference ref = message.message.makeMessageReference();
|
||||
Log.i(K9.LOG_TAG, "MessageList sending message " + ref);
|
||||
|
||||
@ -1254,7 +1240,7 @@ public class MessageList
|
||||
Toast toast = Toast.makeText(this, toastString, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
|
||||
mHandler.sortMessages();
|
||||
mAdapter.sortMessages();
|
||||
}
|
||||
|
||||
private void onCycleSort() {
|
||||
@ -1286,7 +1272,7 @@ public class MessageList
|
||||
for (MessageInfoHolder holder : holders) {
|
||||
messagesToRemove.add(holder.message);
|
||||
}
|
||||
mHandler.removeMessages(holders);
|
||||
mAdapter.removeMessages(holders);
|
||||
mController.deleteMessages(messagesToRemove.toArray(EMPTY_MESSAGE_ARRAY), null);
|
||||
}
|
||||
|
||||
@ -1352,12 +1338,10 @@ public class MessageList
|
||||
try {
|
||||
mController.markAllMessagesRead(mAccount, mCurrentFolder.name);
|
||||
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
holder.read = true;
|
||||
}
|
||||
}
|
||||
mHandler.sortMessages();
|
||||
mAdapter.sortMessages();
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
@ -1452,7 +1436,7 @@ public class MessageList
|
||||
String folderName = folder.getName();
|
||||
mController.setFlag(account, folderName, new Message[] { message }, Flag.SEEN, !holder.read);
|
||||
holder.read = !holder.read;
|
||||
mHandler.sortMessages();
|
||||
mAdapter.sortMessages();
|
||||
}
|
||||
|
||||
private void onToggleFlag(MessageInfoHolder holder) {
|
||||
@ -1462,7 +1446,7 @@ public class MessageList
|
||||
String folderName = folder.getName();
|
||||
mController.setFlag(account, folderName, new Message[] { message }, Flag.FLAGGED, !holder.flagged);
|
||||
holder.flagged = !holder.flagged;
|
||||
mHandler.sortMessages();
|
||||
mAdapter.sortMessages();
|
||||
}
|
||||
|
||||
private void checkMail(Account account, String folderName) {
|
||||
@ -1885,7 +1869,8 @@ public class MessageList
|
||||
}
|
||||
|
||||
class MessageListAdapter extends BaseAdapter {
|
||||
private final List<MessageInfoHolder> messages = java.util.Collections.synchronizedList(new ArrayList<MessageInfoHolder>());
|
||||
private final List<MessageInfoHolder> mMessages =
|
||||
Collections.synchronizedList(new ArrayList<MessageInfoHolder>());
|
||||
|
||||
private final ActivityListener mListener = new ActivityListener() {
|
||||
|
||||
@ -1928,17 +1913,12 @@ public class MessageList
|
||||
|
||||
@Override
|
||||
public void synchronizeMailboxAddOrUpdateMessage(Account account, String folder, Message message) {
|
||||
addOrUpdateMessage(account, folder, message, true);
|
||||
mHandler.addOrUpdateMessages(account, folder, Collections.singletonList(message), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void synchronizeMailboxRemovedMessage(Account account, String folder, Message message) {
|
||||
MessageInfoHolder holder = getMessage(message);
|
||||
if (holder == null) {
|
||||
Log.w(K9.LOG_TAG, "Got callback to remove non-existent message with UID " + message.getUid());
|
||||
} else {
|
||||
removeMessages(Collections.singletonList(holder));
|
||||
}
|
||||
mHandler.removeMessage(message.makeMessageReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1975,20 +1955,17 @@ public class MessageList
|
||||
|
||||
@Override
|
||||
public void listLocalMessagesRemoveMessage(Account account, String folder, Message message) {
|
||||
MessageInfoHolder holder = getMessage(message);
|
||||
if (holder != null) {
|
||||
removeMessages(Collections.singletonList(holder));
|
||||
}
|
||||
mHandler.removeMessage(message.makeMessageReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listLocalMessagesAddMessages(Account account, String folder, List<Message> messages) {
|
||||
addOrUpdateMessages(account, folder, messages, false);
|
||||
mHandler.addOrUpdateMessages(account, folder, messages, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listLocalMessagesUpdateMessage(Account account, String folder, Message message) {
|
||||
addOrUpdateMessage(account, folder, message, false);
|
||||
mHandler.addOrUpdateMessages(account, folder, Collections.singletonList(message), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2012,11 +1989,7 @@ public class MessageList
|
||||
ref.folderName = folder;
|
||||
ref.uid = oldUid;
|
||||
|
||||
MessageInfoHolder holder = getMessage(ref);
|
||||
if (holder != null) {
|
||||
holder.uid = newUid;
|
||||
holder.message.setUid(newUid);
|
||||
}
|
||||
mHandler.changeMessageUid(ref, newUid);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2028,6 +2001,14 @@ public class MessageList
|
||||
}
|
||||
}
|
||||
|
||||
public List<MessageInfoHolder> getMessages() {
|
||||
return mMessages;
|
||||
}
|
||||
|
||||
public void restoreMessages(List<MessageInfoHolder> messages) {
|
||||
mMessages.addAll(messages);
|
||||
}
|
||||
|
||||
private Drawable mAttachmentIcon;
|
||||
private Drawable mForwardedIcon;
|
||||
private Drawable mAnsweredIcon;
|
||||
@ -2041,44 +2022,111 @@ public class MessageList
|
||||
}
|
||||
|
||||
public void markAllMessagesAsDirty() {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mMessages) {
|
||||
holder.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void pruneDirtyMessages() {
|
||||
synchronized (mAdapter.messages) {
|
||||
Iterator<MessageInfoHolder> iter = mAdapter.messages.iterator();
|
||||
while (iter.hasNext()) {
|
||||
MessageInfoHolder holder = iter.next();
|
||||
List<MessageInfoHolder> messagesToRemove = new ArrayList<MessageInfoHolder>();
|
||||
|
||||
for (MessageInfoHolder holder : mMessages) {
|
||||
if (holder.dirty) {
|
||||
if (holder.selected) {
|
||||
messagesToRemove.add(holder);
|
||||
}
|
||||
}
|
||||
removeMessages(messagesToRemove);
|
||||
}
|
||||
|
||||
public void removeMessage(MessageReference messageReference) {
|
||||
MessageInfoHolder holder = getMessage(messageReference);
|
||||
if (holder == null) {
|
||||
Log.w(K9.LOG_TAG, "Got callback to remove non-existent message with UID " +
|
||||
messageReference.uid);
|
||||
} else {
|
||||
removeMessages(Collections.singletonList(holder));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeMessages(final List<MessageInfoHolder> messages) {
|
||||
if (messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MessageInfoHolder message : messages) {
|
||||
if (message != null && (mFolderName == null || (
|
||||
message.folder != null &&
|
||||
message.folder.name.equals(mFolderName)))) {
|
||||
if (message.selected && mSelectedCount > 0) {
|
||||
mSelectedCount--;
|
||||
}
|
||||
mMessages.remove(message);
|
||||
}
|
||||
}
|
||||
resetUnreadCount();
|
||||
|
||||
notifyDataSetChanged();
|
||||
toggleBatchButtons();
|
||||
}
|
||||
mAdapter.removeMessages(Collections.singletonList(holder));
|
||||
|
||||
public void addMessages(final List<MessageInfoHolder> messages) {
|
||||
if (messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean wasEmpty = mMessages.isEmpty();
|
||||
|
||||
for (final MessageInfoHolder message : messages) {
|
||||
if (mFolderName == null || (message.folder != null && message.folder.name.equals(mFolderName))) {
|
||||
int index = Collections.binarySearch(mMessages, message, getComparator());
|
||||
|
||||
if (index < 0) {
|
||||
index = (index * -1) - 1;
|
||||
}
|
||||
|
||||
mMessages.add(index, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param holders
|
||||
* Never {@code null}.
|
||||
*/
|
||||
public void removeMessages(List<MessageInfoHolder> holders) {
|
||||
mHandler.removeMessages(holders);
|
||||
if (wasEmpty) {
|
||||
mListView.setSelection(0);
|
||||
}
|
||||
resetUnreadCount();
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void addOrUpdateMessage(Account account, String folderName, Message message, boolean verifyAgainstSearch) {
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
messages.add(message);
|
||||
addOrUpdateMessages(account, folderName, messages, verifyAgainstSearch);
|
||||
public void changeMessageUid(MessageReference ref, String newUid) {
|
||||
MessageInfoHolder holder = getMessage(ref);
|
||||
if (holder != null) {
|
||||
holder.uid = newUid;
|
||||
holder.message.setUid(newUid);
|
||||
}
|
||||
}
|
||||
|
||||
private void addOrUpdateMessages(final Account account, final String folderName, final List<Message> providedMessages, final boolean verifyAgainstSearch) {
|
||||
// we copy the message list because the callback doesn't expect
|
||||
// the callbacks to mutate it.
|
||||
final List<Message> messages = new ArrayList<Message>(providedMessages);
|
||||
public void resetUnreadCount() {
|
||||
if (mQueryString != null) {
|
||||
int unreadCount = 0;
|
||||
|
||||
for (MessageInfoHolder holder : mMessages) {
|
||||
unreadCount += holder.read ? 0 : 1;
|
||||
}
|
||||
|
||||
mUnreadMessageCount = unreadCount;
|
||||
refreshTitle();
|
||||
}
|
||||
}
|
||||
|
||||
public void sortMessages() {
|
||||
final Comparator<MessageInfoHolder> chainComparator = getComparator();
|
||||
|
||||
Collections.sort(mMessages, chainComparator);
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void addOrUpdateMessages(final Account account, final String folderName,
|
||||
final List<Message> messages, final boolean verifyAgainstSearch) {
|
||||
|
||||
boolean needsSort = false;
|
||||
final List<MessageInfoHolder> messagesToAdd = new ArrayList<MessageInfoHolder>();
|
||||
@ -2100,7 +2148,9 @@ public class MessageList
|
||||
if (m == null) {
|
||||
if (updateForMe(account, folderName)) {
|
||||
m = new MessageInfoHolder();
|
||||
messageHelper.populate(m, message, new FolderInfoHolder(MessageList.this, messageFolder, messageAccount), messageAccount);
|
||||
FolderInfoHolder folderInfoHolder = new FolderInfoHolder(
|
||||
MessageList.this, messageFolder, messageAccount);
|
||||
messageHelper.populate(m, message, folderInfoHolder, messageAccount);
|
||||
messagesToAdd.add(m);
|
||||
} else {
|
||||
if (mQueryString != null) {
|
||||
@ -2108,25 +2158,33 @@ public class MessageList
|
||||
messagesToSearch.add(message);
|
||||
} else {
|
||||
m = new MessageInfoHolder();
|
||||
messageHelper.populate(m, message, new FolderInfoHolder(MessageList.this, messageFolder, messageAccount), messageAccount);
|
||||
FolderInfoHolder folderInfoHolder = new FolderInfoHolder(
|
||||
MessageList.this, messageFolder, messageAccount);
|
||||
messageHelper.populate(m, message, folderInfoHolder,
|
||||
messageAccount);
|
||||
messagesToAdd.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m.dirty = false; // as we reload the message, unset its dirty flag
|
||||
messageHelper.populate(m, message, new FolderInfoHolder(MessageList.this, messageFolder, account), account);
|
||||
FolderInfoHolder folderInfoHolder = new FolderInfoHolder(MessageList.this,
|
||||
messageFolder, account);
|
||||
messageHelper.populate(m, message, folderInfoHolder, account);
|
||||
needsSort = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!messagesToSearch.isEmpty()) {
|
||||
mController.searchLocalMessages(mAccountUuids, mFolderNames, messagesToSearch.toArray(EMPTY_MESSAGE_ARRAY), mQueryString, mIntegrate, mQueryFlags, mForbiddenFlags,
|
||||
mController.searchLocalMessages(mAccountUuids, mFolderNames,
|
||||
messagesToSearch.toArray(EMPTY_MESSAGE_ARRAY), mQueryString, mIntegrate,
|
||||
mQueryFlags, mForbiddenFlags,
|
||||
new MessagingListener() {
|
||||
@Override
|
||||
public void listLocalMessagesAddMessages(Account account, String folder, List<Message> messages) {
|
||||
addOrUpdateMessages(account, folder, messages, false);
|
||||
public void listLocalMessagesAddMessages(Account account, String folder,
|
||||
List<Message> messages) {
|
||||
mHandler.addOrUpdateMessages(account, folder, messages, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -2136,35 +2194,69 @@ public class MessageList
|
||||
}
|
||||
|
||||
if (!messagesToAdd.isEmpty()) {
|
||||
mHandler.addMessages(messagesToAdd);
|
||||
addMessages(messagesToAdd);
|
||||
}
|
||||
|
||||
if (needsSort) {
|
||||
mHandler.sortMessages();
|
||||
mHandler.resetUnreadCount();
|
||||
sortMessages();
|
||||
resetUnreadCount();
|
||||
}
|
||||
}
|
||||
public MessageInfoHolder getMessage(Message message) {
|
||||
return getMessage(message.makeMessageReference());
|
||||
}
|
||||
|
||||
// XXX TODO - make this not use a for loop
|
||||
public MessageInfoHolder getMessage(MessageReference messageReference) {
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
/*
|
||||
* 2010-06-21 - cketti
|
||||
* Added null pointer check. Not sure what's causing 'holder'
|
||||
* to be null. See log provided in issue 1749, comment #15.
|
||||
/**
|
||||
* Find a specific message in the message list.
|
||||
*
|
||||
* Please remove this comment once the cause was found and the
|
||||
* bug(?) fixed.
|
||||
* <p><strong>Note:</strong>
|
||||
* This method was optimized because it is called a lot. Don't change it unless you know
|
||||
* what you are doing.</p>
|
||||
*
|
||||
* @param message
|
||||
* A {@link Message} instance describing the message to look for.
|
||||
*
|
||||
* @return The corresponding {@link MessageInfoHolder} instance if the message was found in
|
||||
* the message list. {@code null} otherwise.
|
||||
*/
|
||||
if ((holder != null) && holder.message.equalsReference(messageReference)) {
|
||||
private MessageInfoHolder getMessage(Message message) {
|
||||
String uid;
|
||||
Folder folder;
|
||||
for (MessageInfoHolder holder : mMessages) {
|
||||
uid = message.getUid();
|
||||
if (holder.uid == uid || uid.equals(holder.uid)) {
|
||||
folder = message.getFolder();
|
||||
if (holder.folder.name.equals(folder.getName()) &&
|
||||
holder.account.equals(folder.getAccount().getUuid())) {
|
||||
return holder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a specific message in the message list.
|
||||
*
|
||||
* <p><strong>Note:</strong>
|
||||
* This method was optimized because it is called a lot. Don't change it unless you know
|
||||
* what you are doing.</p>
|
||||
*
|
||||
* @param messageReference
|
||||
* A {@link MessageReference} instance describing the message to look for.
|
||||
*
|
||||
* @return The corresponding {@link MessageInfoHolder} instance if the message was found in
|
||||
* the message list. {@code null} otherwise.
|
||||
*/
|
||||
private MessageInfoHolder getMessage(MessageReference messageReference) {
|
||||
String uid;
|
||||
for (MessageInfoHolder holder : mMessages) {
|
||||
uid = messageReference.uid;
|
||||
if ((holder.uid == uid || uid.equals(holder.uid)) &&
|
||||
holder.folder.name.equals(messageReference.folderName) &&
|
||||
holder.account.equals(messageReference.accountUuid)) {
|
||||
return holder;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -2195,7 +2287,7 @@ public class MessageList
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return messages.size();
|
||||
return mMessages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2211,20 +2303,14 @@ public class MessageList
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Object getItem(long position) {
|
||||
return getItem((int)position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
try {
|
||||
synchronized (mAdapter.messages) {
|
||||
if (position < mAdapter.messages.size()) {
|
||||
return mAdapter.messages.get(position);
|
||||
}
|
||||
if (position < mMessages.size()) {
|
||||
return mMessages.get(position);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(K9.LOG_TAG, "getItem(" + position + "), but folder.messages.size() = " + mAdapter.messages.size(), e);
|
||||
Log.e(K9.LOG_TAG, "getItem(" + position + "), but folder.messages.size() = " + mMessages.size(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -2435,21 +2521,10 @@ public class MessageList
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isItemSelectable(int position) {
|
||||
if (position < mAdapter.messages.size()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MessageViewHolder
|
||||
@ -2597,8 +2672,7 @@ public class MessageList
|
||||
private boolean computeBatchDirection(boolean flagged) {
|
||||
boolean newState = false;
|
||||
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
if (holder.selected) {
|
||||
if (flagged) {
|
||||
if (!holder.flagged) {
|
||||
@ -2613,18 +2687,17 @@ public class MessageList
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
||||
private boolean anySelected() {
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
if (holder.selected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2657,8 +2730,7 @@ public class MessageList
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
if (holder.selected) {
|
||||
if (v == mBatchDeleteButton) {
|
||||
removeHolderList.add(holder);
|
||||
@ -2670,7 +2742,7 @@ public class MessageList
|
||||
messageList.add(holder.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mAdapter.removeMessages(removeHolderList);
|
||||
|
||||
if (!messageList.isEmpty()) {
|
||||
@ -2685,7 +2757,8 @@ public class MessageList
|
||||
// Should not happen
|
||||
Toast.makeText(this, R.string.no_message_seletected_toast, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mHandler.sortMessages();
|
||||
|
||||
mAdapter.sortMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2704,12 +2777,12 @@ public class MessageList
|
||||
|
||||
private void setAllSelected(boolean isSelected) {
|
||||
mSelectedCount = 0;
|
||||
synchronized (mAdapter.messages) {
|
||||
for (MessageInfoHolder holder : mAdapter.messages) {
|
||||
|
||||
for (MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
holder.selected = isSelected;
|
||||
mSelectedCount += (isSelected ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
mAdapter.notifyDataSetChanged();
|
||||
toggleBatchButtons();
|
||||
}
|
||||
@ -2750,7 +2823,7 @@ public class MessageList
|
||||
}
|
||||
}
|
||||
mController.setFlag(messageList, flag, newState);
|
||||
mHandler.sortMessages();
|
||||
mAdapter.sortMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2909,13 +2982,13 @@ public class MessageList
|
||||
*/
|
||||
private List<MessageInfoHolder> getSelectionFromCheckboxes() {
|
||||
final List<MessageInfoHolder> selection = new ArrayList<MessageInfoHolder>();
|
||||
synchronized (mAdapter.messages) {
|
||||
for (final MessageInfoHolder holder : mAdapter.messages) {
|
||||
|
||||
for (final MessageInfoHolder holder : mAdapter.getMessages()) {
|
||||
if (holder.selected) {
|
||||
selection.add(holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
||||
@ -2944,6 +3017,8 @@ public class MessageList
|
||||
* {@link #move(List, String)}. This method was added mainly because those 2
|
||||
* methods share common behavior.
|
||||
*
|
||||
* Note: Must be called from the UI thread!
|
||||
*
|
||||
* @param holders
|
||||
* Never {@code null}.
|
||||
* @param destination
|
||||
@ -2993,7 +3068,7 @@ public class MessageList
|
||||
if (operation == FolderOperation.MOVE) {
|
||||
mController.moveMessages(account, folderName, messages.toArray(new Message[messages.size()]), destination,
|
||||
null);
|
||||
mHandler.removeMessages(holders);
|
||||
mAdapter.removeMessages(holders);
|
||||
} else {
|
||||
mController.copyMessages(account, folderName, messages.toArray(new Message[messages.size()]), destination,
|
||||
null);
|
||||
|
@ -85,7 +85,7 @@ public class MessageHelper {
|
||||
|
||||
target.uid = message.getUid();
|
||||
|
||||
target.account = account.getDescription();
|
||||
target.account = account.getUuid();
|
||||
target.uri = "email://messages/" + account.getAccountNumber() + "/" + m.getFolder().getName() + "/" + m.getUid();
|
||||
|
||||
} catch (MessagingException me) {
|
||||
|
@ -45,13 +45,16 @@ public class BinaryTempFileBody implements Body {
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
InputStream in = getInputStream();
|
||||
try {
|
||||
Base64OutputStream base64Out = new Base64OutputStream(out);
|
||||
try {
|
||||
IOUtils.copy(in, base64Out);
|
||||
} finally {
|
||||
base64Out.close();
|
||||
}
|
||||
mFile.delete();
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
class BinaryTempFileBodyInputStream extends FilterInputStream {
|
||||
@ -61,8 +64,11 @@ public class BinaryTempFileBody implements Body {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
} finally {
|
||||
mFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1059,15 +1059,20 @@ public class MimeUtility {
|
||||
/*
|
||||
* Now we read the part into a buffer for further processing. Because
|
||||
* the stream is now wrapped we'll remove any transfer encoding at this point.
|
||||
*
|
||||
* We can't wrap this in a try-finally to close the InputStream. It looks like
|
||||
* we depend on the underlying temp file to exist across calls, and closing it
|
||||
* deletes the file, which isn't what we want. We should figure out if this
|
||||
* is really the right way to be doing things, since it's triggering strict
|
||||
* mode warnings.
|
||||
*/
|
||||
InputStream in = part.getBody().getInputStream();
|
||||
return readToString(in, charset);
|
||||
try {
|
||||
String text = readToString(in, charset);
|
||||
|
||||
// Replace the body with a TextBody that already contains the decoded text
|
||||
part.setBody(new TextBody(text));
|
||||
|
||||
return text;
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) { /* Ignore */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user