Change AccountManualConfig to split into incoming and outgoing screens

This commit is contained in:
Wolf-Martell Montwé 2023-05-30 11:16:59 +02:00
parent cda125af7c
commit 724b219d9a
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
12 changed files with 321 additions and 139 deletions

View file

@ -6,7 +6,8 @@ interface AccountSetupContract {
enum class SetupStep {
AUTO_CONFIG,
MANUAL_CONFIG,
INCOMING_CONFIG,
OUTGOING_CONFIG,
OPTIONS,
}

View file

@ -8,8 +8,9 @@ import app.k9mail.feature.account.setup.ui.AccountSetupContract.Event
import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep
import app.k9mail.feature.account.setup.ui.AccountSetupContract.ViewModel
import app.k9mail.feature.account.setup.ui.autoconfig.AccountAutoConfigScreen
import app.k9mail.feature.account.setup.ui.manualconfig.AccountManualConfigScreen
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigScreen
import app.k9mail.feature.account.setup.ui.options.AccountOptionsScreen
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigScreen
import org.koin.androidx.compose.koinViewModel
@Composable
@ -33,10 +34,17 @@ fun AccountSetupScreen(
)
}
SetupStep.MANUAL_CONFIG -> {
AccountManualConfigScreen(
onNextClick = { dispatch(Event.OnNext) },
onBackClick = { dispatch(Event.OnBack) },
SetupStep.INCOMING_CONFIG -> {
AccountIncomingConfigScreen(
onNext = { dispatch(Event.OnNext) },
onBack = { dispatch(Event.OnBack) },
)
}
SetupStep.OUTGOING_CONFIG -> {
AccountOutgoingConfigScreen(
onNext = { dispatch(Event.OnNext) },
onBack = { dispatch(Event.OnBack) },
)
}

View file

@ -21,15 +21,17 @@ class AccountSetupViewModel(
private fun onBack() {
when (state.value.setupStep) {
SetupStep.AUTO_CONFIG -> navigateBack()
SetupStep.MANUAL_CONFIG -> changeToSetupStep(SetupStep.AUTO_CONFIG)
SetupStep.OPTIONS -> changeToSetupStep(SetupStep.MANUAL_CONFIG)
SetupStep.INCOMING_CONFIG -> changeToSetupStep(SetupStep.AUTO_CONFIG)
SetupStep.OUTGOING_CONFIG -> changeToSetupStep(SetupStep.INCOMING_CONFIG)
SetupStep.OPTIONS -> changeToSetupStep(SetupStep.OUTGOING_CONFIG)
}
}
private fun onNext() {
when (state.value.setupStep) {
SetupStep.AUTO_CONFIG -> changeToSetupStep(SetupStep.MANUAL_CONFIG)
SetupStep.MANUAL_CONFIG -> changeToSetupStep(SetupStep.OPTIONS)
SetupStep.AUTO_CONFIG -> changeToSetupStep(SetupStep.INCOMING_CONFIG)
SetupStep.INCOMING_CONFIG -> changeToSetupStep(SetupStep.OUTGOING_CONFIG)
SetupStep.OUTGOING_CONFIG -> changeToSetupStep(SetupStep.OPTIONS)
SetupStep.OPTIONS -> navigateNext()
}
}

View file

@ -0,0 +1,66 @@
package app.k9mail.feature.account.setup.ui.incoming
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBody1
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContent
@Composable
internal fun AccountIncomingConfigContent(
contentPadding: PaddingValues,
modifier: Modifier = Modifier,
) {
ResponsiveWidthContainer(
modifier = Modifier
.testTag("AccountIncomingConfigContent")
.padding(contentPadding)
.fillMaxWidth()
.then(modifier),
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.imePadding(),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
) {
item {
TextBody1(text = "Incoming Config")
}
}
}
}
@Composable
@DevicePreviews
internal fun AccountIncomingConfigContentK9Preview() {
K9Theme {
AccountOutgoingConfigContent(
contentPadding = PaddingValues(),
)
}
}
@Composable
@DevicePreviews
internal fun AccountIncomingConfigContentThunderbirdPreview() {
ThunderbirdTheme {
AccountOutgoingConfigContent(
contentPadding = PaddingValues(),
)
}
}

View file

@ -0,0 +1,62 @@
package app.k9mail.feature.account.setup.ui.incoming
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.template.Scaffold
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.ui.common.AccountSetupBottomBar
import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar
@Composable
fun AccountIncomingConfigScreen(
onNext: () -> Unit,
onBack: () -> Unit,
modifier: Modifier = Modifier,
) {
Scaffold(
topBar = {
AccountSetupTopAppBar(
title = stringResource(id = R.string.account_setup_incoming_config_top_bar_title),
)
},
bottomBar = {
AccountSetupBottomBar(
nextButtonText = stringResource(id = R.string.account_setup_button_next),
backButtonText = stringResource(id = R.string.account_setup_button_back),
onNextClick = onNext,
onBackClick = onBack,
)
},
modifier = modifier,
) { innerPadding ->
AccountIncomingConfigContent(
contentPadding = innerPadding,
)
}
}
@Composable
@DevicePreviews
internal fun AccountIncomingConfigScreenK9Preview() {
K9Theme {
AccountIncomingConfigScreen(
onNext = {},
onBack = {},
)
}
}
@Composable
@DevicePreviews
internal fun AccountIncomingConfigScreenThunderbirdPreview() {
ThunderbirdTheme {
AccountIncomingConfigScreen(
onNext = {},
onBack = {},
)
}
}

View file

@ -1,102 +0,0 @@
package app.k9mail.feature.account.setup.ui.manualconfig
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.atom.button.Button
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonOutlined
import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadline5
import app.k9mail.core.ui.compose.designsystem.template.LazyColumnWithHeaderFooter
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveContentWithBackground
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.setup.R
@Composable
internal fun AccountManualConfigContent(
onNextClick: () -> Unit,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
ResponsiveContentWithBackground(
modifier = Modifier
.testTag("AccountManualConfigContent")
.then(modifier),
) {
LazyColumnWithHeaderFooter(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
footer = {
AccountManualConfigFooter(
onNextClick = onNextClick,
onBackClick = onBackClick,
)
},
) {
item {
TextHeadline5(text = "Manual Config")
}
}
}
}
@Composable
private fun AccountManualConfigFooter(
onNextClick: () -> Unit,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
start = MainTheme.spacings.quadruple,
top = MainTheme.spacings.triple,
end = MainTheme.spacings.quadruple,
bottom = MainTheme.spacings.double,
)
.then(modifier),
horizontalArrangement = Arrangement.SpaceBetween,
) {
ButtonOutlined(
text = stringResource(id = R.string.account_setup_button_back),
onClick = onBackClick,
)
Button(
text = stringResource(id = R.string.account_setup_button_next),
onClick = onNextClick,
)
}
}
@Composable
@DevicePreviews
internal fun AccountManualConfigContentK9Preview() {
K9Theme {
AccountManualConfigContent(
onNextClick = { },
onBackClick = { },
)
}
}
@Composable
@DevicePreviews
internal fun AccountManualConfigContentThunderbirdPreview() {
ThunderbirdTheme {
AccountManualConfigContent(
onNextClick = { },
onBackClick = { },
)
}
}

