Loading feature/mail/folder/api/src/commonMain/kotlin/net/thunderbird/feature/mail/folder/api/OutboxFolderManager.kt +16 −0 Original line number Diff line number Diff line Loading @@ -87,3 +87,19 @@ fun OutboxFolderManager.getOutboxFolderIdSync(uuid: String, createIfMissing: Boo fun OutboxFolderManager.hasPendingMessagesSync(uuid: String): Boolean = runBlocking { hasPendingMessages(uuid = AccountIdFactory.of(uuid)) } /** * Gets the folder ID of the outbox folder for the given account. * * @param uuid The ID of the account. * @return The folder ID of the outbox folder. * @throws IllegalStateException If the outbox folder could not be found. */ @Discouraged( message = "This is a wrapper for Java compatibility. " + "Always use getOutboxFolderIdSync(uuid: AccountId) instead on Kotlin files.", ) @JvmOverloads fun OutboxFolderManager.getOutboxFolderIdSync(uuid: String, createIfMissing: Boolean = true): Long { return getOutboxFolderIdSync(uuid = AccountIdFactory.of(uuid), createIfMissing = createIfMissing) } legacy/core/src/main/java/com/fsck/k9/controller/KoinModule.kt +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ import com.fsck.k9.notification.NotificationController import com.fsck.k9.notification.NotificationStrategy import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.logging.Logger import net.thunderbird.feature.mail.folder.api.OutboxFolderManager import net.thunderbird.feature.notification.api.sender.NotificationSender import org.koin.core.qualifier.named import org.koin.dsl.binds Loading @@ -35,6 +36,7 @@ val controllerModule = module { get<FeatureFlagProvider>(), get<Logger>(named("syncDebug")), get<NotificationSender>(), get<OutboxFolderManager>(), ) } binds arrayOf(MessagingControllerRegistry::class) Loading legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java +39 −22 Original line number Diff line number Diff line Loading @@ -89,6 +89,8 @@ import net.thunderbird.core.featureflag.FeatureFlagResult.Enabled; import net.thunderbird.core.featureflag.compat.FeatureFlagProviderCompat; import net.thunderbird.core.logging.Logger; import net.thunderbird.core.logging.legacy.Log; import net.thunderbird.feature.mail.folder.api.OutboxFolderManager; import net.thunderbird.feature.mail.folder.api.OutboxFolderManagerKt; import net.thunderbird.feature.notification.api.content.AuthenticationErrorNotification; import net.thunderbird.feature.notification.api.content.NotificationFactoryCoroutineCompat; import net.thunderbird.feature.notification.api.sender.NotificationSender; Loading Loading @@ -144,6 +146,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi private final FeatureFlagProvider featureFlagProvider; private final Logger syncDebugLogger; private final NotificationSenderCompat notificationSender; private final OutboxFolderManager outboxFolderManager; private volatile boolean stopped = false; Loading @@ -168,7 +171,8 @@ public class MessagingController implements MessagingControllerRegistry, Messagi List<ControllerExtension> controllerExtensions, FeatureFlagProvider featureFlagProvider, Logger syncDebugLogger, NotificationSender notificationSender NotificationSender notificationSender, OutboxFolderManager outboxFolderManager ) { this.context = context; this.notificationController = notificationController; Loading @@ -183,6 +187,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi this.featureFlagProvider = featureFlagProvider; this.syncDebugLogger = syncDebugLogger; this.notificationSender = new NotificationSenderCompat(notificationSender); this.outboxFolderManager = outboxFolderManager; controllerThread = new Thread(new Runnable() { @Override Loading Loading @@ -1441,16 +1446,11 @@ public class MessagingController implements MessagingControllerRegistry, Messagi */ public void sendMessage(LegacyAccountDto account, Message message, String plaintextSubject, MessagingListener listener) { try { Long outboxFolderId = account.getOutboxFolderId(); if (outboxFolderId == null) { if (BuildConfig.DEBUG) { throw new AssertionError("Outbox does not exist"); } Log.w("Outbox does not exist"); outboxFolderId = specialLocalFoldersCreator.createOutbox(account); } final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); message.setFlag(Flag.SEEN, true); Loading Loading @@ -1509,8 +1509,12 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } private boolean messagesPendingSend(final LegacyAccountDto account) { Long outboxFolderId = account.getOutboxFolderId(); if (outboxFolderId == null) { final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); if (outboxFolderId == -1L) { Log.w("Could not get Outbox folder ID from Account"); return false; } Loading @@ -1532,9 +1536,14 @@ public class MessagingController implements MessagingControllerRegistry, Messagi return; } LocalStore localStore = localStoreProvider.getInstance(account); OutboxStateRepository outboxStateRepository = localStore.getOutboxStateRepository(); LocalFolder localFolder = localStore.getFolder(account.getOutboxFolderId()); final LocalStore localStore = localStoreProvider.getInstance(account); final OutboxStateRepository outboxStateRepository = localStore.getOutboxStateRepository(); final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); final LocalFolder localFolder = localStore.getFolder(outboxFolderId); if (!localFolder.exists()) { Log.w("Outbox does not exist"); return; Loading @@ -1542,9 +1551,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi localFolder.open(); long outboxFolderId = localFolder.getDatabaseId(); List<LocalMessage> localMessages = localFolder.getMessages(); final List<LocalMessage> localMessages = localFolder.getMessages(); int progress = 0; int todo = localMessages.size(); for (MessagingListener l : getListeners()) { Loading Loading @@ -1688,8 +1695,13 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); for (MessagingListener listener : getListeners()) { listener.folderStatusChanged(account, account.getOutboxFolderId()); listener.folderStatusChanged(account, outboxFolderId); } } Loading Loading @@ -2110,8 +2122,13 @@ public class MessagingController implements MessagingControllerRegistry, Messagi Log.d("Delete policy for account %s is %s", account, account.getDeletePolicy()); Long outboxFolderId = account.getOutboxFolderId(); if (outboxFolderId != null && folderId == outboxFolderId && supportsUpload(account)) { final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); if (outboxFolderId != -1L && folderId == outboxFolderId && supportsUpload(account)) { for (String destinationUid : uidMap.values()) { // If the message was in the Outbox, then it has been copied to local Trash, and has // to be copied to remote trash Loading legacy/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java +6 −3 Original line number Diff line number Diff line Loading @@ -39,8 +39,10 @@ import com.fsck.k9.notification.NotificationStrategy; import net.thunderbird.core.common.mail.Protocols; import net.thunderbird.core.logging.Logger; import net.thunderbird.core.outcome.Outcome; import net.thunderbird.feature.mail.folder.api.OutboxFolderManager; import net.thunderbird.feature.notification.api.sender.NotificationSender; import net.thunderbird.feature.notification.testing.fake.FakeInAppOnlyNotification; import net.thunderbird.legacy.core.mailstore.folder.FakeOutboxFolderManager; import org.junit.After; import org.junit.Before; import org.junit.Test; Loading Loading @@ -134,6 +136,8 @@ public class MessagingControllerTest extends K9RobolectricTest { (flowCollector, continuation) -> Outcome.Companion.success(new FakeInAppOnlyNotification()); final OutboxFolderManager fakeOutboxFolderManager = new FakeOutboxFolderManager(FOLDER_ID); controller = new MessagingController( appContext, notificationController, Loading @@ -148,7 +152,8 @@ public class MessagingControllerTest extends K9RobolectricTest { Collections.<ControllerExtension>emptyList(), featureFlagProvider, syncLogger, notificationSender notificationSender, fakeOutboxFolderManager ); configureAccount(); Loading Loading @@ -305,7 +310,6 @@ public class MessagingControllerTest extends K9RobolectricTest { @Test public void sendPendingMessagesSynchronous_withNonExistentOutbox_shouldNotStartSync() throws MessagingException { account.setOutboxFolderId(FOLDER_ID); when(localFolder.exists()).thenReturn(false); controller.addListener(listener); Loading Loading @@ -393,7 +397,6 @@ public class MessagingControllerTest extends K9RobolectricTest { } private void setupAccountWithMessageToSend() throws MessagingException { account.setOutboxFolderId(FOLDER_ID); account.setSentFolderId(SENT_FOLDER_ID); when(localStore.getFolder(SENT_FOLDER_ID)).thenReturn(sentFolder); when(sentFolder.getDatabaseId()).thenReturn(SENT_FOLDER_ID); Loading legacy/core/src/test/java/net/thunderbird/legacy/core/mailstore/folder/FakeOutboxFolderManager.kt +5 −5 Original line number Diff line number Diff line Loading @@ -4,7 +4,8 @@ import net.thunderbird.core.outcome.Outcome import net.thunderbird.feature.account.AccountId import net.thunderbird.feature.mail.folder.api.OutboxFolderManager class FakeOutboxFolderManager( class FakeOutboxFolderManager @JvmOverloads constructor( private val outboxFolderId: Long = 1L, private val outboxIdMapping: MutableMap<AccountId, Long> = mutableMapOf(), ) : OutboxFolderManager { override suspend fun getOutboxFolderId( Loading @@ -12,7 +13,7 @@ class FakeOutboxFolderManager( createIfMissing: Boolean, ): Long { return if (createIfMissing) { outboxIdMapping.getOrPut(key = uuid) { 1L } outboxIdMapping.getOrPut(key = uuid) { outboxFolderId } } else { outboxIdMapping.getOrDefault( key = uuid, Loading @@ -22,8 +23,7 @@ class FakeOutboxFolderManager( } override suspend fun createOutboxFolder(uuid: AccountId): Outcome<Long, Exception> { val id = 1L outboxIdMapping[uuid] = id return Outcome.Success(id) outboxIdMapping[uuid] = outboxFolderId return Outcome.Success(outboxFolderId) } } Loading
feature/mail/folder/api/src/commonMain/kotlin/net/thunderbird/feature/mail/folder/api/OutboxFolderManager.kt +16 −0 Original line number Diff line number Diff line Loading @@ -87,3 +87,19 @@ fun OutboxFolderManager.getOutboxFolderIdSync(uuid: String, createIfMissing: Boo fun OutboxFolderManager.hasPendingMessagesSync(uuid: String): Boolean = runBlocking { hasPendingMessages(uuid = AccountIdFactory.of(uuid)) } /** * Gets the folder ID of the outbox folder for the given account. * * @param uuid The ID of the account. * @return The folder ID of the outbox folder. * @throws IllegalStateException If the outbox folder could not be found. */ @Discouraged( message = "This is a wrapper for Java compatibility. " + "Always use getOutboxFolderIdSync(uuid: AccountId) instead on Kotlin files.", ) @JvmOverloads fun OutboxFolderManager.getOutboxFolderIdSync(uuid: String, createIfMissing: Boolean = true): Long { return getOutboxFolderIdSync(uuid = AccountIdFactory.of(uuid), createIfMissing = createIfMissing) }
legacy/core/src/main/java/com/fsck/k9/controller/KoinModule.kt +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ import com.fsck.k9.notification.NotificationController import com.fsck.k9.notification.NotificationStrategy import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.logging.Logger import net.thunderbird.feature.mail.folder.api.OutboxFolderManager import net.thunderbird.feature.notification.api.sender.NotificationSender import org.koin.core.qualifier.named import org.koin.dsl.binds Loading @@ -35,6 +36,7 @@ val controllerModule = module { get<FeatureFlagProvider>(), get<Logger>(named("syncDebug")), get<NotificationSender>(), get<OutboxFolderManager>(), ) } binds arrayOf(MessagingControllerRegistry::class) Loading
legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java +39 −22 Original line number Diff line number Diff line Loading @@ -89,6 +89,8 @@ import net.thunderbird.core.featureflag.FeatureFlagResult.Enabled; import net.thunderbird.core.featureflag.compat.FeatureFlagProviderCompat; import net.thunderbird.core.logging.Logger; import net.thunderbird.core.logging.legacy.Log; import net.thunderbird.feature.mail.folder.api.OutboxFolderManager; import net.thunderbird.feature.mail.folder.api.OutboxFolderManagerKt; import net.thunderbird.feature.notification.api.content.AuthenticationErrorNotification; import net.thunderbird.feature.notification.api.content.NotificationFactoryCoroutineCompat; import net.thunderbird.feature.notification.api.sender.NotificationSender; Loading Loading @@ -144,6 +146,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi private final FeatureFlagProvider featureFlagProvider; private final Logger syncDebugLogger; private final NotificationSenderCompat notificationSender; private final OutboxFolderManager outboxFolderManager; private volatile boolean stopped = false; Loading @@ -168,7 +171,8 @@ public class MessagingController implements MessagingControllerRegistry, Messagi List<ControllerExtension> controllerExtensions, FeatureFlagProvider featureFlagProvider, Logger syncDebugLogger, NotificationSender notificationSender NotificationSender notificationSender, OutboxFolderManager outboxFolderManager ) { this.context = context; this.notificationController = notificationController; Loading @@ -183,6 +187,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi this.featureFlagProvider = featureFlagProvider; this.syncDebugLogger = syncDebugLogger; this.notificationSender = new NotificationSenderCompat(notificationSender); this.outboxFolderManager = outboxFolderManager; controllerThread = new Thread(new Runnable() { @Override Loading Loading @@ -1441,16 +1446,11 @@ public class MessagingController implements MessagingControllerRegistry, Messagi */ public void sendMessage(LegacyAccountDto account, Message message, String plaintextSubject, MessagingListener listener) { try { Long outboxFolderId = account.getOutboxFolderId(); if (outboxFolderId == null) { if (BuildConfig.DEBUG) { throw new AssertionError("Outbox does not exist"); } Log.w("Outbox does not exist"); outboxFolderId = specialLocalFoldersCreator.createOutbox(account); } final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); message.setFlag(Flag.SEEN, true); Loading Loading @@ -1509,8 +1509,12 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } private boolean messagesPendingSend(final LegacyAccountDto account) { Long outboxFolderId = account.getOutboxFolderId(); if (outboxFolderId == null) { final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); if (outboxFolderId == -1L) { Log.w("Could not get Outbox folder ID from Account"); return false; } Loading @@ -1532,9 +1536,14 @@ public class MessagingController implements MessagingControllerRegistry, Messagi return; } LocalStore localStore = localStoreProvider.getInstance(account); OutboxStateRepository outboxStateRepository = localStore.getOutboxStateRepository(); LocalFolder localFolder = localStore.getFolder(account.getOutboxFolderId()); final LocalStore localStore = localStoreProvider.getInstance(account); final OutboxStateRepository outboxStateRepository = localStore.getOutboxStateRepository(); final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); final LocalFolder localFolder = localStore.getFolder(outboxFolderId); if (!localFolder.exists()) { Log.w("Outbox does not exist"); return; Loading @@ -1542,9 +1551,7 @@ public class MessagingController implements MessagingControllerRegistry, Messagi localFolder.open(); long outboxFolderId = localFolder.getDatabaseId(); List<LocalMessage> localMessages = localFolder.getMessages(); final List<LocalMessage> localMessages = localFolder.getMessages(); int progress = 0; int todo = localMessages.size(); for (MessagingListener l : getListeners()) { Loading Loading @@ -1688,8 +1695,13 @@ public class MessagingController implements MessagingControllerRegistry, Messagi } } final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); for (MessagingListener listener : getListeners()) { listener.folderStatusChanged(account, account.getOutboxFolderId()); listener.folderStatusChanged(account, outboxFolderId); } } Loading Loading @@ -2110,8 +2122,13 @@ public class MessagingController implements MessagingControllerRegistry, Messagi Log.d("Delete policy for account %s is %s", account, account.getDeletePolicy()); Long outboxFolderId = account.getOutboxFolderId(); if (outboxFolderId != null && folderId == outboxFolderId && supportsUpload(account)) { final long outboxFolderId = OutboxFolderManagerKt.getOutboxFolderIdSync( outboxFolderManager, account.getUuid(), true ); if (outboxFolderId != -1L && folderId == outboxFolderId && supportsUpload(account)) { for (String destinationUid : uidMap.values()) { // If the message was in the Outbox, then it has been copied to local Trash, and has // to be copied to remote trash Loading
legacy/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java +6 −3 Original line number Diff line number Diff line Loading @@ -39,8 +39,10 @@ import com.fsck.k9.notification.NotificationStrategy; import net.thunderbird.core.common.mail.Protocols; import net.thunderbird.core.logging.Logger; import net.thunderbird.core.outcome.Outcome; import net.thunderbird.feature.mail.folder.api.OutboxFolderManager; import net.thunderbird.feature.notification.api.sender.NotificationSender; import net.thunderbird.feature.notification.testing.fake.FakeInAppOnlyNotification; import net.thunderbird.legacy.core.mailstore.folder.FakeOutboxFolderManager; import org.junit.After; import org.junit.Before; import org.junit.Test; Loading Loading @@ -134,6 +136,8 @@ public class MessagingControllerTest extends K9RobolectricTest { (flowCollector, continuation) -> Outcome.Companion.success(new FakeInAppOnlyNotification()); final OutboxFolderManager fakeOutboxFolderManager = new FakeOutboxFolderManager(FOLDER_ID); controller = new MessagingController( appContext, notificationController, Loading @@ -148,7 +152,8 @@ public class MessagingControllerTest extends K9RobolectricTest { Collections.<ControllerExtension>emptyList(), featureFlagProvider, syncLogger, notificationSender notificationSender, fakeOutboxFolderManager ); configureAccount(); Loading Loading @@ -305,7 +310,6 @@ public class MessagingControllerTest extends K9RobolectricTest { @Test public void sendPendingMessagesSynchronous_withNonExistentOutbox_shouldNotStartSync() throws MessagingException { account.setOutboxFolderId(FOLDER_ID); when(localFolder.exists()).thenReturn(false); controller.addListener(listener); Loading Loading @@ -393,7 +397,6 @@ public class MessagingControllerTest extends K9RobolectricTest { } private void setupAccountWithMessageToSend() throws MessagingException { account.setOutboxFolderId(FOLDER_ID); account.setSentFolderId(SENT_FOLDER_ID); when(localStore.getFolder(SENT_FOLDER_ID)).thenReturn(sentFolder); when(sentFolder.getDatabaseId()).thenReturn(SENT_FOLDER_ID); Loading
legacy/core/src/test/java/net/thunderbird/legacy/core/mailstore/folder/FakeOutboxFolderManager.kt +5 −5 Original line number Diff line number Diff line Loading @@ -4,7 +4,8 @@ import net.thunderbird.core.outcome.Outcome import net.thunderbird.feature.account.AccountId import net.thunderbird.feature.mail.folder.api.OutboxFolderManager class FakeOutboxFolderManager( class FakeOutboxFolderManager @JvmOverloads constructor( private val outboxFolderId: Long = 1L, private val outboxIdMapping: MutableMap<AccountId, Long> = mutableMapOf(), ) : OutboxFolderManager { override suspend fun getOutboxFolderId( Loading @@ -12,7 +13,7 @@ class FakeOutboxFolderManager( createIfMissing: Boolean, ): Long { return if (createIfMissing) { outboxIdMapping.getOrPut(key = uuid) { 1L } outboxIdMapping.getOrPut(key = uuid) { outboxFolderId } } else { outboxIdMapping.getOrDefault( key = uuid, Loading @@ -22,8 +23,7 @@ class FakeOutboxFolderManager( } override suspend fun createOutboxFolder(uuid: AccountId): Outcome<Long, Exception> { val id = 1L outboxIdMapping[uuid] = id return Outcome.Success(id) outboxIdMapping[uuid] = outboxFolderId return Outcome.Success(outboxFolderId) } }