Add authentication type to incoming server settings screen

This commit is contained in:
cketti 2023-06-28 15:14:42 +02:00
parent 032fa95041
commit d677c542ef
9 changed files with 63 additions and 1 deletions

View file

@ -2,9 +2,10 @@ package app.k9mail.feature.account.setup.domain.entity
import kotlinx.collections.immutable.toImmutableList
internal enum class AuthenticationType {
enum class AuthenticationType {
PasswordCleartext,
PasswordEncrypted,
ClientCertificate,
OAuth2,
;

View file

@ -0,0 +1,22 @@
package app.k9mail.feature.account.setup.ui.common.mapper
import android.content.res.Resources
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.domain.entity.AuthenticationType
internal fun AuthenticationType.toResourceString(resources: Resources): String {
return when (this) {
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

@ -26,12 +26,14 @@ import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.domain.entity.AuthenticationType
import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.ui.common.item.ErrorItem
import app.k9mail.feature.account.setup.ui.common.item.LoadingItem
import app.k9mail.feature.account.setup.ui.common.item.SuccessItem
import app.k9mail.feature.account.setup.ui.common.item.defaultItemPadding
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
@ -132,6 +134,17 @@ internal fun AccountIncomingConfigContent(
)
}
item {
SelectInput(
options = AuthenticationType.all(),
optionToStringTransformation = { it.toResourceString(resources) },
selectedOption = state.authenticationType,
onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) },
label = stringResource(id = R.string.account_setup_incoming_config_authentication_label),
contentPadding = defaultItemPadding(),
)
}
item {
TextInput(
text = state.username.value,

View file

@ -2,6 +2,7 @@ package app.k9mail.feature.account.setup.ui.incoming
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel
import app.k9mail.feature.account.setup.domain.entity.AuthenticationType
import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.toDefaultPort
@ -23,6 +24,7 @@ interface AccountIncomingConfigContract {
val port: NumberInputField = NumberInputField(
IncomingProtocolType.DEFAULT.toDefaultPort(IncomingProtocolType.DEFAULT.defaultConnectionSecurity),
),
val authenticationType: AuthenticationType = AuthenticationType.PasswordCleartext,
val username: StringInputField = StringInputField(),
val password: StringInputField = StringInputField(),
val clientCertificate: String = "",
@ -40,6 +42,7 @@ interface AccountIncomingConfigContract {
data class ServerChanged(val server: String) : Event()
data class SecurityChanged(val security: ConnectionSecurity) : Event()
data class PortChanged(val port: Long?) : Event()
data class AuthenticationTypeChanged(val authenticationType: AuthenticationType) : Event()
data class UsernameChanged(val username: String) : Event()
data class PasswordChanged(val password: String) : Event()
data class ClientCertificateChanged(val clientCertificate: String) : Event()

View file

@ -32,12 +32,14 @@ internal class AccountIncomingConfigViewModel(
}
}
@Suppress("CyclomaticComplexMethod")
override fun event(event: Event) {
when (event) {
is Event.ProtocolTypeChanged -> updateProtocolType(event.protocolType)
is Event.ServerChanged -> updateState { it.copy(server = it.server.updateValue(event.server)) }
is Event.SecurityChanged -> updateSecurity(event.security)
is Event.PortChanged -> updateState { it.copy(port = it.port.updateValue(event.port)) }
is Event.AuthenticationTypeChanged -> updateState { it.copy(authenticationType = event.authenticationType) }
is Event.UsernameChanged -> updateState { it.copy(username = it.username.updateValue(event.username)) }
is Event.PasswordChanged -> updateState { it.copy(password = it.password.updateValue(event.password)) }
is Event.ClientCertificateChanged -> updateState { it.copy(clientCertificate = event.clientCertificate) }

View file

@ -7,6 +7,10 @@
<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_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_none_available">None available</string>
<string name="account_setup_error_network">Network </string>
@ -43,6 +47,7 @@
<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>

View file

@ -1,5 +1,6 @@
package app.k9mail.feature.account.setup.ui.incoming
import app.k9mail.feature.account.setup.domain.entity.AuthenticationType
import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity
@ -21,6 +22,7 @@ class AccountIncomingConfigStateMapperKtTest {
server = StringInputField(value = "imap.example.org"),
port = NumberInputField(value = 993),
security = ConnectionSecurity.TLS,
authenticationType = AuthenticationType.PasswordCleartext,
username = StringInputField(value = "user"),
password = StringInputField(value = "password"),
clientCertificate = "",

View file

@ -1,5 +1,6 @@
package app.k9mail.feature.account.setup.ui.incoming
import app.k9mail.feature.account.setup.domain.entity.AuthenticationType
import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort
@ -22,6 +23,7 @@ class AccountIncomingConfigStateTest {
server = StringInputField(),
security = ConnectionSecurity.DEFAULT,
port = NumberInputField(value = ConnectionSecurity.DEFAULT.toImapDefaultPort()),
authenticationType = AuthenticationType.PasswordCleartext,
username = StringInputField(),
password = StringInputField(),
clientCertificate = "",

View file

@ -4,6 +4,7 @@ import app.cash.turbine.testIn
import app.k9mail.core.common.domain.usecase.validation.ValidationError
import app.k9mail.core.common.domain.usecase.validation.ValidationResult
import app.k9mail.core.ui.compose.testing.MainDispatcherRule
import app.k9mail.feature.account.setup.domain.entity.AuthenticationType
import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort
@ -96,6 +97,17 @@ class AccountIncomingConfigViewModelTest {
)
}
@Test
fun `should change authentication type when AuthenticationTypeChanged event is received`() = runTest {
eventStateTest(
viewModel = testSubject,
initialState = State(),
event = Event.AuthenticationTypeChanged(AuthenticationType.PasswordEncrypted),
expectedState = State(authenticationType = AuthenticationType.PasswordEncrypted),
coroutineScope = backgroundScope,
)
}
@Test
fun `should change state when UsernameChanged event is received`() = runTest {
eventStateTest(