1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-27 19:52:17 -05:00

Bulk deletion for IMAP and stub for other Stores.

This commit is contained in:
Daniel Applebaum 2009-11-29 18:07:34 +00:00
parent f1abdbb769
commit c7e7b9beda
6 changed files with 222 additions and 184 deletions

View File

@ -1874,7 +1874,22 @@ public class MessagingController implements Runnable
} }
} }
} }
private void queueMoveOrCopy(Account account, String srcFolder, String destFolder, boolean isCopy, String uids[])
{
PendingCommand command = new PendingCommand();
command.command = PENDING_COMMAND_MOVE_OR_COPY;
int length = 3 + uids.length;
command.arguments = new String[length];
command.arguments[0] = srcFolder;
command.arguments[1] = destFolder;
command.arguments[2] = Boolean.toString(isCopy);
for (int i = 0; i < uids.length; i++)
{
command.arguments[3 + i] = uids[i];
}
queuePendingCommand(account, command);
}
/** /**
* Process a pending trash message command. * Process a pending trash message command.
* *
@ -1884,11 +1899,26 @@ public class MessagingController implements Runnable
*/ */
private void processPendingMoveOrCopy(PendingCommand command, Account account) private void processPendingMoveOrCopy(PendingCommand command, Account account)
throws MessagingException throws MessagingException
{
Folder remoteSrcFolder = null;
Folder remoteDestFolder = null;
try
{ {
String srcFolder = command.arguments[0]; String srcFolder = command.arguments[0];
String uid = command.arguments[1]; String destFolder = command.arguments[1];
String destFolder = command.arguments[2]; String isCopyS = command.arguments[2];
String isCopyS = command.arguments[3]; Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
remoteSrcFolder = remoteStore.getFolder(srcFolder);
List<Message> messages = new ArrayList<Message>();
for (int i = 3; i < command.arguments.length; i++)
{
String uid = command.arguments[i];
if (!uid.startsWith(Email.LOCAL_UID_PREFIX))
{
messages.add(remoteSrcFolder.getMessage(uid));
}
}
boolean isCopy = false; boolean isCopy = false;
if (isCopyS != null) if (isCopyS != null)
@ -1896,15 +1926,6 @@ public class MessagingController implements Runnable
isCopy = Boolean.parseBoolean(isCopyS); isCopy = Boolean.parseBoolean(isCopyS);
} }
if (account.getErrorFolderName().equals(srcFolder))
{
return;
}
Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication);
Folder remoteSrcFolder = remoteStore.getFolder(srcFolder);
Folder remoteDestFolder = remoteStore.getFolder(destFolder);
if (!remoteSrcFolder.exists()) if (!remoteSrcFolder.exists())
{ {
throw new MessagingException("processingPendingMoveOrCopy: remoteFolder " + srcFolder + " does not exist", true); throw new MessagingException("processingPendingMoveOrCopy: remoteFolder " + srcFolder + " does not exist", true);
@ -1915,20 +1936,10 @@ public class MessagingController implements Runnable
throw new MessagingException("processingPendingMoveOrCopy: could not open remoteSrcFolder " + srcFolder + " read/write", true); throw new MessagingException("processingPendingMoveOrCopy: could not open remoteSrcFolder " + srcFolder + " read/write", true);
} }
Message remoteMessage = null;
if (!uid.startsWith(Email.LOCAL_UID_PREFIX))
{
remoteMessage = remoteSrcFolder.getMessage(uid);
}
if (remoteMessage == null)
{
throw new MessagingException("processingPendingMoveOrCopy: remoteMessage " + uid + " does not exist", true);
}
if (Email.DEBUG) if (Email.DEBUG)
{ {
Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy: source folder = " + srcFolder Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy: source folder = " + srcFolder
+ ", uid = " + uid + ", destination folder = " + destFolder + ", isCopy = " + isCopy); + ", " + messages.size() + " messages, destination folder = " + destFolder + ", isCopy = " + isCopy);
} }
if (isCopy == false && destFolder.equals(account.getTrashFolderName())) if (isCopy == false && destFolder.equals(account.getTrashFolderName()))
{ {
@ -1936,10 +1947,11 @@ public class MessagingController implements Runnable
{ {
Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy doing special case for deleting message"); Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy doing special case for deleting message");
} }
remoteMessage.delete(account.getTrashFolderName()); remoteSrcFolder.delete(messages.toArray(new Message[0]), account.getTrashFolderName());
remoteSrcFolder.close(true);
return;
} }
else
{
remoteDestFolder = remoteStore.getFolder(destFolder);
remoteDestFolder.open(OpenMode.READ_WRITE); remoteDestFolder.open(OpenMode.READ_WRITE);
if (remoteDestFolder.getMode() != OpenMode.READ_WRITE) if (remoteDestFolder.getMode() != OpenMode.READ_WRITE)
@ -1949,14 +1961,26 @@ public class MessagingController implements Runnable
if (isCopy) if (isCopy)
{ {
remoteSrcFolder.copyMessages(new Message[] { remoteMessage }, remoteDestFolder); remoteSrcFolder.copyMessages(messages.toArray(new Message[0]), remoteDestFolder);
} }
else else
{ {
remoteSrcFolder.moveMessages(new Message[] { remoteMessage }, remoteDestFolder); remoteSrcFolder.moveMessages(messages.toArray(new Message[0]), remoteDestFolder);
}
}
remoteSrcFolder.expunge();
}
finally
{
if (remoteSrcFolder != null)
{
remoteSrcFolder.close(false);
}
if (remoteDestFolder != null)
{
remoteDestFolder.close(false);
}
} }
remoteSrcFolder.close(true);
remoteDestFolder.close(true);
} }
@ -3192,10 +3216,8 @@ public class MessagingController implements Runnable
unsuppressMessage(account, srcFolder, origUid); unsuppressMessage(account, srcFolder, origUid);
} }
} }
PendingCommand command = new PendingCommand(); queueMoveOrCopy(account, srcFolder, destFolder, isCopy, new String[] { origUid });
command.command = PENDING_COMMAND_MOVE_OR_COPY;
command.arguments = new String[] { srcFolder, origUid, destFolder, Boolean.toString(isCopy) };
queuePendingCommand(account, command);
processPendingCommands(account); processPendingCommands(account);
} }
catch (MessagingException me) catch (MessagingException me)
@ -3206,63 +3228,44 @@ public class MessagingController implements Runnable
} }
} }
public void deleteMessageList(final Account account, final String folder, final List<Message> messageList, public void deleteMessages(final Account account, final String folder, final Message[] messages,
final MessagingListener listener) final MessagingListener listener)
{ {
for (Message message : messageList) for (Message message : messages)
{ {
suppressMessage(account, folder, message); suppressMessage(account, folder, message);
} }
put("deleteMessageList", null, new Runnable() put("deleteMessages", null, new Runnable()
{ {
public void run() public void run()
{ {
for (Message message : messageList) deleteMessagesSynchronous(account, folder, messages, listener);
{
deleteMessageSynchronous(account, folder, message, listener);
}
} }
}); });
} }
public void deleteMessage(final Account account, final String folder, final Message message, private void deleteMessagesSynchronous(final Account account, final String folder, final Message[] messages,
final MessagingListener listener)
{
suppressMessage(account, folder, message);
put("deleteMessage", null, new Runnable()
{
public void run()
{
deleteMessageSynchronous(account, folder, message, listener);
}
});
}
private void deleteMessageSynchronous(final Account account, final String folder, final Message message,
MessagingListener listener) MessagingListener listener)
{ {
Folder localFolder = null;
Folder localTrashFolder = null;
String[] uids = getUidsFromMessages(messages);
try try
{ {
Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication); Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
Folder localFolder = localStore.getFolder(folder); localFolder = localStore.getFolder(folder);
Message lMessage = localFolder.getMessage(message.getUid());
String origUid = message.getUid();
if (lMessage != null)
{
if (folder.equals(account.getTrashFolderName())) if (folder.equals(account.getTrashFolderName()))
{ {
if (Email.DEBUG) if (Email.DEBUG)
{ {
Log.d(Email.LOG_TAG, "Deleting message in trash folder, not copying"); Log.d(Email.LOG_TAG, "Deleting messages in trash folder, not copying");
} }
lMessage.setFlag(Flag.DELETED, true); localFolder.setFlags(messages, new Flag[] { Flag.DELETED }, true);
} }
else else
{ {
Folder localTrashFolder = localStore.getFolder(account.getTrashFolderName()); localTrashFolder = localStore.getFolder(account.getTrashFolderName());
if (localTrashFolder.exists() == false) if (localTrashFolder.exists() == false)
{ {
localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES); localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES);
@ -3271,20 +3274,22 @@ public class MessagingController implements Runnable
{ {
if (Email.DEBUG) if (Email.DEBUG)
{ {
Log.d(Email.LOG_TAG, "Deleting message in normal folder, moving"); Log.d(Email.LOG_TAG, "Deleting messages in normal folder, moving");
} }
localFolder.moveMessages(new Message[] { message }, localTrashFolder); localFolder.moveMessages(messages, localTrashFolder);
} }
} }
} for (Message message : messages)
localFolder.close(false); {
unsuppressMessage(account, folder, message); unsuppressMessage(account, folder, message);
if (listener != null) if (listener != null)
{ {
listener.messageDeleted(account, folder, message); listener.messageDeleted(account, folder, message);
} }
}
for (MessagingListener l : getListeners()) for (MessagingListener l : getListeners())
{ {
l.folderStatusChanged(account, account.getTrashFolderName()); l.folderStatusChanged(account, account.getTrashFolderName());
@ -3295,6 +3300,8 @@ public class MessagingController implements Runnable
Log.d(Email.LOG_TAG, "Delete policy for account " + account.getDescription() + " is " + account.getDeletePolicy()); Log.d(Email.LOG_TAG, "Delete policy for account " + account.getDescription() + " is " + account.getDeletePolicy());
} }
if (folder.equals(account.getOutboxFolderName())) if (folder.equals(account.getOutboxFolderName()))
{
for (Message message : messages)
{ {
// If the message was in the Outbox, then it has been copied to local Trash, and has // If the message was in the Outbox, then it has been copied to local Trash, and has
// to be copied to remote trash // to be copied to remote trash
@ -3307,24 +3314,22 @@ public class MessagingController implements Runnable
message.getUid() message.getUid()
}; };
queuePendingCommand(account, command); queuePendingCommand(account, command);
}
processPendingCommands(account); processPendingCommands(account);
} }
else if (folder.equals(account.getTrashFolderName()) && account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE) else if (folder.equals(account.getTrashFolderName()) && account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE)
{ {
queueSetFlag(account, folder, Boolean.toString(true), Flag.DELETED.toString(), new String[] { origUid }); queueSetFlag(account, folder, Boolean.toString(true), Flag.DELETED.toString(), uids);
processPendingCommands(account); processPendingCommands(account);
} }
else if (account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE) else if (account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE)
{ {
PendingCommand command = new PendingCommand(); queueMoveOrCopy(account, folder, account.getTrashFolderName(), false, uids);
command.command = PENDING_COMMAND_MOVE_OR_COPY;
command.arguments = new String[] { folder, origUid, account.getTrashFolderName(), "false" };
queuePendingCommand(account, command);
processPendingCommands(account); processPendingCommands(account);
} }
else if (account.getDeletePolicy() == Account.DELETE_POLICY_MARK_AS_READ) else if (account.getDeletePolicy() == Account.DELETE_POLICY_MARK_AS_READ)
{ {
queueSetFlag(account, folder, Boolean.toString(true), Flag.SEEN.toString(), new String[] { origUid }); queueSetFlag(account, folder, Boolean.toString(true), Flag.SEEN.toString(), uids);
processPendingCommands(account); processPendingCommands(account);
} }
else else
@ -3341,6 +3346,27 @@ public class MessagingController implements Runnable
throw new RuntimeException("Error deleting message from local store.", me); throw new RuntimeException("Error deleting message from local store.", me);
} }
finally
{
if (localFolder != null)
{
localFolder.close(false);
}
if (localTrashFolder != null)
{
localTrashFolder.close(false);
}
}
}
private String[] getUidsFromMessages(Message[] messages)
{
String[] uids = new String[messages.length];
for (int i = 0; i < messages.length; i++)
{
uids[i] = messages[i].getUid();
}
return uids;
} }
private void processPendingEmptyTrash(PendingCommand command, Account account) throws MessagingException private void processPendingEmptyTrash(PendingCommand command, Account account) throws MessagingException