View file

@ -1,14 +0,0 @@
package app.k9mail.feature.account.setup.ui.manualconfig
import androidx.compose.runtime.Composable
@Composable
fun AccountManualConfigScreen(
onNextClick: () -> Unit,
onBackClick: () -> Unit,
) {
AccountManualConfigContent(
onNextClick = onNextClick,
onBackClick = onBackClick,
)
}

View file

@ -0,0 +1,65 @@
package app.k9mail.feature.account.setup.ui.outgoing
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBody1
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
@Composable
internal fun AccountOutgoingConfigContent(
contentPadding: PaddingValues,
modifier: Modifier = Modifier,
) {
ResponsiveWidthContainer(
modifier = Modifier
.testTag("AccountOutgoingConfigContent")
.padding(contentPadding)
.fillMaxWidth()
.then(modifier),
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.imePadding(),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
) {
item {
TextBody1(text = "Outgoing Config")
}
}
}
}
@Composable
@DevicePreviews
internal fun AccountOutgoingConfigContentK9Preview() {
K9Theme {
AccountOutgoingConfigContent(
contentPadding = PaddingValues(),
)
}
}
@Composable
@DevicePreviews
internal fun AccountOutgoingConfigContentThunderbirdPreview() {
ThunderbirdTheme {
AccountOutgoingConfigContent(
contentPadding = PaddingValues(),
)
}
}

View file

