Integrate CreateAccountScreen
into account setup flow
This commit is contained in:
parent
849f150138
commit
c0024a2f66
8 changed files with 53 additions and 57 deletions
|
@ -13,6 +13,7 @@ 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.createaccount.CreateAccountViewModel
|
||||
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
|
||||
|
@ -57,7 +58,6 @@ val featureAccountSetupModule: Module = module {
|
|||
|
||||
viewModel {
|
||||
AccountSetupViewModel(
|
||||
createAccount = get(),
|
||||
accountStateRepository = get(),
|
||||
)
|
||||
}
|
||||
|
@ -76,4 +76,11 @@ val featureAccountSetupModule: Module = module {
|
|||
accountStateRepository = get(),
|
||||
)
|
||||
}
|
||||
|
||||
viewModel {
|
||||
CreateAccountViewModel(
|
||||
createAccount = get(),
|
||||
accountStateRepository = get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package app.k9mail.feature.account.setup.ui
|
||||
|
||||
import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel
|
||||
import app.k9mail.feature.account.setup.domain.entity.AccountUuid
|
||||
|
||||
interface AccountSetupContract {
|
||||
|
||||
|
@ -11,6 +12,7 @@ interface AccountSetupContract {
|
|||
OUTGOING_CONFIG,
|
||||
OUTGOING_VALIDATION,
|
||||
OPTIONS,
|
||||
CREATE_ACCOUNT,
|
||||
}
|
||||
|
||||
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>
|
||||
|
@ -27,6 +29,8 @@ interface AccountSetupContract {
|
|||
|
||||
object OnNext : Event
|
||||
object OnBack : Event
|
||||
|
||||
data class OnAccountCreated(val accountUuid: AccountUuid) : Event
|
||||
}
|
||||
|
||||
sealed interface Effect {
|
||||
|
|
|
@ -20,6 +20,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.createaccount.CreateAccountContract
|
||||
import app.k9mail.feature.account.setup.ui.createaccount.CreateAccountScreen
|
||||
import app.k9mail.feature.account.setup.ui.createaccount.CreateAccountViewModel
|
||||
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
|
||||
|
@ -39,6 +42,7 @@ fun AccountSetupScreen(
|
|||
outgoingValidationViewModel: ServerValidationContract.ViewModel =
|
||||
koinViewModel<OutgoingServerValidationViewModel>(),
|
||||
optionsViewModel: AccountOptionsContract.ViewModel = koinViewModel<AccountOptionsViewModel>(),
|
||||
createAccountViewModel: CreateAccountContract.ViewModel = koinViewModel<CreateAccountViewModel>(),
|
||||
) {
|
||||
val (state, dispatch) = viewModel.observe { effect ->
|
||||
when (effect) {
|
||||
|
@ -101,6 +105,14 @@ fun AccountSetupScreen(
|
|||
viewModel = optionsViewModel,
|
||||
)
|
||||
}
|
||||
|
||||
SetupStep.CREATE_ACCOUNT -> {
|
||||
CreateAccountScreen(
|
||||
onNext = { accountUuid -> dispatch(Event.OnAccountCreated(accountUuid)) },
|
||||
onBack = { dispatch(Event.OnBack) },
|
||||
viewModel = createAccountViewModel,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
package app.k9mail.feature.account.setup.ui
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
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.AuthorizationState
|
||||
import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult
|
||||
import app.k9mail.feature.account.setup.domain.DomainContract.UseCase
|
||||
import app.k9mail.feature.account.setup.domain.entity.AccountUuid
|
||||
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
|
||||
import app.k9mail.feature.account.setup.ui.AccountSetupContract.State
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class AccountSetupViewModel(
|
||||
private val createAccount: UseCase.CreateAccount,
|
||||
private val accountStateRepository: AccountDomainContract.AccountStateRepository,
|
||||
initialState: State = State(),
|
||||
) : BaseViewModel<State, Event, Effect>(initialState), AccountSetupContract.ViewModel {
|
||||
|
@ -25,6 +21,8 @@ class AccountSetupViewModel(
|
|||
|
||||
Event.OnBack -> onBack()
|
||||
Event.OnNext -> onNext()
|
||||
|
||||
is Event.OnAccountCreated -> navigateNext(event.accountUuid)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +68,11 @@ class AccountSetupViewModel(
|
|||
changeToSetupStep(SetupStep.OPTIONS)
|
||||
}
|
||||
|
||||
SetupStep.OPTIONS -> onFinish()
|
||||
SetupStep.OPTIONS -> {
|
||||
changeToSetupStep(SetupStep.CREATE_ACCOUNT)
|
||||
}
|
||||
|
||||
SetupStep.CREATE_ACCOUNT -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +102,8 @@ class AccountSetupViewModel(
|
|||
} else {
|
||||
changeToSetupStep(SetupStep.OUTGOING_CONFIG)
|
||||
}
|
||||
|
||||
SetupStep.CREATE_ACCOUNT -> changeToSetupStep(SetupStep.OPTIONS)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,27 +119,7 @@ class AccountSetupViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onFinish() {
|
||||
val accountState = accountStateRepository.getState()
|
||||
|
||||
viewModelScope.launch {
|
||||
val result = createAccount.execute(
|
||||
emailAddress = accountState.emailAddress ?: "",
|
||||
incomingServerSettings = accountState.incomingServerSettings!!,
|
||||
outgoingServerSettings = accountState.outgoingServerSettings!!,
|
||||
authorizationState = accountState.authorizationState?.state,
|
||||
options = accountState.options!!,
|
||||
)
|
||||
|
||||
if (result is AccountCreatorResult.Success) {
|
||||
navigateNext(result.accountUuid)
|
||||
} else {
|
||||
error("Creating account failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateNext(accountUuid: String) = emitEffect(Effect.NavigateNext(accountUuid))
|
||||
private fun navigateNext(accountUuid: AccountUuid) = emitEffect(Effect.NavigateNext(accountUuid.value))
|
||||
|
||||
private fun navigateBack() = emitEffect(Effect.NavigateBack)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCrea
|
|||
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.createaccount.CreateAccountContract
|
||||
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
|
||||
import com.fsck.k9.mail.oauth.AuthStateStorage
|
||||
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
|
||||
|
@ -79,6 +80,7 @@ class AccountSetupModuleKtTest : KoinTest {
|
|||
Boolean::class,
|
||||
Class.forName("net.openid.appauth.AppAuthConfiguration").kotlin,
|
||||
InteractionMode::class,
|
||||
CreateAccountContract.State::class,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ 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.createaccount.FakeCreateAccountViewModel
|
||||
import app.k9mail.feature.account.setup.ui.options.FakeAccountOptionsViewModel
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
|
@ -35,6 +36,7 @@ class AccountSetupScreenKtTest : ComposeTest() {
|
|||
outgoingViewModel = FakeOutgoingServerSettingsViewModel(),
|
||||
outgoingValidationViewModel = FakeServerValidationViewModel(),
|
||||
optionsViewModel = FakeAccountOptionsViewModel(),
|
||||
createAccountViewModel = FakeCreateAccountViewModel(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +66,7 @@ class AccountSetupScreenKtTest : ComposeTest() {
|
|||
outgoingViewModel = FakeOutgoingServerSettingsViewModel(),
|
||||
outgoingValidationViewModel = FakeServerValidationViewModel(),
|
||||
optionsViewModel = FakeAccountOptionsViewModel(),
|
||||
createAccountViewModel = FakeCreateAccountViewModel(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -89,5 +92,6 @@ class AccountSetupScreenKtTest : ComposeTest() {
|
|||
SetupStep.OUTGOING_CONFIG -> "OutgoingServerSettingsContent"
|
||||
SetupStep.OUTGOING_VALIDATION -> "AccountValidationContent"
|
||||
SetupStep.OPTIONS -> "AccountOptionsContent"
|
||||
SetupStep.CREATE_ACCOUNT -> "CreateAccountContent"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,11 @@ import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository
|
|||
import app.k9mail.feature.account.common.domain.entity.AccountOptions
|
||||
import app.k9mail.feature.account.common.domain.entity.AccountState
|
||||
import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity
|
||||
import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult
|
||||
import app.k9mail.feature.account.setup.domain.entity.AccountUuid
|
||||
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 assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isNull
|
||||
import assertk.assertions.prop
|
||||
import com.fsck.k9.mail.AuthType
|
||||
import com.fsck.k9.mail.ServerSettings
|
||||
|
@ -29,22 +27,8 @@ class AccountSetupViewModelTest {
|
|||
|
||||
@Test
|
||||
fun `should forward step state on next event`() = runTest {
|
||||
var createAccountEmailAddress: String? = null
|
||||
var createAccountIncomingServerSettings: ServerSettings? = null
|
||||
var createAccountOutgoingServerSettings: ServerSettings? = null
|
||||
var createAccountAuthorizationState: String? = null
|
||||
var createAccountOptions: AccountOptions? = null
|
||||
val accountStateRepository = InMemoryAccountStateRepository()
|
||||
val viewModel = AccountSetupViewModel(
|
||||
createAccount = { emailAddress, incomingServerSettings, outgoingServerSettings, authState, options ->
|
||||
createAccountEmailAddress = emailAddress
|
||||
createAccountIncomingServerSettings = incomingServerSettings
|
||||
createAccountOutgoingServerSettings = outgoingServerSettings
|
||||
createAccountAuthorizationState = authState
|
||||
createAccountOptions = options
|
||||
|
||||
AccountCreatorResult.Success("accountUuid")
|
||||
},
|
||||
accountStateRepository = accountStateRepository,
|
||||
)
|
||||
val turbines = turbinesWithInitialStateCheck(viewModel, State(setupStep = SetupStep.AUTO_CONFIG))
|
||||
|
@ -133,9 +117,18 @@ class AccountSetupViewModelTest {
|
|||
prop(State::setupStep).isEqualTo(SetupStep.OPTIONS)
|
||||
}
|
||||
|
||||
viewModel.event(AccountSetupContract.Event.OnNext)
|
||||
|
||||
assertThatAndMviTurbinesConsumed(
|
||||
actual = turbines.stateTurbine.awaitItem(),
|
||||
turbines = turbines,
|
||||
) {
|
||||
prop(State::setupStep).isEqualTo(SetupStep.CREATE_ACCOUNT)
|
||||
}
|
||||
|
||||
accountStateRepository.setState(expectedAccountState)
|
||||
|
||||
viewModel.event(AccountSetupContract.Event.OnNext)
|
||||
viewModel.event(AccountSetupContract.Event.OnAccountCreated(AccountUuid("accountUuid")))
|
||||
|
||||
assertThatAndMviTurbinesConsumed(
|
||||
actual = turbines.effectTurbine.awaitItem(),
|
||||
|
@ -143,19 +136,12 @@ class AccountSetupViewModelTest {
|
|||
) {
|
||||
isEqualTo(Effect.NavigateNext("accountUuid"))
|
||||
}
|
||||
|
||||
assertThat(createAccountEmailAddress).isEqualTo(EMAIL_ADDRESS)
|
||||
assertThat(createAccountIncomingServerSettings).isEqualTo(expectedAccountState.incomingServerSettings)
|
||||
assertThat(createAccountOutgoingServerSettings).isEqualTo(expectedAccountState.outgoingServerSettings)
|
||||
assertThat(createAccountAuthorizationState).isNull()
|
||||
assertThat(createAccountOptions).isEqualTo(expectedAccountState.options)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should rewind step state on back event`() = runTest {
|
||||
val initialState = State(setupStep = SetupStep.OPTIONS)
|
||||
val viewModel = AccountSetupViewModel(
|
||||
createAccount = { _, _, _, _, _ -> AccountCreatorResult.Success("accountUuid") },
|
||||
accountStateRepository = InMemoryAccountStateRepository(),
|
||||
initialState = initialState,
|
||||
)
|
||||
|
@ -205,7 +191,6 @@ class AccountSetupViewModelTest {
|
|||
isAutomaticConfig = true,
|
||||
)
|
||||
val viewModel = AccountSetupViewModel(
|
||||
createAccount = { _, _, _, _, _ -> AccountCreatorResult.Success("accountUuid") },
|
||||
accountStateRepository = InMemoryAccountStateRepository(),
|
||||
initialState = initialState,
|
||||
)
|
||||
|
@ -237,7 +222,6 @@ class AccountSetupViewModelTest {
|
|||
isAutomaticConfig = true,
|
||||
)
|
||||
val viewModel = AccountSetupViewModel(
|
||||
createAccount = { _, _, _, _, _ -> AccountCreatorResult.Success("accountUuid") },
|
||||
accountStateRepository = InMemoryAccountStateRepository(),
|
||||
initialState = initialState,
|
||||
)
|
||||
|
@ -269,7 +253,6 @@ class AccountSetupViewModelTest {
|
|||
isAutomaticConfig = true,
|
||||
)
|
||||
val viewModel = AccountSetupViewModel(
|
||||
createAccount = { _, _, _, _, _ -> AccountCreatorResult.Success("accountUuid") },
|
||||
accountStateRepository = InMemoryAccountStateRepository(),
|
||||
initialState = initialState,
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import app.k9mail.feature.account.setup.ui.createaccount.CreateAccountContract.E
|
|||
import app.k9mail.feature.account.setup.ui.createaccount.CreateAccountContract.State
|
||||
import app.k9mail.feature.account.setup.ui.createaccount.CreateAccountContract.ViewModel
|
||||
|
||||
class FakeCreateAccountViewModel(initialState: State) :
|
||||
class FakeCreateAccountViewModel(initialState: State = State()) :
|
||||
BaseViewModel<State, Event, Effect>(initialState), ViewModel {
|
||||
|
||||
val events = mutableListOf<Event>()
|
||||
|
|
Loading…
Reference in a new issue