mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-23 18:02:15 -05:00
Refactor suppression of deleted messages into MessagingController.
Re-enable instant deletes in MessageView Deleted message suppression should be generalized into a flag cache, serving Seen, Flagged, and Answered flags, as well. Copy message to Trash still needs work, so that no duplicates are ever visible and server-sync is more clean. This will be especially important, as the same code will be needed for the future "message copy/move" facility.
This commit is contained in:
parent
9fe3656391
commit
fe2dfb76d0
@ -14,6 +14,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -112,6 +113,82 @@ public class MessagingController implements Runnable {
|
||||
private boolean mBusy;
|
||||
private Application mApplication;
|
||||
|
||||
// Key is accountUuid:folderName:messageUid , value is unimportant
|
||||
private ConcurrentHashMap<String, String> deletedUids = new ConcurrentHashMap<String, String>();
|
||||
|
||||
// Key is accountUuid:folderName , value is a long of the highest message UID ever emptied from Trash
|
||||
private ConcurrentHashMap<String, Long> expungedUid = new ConcurrentHashMap<String, Long>();
|
||||
|
||||
|
||||
private String createMessageKey(Account account, String folder, Message message)
|
||||
{
|
||||
return account.getUuid() + ":" + folder + ":" + message.getUid();
|
||||
}
|
||||
|
||||
private String createFolderKey(Account account, String folder)
|
||||
{
|
||||
return account.getUuid() + ":" + folder;
|
||||
}
|
||||
|
||||
private void suppressMessage(Account account, String folder, Message message)
|
||||
{
|
||||
|
||||
if (account == null || folder == null || message == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String messKey = createMessageKey(account, folder, message);
|
||||
Log.d(Email.LOG_TAG, "Suppressing message with key " + messKey);
|
||||
deletedUids.put(messKey, "true");
|
||||
}
|
||||
|
||||
private void unsuppressMessage(Account account, String folder, Message message)
|
||||
{
|
||||
if (account == null || folder == null || message == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String messKey = createMessageKey(account, folder, message);
|
||||
Log.d(Email.LOG_TAG, "Unsuppressing message with key " + messKey);
|
||||
deletedUids.remove(messKey);
|
||||
}
|
||||
|
||||
|
||||
private boolean isMessageSuppressed(Account account, String folder, Message message)
|
||||
{
|
||||
if (account == null || folder == null || message == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String messKey = createMessageKey(account, folder, message);
|
||||
Log.d(Email.LOG_TAG, "Checking suppression of message with key " + messKey);
|
||||
if (deletedUids.containsKey(messKey))
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Message with key " + messKey + " is suppressed");
|
||||
return true;
|
||||
}
|
||||
Long expungedUidL = expungedUid.get(createFolderKey(account, folder));
|
||||
if (expungedUidL != null)
|
||||
{
|
||||
long expungedUid = expungedUidL;
|
||||
String messageUidS = message.getUid();
|
||||
try
|
||||
{
|
||||
long messageUid = Long.parseLong(messageUidS);
|
||||
if (messageUid <= expungedUid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException nfe)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private MessagingController(Application application) {
|
||||
@ -380,7 +457,9 @@ public class MessagingController implements Runnable {
|
||||
Message[] localMessages = localFolder.getMessages(null);
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
for (Message message : localMessages) {
|
||||
if (!message.isSet(Flag.DELETED)) {
|
||||
|
||||
if (!message.isSet(Flag.DELETED) &&
|
||||
isMessageSuppressed(account, localFolder.getName(), message) == false) {
|
||||
messages.add(message);
|
||||
}
|
||||
}
|
||||
@ -689,10 +768,13 @@ s * critical data as fast as possible, and then we'll fill in the de
|
||||
* (POP) may not be able to give us headers for
|
||||
* ENVELOPE, only size.
|
||||
*/
|
||||
if (isMessageSuppressed(account, folder, message) == false)
|
||||
{
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxNewMessage(account, folder,
|
||||
localFolder.getMessage(message.getUid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -740,7 +822,8 @@ s * critical data as fast as possible, and then we'll fill in the de
|
||||
messageChanged = true;
|
||||
}
|
||||
}
|
||||
if (messageChanged) {
|
||||
if (messageChanged && isMessageSuppressed(account, folder, localMessage) == false)
|
||||
{
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxNewMessage(account, folder, localMessage);
|
||||
}
|
||||
@ -825,13 +908,15 @@ s * critical data as fast as possible, and then we'll fill in the de
|
||||
|
||||
// Set a flag indicating this message has now be fully downloaded
|
||||
localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
|
||||
|
||||
// Update the listener with what we've found
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxNewMessage(
|
||||
account,
|
||||
folder,
|
||||
localMessage);
|
||||
if (isMessageSuppressed(account, folder, localMessage) == false)
|
||||
{
|
||||
// Update the listener with what we've found
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxNewMessage(
|
||||
account,
|
||||
folder,
|
||||
localMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MessagingException me) {
|
||||
@ -919,13 +1004,15 @@ s * critical data as fast as possible, and then we'll fill in the de
|
||||
// viewed.
|
||||
localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
|
||||
}
|
||||
|
||||
// Update the listener with what we've found
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxNewMessage(
|
||||
account,
|
||||
folder,
|
||||
localFolder.getMessage(message.getUid()));
|
||||
if (isMessageSuppressed(account, folder, message) == false)
|
||||
{
|
||||
// Update the listener with what we've found
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.synchronizeMailboxNewMessage(
|
||||
account,
|
||||
folder,
|
||||
localFolder.getMessage(message.getUid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Config.LOGV) {
|
||||
@ -1898,6 +1985,8 @@ s * critical data as fast as possible, and then we'll fill in the de
|
||||
|
||||
public void deleteMessage(final Account account, final String folder, final Message message,
|
||||
final MessagingListener listener) {
|
||||
suppressMessage(account, folder, message);
|
||||
|
||||
put("deleteMessage", null, new Runnable() {
|
||||
public void run() {
|
||||
deleteMessageSynchronous(account, folder, message, listener);
|
||||
@ -1907,53 +1996,60 @@ s * critical data as fast as possible, and then we'll fill in the de
|
||||
|
||||
private void deleteMessageSynchronous(final Account account, final String folder, final Message message,
|
||||
MessagingListener listener) {
|
||||
|
||||
account.getUuid();
|
||||
message.getUid();
|
||||
|
||||
try {
|
||||
Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
|
||||
Folder localFolder = localStore.getFolder(folder);
|
||||
Message lMessage = localFolder.getMessage(message.getUid());
|
||||
|
||||
if (folder.equals(account.getTrashFolderName()))
|
||||
if (lMessage != null)
|
||||
{
|
||||
if (Config.LOGD)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Deleting message in trash folder, not copying");
|
||||
}
|
||||
lMessage.setFlag(Flag.DELETED, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Folder localTrashFolder = localStore.getFolder(account.getTrashFolderName());
|
||||
if (localTrashFolder.exists() == false)
|
||||
{
|
||||
localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES);
|
||||
}
|
||||
if (localTrashFolder.exists() == true)
|
||||
if (folder.equals(account.getTrashFolderName()))
|
||||
{
|
||||
if (Config.LOGD)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Deleting message in normal folder, copying");
|
||||
Log.d(Email.LOG_TAG, "Deleting message in trash folder, not copying");
|
||||
}
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.ENVELOPE);
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
// TODO: Turn the fetch/copy/delete into an atomic move
|
||||
localFolder.fetch(new Message[] { lMessage }, fp, null);
|
||||
localFolder.copyMessages(new Message[] { lMessage }, localTrashFolder);
|
||||
if (folder.equals(account.getOutboxFolderName())) {
|
||||
lMessage.setFlag(Flag.X_DESTROYED, true);
|
||||
lMessage.setFlag(Flag.DELETED, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Folder localTrashFolder = localStore.getFolder(account.getTrashFolderName());
|
||||
if (localTrashFolder.exists() == false)
|
||||
{
|
||||
localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES);
|
||||
}
|
||||
else {
|
||||
lMessage.setFlag(Flag.DELETED, true);
|
||||
if (localTrashFolder.exists() == true)
|
||||
{
|
||||
if (Config.LOGD)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Deleting message in normal folder, copying");
|
||||
}
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.ENVELOPE);
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
// TODO: Turn the fetch/copy/delete into an atomic move
|
||||
localFolder.fetch(new Message[] { lMessage }, fp, null);
|
||||
localFolder.copyMessages(new Message[] { lMessage }, localTrashFolder);
|
||||
if (folder.equals(account.getOutboxFolderName())) {
|
||||
lMessage.setFlag(Flag.X_DESTROYED, true);
|
||||
}
|
||||
else {
|
||||
lMessage.setFlag(Flag.DELETED, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
localFolder.close(false);
|
||||
unsuppressMessage(account, folder, message);
|
||||
if (listener != null) {
|
||||
listener.messageDeleted(account, folder, message);
|
||||
}
|
||||
// for (MessagingListener l : getListeners()) {
|
||||
// l.folderStatusChanged(account, account.getTrashFolderName());
|
||||
// }
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.folderStatusChanged(account, account.getTrashFolderName());
|
||||
}
|
||||
|
||||
if (Config.LOGD)
|
||||
{
|
||||
|
@ -395,8 +395,7 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
// Lower our priority
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
// Synchronously load the list of local messages
|
||||
MessagingController.getInstance(getApplication()).listLocalMessages(
|
||||
mAccount, mFolder, mAdapter.mListener);
|
||||
|
||||
try
|
||||
{
|
||||
Store localStore = Store.getInstance(mAccount.getLocalStoreUri(),
|
||||
@ -418,7 +417,12 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
// at it's leisure
|
||||
MessagingController.getInstance(getApplication()).synchronizeMailbox(
|
||||
mAccount, mFolder, mAdapter.mListener);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).listLocalMessages(
|
||||
mAccount, mFolder, mAdapter.mListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,8 +615,9 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
|
||||
final FolderInfoHolder folder = (FolderInfoHolder) mAdapter
|
||||
.getGroup(groupPosition);
|
||||
if (folder.messages.size() == 0)
|
||||
if (folder.messages.size() == 0 || folder.needsRefresh)
|
||||
{
|
||||
folder.needsRefresh = false;
|
||||
new Thread(new FolderUpdateWorker(folder.name, false)).start();
|
||||
}
|
||||
}
|
||||
@ -771,24 +776,16 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
{
|
||||
holder.folder.unreadMessageCount--;
|
||||
}
|
||||
FolderInfoHolder trashHolder = mAdapter.getFolder(mAccount.getTrashFolderName());
|
||||
if (trashHolder != null)
|
||||
{
|
||||
trashHolder.needsRefresh = true;
|
||||
}
|
||||
|
||||
mAdapter.removeMessage(holder.message.getFolder().getName(), holder.uid);
|
||||
if (holder.folder.name.equals(mAccount.getTrashFolderName()) == false) {
|
||||
mAdapter.addOrUpdateMessage(mAccount.getTrashFolderName(), holder.message);
|
||||
}
|
||||
|
||||
MessagingController.getInstance(getApplication()).deleteMessage(mAccount,
|
||||
holder.message.getFolder().getName(), holder.message,
|
||||
new MessagingListener() {
|
||||
@Override
|
||||
public void messageDeleted(Account account, String folder, Message message) {
|
||||
if (account != mAccount) {
|
||||
return;
|
||||
}
|
||||
mAdapter.removeDeletedUid(folder, message.getUid());
|
||||
}
|
||||
}
|
||||
);
|
||||
holder.message.getFolder().getName(), holder.message, null);
|
||||
|
||||
}
|
||||
|
||||
@ -832,7 +829,6 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
public void controllerCommandCompleted(boolean moreToDo)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "Empty Trash background task completed");
|
||||
mAdapter.removeAllDeletedUids(account.getTrashFolderName());
|
||||
}
|
||||
};
|
||||
|
||||
@ -1280,9 +1276,6 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
return;
|
||||
}
|
||||
FolderInfoHolder holder = getFolder(folder);
|
||||
// if (holder != null) {
|
||||
// holder.deletedUids.clear();
|
||||
// }
|
||||
mHandler.progress(false);
|
||||
mHandler.folderLoading(folder, false);
|
||||
// mHandler.folderStatus(folder, null);
|
||||
@ -1311,7 +1304,6 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
if (holder != null)
|
||||
{
|
||||
holder.lastChecked = 0;
|
||||
// holder.deletedUids.clear();
|
||||
}
|
||||
mHandler.folderSyncing(null);
|
||||
}
|
||||
@ -1327,7 +1319,17 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
addOrUpdateMessage(folder, message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void messageDeleted(Account account,
|
||||
String folder, Message message)
|
||||
{
|
||||
synchronizeMailboxRemovedMessage(account,
|
||||
folder, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void synchronizeMailboxRemovedMessage(Account account,
|
||||
String folder, Message message)
|
||||
{
|
||||
@ -1422,23 +1424,6 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
R.drawable.ic_mms_answered_small);
|
||||
}
|
||||
|
||||
public void removeDeletedUid(String folder, String messageUid) {
|
||||
FolderInfoHolder f = getFolder(folder);
|
||||
if (f != null)
|
||||
{
|
||||
f.deletedUids.remove(messageUid);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllDeletedUids(String folder)
|
||||
{
|
||||
FolderInfoHolder f = getFolder(folder);
|
||||
if (f != null)
|
||||
{
|
||||
f.deletedUids.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllMessages(String folder)
|
||||
{
|
||||
FolderInfoHolder f = getFolder(folder);
|
||||
@ -1465,9 +1450,7 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (f.deletedUids.contains(messageUid) == false) {
|
||||
f.deletedUids.add(messageUid);
|
||||
}
|
||||
|
||||
mHandler.removeMessage(f, m);
|
||||
}
|
||||
|
||||
@ -1489,9 +1472,6 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
private void addOrUpdateMessage(FolderInfoHolder folder, Message message,
|
||||
boolean sort, boolean notify)
|
||||
{
|
||||
if (folder.deletedUids.contains(message.getUid())){
|
||||
return;
|
||||
}
|
||||
MessageInfoHolder m = getMessage(folder, message.getUid());
|
||||
if (m == null)
|
||||
{
|
||||
@ -1855,7 +1835,8 @@ public class FolderMessageList extends ExpandableListActivity
|
||||
|
||||
public boolean lastCheckFailed;
|
||||
|
||||
public List<String> deletedUids = Collections.synchronizedList(new ArrayList<String>());
|
||||
public boolean needsRefresh = false;
|
||||
|
||||
/**
|
||||
* Outbox is handled differently from any other folder.
|
||||
*/
|
||||
|
@ -528,27 +528,19 @@ public class MessageView extends Activity
|
||||
|
||||
findSurroundingMessagesUid();
|
||||
|
||||
MessagingListener listener = new MessagingListener()
|
||||
{
|
||||
public void messageDeleted(Account account, String folder, Message message)
|
||||
{
|
||||
if (mNextMessageUid != null) {
|
||||
onNext();
|
||||
}
|
||||
else if (mPreviousMessageUid != null) {
|
||||
onPrevious();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
MessagingListener waitListener = listener;
|
||||
|
||||
MessagingController.getInstance(getApplication()).deleteMessage(
|
||||
accountForDelete,
|
||||
folderForDelete,
|
||||
messageToDelete,
|
||||
waitListener);
|
||||
null);
|
||||
if (mNextMessageUid != null) {
|
||||
onNext();
|
||||
}
|
||||
else if (mPreviousMessageUid != null) {
|
||||
onPrevious();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -847,12 +839,16 @@ public class MessageView extends Activity
|
||||
|
||||
private void renderAttachments(Part part, int depth) throws MessagingException {
|
||||
String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
String name = MimeUtility.getHeaderParameter(contentType, "name");
|
||||
if (name == null)
|
||||
{
|
||||
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
||||
}
|
||||
if (name != null) {
|
||||
/*
|
||||
* We're guaranteed size because LocalStore.fetch puts it there.
|
||||
*/
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
int size = Integer.parseInt(MimeUtility.getHeaderParameter(contentDisposition, "size"));
|
||||
|
||||
Attachment attachment = new Attachment();
|
||||
|
Loading…
Reference in New Issue
Block a user