Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 4c464336 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #8623 from cketti/special-case-archive

Add archive methods to `MessagingController`
parents a3a343f3 72c48ae4
Loading
Loading
Loading
Loading
+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)
    }
}
+21 −7
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
@@ -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);
    }

@@ -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);
    }
@@ -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) {
@@ -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);
@@ -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);
@@ -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()) {
@@ -2513,7 +2527,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi

    }

    private interface MessageActor {
    interface MessageActor {
        void act(Account account, LocalFolder messageFolder, List<LocalMessage> messages);
    }

@@ -2676,7 +2690,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi
        }
    }

    private enum MoveOrCopyFlavor {
    enum MoveOrCopyFlavor {
        MOVE, COPY, MOVE_AND_MARK_AS_READ
    }
}
+3 −14
Original line number Diff line number Diff line
@@ -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")
        }
@@ -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) {
+6 −4
Original line number Diff line number Diff line
@@ -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)
        }
    }

+9 −1
Original line number Diff line number Diff line
@@ -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() {