Merge pull request #7384 from thunderbird/change_server_settings_form_to_loading_view
Change ServerSettings to support loading state
This commit is contained in:
commit
2c38500608
17 changed files with 106 additions and 44 deletions
|
@ -7,7 +7,7 @@ import app.k9mail.core.featureflag.FeatureFlagKey
|
|||
class InMemoryFeatureFlagFactory : FeatureFlagFactory {
|
||||
override fun createFeatureCatalog(): List<FeatureFlag> {
|
||||
return listOf(
|
||||
FeatureFlag(FeatureFlagKey("new_account_edit"), false),
|
||||
FeatureFlag(FeatureFlagKey("new_account_edit"), true),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,8 @@ class ModifyIncomingServerSettingsViewModelTest {
|
|||
imapPrefix = StringInputField(value = ""),
|
||||
imapUseCompression = true,
|
||||
imapSendClientId = true,
|
||||
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ class ModifyOutgoingServerSettingsViewModelTest {
|
|||
authenticationType = AuthenticationType.PasswordCleartext,
|
||||
username = StringInputField(value = "username"),
|
||||
password = StringInputField(value = "password"),
|
||||
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import app.k9mail.core.ui.compose.common.PreviewDevices
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
|
||||
import app.k9mail.core.ui.compose.theme.K9Theme
|
||||
import app.k9mail.core.ui.compose.theme.MainTheme
|
||||
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
|
||||
import app.k9mail.feature.account.common.domain.entity.InteractionMode
|
||||
import app.k9mail.feature.account.common.ui.loadingerror.rememberContentLoadingErrorViewState
|
||||
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event
|
||||
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State
|
||||
import app.k9mail.feature.account.server.settings.ui.incoming.content.incomingFormItems
|
||||
|
@ -39,19 +41,25 @@ internal fun IncomingServerSettingsContent(
|
|||
.fillMaxWidth()
|
||||
.then(modifier),
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding(),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
ContentLoadingErrorView(
|
||||
state = rememberContentLoadingErrorViewState(state = state),
|
||||
loading = { /* no-op */ },
|
||||
error = { /* no-op */ },
|
||||
) {
|
||||
incomingFormItems(
|
||||
mode = mode,
|
||||
state = state,
|
||||
onEvent = onEvent,
|
||||
resources = resources,
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding(),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
incomingFormItems(
|
||||
mode = mode,
|
||||
state = state,
|
||||
onEvent = onEvent,
|
||||
resources = resources,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import app.k9mail.feature.account.common.domain.entity.toDefaultPort
|
|||
import app.k9mail.feature.account.common.domain.input.NumberInputField
|
||||
import app.k9mail.feature.account.common.domain.input.StringInputField
|
||||
import app.k9mail.feature.account.common.ui.WithInteractionMode
|
||||
import app.k9mail.feature.account.common.ui.loadingerror.LoadingErrorState
|
||||
|
||||
interface IncomingServerSettingsContract {
|
||||
|
||||
|
@ -29,7 +30,10 @@ interface IncomingServerSettingsContract {
|
|||
val imapPrefix: StringInputField = StringInputField(),
|
||||
val imapUseCompression: Boolean = true,
|
||||
val imapSendClientId: Boolean = true,
|
||||
)
|
||||
|
||||
override val isLoading: Boolean = true,
|
||||
override val error: Error? = null,
|
||||
) : LoadingErrorState<Error>
|
||||
|
||||
sealed interface Event {
|
||||
data class ProtocolTypeChanged(val protocolType: IncomingProtocolType) : Event
|
||||
|
@ -45,15 +49,15 @@ interface IncomingServerSettingsContract {
|
|||
data class ImapUseCompressionChanged(val useCompression: Boolean) : Event
|
||||
data class ImapSendClientIdChanged(val sendClientId: Boolean) : Event
|
||||
|
||||
object LoadAccountState : Event
|
||||
data object LoadAccountState : Event
|
||||
|
||||
object OnNextClicked : Event
|
||||
object OnBackClicked : Event
|
||||
data object OnNextClicked : Event
|
||||
data object OnBackClicked : Event
|
||||
}
|
||||
|
||||
sealed interface Effect {
|
||||
object NavigateNext : Effect
|
||||
object NavigateBack : Effect
|
||||
data object NavigateNext : Effect
|
||||
data object NavigateBack : Effect
|
||||
}
|
||||
|
||||
interface Validator {
|
||||
|
|
|
@ -17,7 +17,10 @@ import com.fsck.k9.mail.store.imap.ImapStoreSettings.isUseCompression
|
|||
import com.fsck.k9.mail.store.imap.ImapStoreSettings.pathPrefix
|
||||
|
||||
fun AccountState.toIncomingServerSettingsState() = incomingServerSettings?.toIncomingServerSettingsState()
|
||||
?: State(username = StringInputField(value = emailAddress ?: ""))
|
||||
?: State(
|
||||
username = StringInputField(value = emailAddress ?: ""),
|
||||
isLoading = false,
|
||||
)
|
||||
|
||||
private fun ServerSettings.toIncomingServerSettingsState(): State {
|
||||
return State(
|
||||
|
@ -33,6 +36,9 @@ private fun ServerSettings.toIncomingServerSettingsState(): State {
|
|||
imapPrefix = StringInputField(value = pathPrefix ?: ""),
|
||||
imapUseCompression = isUseCompression,
|
||||
imapSendClientId = isSendClientId,
|
||||
|
||||
isLoading = false,
|
||||
error = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSett
|
|||
import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel
|
||||
|
||||
open class IncomingServerSettingsViewModel(
|
||||
initialState: State = State(),
|
||||
override val mode: InteractionMode,
|
||||
private val validator: Validator,
|
||||
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
|
||||
initialState: State = State(),
|
||||
) : BaseViewModel<State, Event, Effect>(initialState = initialState), ViewModel {
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
|
|
|
@ -13,11 +13,13 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import app.k9mail.core.ui.compose.common.PreviewDevices
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
|
||||
import app.k9mail.core.ui.compose.theme.K9Theme
|
||||
import app.k9mail.core.ui.compose.theme.MainTheme
|
||||
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
|
||||
import app.k9mail.feature.account.common.domain.entity.InteractionMode
|
||||
import app.k9mail.feature.account.common.ui.loadingerror.rememberContentLoadingErrorViewState
|
||||
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event
|
||||
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State
|
||||
import app.k9mail.feature.account.server.settings.ui.outgoing.content.outgoingFormItems
|
||||
|
@ -39,19 +41,25 @@ internal fun OutgoingServerSettingsContent(
|
|||
.fillMaxWidth()
|
||||
.then(modifier),
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding(),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
ContentLoadingErrorView(
|
||||
state = rememberContentLoadingErrorViewState(state = state),
|
||||
loading = { /* no-op */ },
|
||||
error = { /* no-op */ },
|
||||
) {
|
||||
outgoingFormItems(
|
||||
mode = mode,
|
||||
state = state,
|
||||
onEvent = onEvent,
|
||||
resources = resources,
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding(),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
outgoingFormItems(
|
||||
mode = mode,
|
||||
state = state,
|
||||
onEvent = onEvent,
|
||||
resources = resources,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort
|
|||
import app.k9mail.feature.account.common.domain.input.NumberInputField
|
||||
import app.k9mail.feature.account.common.domain.input.StringInputField
|
||||
import app.k9mail.feature.account.common.ui.WithInteractionMode
|
||||
import app.k9mail.feature.account.common.ui.loadingerror.LoadingErrorState
|
||||
|
||||
interface OutgoingServerSettingsContract {
|
||||
|
||||
|
@ -21,7 +22,10 @@ interface OutgoingServerSettingsContract {
|
|||
val username: StringInputField = StringInputField(),
|
||||
val password: StringInputField = StringInputField(),
|
||||
val clientCertificateAlias: String? = null,
|
||||
)
|
||||
|
||||
override val isLoading: Boolean = true,
|
||||
override val error: Error? = null,
|
||||
) : LoadingErrorState<Error>
|
||||
|
||||
sealed interface Event {
|
||||
data class ServerChanged(val server: String) : Event
|
||||
|
@ -32,15 +36,15 @@ interface OutgoingServerSettingsContract {
|
|||
data class PasswordChanged(val password: String) : Event
|
||||
data class ClientCertificateChanged(val clientCertificateAlias: String?) : Event
|
||||
|
||||
object LoadAccountState : Event
|
||||
data object LoadAccountState : Event
|
||||
|
||||
object OnNextClicked : Event
|
||||
object OnBackClicked : Event
|
||||
data object OnNextClicked : Event
|
||||
data object OnBackClicked : Event
|
||||
}
|
||||
|
||||
sealed interface Effect {
|
||||
object NavigateNext : Effect
|
||||
object NavigateBack : Effect
|
||||
data object NavigateNext : Effect
|
||||
data object NavigateBack : Effect
|
||||
}
|
||||
|
||||
interface Validator {
|
||||
|
|
|
@ -17,6 +17,8 @@ fun AccountState.toOutgoingServerSettingsState(): State {
|
|||
?: State(
|
||||
username = StringInputField(value = emailAddress ?: ""),
|
||||
password = StringInputField(value = password),
|
||||
|
||||
isLoading = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -32,6 +34,9 @@ private fun ServerSettings.toOutgoingServerSettingsState(password: String): Stat
|
|||
authenticationType = authenticationType.toAuthenticationType(),
|
||||
username = StringInputField(value = username),
|
||||
password = StringInputField(value = password),
|
||||
|
||||
isLoading = false,
|
||||
error = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,10 @@ import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSett
|
|||
import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel
|
||||
|
||||
open class OutgoingServerSettingsViewModel(
|
||||
initialState: State = State(),
|
||||
override val mode: InteractionMode,
|
||||
private val validator: Validator,
|
||||
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
|
||||
initialState: State = State(),
|
||||
) : BaseViewModel<State, Event, Effect>(initialState = initialState), ViewModel {
|
||||
|
||||
override fun event(event: Event) {
|
||||
|
|
|
@ -26,7 +26,12 @@ class IncomingServerSettingsStateMapperKtTest {
|
|||
|
||||
val result = accountState.toIncomingServerSettingsState()
|
||||
|
||||
assertThat(result).isEqualTo(State(username = StringInputField(value = "test@example.com")))
|
||||
assertThat(result).isEqualTo(
|
||||
State(
|
||||
username = StringInputField(value = "test@example.com"),
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -37,7 +42,7 @@ class IncomingServerSettingsStateMapperKtTest {
|
|||
|
||||
val result = serverSettings.toIncomingServerSettingsState()
|
||||
|
||||
assertThat(result).isEqualTo(INCOMING_IMAP_STATE)
|
||||
assertThat(result).isEqualTo(INCOMING_IMAP_STATE.copy(isLoading = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -30,6 +30,9 @@ class IncomingServerSettingsStateTest {
|
|||
imapAutodetectNamespaceEnabled = true,
|
||||
imapUseCompression = true,
|
||||
imapSendClientId = true,
|
||||
|
||||
isLoading = true,
|
||||
error = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@ class IncomingServerSettingsViewModelTest {
|
|||
imapPrefix = StringInputField(value = ""),
|
||||
imapUseCompression = true,
|
||||
imapSendClientId = true,
|
||||
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,12 @@ class OutgoingServerSettingsStateMapperKtTest {
|
|||
|
||||
val result = accountState.toOutgoingServerSettingsState()
|
||||
|
||||
assertThat(result).isEqualTo(State(username = StringInputField(value = "test@example.com")))
|
||||
assertThat(result).isEqualTo(
|
||||
State(
|
||||
username = StringInputField(value = "test@example.com"),
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -41,6 +46,7 @@ class OutgoingServerSettingsStateMapperKtTest {
|
|||
State(
|
||||
username = StringInputField(value = "test@domain.example"),
|
||||
password = StringInputField(value = INCOMING_SERVER_PASSWORD),
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -53,7 +59,7 @@ class OutgoingServerSettingsStateMapperKtTest {
|
|||
|
||||
val result = accountState.toOutgoingServerSettingsState()
|
||||
|
||||
assertThat(result).isEqualTo(OUTGOING_STATE)
|
||||
assertThat(result).isEqualTo(OUTGOING_STATE.copy(isLoading = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -68,6 +74,7 @@ class OutgoingServerSettingsStateMapperKtTest {
|
|||
assertThat(result).isEqualTo(
|
||||
OUTGOING_STATE.copy(
|
||||
password = StringInputField(value = INCOMING_SERVER_PASSWORD),
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -83,6 +90,7 @@ class OutgoingServerSettingsStateMapperKtTest {
|
|||
assertThat(result).isEqualTo(
|
||||
OUTGOING_STATE.copy(
|
||||
password = StringInputField(value = ""),
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ class OutgoingServerSettingsStateTest {
|
|||
username = StringInputField(),
|
||||
password = StringInputField(),
|
||||
clientCertificateAlias = null,
|
||||
|
||||
isLoading = true,
|
||||
error = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -73,6 +73,8 @@ class OutgoingServerSettingsViewModelTest {
|
|||
authenticationType = AuthenticationType.PasswordCleartext,
|
||||
username = StringInputField(value = "username"),
|
||||
password = StringInputField(value = "password"),
|
||||
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue