Skip to content

Commit

Permalink
Merge pull request #7094 from thundernest/change_to_new_validation_sc…
Browse files Browse the repository at this point in the history
…reen

Change to new validation screen
  • Loading branch information
cketti authored Jul 28, 2023
2 parents 6b3c7a8 + a00ca56 commit efd54b8
Show file tree
Hide file tree
Showing 33 changed files with 481 additions and 997 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ 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 app.k9mail.feature.account.setup.ui.validation.AccountValidationContract
import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel
import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator
import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator
import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator
import okhttp3.OkHttpClient
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.module.Module
import org.koin.core.qualifier.named
import org.koin.dsl.module

val featureAccountSetupModule: Module = module {
Expand Down Expand Up @@ -111,20 +113,29 @@ val featureAccountSetupModule: Module = module {
)
}
viewModel {
AccountIncomingConfigViewModel(
validator = get(),
)
}
viewModel(named(NAME_INCOMING_VALIDATION)) {
AccountValidationViewModel(
validateServerSettings = get(),
initialState = AccountValidationContract.State(
isIncomingValidation = true,
),
)
}
viewModel {
AccountIncomingConfigViewModel(
AccountOutgoingConfigViewModel(
validator = get(),
checkIncomingServerConfig = get(),
)
}
viewModel {
AccountOutgoingConfigViewModel(
validator = get(),
checkOutgoingServerConfig = get(),
viewModel(named(NAME_OUTGOING_VALIDATION)) {
AccountValidationViewModel(
validateServerSettings = get(),
initialState = AccountValidationContract.State(
isIncomingValidation = false,
),
)
}
viewModel {
Expand All @@ -133,3 +144,6 @@ val featureAccountSetupModule: Module = module {
)
}
}

internal const val NAME_INCOMING_VALIDATION = "incoming_validation"
internal const val NAME_OUTGOING_VALIDATION = "outgoing_validation"
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,25 @@ interface AccountSetupContract {
enum class SetupStep {
AUTO_CONFIG,
INCOMING_CONFIG,
INCOMING_VALIDATION,
OUTGOING_CONFIG,
OUTGOING_VALIDATION,
OPTIONS,
}

interface ViewModel : UnidirectionalViewModel<State, Event, Effect>

data class State(
val setupStep: SetupStep = SetupStep.AUTO_CONFIG,
val isAutomaticConfig: Boolean = false,
)

sealed interface Event {
object OnNext : Event

data class OnAutoDiscoveryFinished(
val state: AccountAutoDiscoveryContract.State,
val isAutomaticConfig: Boolean,
) : Event

data class OnStateCollected(
Expand All @@ -44,10 +48,14 @@ interface AccountSetupContract {
val state: AccountIncomingConfigContract.State,
) : Effect

object UpdateIncomingConfigValidation : Effect

data class UpdateOutgoingConfig(
val state: AccountOutgoingConfigContract.State,
) : Effect

object UpdateOutgoingConfigValidation : Effect

data class UpdateOptions(
val state: AccountOptionsContract.State,
) : Effect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ 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.setup.NAME_INCOMING_VALIDATION
import app.k9mail.feature.account.setup.NAME_OUTGOING_VALIDATION
import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect
import app.k9mail.feature.account.setup.ui.AccountSetupContract.Event
import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep
Expand All @@ -13,28 +15,53 @@ import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryVie
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.incoming.toValidationState
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 app.k9mail.feature.account.setup.ui.outgoing.toValidationState
import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract
import app.k9mail.feature.account.setup.ui.validation.AccountValidationScreen
import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.qualifier.named

@Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable
fun AccountSetupScreen(
onFinish: (String) -> Unit,
onBack: () -> Unit,
viewModel: ViewModel = koinViewModel<AccountSetupViewModel>(),
autoDiscoveryViewModel: AccountAutoDiscoveryContract.ViewModel = koinViewModel<AccountAutoDiscoveryViewModel>(),
incomingViewModel: AccountIncomingConfigContract.ViewModel = koinViewModel<AccountIncomingConfigViewModel>(),
incomingValidationViewModel: AccountValidationContract.ViewModel = koinViewModel<AccountValidationViewModel>(
named(
NAME_INCOMING_VALIDATION,
),
),
outgoingViewModel: AccountOutgoingConfigContract.ViewModel = koinViewModel<AccountOutgoingConfigViewModel>(),
outgoingValidationViewModel: AccountValidationContract.ViewModel = koinViewModel<AccountValidationViewModel>(
named(
NAME_OUTGOING_VALIDATION,
),
),
optionsViewModel: AccountOptionsContract.ViewModel = koinViewModel<AccountOptionsViewModel>(),
) {
val (state, dispatch) = viewModel.observe { effect ->
when (effect) {
is Effect.UpdateIncomingConfig -> incomingViewModel.initState(effect.state)
is Effect.UpdateIncomingConfigValidation -> {
incomingValidationViewModel.initState(incomingViewModel.state.value.toValidationState())
}

is Effect.UpdateOutgoingConfig -> outgoingViewModel.initState(effect.state)
is Effect.UpdateOutgoingConfigValidation -> {
outgoingValidationViewModel.initState(outgoingViewModel.state.value.toValidationState())
}

is Effect.UpdateOptions -> optionsViewModel.initState(effect.state)
is Effect.CollectExternalStates -> viewModel.event(
Event.OnStateCollected(
Expand All @@ -53,7 +80,14 @@ fun AccountSetupScreen(
when (state.value.setupStep) {
SetupStep.AUTO_CONFIG -> {
AccountAutoDiscoveryScreen(
onNext = { dispatch(Event.OnAutoDiscoveryFinished(it)) },
onNext = { autoDiscoveryState, isAutomaticConfig ->
dispatch(
Event.OnAutoDiscoveryFinished(
autoDiscoveryState,
isAutomaticConfig,
),
)
},
onBack = { dispatch(Event.OnBack) },
viewModel = autoDiscoveryViewModel,
)
Expand All @@ -67,6 +101,14 @@ fun AccountSetupScreen(
)
}

SetupStep.INCOMING_VALIDATION -> {
AccountValidationScreen(
onNext = { dispatch(Event.OnNext) },
onBack = { dispatch(Event.OnBack) },
viewModel = incomingValidationViewModel,
)
}

SetupStep.OUTGOING_CONFIG -> {
AccountOutgoingConfigScreen(
onNext = { dispatch(Event.OnNext) },
Expand All @@ -75,6 +117,14 @@ fun AccountSetupScreen(
)
}

SetupStep.OUTGOING_VALIDATION -> {
AccountValidationScreen(
onNext = { dispatch(Event.OnNext) },
onBack = { dispatch(Event.OnBack) },
viewModel = outgoingValidationViewModel,
)
}

SetupStep.OPTIONS -> {
AccountOptionsScreen(
onNext = { dispatch(Event.OnNext) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@ class AccountSetupViewModel(

override fun event(event: Event) {
when (event) {
is Event.OnAutoDiscoveryFinished -> onAutoDiscoveryFinished(event.state)
is Event.OnAutoDiscoveryFinished -> {
updateState {
it.copy(
isAutomaticConfig = event.isAutomaticConfig,
)
}
onAutoDiscoveryFinished(event.state)
}

is Event.OnStateCollected -> onStateCollected(
autoDiscoveryState = event.autoDiscoveryState,
incomingState = event.incomingState,
Expand All @@ -40,7 +48,9 @@ class AccountSetupViewModel(
}
}

private fun onAutoDiscoveryFinished(autoDiscoveryState: AccountAutoDiscoveryContract.State) {
private fun onAutoDiscoveryFinished(
autoDiscoveryState: AccountAutoDiscoveryContract.State,
) {
emitEffect(Effect.UpdateIncomingConfig(autoDiscoveryState.toIncomingConfigState()))
emitEffect(Effect.UpdateOutgoingConfig(autoDiscoveryState.toOutgoingConfigState()))
emitEffect(Effect.UpdateOptions(autoDiscoveryState.toOptionsState()))
Expand All @@ -51,16 +61,61 @@ class AccountSetupViewModel(
when (state.value.setupStep) {
SetupStep.AUTO_CONFIG -> navigateBack()
SetupStep.INCOMING_CONFIG -> changeToSetupStep(SetupStep.AUTO_CONFIG)
SetupStep.OUTGOING_CONFIG -> changeToSetupStep(SetupStep.INCOMING_CONFIG)
SetupStep.OPTIONS -> changeToSetupStep(SetupStep.OUTGOING_CONFIG)
SetupStep.INCOMING_VALIDATION -> {
if (state.value.isAutomaticConfig) {
changeToSetupStep(SetupStep.AUTO_CONFIG)
} else {
changeToSetupStep(SetupStep.INCOMING_CONFIG)
}
}

SetupStep.OUTGOING_CONFIG -> changeToSetupStep(SetupStep.INCOMING_VALIDATION)
SetupStep.OUTGOING_VALIDATION -> {
if (state.value.isAutomaticConfig) {
changeToSetupStep(SetupStep.AUTO_CONFIG)
} else {
changeToSetupStep(SetupStep.OUTGOING_CONFIG)
}
}

SetupStep.OPTIONS -> changeToSetupStep(SetupStep.OUTGOING_VALIDATION)
}
}

private fun onNext() {
when (state.value.setupStep) {
SetupStep.AUTO_CONFIG -> changeToSetupStep(SetupStep.INCOMING_CONFIG)
SetupStep.INCOMING_CONFIG -> changeToSetupStep(SetupStep.OUTGOING_CONFIG)
SetupStep.OUTGOING_CONFIG -> changeToSetupStep(SetupStep.OPTIONS)
SetupStep.AUTO_CONFIG -> {
if (state.value.isAutomaticConfig) {
emitEffect(Effect.UpdateIncomingConfigValidation)
emitEffect(Effect.UpdateOutgoingConfigValidation)
changeToSetupStep(SetupStep.INCOMING_VALIDATION)
} else {
changeToSetupStep(SetupStep.INCOMING_CONFIG)
}
}

SetupStep.INCOMING_CONFIG -> {
emitEffect(Effect.UpdateIncomingConfigValidation)
changeToSetupStep(SetupStep.INCOMING_VALIDATION)
}

SetupStep.INCOMING_VALIDATION -> {
if (state.value.isAutomaticConfig) {
changeToSetupStep(SetupStep.OUTGOING_VALIDATION)
} else {
changeToSetupStep(SetupStep.OUTGOING_CONFIG)
}
}

SetupStep.OUTGOING_CONFIG -> {
emitEffect(Effect.UpdateOutgoingConfigValidation)
changeToSetupStep(SetupStep.OUTGOING_VALIDATION)
}

SetupStep.OUTGOING_VALIDATION -> {
changeToSetupStep(SetupStep.OPTIONS)
}

SetupStep.OPTIONS -> onFinish()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ interface AccountAutoDiscoveryContract {
}

sealed class Effect {
object NavigateNext : Effect()
data class NavigateNext(
val isAutomaticConfig: Boolean,
) : Effect()
object NavigateBack : Effect()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryCon

@Composable
internal fun AccountAutoDiscoveryScreen(
onNext: (State) -> Unit,
onNext: (state: State, isAutomaticConfig: Boolean) -> Unit,
onBack: () -> Unit,
viewModel: ViewModel,
modifier: Modifier = Modifier,
) {
val (state, dispatch) = viewModel.observe { effect ->
when (effect) {
Effect.NavigateBack -> onBack()
Effect.NavigateNext -> onNext(viewModel.state.value)
is Effect.NavigateNext -> onNext(viewModel.state.value, effect.isAutomaticConfig)
}
}

Expand Down Expand Up @@ -65,7 +65,7 @@ internal fun AccountAutoDiscoveryScreen(
internal fun AccountAutoDiscoveryScreenK9Preview() {
K9Theme {
AccountAutoDiscoveryScreen(
onNext = {},
onNext = { _, _ -> },
onBack = {},
viewModel = AccountAutoDiscoveryViewModel(
validator = AccountAutoDiscoveryValidator(),
Expand All @@ -80,7 +80,7 @@ internal fun AccountAutoDiscoveryScreenK9Preview() {
internal fun AccountAutoDiscoveryScreenThunderbirdPreview() {
ThunderbirdTheme {
AccountAutoDiscoveryScreen(
onNext = {},
onNext = { _, _ -> },
onBack = {},
viewModel = AccountAutoDiscoveryViewModel(
validator = AccountAutoDiscoveryValidator(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ internal class AccountAutoDiscoveryViewModel(
Event.OnNextClicked -> onNext()
Event.OnBackClicked -> onBack()
Event.OnRetryClicked -> onRetry()
Event.OnEditConfigurationClicked -> navigateNext()
Event.OnEditConfigurationClicked -> {
navigateNext(isAutomaticConfig = false)
}
}
}

Expand Down Expand Up @@ -170,7 +172,7 @@ internal class AccountAutoDiscoveryViewModel(
}

if (!hasError) {
navigateNext()
navigateNext(state.value.autoDiscoverySettings != null)
}
}
}
Expand Down Expand Up @@ -200,5 +202,7 @@ internal class AccountAutoDiscoveryViewModel(

private fun navigateBack() = emitEffect(Effect.NavigateBack)

private fun navigateNext() = emitEffect(Effect.NavigateNext)
private fun navigateNext(isAutomaticConfig: Boolean) {
emitEffect(Effect.NavigateNext(isAutomaticConfig))
}
}
Loading

0 comments on commit efd54b8

Please sign in to comment.