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 b07eb6b86f..5d751563bb 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 @@ -4,6 +4,7 @@ import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase import app.k9mail.feature.navigation.drawer.domain.usecase.GetDisplayAccounts import app.k9mail.feature.navigation.drawer.domain.usecase.GetDisplayFoldersForAccount import app.k9mail.feature.navigation.drawer.domain.usecase.GetDrawerConfig +import app.k9mail.feature.navigation.drawer.domain.usecase.SyncMail import app.k9mail.feature.navigation.drawer.legacy.AccountsViewModel import app.k9mail.feature.navigation.drawer.legacy.FoldersViewModel import app.k9mail.feature.navigation.drawer.ui.DrawerViewModel @@ -35,6 +36,12 @@ val navigationDrawerModule: Module = module { ) } + single { + SyncMail( + messagingController = get(), + ) + } + viewModel { AccountsViewModel( getDisplayAccounts = get(), @@ -58,6 +65,7 @@ val navigationDrawerModule: Module = module { getDrawerConfig = get(), getDisplayAccounts = get(), getDisplayFoldersForAccount = get(), + syncMail = get(), ) } } 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 index d20e395213..84423eb5ea 100644 --- 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 @@ -2,6 +2,7 @@ package app.k9mail.feature.navigation.drawer.domain import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig +import app.k9mail.legacy.account.Account import app.k9mail.legacy.ui.folder.DisplayFolder import kotlinx.coroutines.flow.Flow @@ -19,5 +20,14 @@ interface DomainContract { fun interface GetDisplayFoldersForAccount { operator fun invoke(accountUuid: String): Flow> } + + /** + * Synchronize mail for the given account. + * + * Account can be null to synchronize unified inbox or account list. + */ + fun interface SyncMail { + operator fun invoke(account: Account?): Flow> + } } } diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/SyncMail.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/SyncMail.kt new file mode 100644 index 0000000000..36e8b27436 --- /dev/null +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/SyncMail.kt @@ -0,0 +1,37 @@ +package app.k9mail.feature.navigation.drawer.domain.usecase + +import android.content.Context +import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase +import app.k9mail.legacy.account.Account +import app.k9mail.legacy.message.controller.MessagingControllerMailChecker +import app.k9mail.legacy.message.controller.SimpleMessagingListener +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.flowOn + +class SyncMail( + private val messagingController: MessagingControllerMailChecker, + private val coroutineContext: CoroutineContext = Dispatchers.IO, +) : UseCase.SyncMail { + override fun invoke(account: Account?): Flow> = callbackFlow { + val listener = object : SimpleMessagingListener() { + override fun checkMailFinished(context: Context?, account: Account?) { + trySend(Result.success(Unit)) + close() + } + } + + messagingController.checkMail( + account = account, + ignoreLastCheckedTime = true, + useManualWakeLock = true, + notify = true, + listener = listener, + ) + + awaitClose() + }.flowOn(coroutineContext) +} diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModel.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModel.kt index 7eab4eb63e..8c0991f937 100644 --- a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModel.kt +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount -import app.k9mail.feature.navigation.drawer.domain.usecase.GetDrawerConfig import app.k9mail.feature.navigation.drawer.ui.DrawerContract.Effect import app.k9mail.feature.navigation.drawer.ui.DrawerContract.Event import app.k9mail.feature.navigation.drawer.ui.DrawerContract.State @@ -25,6 +24,7 @@ class DrawerViewModel( private val getDrawerConfig: UseCase.GetDrawerConfig, private val getDisplayAccounts: UseCase.GetDisplayAccounts, private val getDisplayFoldersForAccount: UseCase.GetDisplayFoldersForAccount, + private val syncMail: UseCase.SyncMail, initialState: State = State(), ) : BaseViewModel( initialState = initialState, @@ -138,8 +138,9 @@ class DrawerViewModel( it.copy(isLoading = true) } - // TODO: replace with actual data loading - delay(500) + syncMail(state.value.currentAccount?.account).collect { + // nothing to do + } updateState { it.copy(isLoading = false) diff --git a/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/SyncMailTest.kt b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/SyncMailTest.kt new file mode 100644 index 0000000000..66295504ed --- /dev/null +++ b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/SyncMailTest.kt @@ -0,0 +1,43 @@ +package app.k9mail.feature.navigation.drawer.domain.usecase + +import app.k9mail.legacy.account.Account +import app.k9mail.legacy.message.controller.MessagingControllerMailChecker +import app.k9mail.legacy.message.controller.MessagingListener +import assertk.assertThat +import assertk.assertions.isEqualTo +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class SyncMailTest { + + @Test + fun `should sync mail`() = runTest { + val listenerExecutor: (MessagingListener?) -> Unit = { listener -> + listener?.checkMailFinished(null, null) + } + val testSubject = SyncMail( + messagingController = FakeMessagingControllerMailChecker( + listenerExecutor = listenerExecutor, + ), + ) + + val result = testSubject(null).first() + + assertThat(result.isSuccess).isEqualTo(true) + } + + private class FakeMessagingControllerMailChecker( + private val listenerExecutor: (MessagingListener?) -> Unit = {}, + ) : MessagingControllerMailChecker { + override fun checkMail( + account: Account?, + ignoreLastCheckedTime: Boolean, + useManualWakeLock: Boolean, + notify: Boolean, + listener: MessagingListener?, + ) { + listenerExecutor(listener) + } + } +} diff --git a/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModelTest.kt b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModelTest.kt index 3da4bb90ed..36e2aa8511 100644 --- a/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModelTest.kt +++ b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerViewModelTest.kt @@ -20,6 +20,7 @@ import kotlin.test.Test import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flow @@ -56,7 +57,12 @@ class DrawerViewModelTest { @Test fun `should change loading state when OnRefresh event is received`() = runTest { - val testSubject = createTestSubject() + val testSubject = createTestSubject( + syncMailFlow = flow { + delay(25) + emit(Result.success(Unit)) + }, + ) eventStateTest( viewModel = testSubject, @@ -227,6 +233,7 @@ class DrawerViewModelTest { drawerConfigFlow: Flow = flow { emit(createDrawerConfig()) }, displayAccountsFlow: Flow> = flow { emit(emptyList()) }, displayFoldersMap: Map> = emptyMap(), + syncMailFlow: Flow> = flow { emit(Result.success(Unit)) }, ): DrawerViewModel { return DrawerViewModel( getDrawerConfig = { drawerConfigFlow }, @@ -234,6 +241,7 @@ class DrawerViewModelTest { getDisplayFoldersForAccount = { accountUuid -> flow { emit(displayFoldersMap[accountUuid] ?: emptyList()) } }, + syncMail = { syncMailFlow }, ) }