@ -0,0 +1,62 @@
package app.k9mail.feature.account.setup.ui.outgoing
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.template.Scaffold
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.ui.common.AccountSetupBottomBar
import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar
@Composable
fun AccountOutgoingConfigScreen(
onNext: () -> Unit,
onBack: () -> Unit,
modifier: Modifier = Modifier,
) {
Scaffold(
topBar = {
AccountSetupTopAppBar(
title = stringResource(id = R.string.account_setup_outgoing_config_top_bar_title),
)
},
bottomBar = {
AccountSetupBottomBar(
nextButtonText = stringResource(id = R.string.account_setup_button_next),
backButtonText = stringResource(id = R.string.account_setup_button_back),
onNextClick = onNext,
onBackClick = onBack,
)
},
modifier = modifier,
) { innerPadding ->
AccountOutgoingConfigContent(
contentPadding = innerPadding,
)
}
}
@Composable
@DevicePreviews
internal fun AccountOutgoingConfigScreenK9Preview() {
K9Theme {
AccountOutgoingConfigScreen(
onNext = {},
onBack = {},
)
}
}
@Composable
@DevicePreviews
internal fun AccountOutgoingConfigScreenThunderbirdPreview() {
ThunderbirdTheme {
AccountOutgoingConfigScreen(
onNext = {},
onBack = {},
)
}
}

View file

@ -7,5 +7,9 @@
<string name="account_setup_auto_config_title">K-9 Mail</string>
<string name="account_setup_incoming_config_top_bar_title">Incoming server settings</string>
<string name="account_setup_outgoing_config_top_bar_title">Outgoing server settings</string>
<string name="account_setup_options_top_bar_title">Account options</string>
</resources>

View file

@ -3,15 +3,18 @@ package app.k9mail.feature.account.setup.ui
import app.k9mail.core.ui.compose.testing.ComposeTest
import app.k9mail.core.ui.compose.testing.onNodeWithTag
import app.k9mail.core.ui.compose.testing.setContent
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect
import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep
import app.k9mail.feature.account.setup.ui.AccountSetupContract.State
import assertk.assertThat
import assertk.assertions.isEqualTo
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class AccountSetupScreenKtTest : ComposeTest() {
@Test
@ -19,11 +22,13 @@ class AccountSetupScreenKtTest : ComposeTest() {
val viewModel = FakeAccountSetupViewModel()
setContent {
AccountSetupScreen(
onFinish = { },
onBack = { },
viewModel = viewModel,
)
ThunderbirdTheme {
AccountSetupScreen(
onFinish = { },
onBack = { },
viewModel = viewModel,
)
}
}
for (step in SetupStep.values()) {
@ -40,11 +45,13 @@ class AccountSetupScreenKtTest : ComposeTest() {
var onBackCounter = 0
setContent {
AccountSetupScreen(
onFinish = { onFinishCounter++ },
onBack = { onBackCounter++ },
viewModel = viewModel,
)
ThunderbirdTheme {
AccountSetupScreen(
onFinish = { onFinishCounter++ },
onBack = { onBackCounter++ },
viewModel = viewModel,
)
}
}
assertThat(onFinishCounter).isEqualTo(0)
@ -63,7 +70,8 @@ class AccountSetupScreenKtTest : ComposeTest() {
private fun getTagForStep(step: SetupStep): String = when (step) {
SetupStep.AUTO_CONFIG -> "AccountAutoConfigContent"
SetupStep.MANUAL_CONFIG -> "AccountManualConfigContent"
SetupStep.INCOMING_CONFIG -> "AccountIncomingConfigContent"
SetupStep.OUTGOING_CONFIG -> "AccountOutgoingConfigContent"
SetupStep.OPTIONS -> "AccountOptionsContent"
}
}

View file

@ -12,10 +12,12 @@ import assertk.all
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.prop
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class AccountSetupViewModelTest {
@get:Rule
@ -42,7 +44,16 @@ class AccountSetupViewModelTest {
actual = stateTurbine.awaitItem(),
turbines = turbines,
) {
prop(State::setupStep).isEqualTo(SetupStep.MANUAL_CONFIG)
prop(State::setupStep).isEqualTo(SetupStep.INCOMING_CONFIG)
}
viewModel.event(AccountSetupContract.Event.OnNext)
assertThatAndAllEventsConsumed(
actual = stateTurbine.awaitItem(),
turbines = turbines,
) {
prop(State::setupStep).isEqualTo(SetupStep.OUTGOING_CONFIG)
}
viewModel.event(AccountSetupContract.Event.OnNext)
@ -86,7 +97,16 @@ class AccountSetupViewModelTest {
actual = stateTurbine.awaitItem(),
turbines = turbines,
) {
prop(State::setupStep).isEqualTo(SetupStep.MANUAL_CONFIG)
prop(State::setupStep).isEqualTo(SetupStep.OUTGOING_CONFIG)
}
viewModel.event(AccountSetupContract.Event.OnBack)
assertThatAndAllEventsConsumed(
actual = stateTurbine.awaitItem(),
turbines = turbines,
) {
prop(State::setupStep).isEqualTo(SetupStep.INCOMING_CONFIG)
}
viewModel.event(AccountSetupContract.Event.OnBack)