Move server config to its own module

This commit is contained in:
Wolf-Martell Montwé 2023-09-06 13:41:03 +02:00
parent f141214844
commit 4f2fe9f6e5
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
68 changed files with 424 additions and 360 deletions

View file

@ -0,0 +1,29 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
}
android {
namespace = "app.k9mail.feature.account.server.config"
resourcePrefix = "account_server_config_"
buildTypes {
debug {
manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project"
}
release {
manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project"
}
}
}
dependencies {
implementation(projects.core.ui.compose.designsystem)
implementation(projects.core.common)
implementation(projects.mail.common)
implementation(projects.mail.protocols.imap)
implementation(projects.feature.account.common)
testImplementation(projects.core.ui.compose.testing)
}

View file

@ -0,0 +1,30 @@
package app.k9mail.feature.account.server.config
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigValidator
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigViewModel
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigValidator
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigViewModel
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.module.Module
import org.koin.dsl.module
val featureAccountServerConfigModule: Module = module {
factory<AccountIncomingConfigContract.Validator> { AccountIncomingConfigValidator() }
factory<AccountOutgoingConfigContract.Validator> { AccountOutgoingConfigValidator() }
viewModel {
AccountIncomingConfigViewModel(
validator = get(),
accountStateRepository = get(),
)
}
viewModel {
AccountOutgoingConfigViewModel(
validator = get(),
accountStateRepository = get(),
)
}
}

View file

