From caf6d6b674a54a0b850e9b85f32f5ce58b214f2d Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 19 Oct 2023 12:34:29 +0200 Subject: [PATCH] Create pin : render failures --- .../lockscreen/impl/create/CreatePinEvents.kt | 2 +- .../impl/create/CreatePinPresenter.kt | 22 +++++----- .../lockscreen/impl/create/CreatePinState.kt | 4 +- .../impl/create/CreatePinStateProvider.kt | 17 ++++++-- .../lockscreen/impl/create/CreatePinView.kt | 41 +++++++++++++------ ...CreationFailure.kt => CreatePinFailure.kt} | 6 +-- .../impl/create/validation/PinValidator.kt | 4 +- 7 files changed, 61 insertions(+), 35 deletions(-) rename features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/{PinCreationFailure.kt => CreatePinFailure.kt} (80%) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinEvents.kt index 9e53762c07..78ce529325 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinEvents.kt @@ -18,5 +18,5 @@ package io.element.android.features.lockscreen.impl.create sealed interface CreatePinEvents { data class OnPinEntryChanged(val entryAsText: String) : CreatePinEvents - data object OnClearValidationFailure : CreatePinEvents + data object ClearFailure : CreatePinEvents } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinPresenter.kt index 435de0ebe0..525b80314b 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinPresenter.kt @@ -22,7 +22,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import io.element.android.features.lockscreen.impl.create.model.PinEntry -import io.element.android.features.lockscreen.impl.create.validation.PinCreationFailure +import io.element.android.features.lockscreen.impl.create.validation.CreatePinFailure import io.element.android.features.lockscreen.impl.create.validation.PinValidator import io.element.android.libraries.architecture.Presenter import javax.inject.Inject @@ -44,8 +44,8 @@ class CreatePinPresenter @Inject constructor( var isConfirmationStep by remember { mutableStateOf(false) } - var creationFailure by remember { - mutableStateOf(null) + var createPinFailure by remember { + mutableStateOf(null) } fun handleEvents(event: CreatePinEvents) { @@ -57,7 +57,7 @@ class CreatePinPresenter @Inject constructor( if (confirmPinEntry == choosePinEntry) { //TODO save in db and navigate to next screen } else { - creationFailure = PinCreationFailure.ConfirmationPinNotMatching + createPinFailure = CreatePinFailure.ConfirmationPinNotMatching } } } else { @@ -65,26 +65,26 @@ class CreatePinPresenter @Inject constructor( if (choosePinEntry.isPinComplete()) { when (val pinValidationResult = pinValidator.isPinValid(choosePinEntry)) { is PinValidator.Result.Invalid -> { - creationFailure = pinValidationResult.failure + createPinFailure = pinValidationResult.failure } PinValidator.Result.Valid -> isConfirmationStep = true } } } } - CreatePinEvents.OnClearValidationFailure -> { - when (creationFailure) { - is PinCreationFailure.ConfirmationPinNotMatching -> { + CreatePinEvents.ClearFailure -> { + when (createPinFailure) { + is CreatePinFailure.ConfirmationPinNotMatching -> { choosePinEntry = PinEntry.empty(PIN_SIZE) confirmPinEntry = PinEntry.empty(PIN_SIZE) } - is PinCreationFailure.ChosenPinBlacklisted -> { + is CreatePinFailure.ChosenPinBlacklisted -> { choosePinEntry = PinEntry.empty(PIN_SIZE) } null -> Unit } isConfirmationStep = false - creationFailure = null + createPinFailure = null } } } @@ -93,7 +93,7 @@ class CreatePinPresenter @Inject constructor( choosePinEntry = choosePinEntry, confirmPinEntry = confirmPinEntry, isConfirmationStep = isConfirmationStep, - creationFailure = creationFailure, + createPinFailure = createPinFailure, eventSink = ::handleEvents ) } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinState.kt index 799d4b20a8..914e12ca96 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinState.kt @@ -17,13 +17,13 @@ package io.element.android.features.lockscreen.impl.create import io.element.android.features.lockscreen.impl.create.model.PinEntry -import io.element.android.features.lockscreen.impl.create.validation.PinCreationFailure +import io.element.android.features.lockscreen.impl.create.validation.CreatePinFailure data class CreatePinState( val choosePinEntry: PinEntry, val confirmPinEntry: PinEntry, val isConfirmationStep: Boolean, - val creationFailure: PinCreationFailure?, + val createPinFailure: CreatePinFailure?, val eventSink: (CreatePinEvents) -> Unit ) { val activePinEntry = if (isConfirmationStep) { diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinStateProvider.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinStateProvider.kt index f4d778a296..40287622fd 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinStateProvider.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinStateProvider.kt @@ -18,7 +18,7 @@ package io.element.android.features.lockscreen.impl.create import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.lockscreen.impl.create.model.PinEntry -import io.element.android.features.lockscreen.impl.create.validation.PinCreationFailure +import io.element.android.features.lockscreen.impl.create.validation.CreatePinFailure open class CreatePinStateProvider : PreviewParameterProvider { override val values: Sequence @@ -31,6 +31,17 @@ open class CreatePinStateProvider : PreviewParameterProvider { choosePinEntry = PinEntry.empty(4).fillWith("1789"), isConfirmationStep = true, ), + aCreatePinState( + choosePinEntry = PinEntry.empty(4).fillWith("1789"), + confirmPinEntry = PinEntry.empty(4).fillWith("1788"), + isConfirmationStep = true, + creationFailure = CreatePinFailure.ConfirmationPinNotMatching + ), + aCreatePinState( + choosePinEntry = PinEntry.empty(4).fillWith("1111"), + creationFailure = CreatePinFailure.ChosenPinBlacklisted + ), + ) } @@ -38,12 +49,12 @@ fun aCreatePinState( choosePinEntry: PinEntry = PinEntry.empty(4), confirmPinEntry: PinEntry = PinEntry.empty(4), isConfirmationStep: Boolean = false, - creationFailure: PinCreationFailure? = null, + creationFailure: CreatePinFailure? = null, ) = CreatePinState( choosePinEntry = choosePinEntry, confirmPinEntry = confirmPinEntry, isConfirmationStep = isConfirmationStep, - creationFailure = creationFailure, + createPinFailure = creationFailure, eventSink = {} ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinView.kt index f5b2e49df8..fdce08c229 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/CreatePinView.kt @@ -42,12 +42,13 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.features.lockscreen.impl.create.model.PinDigit import io.element.android.features.lockscreen.impl.create.model.PinEntry +import io.element.android.features.lockscreen.impl.create.validation.CreatePinFailure import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar @@ -76,7 +77,6 @@ fun CreatePinView( .padding(padding) .consumeWindowInsets(padding), header = { CreatePinHeader(state.isConfirmationStep) }, - footer = { CreatePinFooter() }, content = { CreatePinContent(state) } ) } @@ -96,17 +96,6 @@ private fun CreatePinHeader( ) } -@Composable -private fun CreatePinFooter() { - Button( - modifier = Modifier.fillMaxWidth(), - text = "Continue", - onClick = { - - } - ) -} - @Composable private fun CreatePinContent( state: CreatePinState, @@ -121,6 +110,32 @@ private fun CreatePinContent( .padding(top = 36.dp) .fillMaxWidth() ) + if (state.createPinFailure != null) { + ErrorDialog( + modifier = modifier, + title = state.createPinFailure.title(), + content = state.createPinFailure.content(), + onDismiss = { + state.eventSink(CreatePinEvents.ClearFailure) + } + ) + } +} + +@Composable +private fun CreatePinFailure.content(): String { + return when (this) { + CreatePinFailure.ChosenPinBlacklisted -> "You cannot choose this as your PIN code for security reasons" + CreatePinFailure.ConfirmationPinNotMatching -> "Please enter the same PIN twice" + } +} + +@Composable +private fun CreatePinFailure.title(): String { + return when (this) { + CreatePinFailure.ChosenPinBlacklisted -> "Choose a different PIN" + CreatePinFailure.ConfirmationPinNotMatching -> "PINs don't match" + } } @Composable diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinCreationFailure.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/CreatePinFailure.kt similarity index 80% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinCreationFailure.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/CreatePinFailure.kt index 26b1eb5fd8..96c0de0056 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinCreationFailure.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/CreatePinFailure.kt @@ -16,7 +16,7 @@ package io.element.android.features.lockscreen.impl.create.validation -sealed interface PinCreationFailure { - data object ChosenPinBlacklisted : PinCreationFailure - data object ConfirmationPinNotMatching : PinCreationFailure +sealed interface CreatePinFailure { + data object ChosenPinBlacklisted : CreatePinFailure + data object ConfirmationPinNotMatching : CreatePinFailure } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinValidator.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinValidator.kt index 1d97cda60d..8c1854ecee 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinValidator.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/create/validation/PinValidator.kt @@ -25,14 +25,14 @@ class PinValidator @Inject constructor() { sealed interface Result { data object Valid : Result - data class Invalid(val failure: PinCreationFailure) : Result + data class Invalid(val failure: CreatePinFailure) : Result } fun isPinValid(pinEntry: PinEntry): Result { val pinAsText = pinEntry.toText() val isBlacklisted = BLACKLIST.any { it == pinAsText } return if (isBlacklisted) { - Result.Invalid(PinCreationFailure.ChosenPinBlacklisted) + Result.Invalid(CreatePinFailure.ChosenPinBlacklisted) } else { Result.Valid }