From 643c0f1b3b0c76a670ed83789e52db4c5ed0bde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 10 Sep 2024 12:08:21 +0200 Subject: [PATCH] Extract getting DisplayAccounts into use case --- .../drawer/NavigationDrawerModule.kt | 16 +++-- .../drawer/domain/DomainContract.kt | 13 ++++ .../domain/usecase/GetDisplayAccounts.kt | 65 +++++++++++++++++++ .../drawer/legacy/AccountsViewModel.kt | 57 +--------------- 4 files changed, 93 insertions(+), 58 deletions(-) create mode 100644 feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/DomainContract.kt create mode 100644 feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDisplayAccounts.kt diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerModule.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerModule.kt index c9a4d58a32..0c17eb6c32 100644 --- a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerModule.kt +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerModule.kt @@ -1,5 +1,7 @@ package app.k9mail.feature.navigation.drawer +import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase +import app.k9mail.feature.navigation.drawer.domain.usecase.GetDisplayAccounts import app.k9mail.feature.navigation.drawer.legacy.AccountsViewModel import app.k9mail.feature.navigation.drawer.legacy.FoldersViewModel import app.k9mail.feature.navigation.drawer.ui.DrawerViewModel @@ -11,16 +13,20 @@ import org.koin.dsl.module val navigationDrawerModule: Module = module { - viewModel { DrawerViewModel() } - - viewModel { - AccountsViewModel( + single { + GetDisplayAccounts( accountManager = get(), messageCountsProvider = get(), messageListRepository = get(), ) } + viewModel { + AccountsViewModel( + getDisplayAccounts = get(), + ) + } + viewModel { val coreResourceProvider = get() @@ -32,4 +38,6 @@ val navigationDrawerModule: Module = module { getUnifiedInboxDetail = { coreResourceProvider.searchUnifiedInboxDetail() }, ) } + + viewModel { DrawerViewModel() } } diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/DomainContract.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/DomainContract.kt new file mode 100644 index 0000000000..61d6fcc9bd --- /dev/null +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/DomainContract.kt @@ -0,0 +1,13 @@ +package app.k9mail.feature.navigation.drawer.domain + +import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount +import kotlinx.coroutines.flow.Flow + +interface DomainContract { + + interface UseCase { + fun interface GetDisplayAccounts { + fun execute(): Flow> + } + } +} diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDisplayAccounts.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDisplayAccounts.kt new file mode 100644 index 0000000000..7327e90c47 --- /dev/null +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDisplayAccounts.kt @@ -0,0 +1,65 @@ +package app.k9mail.feature.navigation.drawer.domain.usecase + +import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase +import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount +import app.k9mail.legacy.account.Account +import app.k9mail.legacy.account.AccountManager +import app.k9mail.legacy.mailstore.MessageListChangedListener +import app.k9mail.legacy.mailstore.MessageListRepository +import app.k9mail.legacy.message.controller.MessageCounts +import app.k9mail.legacy.message.controller.MessageCountsProvider +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.launch + +class GetDisplayAccounts( + private val accountManager: AccountManager, + private val messageCountsProvider: MessageCountsProvider, + private val messageListRepository: MessageListRepository, + private val coroutineContext: CoroutineContext = Dispatchers.IO, +) : UseCase.GetDisplayAccounts { + + @OptIn(ExperimentalCoroutinesApi::class) + override fun execute(): Flow> { + return accountManager.getAccountsFlow() + .flatMapLatest { accounts -> + val messageCountsFlows: List> = accounts.map { account -> + getMessageCountsFlow(account) + } + + combine(messageCountsFlows) { messageCountsList -> + messageCountsList.mapIndexed { index, messageCounts -> + DisplayAccount( + account = accounts[index], + unreadMessageCount = messageCounts.unread, + starredMessageCount = messageCounts.starred, + ) + } + } + } + } + + private fun getMessageCountsFlow(account: Account): Flow { + return callbackFlow { + send(messageCountsProvider.getMessageCounts(account)) + + val listener = MessageListChangedListener { + launch { + send(messageCountsProvider.getMessageCounts(account)) + } + } + messageListRepository.addListener(account.uuid, listener) + + awaitClose { + messageListRepository.removeListener(listener) + } + }.flowOn(coroutineContext) + } +} diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/legacy/AccountsViewModel.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/legacy/AccountsViewModel.kt index cbf45cd0bf..ca630d6bab 100644 --- a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/legacy/AccountsViewModel.kt +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/legacy/AccountsViewModel.kt @@ -3,62 +3,11 @@ package app.k9mail.feature.navigation.drawer.legacy import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData +import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount -import app.k9mail.legacy.account.Account -import app.k9mail.legacy.account.AccountManager -import app.k9mail.legacy.mailstore.MessageListChangedListener -import app.k9mail.legacy.mailstore.MessageListRepository -import app.k9mail.legacy.message.controller.MessageCounts -import app.k9mail.legacy.message.controller.MessageCountsProvider -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.launch -@OptIn(ExperimentalCoroutinesApi::class) class AccountsViewModel( - accountManager: AccountManager, - private val messageCountsProvider: MessageCountsProvider, - private val messageListRepository: MessageListRepository, + getDisplayAccounts: UseCase.GetDisplayAccounts, ) : ViewModel() { - private val displayAccountFlow: Flow> = accountManager.getAccountsFlow() - .flatMapLatest { accounts -> - val messageCountsFlows: List> = accounts.map { account -> - getMessageCountsFlow(account) - } - - combine(messageCountsFlows) { messageCountsList -> - messageCountsList.mapIndexed { index, messageCounts -> - DisplayAccount( - account = accounts[index], - unreadMessageCount = messageCounts.unread, - starredMessageCount = messageCounts.starred, - ) - } - } - } - - private fun getMessageCountsFlow(account: Account): Flow { - return callbackFlow { - send(messageCountsProvider.getMessageCounts(account)) - - val listener = MessageListChangedListener { - launch { - send(messageCountsProvider.getMessageCounts(account)) - } - } - messageListRepository.addListener(account.uuid, listener) - - awaitClose { - messageListRepository.removeListener(listener) - } - }.flowOn(Dispatchers.IO) - } - - val displayAccountsLiveData: LiveData> = displayAccountFlow.asLiveData() + val displayAccountsLiveData: LiveData> = getDisplayAccounts.execute().asLiveData() }