Skip to content

Commit

Permalink
Modify move and copy mechanisms to allow transfer of messages across …
Browse files Browse the repository at this point in the history
…accounts
  • Loading branch information
Hari committed Aug 25, 2017
1 parent 0f1bc05 commit 36ce2ae
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 92 deletions.
11 changes: 9 additions & 2 deletions k9mail/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@

<application
android:name="K9"
android:allowBackup="false"
android:allowTaskReparenting="false"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/Theme.K9.Startup"
android:resizeableActivity="true"
android:allowBackup="false">
android:theme="@style/Theme.K9.Startup">

<meta-data
android:name="android.app.default_searchable"
Expand Down Expand Up @@ -144,6 +144,13 @@
android:configChanges="locale"
android:label="@string/account_setup_names_title"/>

<activity
android:name=".activity.ChooseAccount"
android:configChanges="locale"
android:label="@string/choose_account_title"
android:noHistory="true"
android:theme="@style/Theme.K9Dialog"/>

<activity
android:name=".activity.ChooseFolder"
android:configChanges="locale"
Expand Down
25 changes: 25 additions & 0 deletions k9mail/src/main/java/com/fsck/k9/activity/ChooseAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.fsck.k9.activity;


import android.content.Intent;

import com.fsck.k9.BaseAccount;


public class ChooseAccount extends AccountList {

public static final String EXTRA_ACCOUNT_UUID = "com.fsck.k9.ChooseAccount_account_uuid";

@Override
protected boolean displaySpecialAccounts() {
return true;
}

@Override
protected void onAccountSelected(BaseAccount account) {
Intent intent = new Intent();
intent.putExtra(EXTRA_ACCOUNT_UUID, account.getUuid());
setResult(RESULT_OK, intent);
finish();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1867,25 +1867,39 @@ void processPendingAppend(PendingAppend command, Account account) throws Messagi
}
}