@ -0,0 +1,33 @@
package app.k9mail.feature.account.server.config.domain
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
interface ServerConfigDomainContract {
interface UseCase {
fun interface ValidateEmailAddress {
fun execute(emailAddress: String): ValidationResult
}
fun interface ValidatePassword {
fun execute(password: String): ValidationResult
}
fun interface ValidateServer {
fun execute(server: String): ValidationResult
}
fun interface ValidatePort {
fun execute(port: Long?): ValidationResult
}
fun interface ValidateUsername {
fun execute(username: String): ValidationResult
}
fun interface ValidateImapPrefix {
fun execute(imapPrefix: String): ValidationResult
}
}
}

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
internal class ValidateEmailAddress : DomainContract.UseCase.ValidateEmailAddress {
class ValidateEmailAddress : UseCase.ValidateEmailAddress {
// TODO replace by new email validation
override fun execute(emailAddress: String): ValidationResult {

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
internal class ValidateImapPrefix : DomainContract.UseCase.ValidateImapPrefix {
internal class ValidateImapPrefix : UseCase.ValidateImapPrefix {
override fun execute(imapPrefix: String): ValidationResult {
return when {

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
internal class ValidatePassword : DomainContract.UseCase.ValidatePassword {
class ValidatePassword : UseCase.ValidatePassword {
// TODO change behavior to allow empty password when no password is required based on auth type
override fun execute(password: String): ValidationResult {

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
internal class ValidatePort : DomainContract.UseCase.ValidatePort {
internal class ValidatePort : UseCase.ValidatePort {
override fun execute(port: Long?): ValidationResult {
return when (port) {

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
internal class ValidateServer : DomainContract.UseCase.ValidateServer {
internal class ValidateServer : UseCase.ValidateServer {
// TODO validate domain, ip4 or ip6
override fun execute(server: String): ValidationResult {

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
internal class ValidateUsername : DomainContract.UseCase.ValidateUsername {
internal class ValidateUsername : UseCase.ValidateUsername {
override fun execute(username: String): ValidationResult {
return when {

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.clientcertificate
package app.k9mail.feature.account.server.config.ui.common
import android.security.KeyChain
import androidx.compose.foundation.layout.Column
@ -11,7 +11,7 @@ import androidx.compose.ui.res.stringResource
import app.k9mail.core.ui.compose.common.activity.LocalActivity
import app.k9mail.core.ui.compose.designsystem.atom.textfield.TextFieldOutlinedFakeSelect
import app.k9mail.core.ui.compose.designsystem.molecule.input.inputContentPadding
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.server.config.R
@Composable
fun ClientCertificateInput(
@ -29,7 +29,7 @@ fun ClientCertificateInput(
) {
val activity = LocalActivity.current
TextFieldOutlinedFakeSelect(
text = alias ?: stringResource(R.string.account_setup_client_certificate_none_selected),
text = alias ?: stringResource(R.string.account_server_config_client_certificate_none_selected),
onClick = {
KeyChain.choosePrivateKeyAlias(activity, onValueChange, null, null, null, -1, alias)
},

View file

@ -0,0 +1,29 @@
package app.k9mail.feature.account.server.config.ui.common.mapper
import android.content.res.Resources
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.server.config.R
internal fun AuthenticationType.toResourceString(resources: Resources): String {
return when (this) {
AuthenticationType.None -> {
resources.getString(R.string.account_server_config_authentication_none)
}
AuthenticationType.PasswordCleartext -> {
resources.getString(R.string.account_server_config_authentication_password_cleartext)
}
AuthenticationType.PasswordEncrypted -> {
resources.getString(R.string.account_server_config_authentication_password_encrypted)
}
AuthenticationType.ClientCertificate -> {
resources.getString(R.string.account_server_config_authentication_client_certificate)
}
AuthenticationType.OAuth2 -> {
resources.getString(R.string.account_server_config_authentication_client_oauth)
}
}
}

View file

@ -0,0 +1,13 @@
package app.k9mail.feature.account.server.config.ui.common.mapper
import android.content.res.Resources
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.server.config.R
internal fun ConnectionSecurity.toResourceString(resources: Resources): String {
return when (this) {
ConnectionSecurity.None -> resources.getString(R.string.account_server_config_connection_security_none)
ConnectionSecurity.StartTLS -> resources.getString(R.string.account_server_config_connection_security_start_tls)
ConnectionSecurity.TLS -> resources.getString(R.string.account_server_config_connection_security_ssl)
}
}

View file

@ -1,25 +1,16 @@
package app.k9mail.feature.account.setup.ui.common
package app.k9mail.feature.account.server.config.ui.common.mapper
import android.content.res.Resources
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError
import app.k9mail.feature.account.setup.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError
import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword.ValidatePasswordError
import app.k9mail.feature.account.setup.domain.usecase.ValidatePort.ValidatePortError
import app.k9mail.feature.account.setup.domain.usecase.ValidateServer.ValidateServerError
import app.k9mail.feature.account.setup.domain.usecase.ValidateUsername.ValidateUsernameError
import app.k9mail.feature.account.server.config.R
import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError
import app.k9mail.feature.account.server.config.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword.ValidatePasswordError
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort.ValidatePortError
import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer.ValidateServerError
import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername.ValidateUsernameError
internal fun ConnectionSecurity.toResourceString(resources: Resources): String {
return when (this) {
ConnectionSecurity.None -> resources.getString(R.string.account_setup_connection_security_none)
ConnectionSecurity.StartTLS -> resources.getString(R.string.account_setup_connection_security_start_tls)
ConnectionSecurity.TLS -> resources.getString(R.string.account_setup_connection_security_ssl)
}
}
internal fun ValidationError.toResourceString(resources: Resources): String {
fun ValidationError.toResourceString(resources: Resources): String {
return when (this) {
is ValidateEmailAddressError -> toEmailAddressErrorString(resources)
is ValidateServerError -> toServerErrorString(resources)
@ -34,11 +25,11 @@ internal fun ValidationError.toResourceString(resources: Resources): String {
private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resources): String {
return when (this) {
is ValidateEmailAddressError.EmptyEmailAddress -> resources.getString(
R.string.account_setup_validation_error_email_address_required,
R.string.account_server_config_validation_error_email_address_required,
)
is ValidateEmailAddressError.InvalidEmailAddress -> resources.getString(
R.string.account_setup_validation_error_email_address_invalid,
R.string.account_server_config_validation_error_email_address_invalid,
)
}
}
@ -46,7 +37,7 @@ private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resou
private fun ValidateServerError.toServerErrorString(resources: Resources): String {
return when (this) {
is ValidateServerError.EmptyServer -> resources.getString(
R.string.account_setup_validation_error_server_required,
R.string.account_server_config_validation_error_server_required,
)
}
}
@ -54,11 +45,11 @@ private fun ValidateServerError.toServerErrorString(resources: Resources): Strin
private fun ValidatePortError.toPortErrorString(resources: Resources): String {
return when (this) {
is ValidatePortError.EmptyPort -> resources.getString(
R.string.account_setup_validation_error_port_required,
R.string.account_server_config_validation_error_port_required,
)
is ValidatePortError.InvalidPort -> resources.getString(
R.string.account_setup_validation_error_port_invalid,
R.string.account_server_config_validation_error_port_invalid,
)
}
}
@ -66,7 +57,7 @@ private fun ValidatePortError.toPortErrorString(resources: Resources): String {
private fun ValidateUsernameError.toUsernameErrorString(resources: Resources): String {
return when (this) {
ValidateUsernameError.EmptyUsername -> resources.getString(
R.string.account_setup_validation_error_username_required,
R.string.account_server_config_validation_error_username_required,
)
}
}
@ -74,7 +65,7 @@ private fun ValidateUsernameError.toUsernameErrorString(resources: Resources): S
private fun ValidatePasswordError.toPasswordErrorString(resources: Resources): String {
return when (this) {
ValidatePasswordError.EmptyPassword -> resources.getString(
R.string.account_setup_validation_error_password_required,
R.string.account_server_config_validation_error_password_required,
)
}
}
@ -82,7 +73,7 @@ private fun ValidatePasswordError.toPasswordErrorString(resources: Resources): S
private fun ValidateImapPrefixError.toImapPrefixErrorString(resources: Resources): String {
return when (this) {
ValidateImapPrefixError.BlankImapPrefix -> resources.getString(
R.string.account_setup_validation_error_imap_prefix_blank,
R.string.account_server_config_validation_error_imap_prefix_blank,
)
}
}

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
@ -28,12 +28,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.ui.item.defaultItemPadding
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.ui.clientcertificate.ClientCertificateInput
import app.k9mail.feature.account.setup.ui.common.mapper.toResourceString
import app.k9mail.feature.account.setup.ui.common.toResourceString
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.R
import app.k9mail.feature.account.server.config.ui.common.ClientCertificateInput
import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
@Suppress("LongMethod")
@Composable
@ -68,7 +67,7 @@ internal fun AccountIncomingConfigContent(
options = IncomingProtocolType.all(),
selectedOption = state.protocolType,
onOptionChange = { onEvent(Event.ProtocolTypeChanged(it)) },
label = stringResource(id = R.string.account_setup_incoming_config_protocol_type_label),
label = stringResource(id = R.string.account_server_config_protocol_type_label),
contentPadding = defaultItemPadding(),
)
}
@ -78,7 +77,7 @@ internal fun AccountIncomingConfigContent(
text = state.server.value,
errorMessage = state.server.error?.toResourceString(resources),
onTextChange = { onEvent(Event.ServerChanged(it)) },
label = stringResource(id = R.string.account_setup_incoming_config_server_label),
label = stringResource(id = R.string.account_server_config_server_label),
contentPadding = defaultItemPadding(),
)
}
@ -89,7 +88,7 @@ internal fun AccountIncomingConfigContent(
optionToStringTransformation = { it.toResourceString(resources) },
selectedOption = state.security,
onOptionChange = { onEvent(Event.SecurityChanged(it)) },
label = stringResource(id = R.string.account_setup_incoming_config_security_label),
label = stringResource(id = R.string.account_server_config_security_label),
contentPadding = defaultItemPadding(),
)
}
@ -99,7 +98,7 @@ internal fun AccountIncomingConfigContent(
value = state.port.value,
errorMessage = state.port.error?.toResourceString(resources),
onValueChange = { onEvent(Event.PortChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_port_label),
label = stringResource(id = R.string.account_server_config_port_label),
contentPadding = defaultItemPadding(),
)
}
@ -110,7 +109,7 @@ internal fun AccountIncomingConfigContent(
optionToStringTransformation = { it.toResourceString(resources) },
selectedOption = state.authenticationType,
onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) },
label = stringResource(id = R.string.account_setup_incoming_config_authentication_label),
label = stringResource(id = R.string.account_server_config_authentication_label),
contentPadding = defaultItemPadding(),
)
}
@ -120,7 +119,7 @@ internal fun AccountIncomingConfigContent(
text = state.username.value,
errorMessage = state.username.error?.toResourceString(resources),
onTextChange = { onEvent(Event.UsernameChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_username_label),
label = stringResource(id = R.string.account_server_config_username_label),
contentPadding = defaultItemPadding(),
)
}
@ -140,7 +139,7 @@ internal fun AccountIncomingConfigContent(
ClientCertificateInput(
alias = state.clientCertificateAlias,
onValueChange = { onEvent(Event.ClientCertificateChanged(it)) },
label = stringResource(id = R.string.account_setup_client_certificate_label),
label = stringResource(id = R.string.account_server_config_client_certificate_label),
contentPadding = defaultItemPadding(),
)
}
@ -148,7 +147,7 @@ internal fun AccountIncomingConfigContent(
if (state.protocolType == IncomingProtocolType.IMAP) {
item {
CheckboxInput(
text = stringResource(id = R.string.account_setup_incoming_config_imap_namespace_label),
text = stringResource(id = R.string.account_server_config_incoming_imap_namespace_label),
checked = state.imapAutodetectNamespaceEnabled,
onCheckedChange = { onEvent(Event.ImapAutoDetectNamespaceChanged(it)) },
contentPadding = defaultItemPadding(),
@ -159,7 +158,7 @@ internal fun AccountIncomingConfigContent(
if (state.imapAutodetectNamespaceEnabled) {
TextInput(
onTextChange = {},
label = stringResource(id = R.string.account_setup_incoming_config_imap_prefix_label),
label = stringResource(id = R.string.account_server_config_incoming_imap_prefix_label),
contentPadding = defaultItemPadding(),
isEnabled = false,
)
@ -168,7 +167,7 @@ internal fun AccountIncomingConfigContent(
text = state.imapPrefix.value,
errorMessage = state.imapPrefix.error?.toResourceString(resources),
onTextChange = { onEvent(Event.ImapPrefixChanged(it)) },
label = stringResource(id = R.string.account_setup_incoming_config_imap_prefix_label),
label = stringResource(id = R.string.account_server_config_incoming_imap_prefix_label),
contentPadding = defaultItemPadding(),
)
}
@ -176,7 +175,7 @@ internal fun AccountIncomingConfigContent(
item {
CheckboxInput(
text = stringResource(id = R.string.account_setup_incoming_config_imap_compression_label),
text = stringResource(id = R.string.account_server_config_incoming_imap_compression_label),
checked = state.imapUseCompression,
onCheckedChange = { onEvent(Event.ImapUseCompressionChanged(it)) },
contentPadding = defaultItemPadding(),
@ -185,7 +184,7 @@ internal fun AccountIncomingConfigContent(
item {
CheckboxInput(
text = stringResource(R.string.account_setup_incoming_config_imap_send_client_id_label),
text = stringResource(R.string.account_server_config_incoming_imap_send_client_id_label),
checked = state.imapSendClientId,
onCheckedChange = { onEvent(Event.ImapSendClientIdChanged(it)) },
contentPadding = defaultItemPadding(),

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable
@ -13,13 +13,13 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
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
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel
import app.k9mail.feature.account.server.config.R
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel
@Composable
internal fun AccountIncomingConfigScreen(
fun AccountIncomingConfigScreen(
onNext: (AccountIncomingConfigContract.State) -> Unit,
onBack: () -> Unit,
viewModel: ViewModel,
@ -43,7 +43,7 @@ internal fun AccountIncomingConfigScreen(
Scaffold(
topBar = {
AccountTopAppBar(
title = stringResource(id = R.string.account_setup_incoming_config_top_bar_title),
title = stringResource(id = R.string.account_server_config_incoming_top_bar_title),
)
},
bottomBar = {

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
@ -8,7 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.mail.store.imap.ImapStoreSettings

View file

@ -1,12 +1,12 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.DomainContract.UseCase
import app.k9mail.feature.account.setup.domain.usecase.ValidateImapPrefix
import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword
import app.k9mail.feature.account.setup.domain.usecase.ValidatePort
import app.k9mail.feature.account.setup.domain.usecase.ValidateServer
import app.k9mail.feature.account.setup.domain.usecase.ValidateUsername
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase
import app.k9mail.feature.account.server.config.domain.usecase.ValidateImapPrefix
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort
import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer
import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername
internal class AccountIncomingConfigValidator(
private val serverValidator: UseCase.ValidateServer = ValidateServer(),

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
@ -6,13 +6,13 @@ 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.toDefaultPort
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Validator
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Validator
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel
internal class AccountIncomingConfigViewModel(
class AccountIncomingConfigViewModel(
private val validator: Validator,
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
initialState: State? = null,

View file

@ -1,6 +1,7 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming.fake
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract
class FakeAccountIncomingConfigValidator(
private val serverAnswer: ValidationResult = ValidationResult.Success,

View file

@ -0,0 +1,22 @@
package app.k9mail.feature.account.server.config.ui.incoming.fake
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel
class FakeAccountIncomingConfigViewModel(
initialState: State = State(),
) : BaseViewModel<State, Event, Effect>(initialState), ViewModel {
val events = mutableListOf<Event>()
override fun event(event: Event) {
events.add(event)
}
fun effect(effect: Effect) {
emitEffect(effect)
}
}

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
@ -27,12 +27,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.common.ui.item.defaultItemPadding
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.ui.clientcertificate.ClientCertificateInput
import app.k9mail.feature.account.setup.ui.common.mapper.toResourceString
import app.k9mail.feature.account.setup.ui.common.toResourceString
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.R
import app.k9mail.feature.account.server.config.ui.common.ClientCertificateInput
import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
@Suppress("LongMethod")
@Composable
@ -67,7 +66,7 @@ internal fun AccountOutgoingConfigContent(
text = state.server.value,
errorMessage = state.server.error?.toResourceString(resources),
onTextChange = { onEvent(Event.ServerChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_server_label),
label = stringResource(id = R.string.account_server_config_server_label),
isRequired = true,
contentPadding = defaultItemPadding(),
)
@ -79,7 +78,7 @@ internal fun AccountOutgoingConfigContent(
optionToStringTransformation = { it.toResourceString(resources) },
selectedOption = state.security,
onOptionChange = { onEvent(Event.SecurityChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_security_label),
label = stringResource(id = R.string.account_server_config_security_label),
contentPadding = defaultItemPadding(),
)
}
@ -89,7 +88,7 @@ internal fun AccountOutgoingConfigContent(
value = state.port.value,
errorMessage = state.port.error?.toResourceString(resources),
onValueChange = { onEvent(Event.PortChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_port_label),
label = stringResource(id = R.string.account_server_config_port_label),
isRequired = true,
contentPadding = defaultItemPadding(),
)
@ -101,7 +100,7 @@ internal fun AccountOutgoingConfigContent(
optionToStringTransformation = { it.toResourceString(resources) },
selectedOption = state.authenticationType,
onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_authentication_label),
label = stringResource(id = R.string.account_server_config_authentication_label),
contentPadding = defaultItemPadding(),
)
}
@ -112,7 +111,7 @@ internal fun AccountOutgoingConfigContent(
text = state.username.value,
errorMessage = state.username.error?.toResourceString(resources),
onTextChange = { onEvent(Event.UsernameChanged(it)) },
label = stringResource(id = R.string.account_setup_outgoing_config_username_label),
label = stringResource(id = R.string.account_server_config_username_label),
isRequired = true,
contentPadding = defaultItemPadding(),
)
@ -135,7 +134,7 @@ internal fun AccountOutgoingConfigContent(
ClientCertificateInput(
alias = state.clientCertificateAlias,
onValueChange = { onEvent(Event.ClientCertificateChanged(it)) },
label = stringResource(id = R.string.account_setup_client_certificate_label),
label = stringResource(id = R.string.account_server_config_client_certificate_label),
contentPadding = defaultItemPadding(),
)
}

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable
@ -13,13 +13,13 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
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
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel
import app.k9mail.feature.account.server.config.R
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel
@Composable
internal fun AccountOutgoingConfigScreen(
fun AccountOutgoingConfigScreen(
onNext: () -> Unit,
onBack: () -> Unit,
viewModel: ViewModel,
@ -43,7 +43,7 @@ internal fun AccountOutgoingConfigScreen(
Scaffold(
topBar = {
AccountTopAppBar(
title = stringResource(id = R.string.account_setup_outgoing_config_top_bar_title),
title = stringResource(id = R.string.account_server_config_outgoing_top_bar_title),
)
},
bottomBar = {

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
internal val AccountOutgoingConfigContract.State.isUsernameFieldVisible: Boolean
get() = authenticationType.isUsernameRequired

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.toAuthType
@ -7,7 +7,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity
import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import com.fsck.k9.mail.ServerSettings
internal fun AccountState.toOutgoingConfigState(): State {

View file

@ -1,10 +1,10 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword
import app.k9mail.feature.account.setup.domain.usecase.ValidatePort
import app.k9mail.feature.account.setup.domain.usecase.ValidateServer
import app.k9mail.feature.account.setup.domain.usecase.ValidateUsername
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort
import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer
import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername
internal class AccountOutgoingConfigValidator(
private val serverValidator: ValidateServer = ValidateServer(),

View file

@ -1,17 +1,17 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
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.toSmtpDefaultPort
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Validator
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Validator
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel
internal class AccountOutgoingConfigViewModel(
class AccountOutgoingConfigViewModel(
private val validator: Validator,
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
initialState: State? = State(),

View file

@ -1,6 +1,7 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing.fake
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract
class FakeAccountOutgoingConfigValidator(
private val serverAnswer: ValidationResult = ValidationResult.Success,

View file

@ -0,0 +1,22 @@
package app.k9mail.feature.account.server.config.ui.outgoing.fake
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel
class FakeAccountOutgoingConfigViewModel(
initialState: State = State(),
) : BaseViewModel<State, Event, Effect>(initialState), ViewModel {
val events = mutableListOf<Event>()
override fun event(event: Event) {
events.add(event)
}
fun effect(effect: Effect) {
emitEffect(effect)
}
}

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="account_server_config_protocol_type_label">Protocol</string>
<string name="account_server_config_server_label">Server</string>
<string name="account_server_config_security_label">Security</string>
<string name="account_server_config_port_label">Port</string>
<string name="account_server_config_authentication_label">Authentication</string>
<string name="account_server_config_username_label">Username</string>
<string name="account_server_config_connection_security_none">None</string>
<string name="account_server_config_connection_security_start_tls">StartTLS</string>
<string name="account_server_config_connection_security_ssl">SSL/TLS</string>
<string name="account_server_config_authentication_none">None</string>
<string name="account_server_config_authentication_password_cleartext">Normal password</string>
<string name="account_server_config_authentication_password_encrypted">Encrypted password</string>
<string name="account_server_config_authentication_client_certificate">Client certificate</string>
<string name="account_server_config_authentication_client_oauth">OAuth 2.0</string>
<string name="account_server_config_client_certificate_none_selected">None</string>
<string name="account_server_config_client_certificate_label">Client certificate</string>
<string name="account_server_config_incoming_top_bar_title">Incoming server settings</string>
<string name="account_server_config_incoming_imap_namespace_label">Auto-detect IMAP namespace</string>
<string name="account_server_config_incoming_imap_prefix_label">IMAP path prefix</string>
<string name="account_server_config_incoming_imap_compression_label">Use compression</string>
<string name="account_server_config_incoming_imap_send_client_id_label">Send client ID</string>
<string name="account_server_config_outgoing_top_bar_title">Outgoing server settings</string>
<string name="account_server_config_validation_error_email_address_required">Email address is required.</string>
<string name="account_server_config_validation_error_email_address_invalid">Email address is invalid.</string>
<string name="account_server_config_validation_error_server_required">Server name is required.</string>
<string name="account_server_config_validation_error_port_required">Port is required.</string>
<string name="account_server_config_validation_error_port_invalid">Port is invalid (must be 165535).</string>
<string name="account_server_config_validation_error_username_required">Username is required.</string>
<string name="account_server_config_validation_error_password_required">Password is required.</string>
<string name="account_server_config_validation_error_imap_prefix_blank">Imap prefix can\'t be blank.</string>
</resources>

View file

@ -1,7 +1,7 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError
import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError
import assertk.assertThat
import assertk.assertions.isInstanceOf
import assertk.assertions.prop

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import assertk.assertThat

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import assertk.assertThat

View file

@ -1,7 +1,7 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.setup.domain.usecase.ValidatePort.ValidatePortError
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort.ValidatePortError
import assertk.assertThat
import assertk.assertions.isInstanceOf
import assertk.assertions.prop

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import assertk.assertThat

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.domain.usecase
package app.k9mail.feature.account.server.config.domain.usecase
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import assertk.assertThat

View file

@ -1,9 +1,10 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.core.ui.compose.testing.ComposeTest
import app.k9mail.core.ui.compose.testing.setContent
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigViewModel
import assertk.assertThat
import assertk.assertions.isEqualTo
import kotlinx.coroutines.test.runTest

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import assertk.assertThat
import assertk.assertions.isEqualTo
import com.fsck.k9.mail.AuthType

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import assertk.assertThat
import assertk.assertions.isEqualTo
import org.junit.Test

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.incoming
package app.k9mail.feature.account.server.config.ui.incoming
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
@ -18,9 +18,10 @@ import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort
import app.k9mail.feature.account.common.domain.entity.toPop3DefaultPort
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigValidator
import assertk.assertThat
import assertk.assertions.isEqualTo
import com.fsck.k9.mail.AuthType

View file

@ -1,9 +1,10 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import app.k9mail.core.ui.compose.testing.ComposeTest
import app.k9mail.core.ui.compose.testing.setContent
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel
import assertk.assertThat
import assertk.assertions.isEqualTo
import kotlinx.coroutines.test.runTest

View file

@ -1,11 +1,11 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
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.MailConnectionSecurity
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import assertk.assertThat
import assertk.assertions.isEqualTo
import com.fsck.k9.mail.AuthType

View file

@ -1,11 +1,11 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
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.toSmtpDefaultPort
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import assertk.assertThat
import assertk.assertions.isEqualTo
import org.junit.Test

View file

@ -1,4 +1,4 @@
package app.k9mail.feature.account.setup.ui.outgoing
package app.k9mail.feature.account.server.config.ui.outgoing
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
@ -16,9 +16,10 @@ 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
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigValidator
import assertk.assertThat
import assertk.assertions.isEqualTo
import com.fsck.k9.mail.AuthType

View file

@ -29,6 +29,7 @@ dependencies {
api(projects.feature.account.common)
implementation(projects.feature.account.oauth)
implementation(projects.feature.account.server.config)
implementation(projects.feature.account.server.certificate)
api(projects.feature.account.server.validation)

View file

@ -4,6 +4,7 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService
import app.k9mail.autodiscovery.service.RealAutoDiscoveryService
import app.k9mail.feature.account.common.featureAccountCommonModule
import app.k9mail.feature.account.oauth.featureAccountOAuthModule
import app.k9mail.feature.account.server.config.featureAccountServerConfigModule
import app.k9mail.feature.account.server.validation.featureAccountServerValidationModule
import app.k9mail.feature.account.setup.domain.DomainContract
import app.k9mail.feature.account.setup.domain.usecase.CreateAccount
@ -12,15 +13,9 @@ import app.k9mail.feature.account.setup.ui.AccountSetupViewModel
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryValidator
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryViewModel
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigValidator
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigViewModel
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsValidator
import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigValidator
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel
import okhttp3.OkHttpClient
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.module.Module
@ -31,6 +26,7 @@ val featureAccountSetupModule: Module = module {
featureAccountCommonModule,
featureAccountOAuthModule,
featureAccountServerValidationModule,
featureAccountServerConfigModule,
)
single<OkHttpClient> {
@ -57,8 +53,6 @@ val featureAccountSetupModule: Module = module {
}
factory<AccountAutoDiscoveryContract.Validator> { AccountAutoDiscoveryValidator() }
factory<AccountIncomingConfigContract.Validator> { AccountIncomingConfigValidator() }
factory<AccountOutgoingConfigContract.Validator> { AccountOutgoingConfigValidator() }
factory<AccountOptionsContract.Validator> { AccountOptionsValidator() }
viewModel {
@ -75,19 +69,6 @@ val featureAccountSetupModule: Module = module {
oAuthViewModel = get(),
)
}
viewModel {
AccountIncomingConfigViewModel(
validator = get(),
accountStateRepository = get(),
)
}
viewModel {
AccountOutgoingConfigViewModel(
validator = get(),
accountStateRepository = get(),
)
}
viewModel {
AccountOptionsViewModel(

View file

@ -4,7 +4,6 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryResult
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.common.domain.entity.AccountOptions
import com.fsck.k9.mail.ServerSettings
import java.security.cert.X509Certificate
interface DomainContract {
@ -13,10 +12,6 @@ interface DomainContract {
suspend fun execute(emailAddress: String): AutoDiscoveryResult
}
fun interface AddServerCertificateException {
suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?)
}
fun interface CreateAccount {
suspend fun execute(
emailAddress: String,
@ -27,34 +22,10 @@ interface DomainContract {
): String
}
fun interface ValidateEmailAddress {
fun execute(emailAddress: String): ValidationResult
}
fun interface ValidatePassword {
fun execute(password: String): ValidationResult
}
fun interface ValidateConfigurationApproval {
fun execute(isApproved: Boolean?, isAutoDiscoveryTrusted: Boolean?): ValidationResult
}
fun interface ValidateServer {
fun execute(server: String): ValidationResult
}
fun interface ValidatePort {
fun execute(port: Long?): ValidationResult
}
fun interface ValidateUsername {
fun execute(username: String): ValidationResult
}
fun interface ValidateImapPrefix {
fun execute(imapPrefix: String): ValidationResult
}
fun interface ValidateAccountName {
fun execute(accountName: String): ValidationResult
}

View file

@ -3,6 +3,12 @@ package app.k9mail.feature.account.setup.ui
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.common.mvi.observe
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigScreen
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigViewModel
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigScreen
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigViewModel
import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION
import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION
import app.k9mail.feature.account.server.validation.ui.ServerValidationContract
@ -15,15 +21,9 @@ import app.k9mail.feature.account.setup.ui.AccountSetupContract.ViewModel
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryScreen
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryViewModel
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigScreen
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigViewModel
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsScreen
import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigScreen
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.qualifier.named

View file

@ -53,13 +53,13 @@ internal fun AccountAutoDiscoveryContent(
if (state.isLoading) {
item(key = "loading") {
LoadingItem(
message = stringResource(id = R.string.account_setup_auto_config_loading_message),
message = stringResource(id = R.string.account_setup_auto_discovery_loading_message),
)
}
} else if (state.error != null) {
item(key = "error") {
ErrorItem(
title = stringResource(id = R.string.account_setup_auto_config_loading_error),
title = stringResource(id = R.string.account_setup_auto_discovery_loading_error),
message = state.error.toResourceString(resources),
onRetry = { onEvent(Event.OnRetryClicked) },
)

View file

@ -5,13 +5,13 @@ import app.k9mail.autodiscovery.api.SmtpServerSettings
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType
import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType
import app.k9mail.feature.account.setup.domain.toServerSettings
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
internal fun AccountAutoDiscoveryContract.State.toAccountState(): AccountState {
return AccountState(

View file

@ -1,14 +1,15 @@
package app.k9mail.feature.account.setup.ui.autodiscovery
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract
import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress
import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword
import app.k9mail.feature.account.setup.domain.DomainContract.UseCase
import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationApproval
import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress
import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword
internal class AccountAutoDiscoveryValidator(
private val emailAddressValidator: UseCase.ValidateEmailAddress = ValidateEmailAddress(),
private val passwordValidator: UseCase.ValidatePassword = ValidatePassword(),
private val emailAddressValidator: ServerConfigDomainContract.UseCase.ValidateEmailAddress = ValidateEmailAddress(),
private val passwordValidator: ServerConfigDomainContract.UseCase.ValidatePassword = ValidatePassword(),
private val configurationApprovalValidator: UseCase.ValidateConfigurationApproval = ValidateConfigurationApproval(),
) : AccountAutoDiscoveryContract.Validator {

View file

@ -9,11 +9,11 @@ import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationAppr
internal fun AutoDiscoveryConnectionSecurity.toResourceString(resources: Resources): String {
return when (this) {
AutoDiscoveryConnectionSecurity.StartTLS -> resources.getString(
R.string.account_setup_connection_security_start_tls,
R.string.account_setup_auto_discovery_connection_security_start_tls,
)
AutoDiscoveryConnectionSecurity.TLS -> resources.getString(
R.string.account_setup_connection_security_ssl,
R.string.account_setup_auto_discovery_connection_security_ssl,
)
}
}
@ -40,7 +40,7 @@ private fun ValidateConfigurationApproval.ValidateConfigurationApprovalError.toC
): String {
return when (this) {
ValidateConfigurationApproval.ValidateConfigurationApprovalError.ApprovalRequired -> resources.getString(
R.string.account_setup_error_configuration_approval_required,
R.string.account_setup_auto_discovery_error_configuration_approval_required,
)
}
}

View file

@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalContext
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.ui.compose.designsystem.molecule.input.EmailAddressInput
import app.k9mail.feature.account.common.ui.item.ListItem
import app.k9mail.feature.account.setup.ui.common.toResourceString
import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString
@Composable
internal fun LazyItemScope.EmailAddressItem(

View file

@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalContext
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.ui.compose.designsystem.molecule.input.PasswordInput
import app.k9mail.feature.account.common.ui.item.ListItem
import app.k9mail.feature.account.setup.ui.common.toResourceString
import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString
@Composable
internal fun LazyItemScope.PasswordItem(

View file

@ -27,7 +27,6 @@ import app.k9mail.core.ui.compose.theme.Icons
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
import app.k9mail.feature.account.setup.ui.autodiscovery.toResourceString
import app.k9mail.feature.account.setup.ui.common.toResourceString
@Composable
internal fun AutoDiscoveryServerSettingsView(

View file

@ -42,7 +42,7 @@ internal fun AutoDiscoveryStatusBodyView(
Spacer(modifier = Modifier.height(MainTheme.sizes.smaller))
TextBody2(
text = stringResource(
id = R.string.account_setup_auto_config_status_disclaimer_untrusted_configuration,
id = R.string.account_setup_auto_discovery_status_disclaimer_untrusted_configuration,
),
modifier = Modifier.fillMaxWidth(),
)
@ -94,7 +94,7 @@ internal fun EditConfigurationButton(
.then(modifier),
) {
ButtonText(
text = stringResource(id = R.string.account_setup_auto_config_status_edit_configuration_button_label),
text = stringResource(id = R.string.account_setup_auto_discovery_status_edit_configuration_button_label),
onClick = onEditConfigurationClick,
color = MainTheme.colors.warning,
contentPadding = buttonContentPadding(

View file

@ -13,22 +13,22 @@ enum class AutoDiscoveryStatusHeaderState(
) {
NoSettings(
icon = Icons.Outlined.info,
titleResourceId = R.string.account_setup_auto_config_status_header_title_configuration_not_found,
subtitleResourceId = R.string.account_setup_auto_config_status_header_subtitle_configuration_not_found,
titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_not_found,
subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_not_found,
isExpandable = false,
),
Trusted(
icon = Icons.Outlined.check,
titleResourceId = R.string.account_setup_auto_config_status_header_title_configuration_found,
subtitleResourceId = R.string.account_setup_auto_config_status_header_subtitle_configuration_trusted,
titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_found,
subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_trusted,
isExpandable = true,
),
Untrusted(
icon = Icons.Outlined.info,
titleResourceId = R.string.account_setup_auto_config_status_header_title_configuration_found,
subtitleResourceId = R.string.account_setup_auto_config_status_header_subtitle_configuration_untrusted,
titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_found,
subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_untrusted,
isExpandable = true,
),
}

View file

@ -24,7 +24,7 @@ internal fun ConfigurationApprovalView(
CheckboxInput(
text = stringResource(
id = R.string.account_setup_auto_config_status_checkbox_configuration_untrusted_confirmation_label,
id = R.string.account_setup_auto_discovery_status_checkbox_configuration_untrusted_confirmation_label,
),
checked = approvalState.value ?: false,
onCheckedChange = onConfigurationApprovalChange,

View file

@ -1,25 +0,0 @@
package app.k9mail.feature.account.setup.ui.common.mapper
import android.content.res.Resources
import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.setup.R
internal fun AuthenticationType.toResourceString(resources: Resources): String {
return when (this) {
AuthenticationType.None -> {
resources.getString(R.string.account_setup_authentication_none)
}
AuthenticationType.PasswordCleartext -> {
resources.getString(R.string.account_setup_authentication_password_cleartext)
}
AuthenticationType.PasswordEncrypted -> {
resources.getString(R.string.account_setup_authentication_password_encrypted)
}
AuthenticationType.ClientCertificate -> {
resources.getString(R.string.account_setup_authentication_client_certificate)
}
AuthenticationType.OAuth2 -> {
resources.getString(R.string.account_setup_authentication_client_oauth)
}
}
}

View file

@ -2,57 +2,23 @@
<resources>
<string name="account_setup_title">K-9 Mail</string>
<string name="account_setup_button_finish">Finish</string>
<string name="account_setup_connection_security_none">None</string>
<string name="account_setup_connection_security_ssl">SSL/TLS</string>
<string name="account_setup_connection_security_start_tls">StartTLS</string>
<string name="account_setup_authentication_none">None</string>
<string name="account_setup_authentication_password_cleartext">Normal password</string>
<string name="account_setup_authentication_password_encrypted">Encrypted password</string>
<string name="account_setup_authentication_client_certificate">Client certificate</string>
<string name="account_setup_authentication_client_oauth">OAuth 2.0</string>
<string name="account_setup_client_certificate_label">Client certificate</string>
<string name="account_setup_client_certificate_none_selected">None</string>
<string name="account_setup_error_network">Network </string>
<string name="account_setup_error_unknown">Unknown error</string>
<string name="account_setup_validation_error_email_address_required">Email address is required.</string>
<string name="account_setup_validation_error_email_address_invalid">Email address is invalid.</string>
<string name="account_setup_validation_error_server_required">Server name is required.</string>
<string name="account_setup_validation_error_port_required">Port is required.</string>
<string name="account_setup_validation_error_port_invalid">Port is invalid (must be 165535).</string>
<string name="account_setup_validation_error_username_required">Username is required.</string>
<string name="account_setup_validation_error_password_required">Password is required.</string>
<string name="account_setup_validation_error_imap_prefix_blank">Imap prefix can\'t be blank.</string>
<string name="account_setup_auto_config_loading_message">Finding email details</string>
<string name="account_setup_auto_config_loading_error">Failed to load email configuration</string>
<string name="account_setup_auto_config_status_header_title_configuration_found">Configuration Found</string>
<string name="account_setup_auto_config_status_header_title_configuration_not_found">Configuration Not Found</string>
<string name="account_setup_auto_config_status_header_subtitle_configuration_trusted">Configure automatically</string>
<string name="account_setup_auto_config_status_header_subtitle_configuration_untrusted">This configuration is not trusted</string>
<string name="account_setup_auto_config_status_disclaimer_untrusted_configuration">We received the configuration for your email server over a connection that isn\'t as secure as we\'d like. This means that there is a tiny chance that someone could have altered it. Could you please double-check the provided configuration to make sure it\'s as it should be?</string>
<string name="account_setup_auto_config_status_header_subtitle_configuration_not_found">Configure manually</string>
<string name="account_setup_auto_config_status_edit_configuration_button_label">Edit configuration</string>
<string name="account_setup_auto_config_status_checkbox_configuration_untrusted_confirmation_label">I trust this configuration</string>
<string name="account_setup_error_configuration_approval_required">It is required to approve the configuration.</string>
<string name="account_setup_incoming_config_top_bar_title">Incoming server settings</string>
<string name="account_setup_incoming_config_protocol_type_label">Protocol</string>
<string name="account_setup_incoming_config_server_label">Server</string>
<string name="account_setup_incoming_config_security_label">Security</string>
<string name="account_setup_incoming_config_authentication_label">Authentication</string>
<string name="account_setup_incoming_config_imap_namespace_label">Auto-detect IMAP namespace</string>
<string name="account_setup_incoming_config_imap_prefix_label">IMAP path prefix</string>
<string name="account_setup_incoming_config_imap_compression_label">Use compression</string>
<string name="account_setup_incoming_config_imap_send_client_id_label">Send client ID</string>
<string name="account_setup_outgoing_config_top_bar_title">Outgoing server settings</string>
<string name="account_setup_outgoing_config_server_label">Server</string>
<string name="account_setup_outgoing_config_security_label">Security</string>
<string name="account_setup_outgoing_config_port_label">Port</string>
<string name="account_setup_outgoing_config_authentication_label">Authentication</string>
<string name="account_setup_outgoing_config_username_label">Username</string>
<string name="account_setup_auto_discovery_connection_security_start_tls">StartTLS</string>
<string name="account_setup_auto_discovery_connection_security_ssl">SSL/TLS</string>
<string name="account_setup_auto_discovery_loading_message">Finding email details</string>
<string name="account_setup_auto_discovery_loading_error">Failed to load email configuration</string>
<string name="account_setup_auto_discovery_status_header_title_configuration_found">Configuration Found</string>
<string name="account_setup_auto_discovery_status_header_title_configuration_not_found">Configuration Not Found</string>
<string name="account_setup_auto_discovery_status_header_subtitle_configuration_trusted">Configure automatically</string>
<string name="account_setup_auto_discovery_status_header_subtitle_configuration_untrusted">This configuration is not trusted</string>
<string name="account_setup_auto_discovery_status_disclaimer_untrusted_configuration">We received the configuration for your email server over a connection that isn\'t as secure as we\'d like. This means that there is a tiny chance that someone could have altered it. Could you please double-check the provided configuration to make sure it\'s as it should be?</string>
<string name="account_setup_auto_discovery_status_header_subtitle_configuration_not_found">Configure manually</string>
<string name="account_setup_auto_discovery_status_edit_configuration_button_label">Edit configuration</string>
<string name="account_setup_auto_discovery_status_checkbox_configuration_untrusted_confirmation_label">I trust this configuration</string>
<string name="account_setup_auto_discovery_error_configuration_approval_required">It is required to approve the configuration.</string>
<string name="account_setup_options_top_bar_title">Account options</string>
<string name="account_setup_options_section_display_options">Display options</string>

View file

@ -5,14 +5,14 @@ import app.k9mail.core.common.oauth.OAuthConfigurationFactory
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.oauth.ui.AccountOAuthContract
import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.server.validation.ui.ServerValidationContract
import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator
import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult
import app.k9mail.feature.account.setup.ui.AccountSetupContract
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
import com.fsck.k9.mail.oauth.AuthStateStorage
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory

View file

@ -4,14 +4,14 @@ 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.server.config.ui.incoming.fake.FakeAccountIncomingConfigViewModel
import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel
import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel
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 app.k9mail.feature.account.setup.ui.autodiscovery.FakeAccountAutoDiscoveryViewModel
import app.k9mail.feature.account.setup.ui.incoming.FakeAccountIncomingConfigViewModel
import app.k9mail.feature.account.setup.ui.options.FakeAccountOptionsViewModel
import app.k9mail.feature.account.setup.ui.outgoing.FakeAccountOutgoingConfigViewModel
import assertk.assertThat
import assertk.assertions.isEqualTo
import kotlinx.coroutines.test.runTest

View file

@ -10,12 +10,12 @@ import app.k9mail.feature.account.common.domain.entity.AuthenticationType
import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.common.domain.input.NumberInputField
import app.k9mail.feature.account.common.domain.input.StringInputField
import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract
import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType
import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
import assertk.assertThat
import assertk.assertions.isEqualTo
import org.junit.Test

View file

@ -1,22 +0,0 @@
package app.k9mail.feature.account.setup.ui.incoming
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel
class FakeAccountIncomingConfigViewModel(
initialState: State = State(),
) : BaseViewModel<State, Event, Effect>(initialState), ViewModel {
val events = mutableListOf<Event>()
override fun event(event: Event) {
events.add(event)
}
fun effect(effect: Effect) {
emitEffect(effect)
}
}

View file

@ -1,22 +0,0 @@
package app.k9mail.feature.account.setup.ui.outgoing
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel
class FakeAccountOutgoingConfigViewModel(
initialState: State = State(),
) : BaseViewModel<State, Event, Effect>(initialState), ViewModel {
val events = mutableListOf<Event>()
override fun event(event: Event) {
events.add(event)
}
fun effect(effect: Effect) {
emitEffect(effect)
}
}

View file

@ -48,6 +48,7 @@ include(
":feature:account:oauth",
":feature:account:setup",
":feature:account:server:certificate",
":feature:account:server:config",
":feature:account:server:validation",
)