diff --git a/app/core/src/main/java/com/fsck/k9/Preferences.kt b/app/core/src/main/java/com/fsck/k9/Preferences.kt index c74ac1ccf..aa9f9d18a 100644 --- a/app/core/src/main/java/com/fsck/k9/Preferences.kt +++ b/app/core/src/main/java/com/fsck/k9/Preferences.kt @@ -13,13 +13,24 @@ import java.util.HashMap import java.util.LinkedList import java.util.UUID import java.util.concurrent.CopyOnWriteArraySet +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.sendBlocking +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.flowOn import timber.log.Timber class Preferences internal constructor( private val context: Context, private val storagePersister: StoragePersister, private val localStoreProvider: LocalStoreProvider, - private val accountPreferenceSerializer: AccountPreferenceSerializer + private val accountPreferenceSerializer: AccountPreferenceSerializer, + private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO ) : AccountManager { private val accountLock = Any() @@ -107,6 +118,33 @@ class Preferences internal constructor( } } + @OptIn(ExperimentalCoroutinesApi::class) + override fun getAccountFlow(accountUuid: String): Flow { + return callbackFlow { + val initialAccount = getAccount(accountUuid) ?: return@callbackFlow + send(initialAccount) + + val listener = AccountsChangeListener { + val account = getAccount(accountUuid) + if (account != null) { + try { + sendBlocking(account) + } catch (e: Exception) { + Timber.w(e, "Error while trying to send to channel") + } + } else { + channel.close() + } + } + addOnAccountsChangeListener(listener) + + awaitClose { + removeOnAccountsChangeListener(listener) + } + }.buffer(capacity = Channel.CONFLATED) + .flowOn(backgroundDispatcher) + } + fun newAccount(): Account { val accountUuid = UUID.randomUUID().toString() val account = Account(accountUuid) diff --git a/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt b/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt index 54409a6db..f3204500b 100644 --- a/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt +++ b/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt @@ -2,7 +2,6 @@ package com.fsck.k9.mailstore import com.fsck.k9.Account import com.fsck.k9.Account.FolderMode -import com.fsck.k9.AccountsChangeListener import com.fsck.k9.mail.FolderClass import com.fsck.k9.preferences.AccountManager import kotlinx.coroutines.CoroutineDispatcher @@ -16,6 +15,7 @@ import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import com.fsck.k9.mail.FolderType as RemoteFolderType @@ -229,22 +229,7 @@ class FolderRepository( } private fun Account.getFolderPushModeFlow(): Flow { - val account = this@getFolderPushModeFlow - return callbackFlow { - send(account.folderPushMode) - - val listener = AccountsChangeListener { - launch { - send(account.folderPushMode) - } - } - accountManager.addOnAccountsChangeListener(listener) - - awaitClose { - accountManager.removeOnAccountsChangeListener(listener) - } - }.distinctUntilChanged() - .flowOn(ioDispatcher) + return accountManager.getAccountFlow(uuid).map { it.folderPushMode } } private val RemoteFolderDetails.effectivePushClass: FolderClass diff --git a/app/core/src/main/java/com/fsck/k9/preferences/AccountManager.kt b/app/core/src/main/java/com/fsck/k9/preferences/AccountManager.kt index 1f5db503e..d152ab705 100644 --- a/app/core/src/main/java/com/fsck/k9/preferences/AccountManager.kt +++ b/app/core/src/main/java/com/fsck/k9/preferences/AccountManager.kt @@ -3,9 +3,11 @@ package com.fsck.k9.preferences import com.fsck.k9.Account import com.fsck.k9.AccountRemovedListener import com.fsck.k9.AccountsChangeListener +import kotlinx.coroutines.flow.Flow interface AccountManager { fun getAccount(accountUuid: String): Account? + fun getAccountFlow(accountUuid: String): Flow fun addAccountRemovedListener(listener: AccountRemovedListener) fun moveAccount(account: Account, newPosition: Int) fun addOnAccountsChangeListener(accountsChangeListener: AccountsChangeListener)