Change server settings to support interaction mode

This commit is contained in:
Wolf-Martell Montwé 2023-09-11 17:52:28 +02:00
parent 61b76c31da
commit d721153062
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
19 changed files with 55 additions and 4 deletions

View file

@ -0,0 +1,9 @@
package app.k9mail.feature.account.common.domain.entity
/**
* Enum representing the mode a user is interacting with an account or setting.
*/
enum class InteractionMode {
Create,
Edit,
}

View file

@ -0,0 +1,10 @@
package app.k9mail.feature.account.common.ui
import app.k9mail.feature.account.common.domain.entity.InteractionMode
/**
* Interface for screens that can be used in different interaction modes.
*/
interface WithInteractionMode {
val mode: InteractionMode
}

View file

@ -2,6 +2,7 @@ package app.k9mail.feature.account.edit.ui
import androidx.lifecycle.viewModelScope
import app.k9mail.feature.account.common.domain.AccountDomainContract
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.edit.domain.AccountEditDomainContract
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel
@ -15,6 +16,7 @@ class EditIncomingServerSettingsViewModel(
accountStateRepository: AccountDomainContract.AccountStateRepository,
initialState: IncomingServerSettingsContract.State = IncomingServerSettingsContract.State(),
) : IncomingServerSettingsViewModel(
mode = InteractionMode.Edit,
validator = validator,
accountStateRepository = accountStateRepository,
initialState = initialState,

View file

@ -2,6 +2,7 @@ package app.k9mail.feature.account.edit.ui
import androidx.lifecycle.viewModelScope
import app.k9mail.feature.account.common.domain.AccountDomainContract
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.edit.domain.AccountEditDomainContract
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsViewModel
@ -15,6 +16,7 @@ class EditOutgoingServerSettingsViewModel(
accountStateRepository: AccountDomainContract.AccountStateRepository,
initialState: OutgoingServerSettingsContract.State = OutgoingServerSettingsContract.State(),
) : OutgoingServerSettingsViewModel(
mode = InteractionMode.Edit,
validator = validator,
accountStateRepository = accountStateRepository,
initialState = initialState,

View file

@ -4,6 +4,7 @@ import android.content.Context
import app.k9mail.core.common.oauth.OAuthConfigurationFactory
import app.k9mail.feature.account.common.AccountCommonExternalContract
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract
@ -58,6 +59,7 @@ class AccountEditModuleKtTest : KoinTest {
ServerCertificateErrorContract.State::class,
IncomingServerSettingsContract.State::class,
OutgoingServerSettingsContract.State::class,
InteractionMode::class,
),
)

View file

@ -1,5 +1,6 @@
package app.k9mail.feature.account.server.settings
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsValidator
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel
@ -16,6 +17,7 @@ val featureAccountServerSettingsModule: Module = module {
viewModel {
IncomingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = get(),
accountStateRepository = get(),
)
@ -23,6 +25,7 @@ val featureAccountServerSettingsModule: Module = module {
viewModel {
OutgoingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = get(),
accountStateRepository = get(),
)

View file

@ -8,10 +8,11 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.domain.entity.toDefaultPort
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.common.ui.WithInteractionMode
interface IncomingServerSettingsContract {
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>, WithInteractionMode
data class State(
val protocolType: IncomingProtocolType = IncomingProtocolType.DEFAULT,

View file

@ -10,6 +10,7 @@ import app.k9mail.core.ui.compose.common.mvi.observe
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.common.domain.entity.InteractionMode
import app.k9mail.feature.account.common.ui.AccountTopAppBar
import app.k9mail.feature.account.common.ui.WizardNavigationBar
import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository
@ -70,6 +71,7 @@ internal fun IncomingServerSettingsScreenK9Preview() {
onNext = {},
onBack = {},
viewModel = IncomingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = IncomingServerSettingsValidator(),
accountStateRepository = PreviewAccountStateRepository(),
),
@ -85,6 +87,7 @@ internal fun IncomingServerSettingsScreenThunderbirdPreview() {
onNext = {},
onBack = {},
viewModel = IncomingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = IncomingServerSettingsValidator(),
accountStateRepository = PreviewAccountStateRepository(),
),

View file

@ -5,6 +5,7 @@ import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.common.domain.AccountDomainContract
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.common.domain.entity.toDefaultPort
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event
@ -13,6 +14,7 @@ import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSett
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel
open class IncomingServerSettingsViewModel(
override val mode: InteractionMode,
private val validator: Validator,
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
initialState: State = State(),

View file

@ -1,12 +1,14 @@
package app.k9mail.feature.account.server.settings.ui.incoming.fake
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel
class FakeIncomingServerSettingsViewModel(
override val mode: InteractionMode = InteractionMode.Create,
initialState: State = State(),
) : BaseViewModel<State, Event, Effect>(initialState), ViewModel {

View file

@ -7,10 +7,11 @@ import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.common.ui.WithInteractionMode
interface OutgoingServerSettingsContract {
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>, WithInteractionMode
data class State(
val server: StringInputField = StringInputField(),

View file

@ -10,6 +10,7 @@ import app.k9mail.core.ui.compose.common.mvi.observe
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.common.domain.entity.InteractionMode
import app.k9mail.feature.account.common.ui.AccountTopAppBar
import app.k9mail.feature.account.common.ui.WizardNavigationBar
import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository
@ -70,6 +71,7 @@ internal fun OutgoingServerSettingsScreenK9Preview() {
onNext = {},
onBack = {},
viewModel = OutgoingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = OutgoingServerSettingsValidator(),
accountStateRepository = PreviewAccountStateRepository(),
),
@ -85,6 +87,7 @@ internal fun OutgoingServerSettingsScreenThunderbirdPreview() {
onNext = {},
onBack = {},
viewModel = OutgoingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = OutgoingServerSettingsValidator(),
accountStateRepository = PreviewAccountStateRepository(),
),

View file

@ -4,6 +4,7 @@ import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.common.domain.AccountDomainContract
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event
@ -12,6 +13,7 @@ import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSett
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel
open class OutgoingServerSettingsViewModel(
override val mode: InteractionMode,
private val validator: Validator,
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
initialState: State = State(),

View file

@ -1,12 +1,14 @@
package app.k9mail.feature.account.server.settings.ui.outgoing.fake
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel
class FakeOutgoingServerSettingsViewModel(
override val mode: InteractionMode = InteractionMode.Create,
initialState: State = State(),
) : BaseViewModel<State, Event, Effect>(initialState), ViewModel {

View file

@ -15,7 +15,7 @@ class IncomingServerSettingsScreenKtTest : ComposeTest() {
@Test
fun `should delegate navigation effects`() = runTest {
val initialState = State()
val viewModel = FakeIncomingServerSettingsViewModel(initialState)
val viewModel = FakeIncomingServerSettingsViewModel(initialState = initialState)
var onNextCounter = 0
var onBackCounter = 0

View file

@ -12,6 +12,7 @@ import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort
import app.k9mail.feature.account.common.domain.entity.toPop3DefaultPort
@ -350,6 +351,7 @@ class IncomingServerSettingsViewModelTest {
fun `should change state and not emit NavigateNext effect when OnNextClicked event received and input invalid`() =
runTest {
val testSubject = IncomingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = FakeIncomingServerSettingsValidator(
serverAnswer = ValidationResult.Failure(TestError),
),
@ -398,6 +400,7 @@ class IncomingServerSettingsViewModelTest {
validator: IncomingServerSettingsContract.Validator = FakeIncomingServerSettingsValidator(),
repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(),
) = IncomingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = validator,
accountStateRepository = repository,
initialState = initialState,

View file

@ -15,7 +15,7 @@ class OutgoingServerSettingsScreenKtTest : ComposeTest() {
@Test
fun `should delegate navigation effects`() = runTest {
val initialState = State()
val viewModel = FakeOutgoingServerSettingsViewModel(initialState)
val viewModel = FakeOutgoingServerSettingsViewModel(initialState = initialState)
var onNextCounter = 0
var onBackCounter = 0

View file

@ -11,6 +11,7 @@ import app.k9mail.feature.account.common.domain.AccountDomainContract
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort
import app.k9mail.feature.account.common.domain.input.NumberInputField
@ -305,6 +306,7 @@ class OutgoingServerSettingsViewModelTest {
validator: OutgoingServerSettingsContract.Validator = FakeOutgoingServerSettingsValidator(),
repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(),
) = OutgoingServerSettingsViewModel(
mode = InteractionMode.Create,
validator = validator,
accountStateRepository = repository,
initialState = initialState,

View file

@ -4,6 +4,7 @@ import android.content.Context
import app.k9mail.core.common.oauth.OAuthConfigurationFactory
import app.k9mail.feature.account.common.AccountCommonExternalContract
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.InteractionMode
import app.k9mail.feature.account.oauth.ui.AccountOAuthContract
import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract
@ -77,6 +78,7 @@ class AccountSetupModuleKtTest : KoinTest {
Context::class,
Boolean::class,
Class.forName("net.openid.appauth.AppAuthConfiguration").kotlin,
InteractionMode::class,
),
)