diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerExternalContract.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerExternalContract.kt new file mode 100644 index 0000000000..16db5fc39a --- /dev/null +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/NavigationDrawerExternalContract.kt @@ -0,0 +1,10 @@ +package app.k9mail.feature.navigation.drawer + +import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig + +interface NavigationDrawerExternalContract { + + fun interface DrawerConfigLoader { + fun loadDrawerConfig(): DrawerConfig + } +} 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 835f3a893e..b07eb6b86f 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 @@ -3,6 +3,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.domain.usecase.GetDisplayFoldersForAccount +import app.k9mail.feature.navigation.drawer.domain.usecase.GetDrawerConfig import app.k9mail.feature.navigation.drawer.legacy.AccountsViewModel import app.k9mail.feature.navigation.drawer.legacy.FoldersViewModel import app.k9mail.feature.navigation.drawer.ui.DrawerViewModel @@ -14,6 +15,12 @@ import org.koin.dsl.module val navigationDrawerModule: Module = module { + single { + GetDrawerConfig( + configProver = get(), + ) + } + single { GetDisplayAccounts( accountManager = get(), @@ -48,6 +55,7 @@ val navigationDrawerModule: Module = module { viewModel { DrawerViewModel( + getDrawerConfig = get(), getDisplayAccounts = get(), getDisplayFoldersForAccount = 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 468de79c14..d20e395213 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 @@ -1,12 +1,17 @@ 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.ui.folder.DisplayFolder import kotlinx.coroutines.flow.Flow interface DomainContract { interface UseCase { + fun interface GetDrawerConfig { + operator fun invoke(): Flow + } + fun interface GetDisplayAccounts { operator fun invoke(): Flow> } diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/entity/DrawerConfig.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/entity/DrawerConfig.kt new file mode 100644 index 0000000000..07c6168016 --- /dev/null +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/entity/DrawerConfig.kt @@ -0,0 +1,6 @@ +package app.k9mail.feature.navigation.drawer.domain.entity + +data class DrawerConfig( + val showUnifiedInbox: Boolean, + val showStarredCount: Boolean, +) diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDrawerConfig.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDrawerConfig.kt new file mode 100644 index 0000000000..0bff8bad1c --- /dev/null +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDrawerConfig.kt @@ -0,0 +1,17 @@ +package app.k9mail.feature.navigation.drawer.domain.usecase + +import app.k9mail.feature.navigation.drawer.NavigationDrawerExternalContract.DrawerConfigLoader +import app.k9mail.feature.navigation.drawer.domain.DomainContract.UseCase +import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +class GetDrawerConfig( + private val configProver: DrawerConfigLoader, +) : UseCase.GetDrawerConfig { + override operator fun invoke(): Flow { + return flow { + emit(configProver.loadDrawerConfig()) + } + } +} diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContent.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContent.kt index 3ad4ae63ab..00e8765eae 100644 --- a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContent.kt +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContent.kt @@ -50,7 +50,7 @@ fun DrawerContent( onFolderClick = { folder -> onEvent(Event.OnFolderClick(folder)) }, - showStarredCount = state.showStarredCount, + showStarredCount = state.config.showStarredCount, ) } } diff --git a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContract.kt b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContract.kt index 2c96749a1b..7f4f0b85c6 100644 --- a/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContract.kt +++ b/feature/navigation/drawer/src/main/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerContract.kt @@ -3,6 +3,7 @@ package app.k9mail.feature.navigation.drawer.ui import androidx.compose.runtime.Stable import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel 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.collections.immutable.ImmutableList @@ -14,11 +15,14 @@ interface DrawerContract { @Stable data class State( + val config: DrawerConfig = DrawerConfig( + showUnifiedInbox = false, + showStarredCount = false, + ), val accounts: ImmutableList = persistentListOf(), val currentAccount: DisplayAccount? = null, val folders: ImmutableList = persistentListOf(), val selectedFolder: DisplayFolder? = null, - val showStarredCount: Boolean = false, val isLoading: Boolean = false, ) 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 0522331c0e..7eab4eb63e 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,6 +4,7 @@ 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 @@ -21,6 +22,7 @@ import kotlinx.coroutines.launch @Suppress("MagicNumber") class DrawerViewModel( + private val getDrawerConfig: UseCase.GetDrawerConfig, private val getDisplayAccounts: UseCase.GetDisplayAccounts, private val getDisplayFoldersForAccount: UseCase.GetDisplayFoldersForAccount, initialState: State = State(), @@ -30,6 +32,14 @@ class DrawerViewModel( ViewModel { init { + viewModelScope.launch { + getDrawerConfig().collectLatest { config -> + updateState { + it.copy(config = config) + } + } + } + viewModelScope.launch { loadAccounts() } diff --git a/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDrawerConfigTest.kt b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDrawerConfigTest.kt new file mode 100644 index 0000000000..60cb138c81 --- /dev/null +++ b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/domain/usecase/GetDrawerConfigTest.kt @@ -0,0 +1,32 @@ +package app.k9mail.feature.navigation.drawer.domain.usecase + +import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig +import assertk.assertThat +import assertk.assertions.isEqualTo +import kotlin.test.Test +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest + +class GetDrawerConfigTest { + + @Test + fun `should get drawer config`() = runTest { + val drawerConfig = DrawerConfig( + showUnifiedInbox = true, + showStarredCount = true, + ) + + val testSubject = GetDrawerConfig( + configProver = { drawerConfig }, + ) + + val result = testSubject().first() + + assertThat(result).isEqualTo( + DrawerConfig( + showUnifiedInbox = true, + showStarredCount = true, + ), + ) + } +} diff --git a/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerStateTest.kt b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerStateTest.kt index 6f36a5801d..c73bcd1f11 100644 --- a/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerStateTest.kt +++ b/feature/navigation/drawer/src/test/kotlin/app/k9mail/feature/navigation/drawer/ui/DrawerStateTest.kt @@ -1,5 +1,6 @@ package app.k9mail.feature.navigation.drawer.ui +import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig import app.k9mail.feature.navigation.drawer.ui.DrawerContract.State import assertk.assertThat import assertk.assertions.isEqualTo @@ -14,11 +15,14 @@ class DrawerStateTest { assertThat(state).isEqualTo( State( + config = DrawerConfig( + showUnifiedInbox = false, + showStarredCount = false, + ), accounts = persistentListOf(), currentAccount = null, folders = persistentListOf(), selectedFolder = null, - showStarredCount = false, isLoading = false, ), ) 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 e7a035a399..3da4bb90ed 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 @@ -7,6 +7,7 @@ import app.k9mail.core.ui.compose.testing.mvi.assertThatAndEffectTurbineConsumed import app.k9mail.core.ui.compose.testing.mvi.eventStateTest import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount +import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig 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 @@ -32,6 +33,27 @@ class DrawerViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() + @Test + fun `should collect drawer config`() = runTest { + val drawerConfig = createDrawerConfig() + val getDrawerConfigFlow = MutableStateFlow(drawerConfig) + val testSubject = createTestSubject( + drawerConfigFlow = getDrawerConfigFlow, + ) + + advanceUntilIdle() + + assertThat(testSubject.state.value.config).isEqualTo(drawerConfig) + + val newDrawerConfig = createDrawerConfig(showUnifiedInbox = true) + + getDrawerConfigFlow.emit(newDrawerConfig) + + advanceUntilIdle() + + assertThat(testSubject.state.value.config).isEqualTo(newDrawerConfig) + } + @Test fun `should change loading state when OnRefresh event is received`() = runTest { val testSubject = createTestSubject() @@ -51,7 +73,7 @@ class DrawerViewModelTest { @Test fun `should collect display accounts when created and select first as current`() = runTest { - val displayAccounts = createDisplayAccountList(3) + val displayAccounts = createDisplayAccountList(2) val getDisplayAccountsFlow = MutableStateFlow(displayAccounts) val testSubject = createTestSubject( displayAccountsFlow = getDisplayAccountsFlow, @@ -202,10 +224,12 @@ class DrawerViewModelTest { } private fun createTestSubject( + drawerConfigFlow: Flow = flow { emit(createDrawerConfig()) }, displayAccountsFlow: Flow> = flow { emit(emptyList()) }, displayFoldersMap: Map> = emptyMap(), ): DrawerViewModel { return DrawerViewModel( + getDrawerConfig = { drawerConfigFlow }, getDisplayAccounts = { displayAccountsFlow }, getDisplayFoldersForAccount = { accountUuid -> flow { emit(displayFoldersMap[accountUuid] ?: emptyList()) } @@ -213,6 +237,16 @@ class DrawerViewModelTest { ) } + private fun createDrawerConfig( + showUnifiedInbox: Boolean = false, + showStarredCount: Boolean = false, + ): DrawerConfig { + return DrawerConfig( + showUnifiedInbox = showUnifiedInbox, + showStarredCount = showStarredCount, + ) + } + private fun createDisplayAccount( uuid: String = "uuid", name: String = "name", diff --git a/legacy/common/build.gradle.kts b/legacy/common/build.gradle.kts index 9eaf6c8c6c..2d980ed0de 100644 --- a/legacy/common/build.gradle.kts +++ b/legacy/common/build.gradle.kts @@ -15,6 +15,7 @@ dependencies { implementation(projects.feature.account.setup) implementation(projects.feature.account.edit) + implementation(projects.feature.navigation.drawer) implementation(projects.feature.settings.import) implementation(projects.feature.widget.unread) diff --git a/legacy/common/src/main/java/com/fsck/k9/feature/FeatureModule.kt b/legacy/common/src/main/java/com/fsck/k9/feature/FeatureModule.kt index d9e2e7c222..94e259d0b2 100644 --- a/legacy/common/src/main/java/com/fsck/k9/feature/FeatureModule.kt +++ b/legacy/common/src/main/java/com/fsck/k9/feature/FeatureModule.kt @@ -1,6 +1,7 @@ package com.fsck.k9.feature import app.k9mail.feature.launcher.FeatureLauncherExternalContract +import app.k9mail.feature.navigation.drawer.NavigationDrawerExternalContract import org.koin.android.ext.koin.androidContext import org.koin.dsl.module @@ -10,4 +11,8 @@ val featureModule = module { context = androidContext(), ) } + + single { + NavigationDrawerConfigLoader() + } } diff --git a/legacy/common/src/main/java/com/fsck/k9/feature/NavigationDrawerConfigLoader.kt b/legacy/common/src/main/java/com/fsck/k9/feature/NavigationDrawerConfigLoader.kt new file mode 100644 index 0000000000..fb8fb70ff6 --- /dev/null +++ b/legacy/common/src/main/java/com/fsck/k9/feature/NavigationDrawerConfigLoader.kt @@ -0,0 +1,14 @@ +package com.fsck.k9.feature + +import app.k9mail.feature.navigation.drawer.NavigationDrawerExternalContract.DrawerConfigLoader +import app.k9mail.feature.navigation.drawer.domain.entity.DrawerConfig +import com.fsck.k9.K9 + +class NavigationDrawerConfigLoader : DrawerConfigLoader { + override fun loadDrawerConfig(): DrawerConfig { + return DrawerConfig( + showUnifiedInbox = K9.isShowUnifiedInbox, + showStarredCount = K9.isShowStarredCount, + ) + } +}