View File

@ -857,7 +857,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
/* /*
* We're sending a previously saved draft, so delete the old draft first. * We're sending a previously saved draft, so delete the old draft first.
*/ */
MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mFolder, mSourceMessage, null); MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mFolder, new Message[] { mSourceMessage }, null);
} }
if (mDraftUid != null) if (mDraftUid != null)
{ {
@ -866,7 +866,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
*/ */
Message draftMessage = new MimeMessage(); Message draftMessage = new MimeMessage();
draftMessage.setUid(mDraftUid); draftMessage.setUid(mDraftUid);
MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mAccount.getDraftsFolderName(), draftMessage, null); MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mAccount.getDraftsFolderName(), new Message[] { draftMessage }, null);
} }
MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null); MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null);
} }
@ -901,13 +901,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
{ {
if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessageUid != null) if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessageUid != null)
{ {
MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mFolder, mSourceMessage, null); MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mFolder, new Message[] { mSourceMessage }, null);
} }
} }
if (mDraftUid != null) if (mDraftUid != null)
{ {
Message draftMessage = new MimeMessage(); Message draftMessage = new MimeMessage();
MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mAccount.getDraftsFolderName(), draftMessage, null); MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mAccount.getDraftsFolderName(), new Message[] { draftMessage }, null);
} }
mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT); mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT);
mDraftNeedsSaving = false; mDraftNeedsSaving = false;

