Browse Source

[Verify Session] Add missing 'start verification' screen. (#241)

* Add missing 'start verification' screen. 
* Fix retries sometimes not working because of `SessionVerificationController.setDelegate`.
* Make the negative button invisible when not needed.
test/jme/compound-poc
Jorge Martin Espinosa 2 years ago committed by GitHub
parent
commit
09c275d883
  1. 5
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt
  2. 1
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt
  3. 2
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateMachine.kt
  4. 3
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt
  5. 26
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt
  6. 8
      features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt
  7. 3
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt
  8. 1
      libraries/ui-strings/src/main/res/values/strings_eax.xml
  9. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
  10. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_5,NEXUS_5,1.0,en].png

5
features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt

@ -85,11 +85,14 @@ class VerifySelfSessionPresenter @Inject constructor( @@ -85,11 +85,14 @@ class VerifySelfSessionPresenter @Inject constructor(
StateMachineState.RequestingVerification,
StateMachineState.StartingSasVerification,
StateMachineState.SasVerificationStarted,
StateMachineState.VerificationRequestAccepted,
StateMachineState.Canceling -> {
VerifySelfSessionState.VerificationStep.AwaitingOtherDeviceResponse
}
StateMachineState.VerificationRequestAccepted -> {
VerifySelfSessionState.VerificationStep.Ready
}
StateMachineState.Canceled -> {
VerifySelfSessionState.VerificationStep.Canceled
}

1
features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt

@ -32,6 +32,7 @@ data class VerifySelfSessionState( @@ -32,6 +32,7 @@ data class VerifySelfSessionState(
object Initial : VerificationStep
object Canceled : VerificationStep
object AwaitingOtherDeviceResponse : VerificationStep
object Ready : VerificationStep
data class Verifying(val emojiList: List<VerificationEmoji>, val state: Async<Unit>) : VerificationStep
object Completed : VerificationStep
}

2
features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateMachine.kt

@ -81,6 +81,7 @@ class VerifySelfSessionStateMachine( @@ -81,6 +81,7 @@ class VerifySelfSessionStateMachine(
// Observe the verification service state, translate it to state machine input events
sessionVerificationService.verificationFlowState.onEach { verificationAttemptState ->
when (verificationAttemptState) {
VerificationFlowState.Initial -> stateMachine.restart()
VerificationFlowState.AcceptedVerificationRequest -> {
stateMachine.process(Event.DidAcceptVerificationRequest)
}
@ -102,7 +103,6 @@ class VerifySelfSessionStateMachine( @@ -102,7 +103,6 @@ class VerifySelfSessionStateMachine(
VerificationFlowState.Failed -> {
stateMachine.process(Event.DidFail)
}
else -> Unit
}
}.launchIn(coroutineScope)
}

3
features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt

@ -36,6 +36,9 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS @@ -36,6 +36,9 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
aVerifySelfSessionState().copy(
verificationFlowStep = VerifySelfSessionState.VerificationStep.Canceled
),
aVerifySelfSessionState().copy(
verificationFlowStep = VerifySelfSessionState.VerificationStep.Ready
),
// Add other state here
)
}

26
features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt

@ -106,19 +106,19 @@ internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = @@ -106,19 +106,19 @@ internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier =
FlowStep.Initial -> R.drawable.ic_verification_devices
FlowStep.Canceled -> R.drawable.ic_verification_warning
FlowStep.AwaitingOtherDeviceResponse -> R.drawable.ic_verification_waiting
is FlowStep.Verifying, FlowStep.Completed -> R.drawable.ic_verification_emoji
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.drawable.ic_verification_emoji
}
val titleTextId = when (verificationFlowStep) {
FlowStep.Initial -> StringR.string.verification_title_initial
FlowStep.Canceled -> StringR.string.verification_title_canceled
FlowStep.AwaitingOtherDeviceResponse -> StringR.string.verification_title_waiting
is FlowStep.Verifying, FlowStep.Completed -> StringR.string.verification_title_verifying
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> StringR.string.verification_title_verifying
}
val subtitleTextId = when (verificationFlowStep) {
FlowStep.Initial -> StringR.string.verification_subtitle_initial
FlowStep.Canceled -> StringR.string.verification_subtitle_canceled
FlowStep.AwaitingOtherDeviceResponse -> StringR.string.verification_subtitle_waiting
is FlowStep.Verifying, FlowStep.Completed -> StringR.string.verification_subtitle_verifying
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> StringR.string.verification_subtitle_verifying
}
Column(modifier) {
Spacer(Modifier.height(68.dp))
@ -167,7 +167,7 @@ internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) { @@ -167,7 +167,7 @@ internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) {
Column(modifier) {
Spacer(Modifier.height(56.dp))
when (flowState) {
FlowStep.Initial, FlowStep.Canceled, FlowStep.Completed -> Unit
FlowStep.Initial, FlowStep.Ready, FlowStep.Canceled, FlowStep.Completed -> Unit
FlowStep.AwaitingOtherDeviceResponse -> ContentWaiting()
is FlowStep.Verifying -> ContentVerifying(flowState)
}
@ -219,6 +219,7 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) @@ -219,6 +219,7 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
StringR.string.verification_positive_button_verifying_start
}
}
FlowStep.Ready -> StringR.string.verification_positive_button_ready
else -> null
}
val negativeButtonTitle = when (verificationViewState) {
@ -231,6 +232,7 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) @@ -231,6 +232,7 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
val positiveButtonEvent = when (verificationViewState) {
FlowStep.Initial -> VerifySelfSessionViewEvents.RequestVerification
FlowStep.Ready -> VerifySelfSessionViewEvents.StartSasVerification
is FlowStep.Verifying -> if (!isVerifying) VerifySelfSessionViewEvents.ConfirmVerification else null
FlowStep.Canceled -> VerifySelfSessionViewEvents.Restart
else -> null
@ -264,13 +266,15 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) @@ -264,13 +266,15 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
positiveButtonTitle?.let { Text(stringResource(it)) }
}
}
Spacer(modifier = Modifier.height(16.dp))
TextButton(
modifier = Modifier.fillMaxWidth(),
onClick = negativeButtonCallback,
enabled = negativeButtonEnabled,
) {
negativeButtonTitle?.let { Text(stringResource(it)) }
if (negativeButtonTitle != null) {
Spacer(modifier = Modifier.height(16.dp))
TextButton(
modifier = Modifier.fillMaxWidth(),
onClick = negativeButtonCallback,
enabled = negativeButtonEnabled,
) {
Text(stringResource(negativeButtonTitle))
}
}
Spacer(Modifier.height(40.dp))
}

