0
0
mirror of https://github.com/thunderbird/thunderbird-android.git synced 2024-09-19 19:52:14 +02:00

Add SyncMail use case

This commit is contained in:
Wolf-Martell Montwé 2024-09-13 17:51:07 +02:00
parent e36d37a6f2
commit 29d798b626
No known key found for this signature in database
GPG Key ID: 6D45B21512ACBF72
6 changed files with 111 additions and 4 deletions

View File

@ -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<UseCase.SyncMail> {
SyncMail(
messagingController = get(),
)
}
viewModel {
AccountsViewModel(
getDisplayAccounts = get(),
@ -58,6 +65,7 @@ val navigationDrawerModule: Module = module {
getDrawerConfig = get(),
getDisplayAccounts = get(),
getDisplayFoldersForAccount = get(),
syncMail = get(),
)
}
}

View File

@ -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<List<DisplayFolder>>
}
/**
* 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<Result<Unit>>
}
}
}

View File

@ -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<Result<Unit>> = 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)
}

View File

@ -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<State, Event, Effect>(
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)

View File

@ -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)
}
}
}

View File

@ -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<DrawerConfig> = flow { emit(createDrawerConfig()) },
displayAccountsFlow: Flow<List<DisplayAccount>> = flow { emit(emptyList()) },
displayFoldersMap: Map<String, List<DisplayFolder>> = emptyMap(),
syncMailFlow: Flow<Result<Unit>> = 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 },
)
}