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 authored and Valodim committed Mar 14, 2018
1 parent a8c4f69 commit 48ffbfd
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1833,13 +1833,27 @@ private void queueMoveOrCopy(Account account, String srcFolder, String destFolde
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 {
PendingCommand command = PendingMoveOrCopy.create(srcFolder, destFolder, isCopy, uidMap);
queuePendingCommand(srcAccount, command);
}
} else {
PendingCommand command = PendingMoveOrCopy.create(srcFolder, destFolder, isCopy, uidMap);
queuePendingCommand(account, command);
if (uidMap == null) {
return;
}

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 @@ -2875,7 +2889,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 @@ -2884,15 +2898,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 @@ -2903,7 +2917,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) {
Timber.e(e, "Exception while moving messages");
}
Expand All @@ -2915,26 +2930,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 @@ -2943,7 +2958,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) {
Timber.e(e, "Exception while copying messages");
Expand All @@ -2957,24 +2972,33 @@ 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) {
Timber.i("moveOrCopyMessageSynchronous: source account = %s, source folder = %s, %d messages, " +
"destination account = %s, destination folder = %s, isCopy = %s", srcAccount.getName(),
srcFolder, inMessages.size(), destAccount.getName(), destFolder, isCopy);

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

if (!isCopy && (!srcRemoteStore.isMoveCapable() || !destRemoteStore.isMoveCapable())) {
Timber.e("Cannot move: incompatible source or destination store!");
return;
}
if (isCopy && !remoteStore.isCopyCapable()) {
if (isCopy && (!srcRemoteStore.isCopyCapable() || !destRemoteStore.isCopyCapable())) {
Timber.e("Cannot copy: incompatible source or destination store!");
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 @@ -2997,9 +3021,6 @@ 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);

Map<String, String> uidMap;

if (isCopy) {
Expand All @@ -3014,7 +3035,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 @@ -3023,28 +3044,29 @@ 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);
Expand Down Expand Up @@ -3255,15 +3277,16 @@ private void deleteMessagesSynchronous(final Account account, final String folde
if (folder.equals(account.getTrashFolderName())) {
queueSetFlag(account, folder, true, Flag.DELETED, syncedMessageUids);
} else {
queueMoveOrCopy(account, folder, account.getTrashFolderName(), false,
syncedMessageUids, uidMap);
queueMoveOrCopy(account, folder, account.getTrashFolderName(), false, syncedMessageUids);
}
processPendingCommands(account);
} else if (account.getDeletePolicy() == DeletePolicy.MARK_AS_READ) {
queueSetFlag(account, folder, true, Flag.SEEN, syncedMessageUids);
processPendingCommands(account);
} else {
Timber.d("Delete policy %s prevents delete from server", account.getDeletePolicy());
// TODO
// queueMoveOrCopy(account, folder, account, account.getTrashFolderName(), false, uids, uidMap);
}
}

Expand Down
Loading

0 comments on commit 48ffbfd

Please sign in to comment.