Add AutoDiscoveryStatusItem

This commit is contained in:
Wolf-Martell Montwé 2023-06-14 13:23:55 +02:00
parent 2ce5688fb4
commit 2a720fa5bf
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
9 changed files with 294 additions and 4 deletions

View file

@ -3,10 +3,11 @@ package app.k9mail.core.ui.compose.theme
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.icons.filled.Inbox
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.MoveToInbox
import androidx.compose.material.icons.filled.Notifications
import androidx.compose.material.icons.filled.Outbox
import androidx.compose.material.icons.filled.Security
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material.icons.outlined.ArrowBack
@ -17,15 +18,18 @@ import androidx.compose.material.icons.outlined.Error
import androidx.compose.material.icons.outlined.ErrorOutline
import androidx.compose.material.icons.outlined.ExpandLess
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Menu
import androidx.compose.material.icons.outlined.WarningAmber
import androidx.compose.material.icons.Icons as MaterialIcons
object Icons {
object Filled {
val error = MaterialIcons.Filled.Error
val inbox = MaterialIcons.Filled.Inbox
val inbox = MaterialIcons.Filled.MoveToInbox
val notification = MaterialIcons.Filled.Notifications
val outbox = MaterialIcons.Filled.Outbox
val security = MaterialIcons.Filled.Security
val passwordVisibility = MaterialIcons.Filled.Visibility
val passwordVisibilityOff = MaterialIcons.Filled.VisibilityOff
val user = MaterialIcons.Filled.AccountCircle
@ -37,6 +41,8 @@ object Icons {
val arrowDropUp = MaterialIcons.Outlined.ArrowDropUp
val menu = MaterialIcons.Outlined.Menu
val check = MaterialIcons.Outlined.Check
val info = MaterialIcons.Outlined.Info
val warning = MaterialIcons.Outlined.WarningAmber
val error = MaterialIcons.Outlined.ErrorOutline
val expandMore = MaterialIcons.Outlined.ExpandMore
val expandLess = MaterialIcons.Outlined.ExpandLess

View file

@ -30,9 +30,10 @@ interface AccountAutoConfigContract {
data class EmailAddressChanged(val emailAddress: String) : Event()
data class PasswordChanged(val password: String) : Event()
object OnRetryClicked : Event()
object OnNextClicked : Event()
object OnBackClicked : Event()
object OnRetryClicked : Event()
object OnEditConfigurationClicked : Event()
}
sealed class Effect {

View file

@ -2,6 +2,18 @@ package app.k9mail.feature.account.setup.ui.autoconfig
import android.content.res.Resources
import app.k9mail.feature.account.setup.R
import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity
internal fun AutoDiscoveryConnectionSecurity.toResourceString(resources: Resources): String {
return when (this) {
AutoDiscoveryConnectionSecurity.StartTLS -> resources.getString(
R.string.account_setup_connection_security_start_tls,
)
AutoDiscoveryConnectionSecurity.TLS -> resources.getString(
R.string.account_setup_connection_security_ssl,
)
}
}
internal fun AccountAutoConfigContract.Error.toResourceString(resources: Resources): String {
return when (this) {

View file

@ -0,0 +1,22 @@
package app.k9mail.feature.account.setup.ui.autoconfig.item
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import app.k9mail.autodiscovery.api.AutoDiscoveryResult
import app.k9mail.feature.account.setup.ui.autoconfig.view.AutoDiscoveryStatusView
import app.k9mail.feature.account.setup.ui.common.item.ListItem
@Composable
fun LazyItemScope.AutoDiscoveryStatusItem(
autoDiscoverySettings: AutoDiscoveryResult.Settings?,
modifier: Modifier = Modifier,
) {
ListItem(
modifier = modifier,
) {
AutoDiscoveryStatusView(
settings = autoDiscoverySettings,
)
}
}

View file

@ -9,6 +9,14 @@ internal fun LazyListScope.contentItems(
state: State,
onEvent: (Event) -> Unit,
) {
if (state.configStep == ConfigStep.PASSWORD) {
item(key = "autodiscovery") {
AutoDiscoveryStatusItem(
autoDiscoverySettings = state.autoDiscoverySettings,
)
}
}
item(key = "email") {
EmailAddressItem(
emailAddress = state.emailAddress.value,

View file

@ -0,0 +1,7 @@
package app.k9mail.feature.account.setup.ui.autoconfig.view
sealed interface AutoDiscoveryStatusHeaderState {
object NoSettings : AutoDiscoveryStatusHeaderState
object Trusted : AutoDiscoveryStatusHeaderState
object Untrusted : AutoDiscoveryStatusHeaderState
}

View file

@ -0,0 +1,127 @@
package app.k9mail.feature.account.setup.ui.autoconfig.view
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.atom.Icon
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBody2
import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadline6
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.R
@Suppress("LongMethod")
@Composable
internal fun AutoDiscoveryStatusHeaderView(
state: AutoDiscoveryStatusHeaderState,
modifier: Modifier = Modifier,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.then(modifier),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = when (state) {
AutoDiscoveryStatusHeaderState.NoSettings -> Icons.Outlined.info
AutoDiscoveryStatusHeaderState.Trusted -> Icons.Outlined.check
AutoDiscoveryStatusHeaderState.Untrusted -> Icons.Outlined.info
},
tint = selectColor(state),
modifier = Modifier.padding(MainTheme.spacings.default)
.requiredSize(MainTheme.sizes.medium),
)
Column(
modifier = Modifier
.weight(1f)
.padding(
start = MainTheme.spacings.default,
top = MainTheme.spacings.half,
bottom = MainTheme.spacings.half,
),
) {
TextHeadline6(
text = stringResource(
id = when (state) {
AutoDiscoveryStatusHeaderState.NoSettings -> {
R.string.account_setup_auto_config_status_header_title_configuration_not_found
}
AutoDiscoveryStatusHeaderState.Trusted,
AutoDiscoveryStatusHeaderState.Untrusted,
-> {
R.string.account_setup_auto_config_status_header_title_configuration_found
}
},
),
)
TextBody2(
text = stringResource(
when (state) {
AutoDiscoveryStatusHeaderState.NoSettings -> {
R.string.account_setup_auto_config_status_header_subtitle_configuration_not_found
}
AutoDiscoveryStatusHeaderState.Trusted -> {
R.string.account_setup_auto_config_status_header_subtitle_configuration_trusted
}
AutoDiscoveryStatusHeaderState.Untrusted -> {
R.string.account_setup_auto_config_status_header_subtitle_configuration_untrusted
}
},
),
color = selectColor(state),
)
}
}
}
@Composable
private fun selectColor(state: AutoDiscoveryStatusHeaderState): Color {
return when (state) {
AutoDiscoveryStatusHeaderState.NoSettings -> MainTheme.colors.primary
AutoDiscoveryStatusHeaderState.Trusted -> MainTheme.colors.success
AutoDiscoveryStatusHeaderState.Untrusted -> MainTheme.colors.warning
}
}
@Preview
@Composable
internal fun AutoDiscoveryStatusHeaderViewTrustedCollapsedPreview() {
PreviewWithThemes {
AutoDiscoveryStatusHeaderView(
state = AutoDiscoveryStatusHeaderState.Trusted,
)
}
}
@Preview
@Composable
internal fun AutoDiscoveryStatusHeaderViewUntrustedCollapsedPreview() {
PreviewWithThemes {
AutoDiscoveryStatusHeaderView(
state = AutoDiscoveryStatusHeaderState.Untrusted,
)
}
}
@Preview
@Composable
internal fun AutoDiscoveryStatusHeaderNoSettingsPreview() {
PreviewWithThemes {
AutoDiscoveryStatusHeaderView(
state = AutoDiscoveryStatusHeaderState.NoSettings,
)
}
}

View file

@ -0,0 +1,102 @@
package app.k9mail.feature.account.setup.ui.autoconfig.view
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import app.k9mail.autodiscovery.api.AuthenticationType
import app.k9mail.autodiscovery.api.AutoDiscoveryResult
import app.k9mail.autodiscovery.api.ConnectionSecurity
import app.k9mail.autodiscovery.api.ImapServerSettings
import app.k9mail.autodiscovery.api.SmtpServerSettings
import app.k9mail.core.common.net.toHostname
import app.k9mail.core.common.net.toPort
import app.k9mail.core.ui.compose.designsystem.atom.Surface
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
@Composable
internal fun AutoDiscoveryStatusView(
settings: AutoDiscoveryResult.Settings?,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier,
) {
Surface(
shape = MainTheme.shapes.small,
modifier = Modifier
.border(1.dp, Color.Gray.copy(alpha = 0.5f)),
) {
Column(
modifier = Modifier.padding(MainTheme.spacings.default),
) {
AutoDiscoveryStatusHeaderView(
state = if (settings == null) {
AutoDiscoveryStatusHeaderState.NoSettings
} else if (settings.isTrusted) {
AutoDiscoveryStatusHeaderState.Trusted
} else {
AutoDiscoveryStatusHeaderState.Untrusted
},
)
}
}
}
}
@Preview(showBackground = true)
@Composable
internal fun AutoDiscoveryStatusViewTrustedPreview() {
PreviewWithThemes {
AutoDiscoveryStatusView(
settings = AutoDiscoveryResult.Settings(
incomingServerSettings = ImapServerSettings(
hostname = "imap.example.com".toHostname(),
port = 993.toPort(),
connectionSecurity = ConnectionSecurity.TLS,
authenticationType = AuthenticationType.PasswordEncrypted,
username = "",
),
outgoingServerSettings = SmtpServerSettings(
hostname = "smtp.example.com".toHostname(),
port = 465.toPort(),
connectionSecurity = ConnectionSecurity.TLS,
authenticationType = AuthenticationType.PasswordEncrypted,
username = "",
),
isTrusted = true,
),
)
}
}
@Preview(showBackground = true)
@Composable
internal fun AutoDiscoveryStatusViewUntrustedPreview() {
PreviewWithThemes {
AutoDiscoveryStatusView(
settings = AutoDiscoveryResult.Settings(
incomingServerSettings = ImapServerSettings(
hostname = "imap.example.com".toHostname(),
port = 993.toPort(),
connectionSecurity = ConnectionSecurity.TLS,
authenticationType = AuthenticationType.PasswordEncrypted,
username = "",
),
outgoingServerSettings = SmtpServerSettings(
hostname = "smtp.example.com".toHostname(),
port = 465.toPort(),
connectionSecurity = ConnectionSecurity.TLS,
authenticationType = AuthenticationType.PasswordEncrypted,
username = "",
),
isTrusted = false,
),
)
}
}

View file

@ -22,8 +22,13 @@
<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 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_header_subtitle_configuration_not_found">Configure manually</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>