Loading legacy/core/src/main/java/com/fsck/k9/controller/ArchiveOperations.kt 0 → 100644 +91 −0 Original line number Diff line number Diff line package com.fsck.k9.controller import app.k9mail.legacy.account.Account import app.k9mail.legacy.message.controller.MessageReference import com.fsck.k9.controller.MessagingController.MessageActor import com.fsck.k9.controller.MessagingController.MoveOrCopyFlavor import com.fsck.k9.mailstore.LocalFolder import com.fsck.k9.mailstore.LocalMessage import timber.log.Timber internal class ArchiveOperations( private val messagingController: MessagingController, ) { fun archiveThreads(messages: List<MessageReference>) { archiveByFolder("archiveThreads", messages) { account, folderId, messagesInFolder, archiveFolderId -> archiveThreads(account, folderId, messagesInFolder, archiveFolderId) } } fun archiveMessages(messages: List<MessageReference>) { archiveByFolder("archiveMessages", messages) { account, folderId, messagesInFolder, archiveFolderId -> archiveMessages(account, folderId, messagesInFolder, archiveFolderId) } } fun archiveMessage(message: MessageReference) { archiveMessages(listOf(message)) } private fun archiveByFolder( description: String, messages: List<MessageReference>, action: (account: Account, folderId: Long, messagesInFolder: List<LocalMessage>, archiveFolderId: Long) -> Unit, ) { actOnMessagesGroupedByAccountAndFolder(messages) { account, messageFolder, messagesInFolder -> val sourceFolderId = messageFolder.databaseId when (val archiveFolderId = account.archiveFolderId) { null -> { Timber.v("No archive folder configured for account %s", account) } sourceFolderId -> { Timber.v("Skipping messages already in archive folder") } else -> { messagingController.suppressMessages(account, messagesInFolder) messagingController.putBackground(description, null) { action(account, sourceFolderId, messagesInFolder, archiveFolderId) } } } } } private fun archiveThreads( account: Account, sourceFolderId: Long, messages: List<LocalMessage>, archiveFolderId: Long, ) { val messagesInThreads = messagingController.collectMessagesInThreads(account, messages) archiveMessages(account, sourceFolderId, messagesInThreads, archiveFolderId) } private fun archiveMessages( account: Account, sourceFolderId: Long, messages: List<LocalMessage>, archiveFolderId: Long, ) { messagingController.moveOrCopyMessageSynchronous( account, sourceFolderId, messages, archiveFolderId, MoveOrCopyFlavor.MOVE, ) } private fun actOnMessagesGroupedByAccountAndFolder( messages: List<MessageReference>, block: (account: Account, messageFolder: LocalFolder, messages: List<LocalMessage>) -> Unit, ) { val actor = MessageActor { account, messageFolder, messagesInFolder -> block(account, messageFolder, messagesInFolder) } messagingController.actOnMessagesGroupedByAccountAndFolder(messages, actor) } } legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java +21 −7 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener(); private final DraftOperations draftOperations; private final NotificationOperations notificationOperations; private final ArchiveOperations archiveOperations; private volatile boolean stopped = false; Loading Loading @@ -170,6 +171,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi draftOperations = new DraftOperations(this, messageStoreManager, saveMessageDataCreator); notificationOperations = new NotificationOperations(notificationController, preferences, messageStoreManager); archiveOperations = new ArchiveOperations(this); } private void initializeControllerExtensions(List<ControllerExtension> controllerExtensions) { Loading Loading @@ -232,7 +234,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi putCommand(queuedCommands, description, listener, runnable, true); } private void putBackground(String description, MessagingListener listener, Runnable runnable) { void putBackground(String description, MessagingListener listener, Runnable runnable) { putCommand(queuedCommands, description, listener, runnable, false); } Loading Loading @@ -319,7 +321,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } private void suppressMessages(Account account, List<LocalMessage> messages) { void suppressMessages(Account account, List<LocalMessage> messages) { MessageListCache cache = MessageListCache.getCache(account.getUuid()); cache.hideMessages(messages); } Loading Loading @@ -1749,7 +1751,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi copyMessages(account, srcFolderId, Collections.singletonList(message), destFolderId); } private void moveOrCopyMessageSynchronous(Account account, long srcFolderId, List<LocalMessage> inMessages, void moveOrCopyMessageSynchronous(Account account, long srcFolderId, List<LocalMessage> inMessages, long destFolderId, MoveOrCopyFlavor operation) { if (operation == MoveOrCopyFlavor.MOVE_AND_MARK_AS_READ) { Loading Loading @@ -1871,6 +1873,18 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } public void archiveThreads(List<MessageReference> messages) { archiveOperations.archiveThreads(messages); } public void archiveMessages(List<MessageReference> messages) { archiveOperations.archiveMessages(messages); } public void archiveMessage(MessageReference message) { archiveOperations.archiveMessage(message); } public void expunge(Account account, long folderId) { putBackground("expunge", null, () -> { queueExpunge(account, folderId); Loading Loading @@ -1919,7 +1933,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } private List<LocalMessage> collectMessagesInThreads(Account account, List<LocalMessage> messages) List<LocalMessage> collectMessagesInThreads(Account account, List<LocalMessage> messages) throws MessagingException { LocalStore localStore = localStoreProvider.getInstance(account); Loading Loading @@ -2457,7 +2471,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi serverSettings.authenticationType == AuthType.XOAUTH2 && account.getOAuthState() == null; } private void actOnMessagesGroupedByAccountAndFolder(List<MessageReference> messages, MessageActor actor) { void actOnMessagesGroupedByAccountAndFolder(List<MessageReference> messages, MessageActor actor) { Map<String, Map<Long, List<MessageReference>>> accountMap = groupMessagesByAccountAndFolder(messages); for (Map.Entry<String, Map<Long, List<MessageReference>>> entry : accountMap.entrySet()) { Loading Loading @@ -2513,7 +2527,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } private interface MessageActor { interface MessageActor { void act(Account account, LocalFolder messageFolder, List<LocalMessage> messages); } Loading Loading @@ -2676,7 +2690,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } private enum MoveOrCopyFlavor { enum MoveOrCopyFlavor { MOVE, COPY, MOVE_AND_MARK_AS_READ } } legacy/core/src/main/java/com/fsck/k9/notification/NotificationActionService.kt +3 −14 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ class NotificationActionService : Service() { when (intent.action) { ACTION_MARK_AS_READ -> markMessagesAsRead(intent, account) ACTION_DELETE -> deleteMessages(intent) ACTION_ARCHIVE -> archiveMessages(intent, account) ACTION_ARCHIVE -> archiveMessages(intent) ACTION_SPAM -> markMessageAsSpam(intent, account) ACTION_DISMISS -> Timber.i("Notification dismissed") } Loading Loading @@ -88,24 +88,13 @@ class NotificationActionService : Service() { messagingController.deleteMessages(messageReferences) } private fun archiveMessages(intent: Intent, account: Account) { private fun archiveMessages(intent: Intent) { Timber.i("NotificationActionService archiving messages") val archiveFolderId = account.archiveFolderId if (archiveFolderId == null || !messagingController.isMoveCapable(account)) { Timber.w("Cannot archive messages") return } val messageReferenceStrings = intent.getStringArrayListExtra(EXTRA_MESSAGE_REFERENCES) val messageReferences = MessageReferenceHelper.toMessageReferenceList(messageReferenceStrings) for (messageReference in messageReferences) { if (messagingController.isMoveCapable(messageReference)) { val sourceFolderId = messageReference.folderId messagingController.moveMessage(account, sourceFolderId, messageReference, archiveFolderId) } } messagingController.archiveMessages(messageReferences) } private fun markMessageAsSpam(intent: Intent, account: Account) { Loading legacy/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListFragment.kt +6 −4 Original line number Diff line number Diff line Loading @@ -1113,10 +1113,12 @@ class MessageListFragment : } private fun onArchive(messages: List<MessageReference>) { for ((account, messagesInAccount) in groupMessagesByAccount(messages)) { account.archiveFolderId?.let { archiveFolderId -> move(messagesInAccount, archiveFolderId) } if (!checkCopyOrMovePossible(messages, FolderOperation.MOVE)) return if (showingThreadedList) { messagingController.archiveThreads(messages) } else { messagingController.archiveMessages(messages) } } Loading legacy/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.kt +9 −1 Original line number Diff line number Diff line Loading @@ -536,7 +536,15 @@ class MessageViewFragment : } fun onArchive() { onRefile(account.archiveFolderId) if (!account.hasArchiveFolder()) return if (!messagingController.isMoveCapable(messageReference)) { Toast.makeText(activity, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG).show() return } fragmentListener.performNavigationAfterMessageRemoval() messagingController.archiveMessage(messageReference) } private fun onSpam() { Loading Loading
legacy/core/src/main/java/com/fsck/k9/controller/ArchiveOperations.kt 0 → 100644 +91 −0 Original line number Diff line number Diff line package com.fsck.k9.controller import app.k9mail.legacy.account.Account import app.k9mail.legacy.message.controller.MessageReference import com.fsck.k9.controller.MessagingController.MessageActor import com.fsck.k9.controller.MessagingController.MoveOrCopyFlavor import com.fsck.k9.mailstore.LocalFolder import com.fsck.k9.mailstore.LocalMessage import timber.log.Timber internal class ArchiveOperations( private val messagingController: MessagingController, ) { fun archiveThreads(messages: List<MessageReference>) { archiveByFolder("archiveThreads", messages) { account, folderId, messagesInFolder, archiveFolderId -> archiveThreads(account, folderId, messagesInFolder, archiveFolderId) } } fun archiveMessages(messages: List<MessageReference>) { archiveByFolder("archiveMessages", messages) { account, folderId, messagesInFolder, archiveFolderId -> archiveMessages(account, folderId, messagesInFolder, archiveFolderId) } } fun archiveMessage(message: MessageReference) { archiveMessages(listOf(message)) } private fun archiveByFolder( description: String, messages: List<MessageReference>, action: (account: Account, folderId: Long, messagesInFolder: List<LocalMessage>, archiveFolderId: Long) -> Unit, ) { actOnMessagesGroupedByAccountAndFolder(messages) { account, messageFolder, messagesInFolder -> val sourceFolderId = messageFolder.databaseId when (val archiveFolderId = account.archiveFolderId) { null -> { Timber.v("No archive folder configured for account %s", account) } sourceFolderId -> { Timber.v("Skipping messages already in archive folder") } else -> { messagingController.suppressMessages(account, messagesInFolder) messagingController.putBackground(description, null) { action(account, sourceFolderId, messagesInFolder, archiveFolderId) } } } } } private fun archiveThreads( account: Account, sourceFolderId: Long, messages: List<LocalMessage>, archiveFolderId: Long, ) { val messagesInThreads = messagingController.collectMessagesInThreads(account, messages) archiveMessages(account, sourceFolderId, messagesInThreads, archiveFolderId) } private fun archiveMessages( account: Account, sourceFolderId: Long, messages: List<LocalMessage>, archiveFolderId: Long, ) { messagingController.moveOrCopyMessageSynchronous( account, sourceFolderId, messages, archiveFolderId, MoveOrCopyFlavor.MOVE, ) } private fun actOnMessagesGroupedByAccountAndFolder( messages: List<MessageReference>, block: (account: Account, messageFolder: LocalFolder, messages: List<LocalMessage>) -> Unit, ) { val actor = MessageActor { account, messageFolder, messagesInFolder -> block(account, messageFolder, messagesInFolder) } messagingController.actOnMessagesGroupedByAccountAndFolder(messages, actor) } }
legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java +21 −7 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener(); private final DraftOperations draftOperations; private final NotificationOperations notificationOperations; private final ArchiveOperations archiveOperations; private volatile boolean stopped = false; Loading Loading @@ -170,6 +171,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi draftOperations = new DraftOperations(this, messageStoreManager, saveMessageDataCreator); notificationOperations = new NotificationOperations(notificationController, preferences, messageStoreManager); archiveOperations = new ArchiveOperations(this); } private void initializeControllerExtensions(List<ControllerExtension> controllerExtensions) { Loading Loading @@ -232,7 +234,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi putCommand(queuedCommands, description, listener, runnable, true); } private void putBackground(String description, MessagingListener listener, Runnable runnable) { void putBackground(String description, MessagingListener listener, Runnable runnable) { putCommand(queuedCommands, description, listener, runnable, false); } Loading Loading @@ -319,7 +321,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } private void suppressMessages(Account account, List<LocalMessage> messages) { void suppressMessages(Account account, List<LocalMessage> messages) { MessageListCache cache = MessageListCache.getCache(account.getUuid()); cache.hideMessages(messages); } Loading Loading @@ -1749,7 +1751,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi copyMessages(account, srcFolderId, Collections.singletonList(message), destFolderId); } private void moveOrCopyMessageSynchronous(Account account, long srcFolderId, List<LocalMessage> inMessages, void moveOrCopyMessageSynchronous(Account account, long srcFolderId, List<LocalMessage> inMessages, long destFolderId, MoveOrCopyFlavor operation) { if (operation == MoveOrCopyFlavor.MOVE_AND_MARK_AS_READ) { Loading Loading @@ -1871,6 +1873,18 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } public void archiveThreads(List<MessageReference> messages) { archiveOperations.archiveThreads(messages); } public void archiveMessages(List<MessageReference> messages) { archiveOperations.archiveMessages(messages); } public void archiveMessage(MessageReference message) { archiveOperations.archiveMessage(message); } public void expunge(Account account, long folderId) { putBackground("expunge", null, () -> { queueExpunge(account, folderId); Loading Loading @@ -1919,7 +1933,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } private List<LocalMessage> collectMessagesInThreads(Account account, List<LocalMessage> messages) List<LocalMessage> collectMessagesInThreads(Account account, List<LocalMessage> messages) throws MessagingException { LocalStore localStore = localStoreProvider.getInstance(account); Loading Loading @@ -2457,7 +2471,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi serverSettings.authenticationType == AuthType.XOAUTH2 && account.getOAuthState() == null; } private void actOnMessagesGroupedByAccountAndFolder(List<MessageReference> messages, MessageActor actor) { void actOnMessagesGroupedByAccountAndFolder(List<MessageReference> messages, MessageActor actor) { Map<String, Map<Long, List<MessageReference>>> accountMap = groupMessagesByAccountAndFolder(messages); for (Map.Entry<String, Map<Long, List<MessageReference>>> entry : accountMap.entrySet()) { Loading Loading @@ -2513,7 +2527,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } private interface MessageActor { interface MessageActor { void act(Account account, LocalFolder messageFolder, List<LocalMessage> messages); } Loading Loading @@ -2676,7 +2690,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } private enum MoveOrCopyFlavor { enum MoveOrCopyFlavor { MOVE, COPY, MOVE_AND_MARK_AS_READ } }
legacy/core/src/main/java/com/fsck/k9/notification/NotificationActionService.kt +3 −14 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ class NotificationActionService : Service() { when (intent.action) { ACTION_MARK_AS_READ -> markMessagesAsRead(intent, account) ACTION_DELETE -> deleteMessages(intent) ACTION_ARCHIVE -> archiveMessages(intent, account) ACTION_ARCHIVE -> archiveMessages(intent) ACTION_SPAM -> markMessageAsSpam(intent, account) ACTION_DISMISS -> Timber.i("Notification dismissed") } Loading Loading @@ -88,24 +88,13 @@ class NotificationActionService : Service() { messagingController.deleteMessages(messageReferences) } private fun archiveMessages(intent: Intent, account: Account) { private fun archiveMessages(intent: Intent) { Timber.i("NotificationActionService archiving messages") val archiveFolderId = account.archiveFolderId if (archiveFolderId == null || !messagingController.isMoveCapable(account)) { Timber.w("Cannot archive messages") return } val messageReferenceStrings = intent.getStringArrayListExtra(EXTRA_MESSAGE_REFERENCES) val messageReferences = MessageReferenceHelper.toMessageReferenceList(messageReferenceStrings) for (messageReference in messageReferences) { if (messagingController.isMoveCapable(messageReference)) { val sourceFolderId = messageReference.folderId messagingController.moveMessage(account, sourceFolderId, messageReference, archiveFolderId) } } messagingController.archiveMessages(messageReferences) } private fun markMessageAsSpam(intent: Intent, account: Account) { Loading
legacy/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListFragment.kt +6 −4 Original line number Diff line number Diff line Loading @@ -1113,10 +1113,12 @@ class MessageListFragment : } private fun onArchive(messages: List<MessageReference>) { for ((account, messagesInAccount) in groupMessagesByAccount(messages)) { account.archiveFolderId?.let { archiveFolderId -> move(messagesInAccount, archiveFolderId) } if (!checkCopyOrMovePossible(messages, FolderOperation.MOVE)) return if (showingThreadedList) { messagingController.archiveThreads(messages) } else { messagingController.archiveMessages(messages) } } Loading
legacy/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.kt +9 −1 Original line number Diff line number Diff line Loading @@ -536,7 +536,15 @@ class MessageViewFragment : } fun onArchive() { onRefile(account.archiveFolderId) if (!account.hasArchiveFolder()) return if (!messagingController.isMoveCapable(messageReference)) { Toast.makeText(activity, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG).show() return } fragmentListener.performNavigationAfterMessageRemoval() messagingController.archiveMessage(messageReference) } private fun onSpam() { Loading