Merge pull request #7569 from thunderbird/change-special-folder-success-to-loading

Change special folder success to loading and change navigation
This commit is contained in:
Wolf-Martell Montwé 2024-01-26 16:22:35 +00:00 committed by GitHub
commit 4dad5313e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 31 additions and 89 deletions

View file

@ -129,8 +129,18 @@ fun AccountSetupNavHost(
composable(route = NESTED_NAVIGATION_SPECIAL_FOLDERS) {
SpecialFoldersScreen(
onNext = {
navController.navigate(NESTED_NAVIGATION_DISPLAY_OPTIONS)
onNext = { isManualSetup ->
navController.navigate(NESTED_NAVIGATION_DISPLAY_OPTIONS) {
if (isManualSetup) {
popUpTo(NESTED_NAVIGATION_SPECIAL_FOLDERS)
} else {
if (isAutomaticConfig) {
popUpTo(NESTED_NAVIGATION_AUTO_CONFIG)
} else {
popUpTo(NESTED_NAVIGATION_OUTGOING_SERVER_CONFIG)
}
}
}
},
onBack = { navController.popBackStack() },
viewModel = koinViewModel<SpecialFoldersViewModel>(),

View file

@ -1,29 +1,19 @@
package app.k9mail.feature.account.setup.ui.specialfolders
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.atom.Icon
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonText
import app.k9mail.core.ui.compose.designsystem.atom.text.TextSubtitle1
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
import app.k9mail.core.ui.compose.designsystem.molecule.ErrorView
import app.k9mail.core.ui.compose.designsystem.molecule.LoadingView
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
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.common.ui.AppTitleTopHeader
@ -66,9 +56,9 @@ fun SpecialFoldersContent(
modifier = Modifier.fillMaxSize(),
) {
if (state.isSuccess) {
SuccessView(
LoadingView(
message = stringResource(id = R.string.account_setup_special_folders_success_message),
onEditClick = { onEvent(Event.OnEditClicked) },
modifier = Modifier.padding(horizontal = MainTheme.spacings.double),
)
} else {
SpecialFoldersFormContent(
@ -82,46 +72,6 @@ fun SpecialFoldersContent(
}
}
@Composable
fun SuccessView(
message: String,
onEditClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(MainTheme.spacings.double)
.then(modifier),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
) {
TextSubtitle1(
text = message,
textAlign = TextAlign.Center,
)
Row(
modifier = Modifier.height(MainTheme.sizes.larger),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Outlined.celebration,
tint = MainTheme.colors.secondary,
modifier = Modifier.requiredSize(MainTheme.sizes.large),
)
}
Row(
verticalAlignment = Alignment.CenterVertically,
) {
ButtonText(
text = stringResource(id = R.string.account_setup_special_folders_edit_folders_button_label),
onClick = onEditClick,
)
}
}
}
@Composable
private fun SpecialFoldersErrorView(
failure: SpecialFoldersContract.Failure,

View file

@ -15,6 +15,7 @@ interface SpecialFoldersContract {
data class State(
val formState: FormState = FormState(),
val isManualSetup: Boolean = false,
val isSuccess: Boolean = false,
override val error: Failure? = null,
override val isLoading: Boolean = true,
@ -36,7 +37,6 @@ interface SpecialFoldersContract {
sealed interface Event {
data object LoadSpecialFolderOptions : Event
data object OnEditClicked : Event
data object OnRetryClicked : Event
data object OnNextClicked : Event
data object OnBackClicked : Event
@ -51,7 +51,10 @@ interface SpecialFoldersContract {
}
sealed interface Effect {
data object NavigateNext : Effect
data class NavigateNext(
val isManualSetup: Boolean,
) : Effect
data object NavigateBack : Effect
}

View file

@ -17,14 +17,14 @@ import app.k9mail.feature.account.setup.ui.specialfolders.fake.FakeSpecialFolder
@Composable
fun SpecialFoldersScreen(
onNext: () -> Unit,
onNext: (isManualSetup: Boolean) -> Unit,
onBack: () -> Unit,
viewModel: ViewModel,
modifier: Modifier = Modifier,
) {
val (state, dispatch) = viewModel.observe { effect ->
when (effect) {
Effect.NavigateNext -> onNext()
is Effect.NavigateNext -> onNext(effect.isManualSetup)
Effect.NavigateBack -> onBack()
}
}
@ -43,7 +43,7 @@ fun SpecialFoldersScreen(
onNextClick = { dispatch(Event.OnNextClicked) },
onBackClick = { dispatch(Event.OnBackClicked) },
state = WizardNavigationBarState(
isNextEnabled = state.value.isLoading.not(),
showNext = state.value.isManualSetup && state.value.isLoading.not(),
),
)
},

View file

@ -37,7 +37,6 @@ class SpecialFoldersViewModel(
Event.OnNextClicked -> onNextClicked()
Event.OnBackClicked -> onBackClicked()
Event.OnEditClicked -> onEditClicked()
Event.OnRetryClicked -> onRetryClicked()
}
}
@ -65,6 +64,7 @@ class SpecialFoldersViewModel(
is ValidationResult.Failure -> {
updateState {
it.copy(
isManualSetup = true,
isSuccess = false,
isLoading = false,
)
@ -129,7 +129,7 @@ class SpecialFoldersViewModel(
private fun navigateNext() {
viewModelScope.coroutineContext.cancelChildren()
emitEffect(Effect.NavigateNext)
emitEffect(Effect.NavigateNext(isManualSetup = state.value.isManualSetup))
}
private fun onBackClicked() {
@ -137,15 +137,6 @@ class SpecialFoldersViewModel(
emitEffect(Effect.NavigateBack)
}
private fun onEditClicked() {
viewModelScope.coroutineContext.cancelChildren()
updateState { state ->
state.copy(
isSuccess = false,
)
}
}
private fun onRetryClicked() {
viewModelScope.coroutineContext.cancelChildren()
updateState {

View file

@ -39,7 +39,6 @@
<string name="account_setup_special_folders_trash_folder_label">Trash folder</string>
<string name="account_setup_special_folders_folder_none">None</string>
<string name="account_setup_special_folders_folder_automatic">Automatic (%s)</string>
<string name="account_setup_special_folders_edit_folders_button_label">Edit special folders</string>
<string name="account_setup_options_top_bar_title">Account options</string>
<string name="account_setup_options_section_display_options">Display options</string>

View file

@ -33,7 +33,7 @@ class SpecialFoldersScreenKtTest : ComposeTest() {
assertThat(onNextCounter).isEqualTo(0)
assertThat(onBackCounter).isEqualTo(0)
viewModel.effect(Effect.NavigateNext)
viewModel.effect(Effect.NavigateNext(true))
assertThat(onNextCounter).isEqualTo(1)
assertThat(onBackCounter).isEqualTo(0)

View file

@ -16,6 +16,7 @@ class SpecialFoldersStateTest {
assertThat(state).isEqualTo(
State(
formState = FormState(),
isManualSetup = false,
isSuccess = false,
error = null,
isLoading = true,

View file

@ -75,7 +75,7 @@ class SpecialFoldersViewModelTest {
}
turbines.assertThatAndEffectTurbineConsumed {
isEqualTo(Effect.NavigateNext)
isEqualTo(Effect.NavigateNext(false))
}
assertThat(accountStateRepository.getState()).isEqualTo(
@ -108,6 +108,7 @@ class SpecialFoldersViewModelTest {
testSubject.event(Event.LoadSpecialFolderOptions)
val unvalidatedState = initialState.copy(
isManualSetup = true,
isLoading = false,
isSuccess = false,
formState = FormState(
@ -187,7 +188,7 @@ class SpecialFoldersViewModelTest {
@Test
fun `should save form data and emit NavigateNext effect when OnNextClicked event received`() = runTest {
val initialState = State(isSuccess = true)
val initialState = State(isManualSetup = true)
val accountStateRepository = InMemoryAccountStateRepository()
val testSubject = createTestSubject(
initialState = initialState,
@ -200,7 +201,7 @@ class SpecialFoldersViewModelTest {
assertThat(turbines.awaitStateItem()).isEqualTo(initialState.copy(isLoading = false))
turbines.assertThatAndEffectTurbineConsumed {
isEqualTo(Effect.NavigateNext)
isEqualTo(Effect.NavigateNext(true))
}
assertThat(accountStateRepository.getState()).isEqualTo(
@ -228,19 +229,6 @@ class SpecialFoldersViewModelTest {
}
}
@Test
fun `should show form when OnEditClicked event received`() = runTest {
val initialState = State(isSuccess = true)
val testSubject = createTestSubject(initialState = initialState)
val turbines = turbinesWithInitialStateCheck(testSubject, initialState)
testSubject.event(Event.OnEditClicked)
turbines.assertThatAndStateTurbineConsumed {
isEqualTo(initialState.copy(isSuccess = false))
}
}
@Test
fun `should show form when OnRetryClicked event received`() = runTest {
val initialState = State(error = SpecialFoldersContract.Failure.LoadFoldersFailed("irrelevant"))
@ -281,7 +269,7 @@ class SpecialFoldersViewModelTest {
)
turbines.assertThatAndEffectTurbineConsumed {
isEqualTo(Effect.NavigateNext)
isEqualTo(Effect.NavigateNext(false))
}
}