Skip to content

Commit

Permalink
Merge pull request element-hq#3829 from element-hq/feature/bma/verifi…
Browse files Browse the repository at this point in the history
…cationIteration

Verification UI / UX iteration
  • Loading branch information
bmarty authored Nov 7, 2024
2 parents a6fedba + 88d0498 commit bee708c
Show file tree
Hide file tree
Showing 17 changed files with 96 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ fun IncomingVerificationView(
@Composable
private fun IncomingVerificationHeader(step: Step) {
val iconStyle = when (step) {
Step.Canceled,
Step.Canceled -> BigIcon.Style.AlertSolid
is Step.Initial -> BigIcon.Style.Default(CompoundIcons.LockSolid())
is Step.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction())
Step.Completed -> BigIcon.Style.SuccessSolid
Step.Failure -> BigIcon.Style.AlertSolid
}
val titleTextId = when (step) {
Step.Canceled -> CommonStrings.common_verification_cancelled
Step.Canceled -> R.string.screen_session_verification_request_failure_title
is Step.Initial -> R.string.screen_session_verification_request_title
is Step.Verifying -> when (step.data) {
is SessionVerificationData.Decimals -> R.string.screen_session_verification_compare_numbers_title
Expand All @@ -97,7 +97,7 @@ private fun IncomingVerificationHeader(step: Step) {
Step.Failure -> R.string.screen_session_verification_request_failure_title
}
val subtitleTextId = when (step) {
Step.Canceled -> R.string.screen_session_verification_cancelled_subtitle
Step.Canceled -> R.string.screen_session_verification_request_failure_subtitle
is Step.Initial -> R.string.screen_session_verification_request_subtitle
is Step.Verifying -> when (step.data) {
is SessionVerificationData.Decimals -> R.string.screen_session_verification_compare_numbers_subtitle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
fun handleEvents(event: VerifySelfSessionViewEvents) {
Timber.d("Verification user action: ${event::class.simpleName}")
when (event) {
VerifySelfSessionViewEvents.UseAnotherDevice -> stateAndDispatch.dispatchAction(StateMachineEvent.UseAnotherDevice)
VerifySelfSessionViewEvents.RequestVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.RequestVerification)
VerifySelfSessionViewEvents.StartSasVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.StartSasVerification)
VerifySelfSessionViewEvents.ConfirmVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.AcceptChallenge)
Expand Down Expand Up @@ -134,6 +135,9 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
isLastDevice = encryptionService.isLastDevice.value
)
}
VerifySelfSessionStateMachine.State.UseAnotherDevice -> {
VerifySelfSessionState.Step.UseAnotherDevice
}
StateMachineState.RequestingVerification,
StateMachineState.StartingSasVerification,
StateMachineState.SasVerificationStarted,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ data class VerifySelfSessionState(

// FIXME canEnterRecoveryKey value is never read.
data class Initial(val canEnterRecoveryKey: Boolean, val isLastDevice: Boolean = false) : Step
data object UseAnotherDevice : Step
data object Canceled : Step
data object AwaitingOtherDeviceResponse : Step
data object Ready : Step
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ class VerifySelfSessionStateMachine @Inject constructor(
init {
spec {
inState<State.Initial> {
on { _: Event.UseAnotherDevice, state ->
state.override { State.UseAnotherDevice.andLogStateChange() }
}
}
inState<State.UseAnotherDevice> {
on { _: Event.RequestVerification, state ->
state.override { State.RequestingVerification.andLogStateChange() }
}
on { _: Event.StartSasVerification, state ->
state.override { State.StartingSasVerification.andLogStateChange() }
}
}
inState<State.RequestingVerification> {
onEnterEffect {
Expand All @@ -64,9 +66,6 @@ class VerifySelfSessionStateMachine @Inject constructor(
}
}
inState<State.Canceled> {
on { _: Event.RequestVerification, state ->
state.override { State.RequestingVerification.andLogStateChange() }
}
on { _: Event.Reset, state ->
state.override { State.Initial.andLogStateChange() }
}
Expand Down Expand Up @@ -119,6 +118,7 @@ class VerifySelfSessionStateMachine @Inject constructor(
on { _: Event.Cancel, state: MachineState<State> ->
when (state.snapshot) {
State.Initial, State.Completed, State.Canceled -> state.noChange()
State.UseAnotherDevice -> state.override { State.Initial.andLogStateChange() }
// For some reason `cancelVerification` is not calling its delegate `didCancel` method so we don't pass from
// `Canceling` state to `Canceled` automatically anymore
else -> {
Expand All @@ -144,6 +144,9 @@ class VerifySelfSessionStateMachine @Inject constructor(
/** The initial state, before verification started. */
data object Initial : State

/** Let the user know that they need to get ready on their other session. */
data object UseAnotherDevice : State

/** Waiting for verification acceptance. */
data object RequestingVerification : State

Expand Down Expand Up @@ -175,6 +178,9 @@ class VerifySelfSessionStateMachine @Inject constructor(
}

sealed interface Event {
/** User wants to use another session. */
data object UseAnotherDevice : Event

/** Request verification. */
data object RequestVerification : Event

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
aVerifySelfSessionState(
step = Step.Skipped
),
aVerifySelfSessionState(
step = Step.UseAnotherDevice
),
// Add other state here
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ fun VerifySelfSessionView(
fun cancelOrResetFlow() {
when (step) {
is Step.Canceled -> state.eventSink(VerifySelfSessionViewEvents.Reset)
is Step.AwaitingOtherDeviceResponse, Step.Ready -> state.eventSink(VerifySelfSessionViewEvents.Cancel)
is Step.AwaitingOtherDeviceResponse,
Step.UseAnotherDevice,
Step.Ready -> state.eventSink(VerifySelfSessionViewEvents.Cancel)
is Step.Verifying -> {
if (!step.state.isLoading()) {
state.eventSink(VerifySelfSessionViewEvents.DeclineVerification)
Expand Down Expand Up @@ -159,16 +161,20 @@ fun VerifySelfSessionView(
private fun VerifySelfSessionHeader(step: Step) {
val iconStyle = when (step) {
Step.Loading -> error("Should not happen")
is Step.Initial, Step.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.LockSolid())
is Step.Initial -> BigIcon.Style.Default(CompoundIcons.LockSolid())
Step.UseAnotherDevice -> BigIcon.Style.Default(CompoundIcons.Devices())
Step.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.Devices())
Step.Canceled -> BigIcon.Style.AlertSolid
Step.Ready, is Step.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction())
Step.Completed -> BigIcon.Style.SuccessSolid
is Step.Skipped -> return
}
val titleTextId = when (step) {
Step.Loading -> error("Should not happen")
is Step.Initial, Step.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_title
Step.Canceled -> CommonStrings.common_verification_cancelled
is Step.Initial -> R.string.screen_identity_confirmation_title
Step.UseAnotherDevice -> R.string.screen_session_verification_use_another_device_title
Step.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_another_device_title
Step.Canceled -> CommonStrings.common_verification_failed
Step.Ready -> R.string.screen_session_verification_compare_emojis_title
Step.Completed -> R.string.screen_identity_confirmed_title
is Step.Verifying -> when (step.data) {
Expand All @@ -179,8 +185,10 @@ private fun VerifySelfSessionHeader(step: Step) {
}
val subtitleTextId = when (step) {
Step.Loading -> error("Should not happen")
is Step.Initial, Step.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_subtitle
Step.Canceled -> R.string.screen_session_verification_cancelled_subtitle
is Step.Initial -> R.string.screen_identity_confirmation_subtitle
Step.UseAnotherDevice -> R.string.screen_session_verification_use_another_device_subtitle
Step.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_another_device_subtitle
Step.Canceled -> R.string.screen_session_verification_failed_subtitle
Step.Ready -> R.string.screen_session_verification_ready_subtitle
Step.Completed -> R.string.screen_identity_confirmed_subtitle
is Step.Verifying -> when (step.data) {
Expand Down Expand Up @@ -252,7 +260,7 @@ private fun VerifySelfSessionBottomMenu(
Button(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.screen_identity_use_another_device),
onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) },
onClick = { eventSink(VerifySelfSessionViewEvents.UseAnotherDevice) },
)
}
Button(
Expand All @@ -267,18 +275,26 @@ private fun VerifySelfSessionBottomMenu(
)
}
}
is Step.Canceled -> {
is Step.UseAnotherDevice -> {
VerificationBottomMenu {
Button(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.screen_session_verification_positive_button_canceled),
text = stringResource(CommonStrings.action_start_verification),
onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) },
)
TextButton(
// Placeholder so the 1st button keeps its vertical position
Spacer(modifier = Modifier.height(40.dp))
}
}
is Step.Canceled -> {
VerificationBottomMenu {
Button(
modifier = Modifier.fillMaxWidth(),
text = stringResource(CommonStrings.action_cancel),
text = stringResource(CommonStrings.action_done),
onClick = onCancelClick,
)
// Placeholder so the 1st button keeps its vertical position
Spacer(modifier = Modifier.height(40.dp))
}
}
is Step.Ready -> {
Expand All @@ -302,6 +318,7 @@ private fun VerifySelfSessionBottomMenu(
text = stringResource(R.string.screen_identity_waiting_on_other_device),
onClick = {},
showProgress = true,
enabled = false,
)
// Placeholder so the 1st button keeps its vertical position
Spacer(modifier = Modifier.height(40.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package io.element.android.features.verifysession.impl.outgoing

sealed interface VerifySelfSessionViewEvents {
data object UseAnotherDevice : VerifySelfSessionViewEvents
data object RequestVerification : VerifySelfSessionViewEvents
data object StartSasVerification : VerifySelfSessionViewEvents
data object ConfirmVerification : VerifySelfSessionViewEvents
Expand Down
4 changes: 4 additions & 0 deletions features/verifysession/impl/src/main/res/values/localazy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
<string name="screen_session_verification_request_title">"Verification requested"</string>
<string name="screen_session_verification_they_dont_match">"They don’t match"</string>
<string name="screen_session_verification_they_match">"They match"</string>
<string name="screen_session_verification_use_another_device_subtitle">"Make sure you have the app open in the other device before starting verification from here."</string>
<string name="screen_session_verification_use_another_device_title">"Open the app on another verified device"</string>
<string name="screen_session_verification_waiting_another_device_subtitle">"You should see a popup on the other device. Start the verification from there now."</string>
<string name="screen_session_verification_waiting_another_device_title">"Start verification on the other device"</string>
<string name="screen_session_verification_waiting_to_accept_subtitle">"Accept the request to start the verification process in your other session to continue."</string>
<string name="screen_session_verification_waiting_to_accept_title">"Waiting to accept request"</string>
<string name="screen_signout_in_progress_dialog_content">"Signing out…"</string>
Expand Down
Loading

0 comments on commit bee708c

Please sign in to comment.