private void queueMoveOrCopy(Account account, String srcFolder, String destFolder, boolean isCopy,
List<String> uids) {
private void queueMoveOrCopy(Account account, String srcFolder, String destFolder,
boolean isCopy, List<String> uids) {
if (account.getErrorFolderName().equals(srcFolder)) {
return;
}
PendingCommand command = PendingMoveOrCopy.create(srcFolder, destFolder, isCopy, uids);
queuePendingCommand(account, command);
}

private void queueMoveOrCopy(Account account, String srcFolder, String destFolder,
private void queueMoveOrCopy(Account srcAccount, String srcFolder, Account destAccount, String destFolder,
boolean isCopy, List<String> uids, Map<String, String> uidMap) {
if (uidMap == null || uidMap.isEmpty()) {
queueMoveOrCopy(account, srcFolder, destFolder, isCopy, uids);
if (srcAccount.equals(destAccount)) {
if (uidMap == null || uidMap.isEmpty()) {
queueMoveOrCopy(srcAccount, srcFolder, destFolder, isCopy, uids);
} else {
if (srcAccount.getErrorFolderName().equals(srcFolder)) {
return;
}
PendingCommand command = PendingMoveOrCopy.create(srcFolder, destFolder, isCopy, uidMap);
queuePendingCommand(srcAccount, command);
}
} else {
if (account.getErrorFolderName().equals(srcFolder)) {
if (uidMap == null) {
return;
}
PendingCommand command = PendingMoveOrCopy.create(srcFolder, destFolder, isCopy, uidMap);
queuePendingCommand(account, command);

for (String uid : uidMap.values()) {
PendingCommand command = PendingAppend.create(destFolder, uid);
queuePendingCommand(destAccount, command);
}
if (!isCopy) {
queueSetFlag(srcAccount, srcFolder, true, Flag.DELETED, uids);
}
}
}

Expand Down Expand Up @@ -3027,7 +3041,7 @@ public boolean isCopyCapable(final Account account) {
}

public void moveMessages(final Account srcAccount, final String srcFolder,
List<MessageReference> messageReferences, final String destFolder) {
List<MessageReference> messageReferences, final Account destAccount, final String destFolder) {
actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() {
@Override
public void act(final Account account, LocalFolder messageFolder, final List<LocalMessage> messages) {
Expand All @@ -3036,15 +3050,15 @@ public void act(final Account account, LocalFolder messageFolder, final List<Loc
putBackground("moveMessages", null, new Runnable() {
@Override
public void run() {
moveOrCopyMessageSynchronous(account, srcFolder, messages, destFolder, false);
moveOrCopyMessageSynchronous(account, srcFolder, messages, destAccount, destFolder, false);
}
});
}
});
}

public void moveMessagesInThread(Account srcAccount, final String srcFolder,
final List<MessageReference> messageReferences, final String destFolder) {
final List<MessageReference> messageReferences, final Account destAccount, final String destFolder) {
actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() {
@Override
public void act(final Account account, LocalFolder messageFolder, final List<LocalMessage> messages) {
Expand All @@ -3055,7 +3069,8 @@ public void act(final Account account, LocalFolder messageFolder, final List<Loc
public void run() {
try {
List<Message> messagesInThreads = collectMessagesInThreads(account, messages);
moveOrCopyMessageSynchronous(account, srcFolder, messagesInThreads, destFolder, false);
moveOrCopyMessageSynchronous(account, srcFolder, messagesInThreads, destAccount, destFolder,
false);
} catch (MessagingException e) {
addErrorMessage(account, "Exception while moving messages", e);
}
Expand All @@ -3067,26 +3082,26 @@ public void run() {

public void moveMessage(final Account account, final String srcFolder, final MessageReference message,
final String destFolder) {
moveMessages(account, srcFolder, Collections.singletonList(message), destFolder);
moveMessages(account, srcFolder, Collections.singletonList(message), account, destFolder);
}

public void copyMessages(final Account srcAccount, final String srcFolder,
final List<MessageReference> messageReferences, final String destFolder) {
final List<MessageReference> messageReferences, final Account destAccount, final String destFolder) {
actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() {
@Override
public void act(final Account account, LocalFolder messageFolder, final List<LocalMessage> messages) {
putBackground("copyMessages", null, new Runnable() {
@Override
public void run() {
moveOrCopyMessageSynchronous(srcAccount, srcFolder, messages, destFolder, true);
moveOrCopyMessageSynchronous(srcAccount, srcFolder, messages, destAccount, destFolder, true);
}
});
}
});
}

public void copyMessagesInThread(Account srcAccount, final String srcFolder,
final List<MessageReference> messageReferences, final String destFolder) {
final List<MessageReference> messageReferences, final Account destAccount, final String destFolder) {
actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() {
@Override
public void act(final Account account, LocalFolder messageFolder, final List<LocalMessage> messages) {
Expand All @@ -3095,7 +3110,7 @@ public void act(final Account account, LocalFolder messageFolder, final List<Loc
public void run() {
try {
List<Message> messagesInThreads = collectMessagesInThreads(account, messages);
moveOrCopyMessageSynchronous(account, srcFolder, messagesInThreads, destFolder,
moveOrCopyMessageSynchronous(account, srcFolder, messagesInThreads, destAccount, destFolder,
true);
} catch (MessagingException e) {
addErrorMessage(account, "Exception while copying messages", e);
Expand All @@ -3109,24 +3124,30 @@ public void run() {
public void copyMessage(final Account account, final String srcFolder, final MessageReference message,
final String destFolder) {

copyMessages(account, srcFolder, Collections.singletonList(message), destFolder);
copyMessages(account, srcFolder, Collections.singletonList(message), account, destFolder);
}

private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder,
final List<? extends Message> inMessages, final String destFolder, final boolean isCopy) {
private void moveOrCopyMessageSynchronous(final Account srcAccount, final String srcFolder,
final List<? extends Message> inMessages, final Account destAccount, final String destFolder,
final boolean isCopy) {

try {
LocalStore localStore = account.getLocalStore();
Store remoteStore = account.getRemoteStore();
if (!isCopy && (!remoteStore.isMoveCapable() || !localStore.isMoveCapable())) {
LocalStore srcLocalStore = srcAccount.getLocalStore();
Store srcRemoteStore = srcAccount.getRemoteStore();
LocalStore destLocalStore = destAccount.getLocalStore();
Store destRemoteStore = destAccount.getRemoteStore();

if (!isCopy && (!srcRemoteStore.isMoveCapable() || !srcLocalStore.isMoveCapable() ||
!destRemoteStore.isMoveCapable() || !destLocalStore.isMoveCapable())) {
return;
}
if (isCopy && (!remoteStore.isCopyCapable() || !localStore.isCopyCapable())) {
if (isCopy && (!srcRemoteStore.isCopyCapable() || !srcLocalStore.isCopyCapable() ||
!destRemoteStore.isCopyCapable() || !destLocalStore.isCopyCapable())) {
return;
}

LocalFolder localSrcFolder = localStore.getFolder(srcFolder);
Folder localDestFolder = localStore.getFolder(destFolder);
LocalFolder localSrcFolder = srcLocalStore.getFolder(srcFolder);
LocalFolder localDestFolder = destLocalStore.getFolder(destFolder);

boolean unreadCountAffected = false;
List<String> uids = new LinkedList<>();
Expand All @@ -3149,8 +3170,9 @@ private void moveOrCopyMessageSynchronous(final Account account, final String sr
origUidMap.put(message.getUid(), message);
}

Timber.i("moveOrCopyMessageSynchronous: source folder = %s, %d messages, destination folder = %s, " +
"isCopy = %s", srcFolder, messages.size(), destFolder, isCopy);
Timber.i("moveOrCopyMessageSynchronous: source account = %s, source folder = %s, %d messages, " +
"destination account = %s, destination folder = %s, isCopy = %s", srcAccount.getName(),
srcFolder, messages.size(), destAccount.getName(), destFolder, isCopy);

Map<String, String> uidMap;

Expand All @@ -3166,7 +3188,7 @@ private void moveOrCopyMessageSynchronous(final Account account, final String sr
// folder, notify the listeners.
int unreadMessageCount = localDestFolder.getUnreadMessageCount();
for (MessagingListener l : getListeners()) {
l.folderStatusChanged(account, destFolder, unreadMessageCount);
l.folderStatusChanged(srcAccount, destFolder, unreadMessageCount);
}
}
} else {
Expand All @@ -3175,33 +3197,34 @@ private void moveOrCopyMessageSynchronous(final Account account, final String sr
String origUid = entry.getKey();
Message message = entry.getValue();
for (MessagingListener l : getListeners()) {
l.messageUidChanged(account, srcFolder, origUid, message.getUid());
l.messageUidChanged(srcAccount, srcFolder, origUid, message.getUid());
}
}
unsuppressMessages(account, messages);
unsuppressMessages(srcAccount, messages);

if (unreadCountAffected) {
// If this move operation changes the unread count, notify the listeners
// that the unread count changed in both the source and destination folder.
int unreadMessageCountSrc = localSrcFolder.getUnreadMessageCount();
int unreadMessageCountDest = localDestFolder.getUnreadMessageCount();
for (MessagingListener l : getListeners()) {
l.folderStatusChanged(account, srcFolder, unreadMessageCountSrc);
l.folderStatusChanged(account, destFolder, unreadMessageCountDest);
l.folderStatusChanged(srcAccount, srcFolder, unreadMessageCountSrc);
l.folderStatusChanged(srcAccount, destFolder, unreadMessageCountDest);
}
}
}

List<String> origUidKeys = new ArrayList<>(origUidMap.keySet());
queueMoveOrCopy(account, srcFolder, destFolder, isCopy, origUidKeys, uidMap);
queueMoveOrCopy(srcAccount, srcFolder, destAccount, destFolder, isCopy, origUidKeys, uidMap);
}

processPendingCommands(account);
processPendingCommands(srcAccount);
processPendingCommandsSynchronous(destAccount);
} catch (UnavailableStorageException e) {
Timber.i("Failed to move/copy message because storage is not available - trying again later.");
throw new UnavailableAccountException(e);
} catch (MessagingException me) {
addErrorMessage(account, null, me);
addErrorMessage(srcAccount, null, me);

throw new RuntimeException("Error moving message", me);
}
Expand Down Expand Up @@ -3390,7 +3413,7 @@ private void deleteMessagesSynchronous(final Account account, final String folde
if (folder.equals(account.getTrashFolderName())) {
queueSetFlag(account, folder, true, Flag.DELETED, uids);
} else {
queueMoveOrCopy(account, folder, account.getTrashFolderName(), false, uids, uidMap);
queueMoveOrCopy(account, folder, account, account.getTrashFolderName(), false, uids, uidMap);
}
processPendingCommands(account);
} else if (account.getDeletePolicy() == DeletePolicy.MARK_AS_READ) {
Expand Down
Loading

0 comments on commit 36ce2ae

Please sign in to comment.