8
features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt

@ -56,6 +56,10 @@ class VerifySelfSessionPresenterTests { @@ -56,6 +56,10 @@ class VerifySelfSessionPresenterTests {
eventSink(VerifySelfSessionViewEvents.RequestVerification)
// Await for other device response:
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.AwaitingOtherDeviceResponse)
// Await for the state to be Ready
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Ready)
// Await for other device response (again):
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.AwaitingOtherDeviceResponse)
// Finally, ChallengeReceived:
val verifyingState = awaitItem()
assertThat(verifyingState.verificationFlowStep).isInstanceOf(VerificationStep.Verifying::class.java)
@ -233,8 +237,8 @@ class VerifySelfSessionPresenterTests { @@ -233,8 +237,8 @@ class VerifySelfSessionPresenterTests {
}
private suspend fun ReceiveTurbine<VerifySelfSessionState>.awaitChallengeReceivedState(): VerifySelfSessionState {
// Skip 'waiting for response' state
skipItems(1)
// Skip 'waiting for response', 'ready' and 'starting verification' state
skipItems(3)
// Received challenge
return awaitItem()
}

3
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt

@ -38,6 +38,7 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification @@ -38,6 +38,7 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification
_isReady.value = value != null
// If status was 'Unknown', move it to either 'Verified' or 'NotVerified'
if (value != null) {
value.setDelegate(this)
updateVerificationStatus(value.isVerified())
}
}
@ -52,7 +53,6 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification @@ -52,7 +53,6 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification
override val sessionVerifiedStatus: StateFlow<SessionVerifiedStatus> = _sessionVerifiedStatus.asStateFlow()
override fun requestVerification() = tryOrFail {
verificationController?.setDelegate(this)
verificationController?.requestVerification()
}
@ -63,7 +63,6 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification @@ -63,7 +63,6 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification
override fun declineVerification() = tryOrFail { verificationController?.declineVerification() }
override fun startVerification() = tryOrFail {
verificationController?.setDelegate(this)
verificationController?.startSasVerification()
}

1
libraries/ui-strings/src/main/res/values/strings_eax.xml

@ -47,6 +47,7 @@ @@ -47,6 +47,7 @@
<string name="verification_positive_button_initial">I am ready</string>
<string name="verification_positive_button_canceled">Retry verification</string>
<string name="verification_positive_button_ready">Start</string>
<string name="verification_positive_button_verifying_start">They match</string>
<string name="verification_positive_button_verifying_ongoing">Waiting to match</string>

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.
Loading…
Cancel
Save