Always display 'lost recovery key?' option (#2745)

* Always display 'lost recovery key?' option

* Use `isLastDevice` it to display only 'enter recovery key' option for verification.

* Update strings. This should fix the wrong term 'passcode' being used in the recovery key screen title.

* Disable 'lost your recovery key?' button while the screen is in a loading state

* Update screenshots

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa 2024-04-25 15:28:24 +02:00 committed by GitHub
parent 6219190ef1
commit 7397df806b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 181 additions and 83 deletions

View file

@ -43,7 +43,6 @@ class VerifySelfSessionNode @AssistedInject constructor(
state = state,
modifier = modifier,
onEnterRecoveryKey = callback::onEnterRecoveryKey,
onCreateNewRecoveryKey = callback::onCreateNewRecoveryKey,
onFinished = callback::onDone,
)
}

View file

@ -103,7 +103,10 @@ class VerifySelfSessionPresenter @Inject constructor(
): VerifySelfSessionState.VerificationStep =
when (val machineState = this) {
StateMachineState.Initial, null -> {
VerifySelfSessionState.VerificationStep.Initial(canEnterRecoveryKey = canEnterRecoveryKey, isLastDevice = encryptionService.isLastDevice.value)
VerifySelfSessionState.VerificationStep.Initial(
canEnterRecoveryKey = canEnterRecoveryKey,
isLastDevice = encryptionService.isLastDevice.value
)
}
StateMachineState.RequestingVerification,
StateMachineState.StartingSasVerification,

View file

@ -29,7 +29,7 @@ data class VerifySelfSessionState(
) {
@Stable
sealed interface VerificationStep {
data class Initial(val canEnterRecoveryKey: Boolean, val isLastDevice: Boolean) : VerificationStep
data class Initial(val canEnterRecoveryKey: Boolean, val isLastDevice: Boolean = false) : VerificationStep
data object Canceled : VerificationStep
data object AwaitingOtherDeviceResponse : VerificationStep
data object Ready : VerificationStep

View file

@ -45,7 +45,7 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
verificationFlowStep = VerificationStep.Verifying(aDecimalsSessionVerificationData(), AsyncData.Uninitialized)
),
aVerifySelfSessionState(
verificationFlowStep = VerificationStep.Initial(canEnterRecoveryKey = true, isLastDevice = false)
verificationFlowStep = VerificationStep.Initial(canEnterRecoveryKey = true)
),
aVerifySelfSessionState(
verificationFlowStep = VerificationStep.Initial(canEnterRecoveryKey = true, isLastDevice = true)
@ -71,7 +71,7 @@ private fun aDecimalsSessionVerificationData(
}
internal fun aVerifySelfSessionState(
verificationFlowStep: VerificationStep = VerificationStep.Initial(canEnterRecoveryKey = false, isLastDevice = false),
verificationFlowStep: VerificationStep = VerificationStep.Initial(canEnterRecoveryKey = false),
displaySkipButton: Boolean = false,
eventSink: (VerifySelfSessionViewEvents) -> Unit = {},
) = VerifySelfSessionState(

View file

@ -66,7 +66,6 @@ import io.element.android.features.verifysession.impl.VerifySelfSessionState.Ver
fun VerifySelfSessionView(
state: VerifySelfSessionState,
onEnterRecoveryKey: () -> Unit,
onCreateNewRecoveryKey: () -> Unit,
onFinished: () -> Unit,
modifier: Modifier = Modifier,
) {
@ -115,7 +114,6 @@ fun VerifySelfSessionView(
screenState = state,
goBack = ::resetFlow,
onEnterRecoveryKey = onEnterRecoveryKey,
onCreateNewRecoveryKey = onCreateNewRecoveryKey,
onFinished = onFinished,
)
}
@ -228,7 +226,6 @@ private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifie
private fun BottomMenu(
screenState: VerifySelfSessionState,
onEnterRecoveryKey: () -> Unit,
onCreateNewRecoveryKey: () -> Unit,
goBack: () -> Unit,
onFinished: () -> Unit,
) {
@ -243,8 +240,6 @@ private fun BottomMenu(
BottomMenu(
positiveButtonTitle = stringResource(R.string.screen_session_verification_enter_recovery_key),
onPositiveButtonClicked = onEnterRecoveryKey,
negativeButtonTitle = stringResource(R.string.screen_identity_confirmation_create_new_recovery_key),
onNegativeButtonClicked = onCreateNewRecoveryKey,
)
} else {
BottomMenu(
@ -346,7 +341,6 @@ internal fun VerifySelfSessionViewPreview(@PreviewParameter(VerifySelfSessionSta
VerifySelfSessionView(
state = state,
onEnterRecoveryKey = {},
onCreateNewRecoveryKey = {},
onFinished = {},
)
}

View file

@ -53,7 +53,7 @@ class VerifySelfSessionPresenterTests {
presenter.present()
}.test {
awaitItem().run {
assertThat(verificationFlowStep).isEqualTo(VerificationStep.Initial(false, false))
assertThat(verificationFlowStep).isEqualTo(VerificationStep.Initial(false))
assertThat(displaySkipButton).isTrue()
}
}
@ -80,7 +80,7 @@ class VerifySelfSessionPresenterTests {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(true, false))
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(true))
}
}
@ -95,7 +95,7 @@ class VerifySelfSessionPresenterTests {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(true, true))
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(canEnterRecoveryKey = true, isLastDevice = true))
}
}
@ -118,7 +118,7 @@ class VerifySelfSessionPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.verificationFlowStep).isEqualTo(VerificationStep.Initial(false, false))
assertThat(initialState.verificationFlowStep).isEqualTo(VerificationStep.Initial(false))
val eventSink = initialState.eventSink
eventSink(VerifySelfSessionViewEvents.StartSasVerification)
// Await for other device response:
@ -137,7 +137,7 @@ class VerifySelfSessionPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.verificationFlowStep).isEqualTo(VerificationStep.Initial(false, false))
assertThat(initialState.verificationFlowStep).isEqualTo(VerificationStep.Initial(false))
val eventSink = initialState.eventSink
eventSink(VerifySelfSessionViewEvents.Cancel)
expectNoEvents()
@ -172,7 +172,7 @@ class VerifySelfSessionPresenterTests {
awaitItem().eventSink(VerifySelfSessionViewEvents.RequestVerification)
service.shouldFail = false
assertThat(awaitItem().verificationFlowStep).isInstanceOf(VerificationStep.AwaitingOtherDeviceResponse::class.java)
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(false, false))
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(false))
}
}
@ -231,7 +231,7 @@ class VerifySelfSessionPresenterTests {
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Canceled)
state.eventSink(VerifySelfSessionViewEvents.Reset)
// Went back to initial state
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(false, false))
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial(false))
cancelAndIgnoreRemainingEvents()
}
}
@ -315,7 +315,7 @@ class VerifySelfSessionPresenterTests {
sessionVerificationData: SessionVerificationData = SessionVerificationData.Emojis(emptyList()),
): VerifySelfSessionState {
var state = awaitItem()
assertThat(state.verificationFlowStep).isEqualTo(VerificationStep.Initial(false, false))
assertThat(state.verificationFlowStep).isEqualTo(VerificationStep.Initial(false))
state.eventSink(VerifySelfSessionViewEvents.RequestVerification)
// Await for other device response:
state = awaitItem()

View file

@ -144,7 +144,7 @@ class VerifySelfSessionViewTest {
ensureCalledOnce { callback ->
rule.setVerifySelfSessionView(
aVerifySelfSessionState(
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial(true, false),
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial(true),
eventSink = eventsRecorder
),
onEnterRecoveryKey = callback,
@ -153,22 +153,6 @@ class VerifySelfSessionViewTest {
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on create new recovery key calls the expected callback`() {
val eventsRecorder = EventsRecorder<VerifySelfSessionViewEvents>(expectEvents = false)
ensureCalledOnce { callback ->
rule.setVerifySelfSessionView(
aVerifySelfSessionState(
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial(true, true),
eventSink = eventsRecorder
),
onCreateNewRecoveryKey = callback,
)
rule.clickOn(R.string.screen_identity_confirmation_create_new_recovery_key)
}
}
@Test
fun `clicking on they match emits the expected event`() {
val eventsRecorder = EventsRecorder<VerifySelfSessionViewEvents>()
@ -206,7 +190,7 @@ class VerifySelfSessionViewTest {
val eventsRecorder = EventsRecorder<VerifySelfSessionViewEvents>()
rule.setVerifySelfSessionView(
aVerifySelfSessionState(
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial(canEnterRecoveryKey = true, isLastDevice = false),
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial(canEnterRecoveryKey = true),
displaySkipButton = true,
eventSink = eventsRecorder
),
@ -232,14 +216,12 @@ class VerifySelfSessionViewTest {
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setVerifySelfSessionView(
state: VerifySelfSessionState,
onEnterRecoveryKey: () -> Unit = EnsureNeverCalled(),
onCreateNewRecoveryKey: () -> Unit = EnsureNeverCalled(),
onFinished: () -> Unit = EnsureNeverCalled(),
) {
rule.setContent {
VerifySelfSessionView(
state = state,
onEnterRecoveryKey = onEnterRecoveryKey,
onCreateNewRecoveryKey = onCreateNewRecoveryKey,
onFinished = onFinished,
)
}