View File

@ -882,7 +882,7 @@ public class MessageList
private void onDelete(MessageInfoHolder holder, int position) private void onDelete(MessageInfoHolder holder, int position)
{ {
mAdapter.removeMessage(holder); mAdapter.removeMessage(holder);
MessagingController.getInstance(getApplication()).deleteMessage(mAccount, holder.message.getFolder().getName(), holder.message, null); MessagingController.getInstance(getApplication()).deleteMessages(mAccount, holder.message.getFolder().getName(), new Message[] { holder.message }, null);
mListView.setSelection(position); mListView.setSelection(position);
} }
@ -2257,7 +2257,7 @@ public class MessageList
{ {
if (mBatchDeleteButton == v) if (mBatchDeleteButton == v)
{ {
MessagingController.getInstance(getApplication()).deleteMessageList(mAccount, mCurrentFolder.name, messageList, null); MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mCurrentFolder.name, messageList.toArray(new Message[0]), null);
mSelectedCount = 0; mSelectedCount = 0;
configureBatchButtons(); configureBatchButtons();
} }

View File

@ -758,10 +758,10 @@ public class MessageView extends K9Activity
// Remove this message's Uid locally // Remove this message's Uid locally
mMessageUids.remove(messageToDelete.getUid()); mMessageUids.remove(messageToDelete.getUid());
MessagingController.getInstance(getApplication()).deleteMessage( MessagingController.getInstance(getApplication()).deleteMessages(
accountForDelete, accountForDelete,
folderForDelete, folderForDelete,
messageToDelete, new Message[] { messageToDelete },
null); null);
if (mNextMessageUid != null) if (mNextMessageUid != null)
{ {

View File

@ -103,6 +103,15 @@ public abstract class Folder
public void moveMessages(Message[] msgs, Folder folder) throws MessagingException {} ; public void moveMessages(Message[] msgs, Folder folder) throws MessagingException {} ;
public void delete(Message[] msgs, String trashFolderName) throws MessagingException
{
for (Message message : msgs)
{
Message myMessage = getMessage(message.getUid());
myMessage.delete(trashFolderName);
}
}
public abstract void setFlags(Message[] messages, Flag[] flags, boolean value) public abstract void setFlags(Message[] messages, Flag[] flags, boolean value)
throws MessagingException; throws MessagingException;

View File

@ -769,6 +769,47 @@ public class ImapStore extends Store
setFlags(messages, new Flag[] { Flag.DELETED }, true); setFlags(messages, new Flag[] { Flag.DELETED }, true);
} }
public void delete(Message[] messages, String trashFolderName) throws MessagingException
{
if (getName().equals(trashFolderName))
{
setFlags(messages, new Flag[] { Flag.DELETED }, true);
expunge();
}
else
{
ImapFolder remoteTrashFolder = (ImapFolder)getStore().getFolder(trashFolderName);
/*
* Attempt to copy the remote message to the remote trash folder.
*/
remoteTrashFolder.mExists = false; // Force redetection of Trash folder; some desktops delete it
if (!remoteTrashFolder.exists())
{
/*
* If the remote trash folder doesn't exist we try to create it.
*/
Log.i(Email.LOG_TAG, "IMAPMessage.delete: attempting to create remote '" + trashFolderName + "' folder for " + getLogId());
remoteTrashFolder.create(FolderType.HOLDS_MESSAGES);
}
if (remoteTrashFolder.exists())
{
if (Email.DEBUG)
{
Log.d(Email.LOG_TAG, "IMAPMessage.delete: copying remote " + messages.length + " messages to '" + trashFolderName + "' for " + getLogId());
}
moveMessages(messages, remoteTrashFolder);
expunge();
}
else
{
throw new MessagingException("IMAPMessage.delete: remote Trash folder " + trashFolderName + " does not exist and could not be created for " + getLogId()
, true);
}
}
}
@Override @Override
public int getMessageCount() public int getMessageCount()
{ {
@ -2256,46 +2297,8 @@ public class ImapStore extends Store
@Override @Override
public void delete(String trashFolderName) throws MessagingException public void delete(String trashFolderName) throws MessagingException
{ {
ImapFolder iFolder = (ImapFolder)getFolder(); getFolder().delete(new Message[] { this }, trashFolderName);
if (iFolder.getName().equals(trashFolderName))
{
setFlag(Flag.DELETED, true);
iFolder.expunge();
} }
else
{
ImapFolder remoteTrashFolder = (ImapFolder)iFolder.getStore().getFolder(trashFolderName);
/*
* Attempt to copy the remote message to the remote trash folder.
*/
remoteTrashFolder.mExists = false; // Force redetection of Trash folder; some desktops delete it
if (!remoteTrashFolder.exists())
{
/*
* If the remote trash folder doesn't exist we try to create it.
*/
Log.i(Email.LOG_TAG, "IMAPMessage.delete: attempting to create remote '" + trashFolderName + "' folder for " + iFolder.getLogId());
remoteTrashFolder.create(FolderType.HOLDS_MESSAGES);
}
if (remoteTrashFolder.exists())
{
if (Email.DEBUG)
{
Log.d(Email.LOG_TAG, "IMAPMessage.delete: copying remote message to '" + trashFolderName + "' for " + iFolder.getLogId());
}
iFolder.copyMessages(new Message[] { this }, remoteTrashFolder);
setFlag(Flag.DELETED, true);
iFolder.expunge();
}
else
{
throw new MessagingException("IMAPMessage.delete: remote Trash folder " + trashFolderName + " does not exist and could not be created for " + iFolder.getLogId()
, true);
}
}
}
} }
class ImapBodyPart extends MimeBodyPart class ImapBodyPart extends MimeBodyPart