Skip to content

Commit bee708c

Browse files
authored
Merge pull request #3829 from element-hq/feature/bma/verificationIteration
Verification UI / UX iteration
2 parents a6fedba + 88d0498 commit bee708c

17 files changed

+96
-128
lines changed

features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationView.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ fun IncomingVerificationView(
8080
@Composable
8181
private fun IncomingVerificationHeader(step: Step) {
8282
val iconStyle = when (step) {
83-
Step.Canceled,
83+
Step.Canceled -> BigIcon.Style.AlertSolid
8484
is Step.Initial -> BigIcon.Style.Default(CompoundIcons.LockSolid())
8585
is Step.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction())
8686
Step.Completed -> BigIcon.Style.SuccessSolid
8787
Step.Failure -> BigIcon.Style.AlertSolid
8888
}
8989
val titleTextId = when (step) {
90-
Step.Canceled -> CommonStrings.common_verification_cancelled
90+
Step.Canceled -> R.string.screen_session_verification_request_failure_title
9191
is Step.Initial -> R.string.screen_session_verification_request_title
9292
is Step.Verifying -> when (step.data) {
9393
is SessionVerificationData.Decimals -> R.string.screen_session_verification_compare_numbers_title
@@ -97,7 +97,7 @@ private fun IncomingVerificationHeader(step: Step) {
9797
Step.Failure -> R.string.screen_session_verification_request_failure_title
9898
}
9999
val subtitleTextId = when (step) {
100-
Step.Canceled -> R.string.screen_session_verification_cancelled_subtitle
100+
Step.Canceled -> R.string.screen_session_verification_request_failure_subtitle
101101
is Step.Initial -> R.string.screen_session_verification_request_subtitle
102102
is Step.Verifying -> when (step.data) {
103103
is SessionVerificationData.Decimals -> R.string.screen_session_verification_compare_numbers_subtitle

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
104104
fun handleEvents(event: VerifySelfSessionViewEvents) {
105105
Timber.d("Verification user action: ${event::class.simpleName}")
106106
when (event) {
107+
VerifySelfSessionViewEvents.UseAnotherDevice -> stateAndDispatch.dispatchAction(StateMachineEvent.UseAnotherDevice)
107108
VerifySelfSessionViewEvents.RequestVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.RequestVerification)
108109
VerifySelfSessionViewEvents.StartSasVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.StartSasVerification)
109110
VerifySelfSessionViewEvents.ConfirmVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.AcceptChallenge)
@@ -134,6 +135,9 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
134135
isLastDevice = encryptionService.isLastDevice.value
135136
)
136137
}
138+
VerifySelfSessionStateMachine.State.UseAnotherDevice -> {
139+
VerifySelfSessionState.Step.UseAnotherDevice
140+
}
137141
StateMachineState.RequestingVerification,
138142
StateMachineState.StartingSasVerification,
139143
StateMachineState.SasVerificationStarted,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ data class VerifySelfSessionState(
2626

2727
// FIXME canEnterRecoveryKey value is never read.
2828
data class Initial(val canEnterRecoveryKey: Boolean, val isLastDevice: Boolean = false) : Step
29+
data object UseAnotherDevice : Step
2930
data object Canceled : Step
3031
data object AwaitingOtherDeviceResponse : Step
3132
data object Ready : Step

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ class VerifySelfSessionStateMachine @Inject constructor(
3838
init {
3939
spec {
4040
inState<State.Initial> {
41+
on { _: Event.UseAnotherDevice, state ->
42+
state.override { State.UseAnotherDevice.andLogStateChange() }
43+
}
44+
}
45+
inState<State.UseAnotherDevice> {
4146
on { _: Event.RequestVerification, state ->
4247
state.override { State.RequestingVerification.andLogStateChange() }
4348
}
44-
on { _: Event.StartSasVerification, state ->
45-
state.override { State.StartingSasVerification.andLogStateChange() }
46-
}
4749
}
4850
inState<State.RequestingVerification> {
4951
onEnterEffect {
@@ -64,9 +66,6 @@ class VerifySelfSessionStateMachine @Inject constructor(
6466
}
6567
}
6668
inState<State.Canceled> {
67-
on { _: Event.RequestVerification, state ->
68-
state.override { State.RequestingVerification.andLogStateChange() }
69-
}
7069
on { _: Event.Reset, state ->
7170
state.override { State.Initial.andLogStateChange() }
7271
}
@@ -119,6 +118,7 @@ class VerifySelfSessionStateMachine @Inject constructor(
119118
on { _: Event.Cancel, state: MachineState<State> ->
120119
when (state.snapshot) {
121120
State.Initial, State.Completed, State.Canceled -> state.noChange()
121+
State.UseAnotherDevice -> state.override { State.Initial.andLogStateChange() }
122122
// For some reason `cancelVerification` is not calling its delegate `didCancel` method so we don't pass from
123123
// `Canceling` state to `Canceled` automatically anymore
124124
else -> {
@@ -144,6 +144,9 @@ class VerifySelfSessionStateMachine @Inject constructor(
144144
/** The initial state, before verification started. */
145145
data object Initial : State
146146

147+
/** Let the user know that they need to get ready on their other session. */
148+
data object UseAnotherDevice : State
149+
147150
/** Waiting for verification acceptance. */
148151
data object RequestingVerification : State
149152

@@ -175,6 +178,9 @@ class VerifySelfSessionStateMachine @Inject constructor(
175178
}
176179

177180
sealed interface Event {
181+
/** User wants to use another session. */
182+
data object UseAnotherDevice : Event
183+
178184
/** Request verification. */
179185
data object RequestVerification : Event
180186

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
5656
aVerifySelfSessionState(
5757
step = Step.Skipped
5858
),
59+
aVerifySelfSessionState(
60+
step = Step.UseAnotherDevice
61+
),
5962
// Add other state here
6063
)
6164
}

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

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ fun VerifySelfSessionView(
6666
fun cancelOrResetFlow() {
6767
when (step) {
6868
is Step.Canceled -> state.eventSink(VerifySelfSessionViewEvents.Reset)
69-
is Step.AwaitingOtherDeviceResponse, Step.Ready -> state.eventSink(VerifySelfSessionViewEvents.Cancel)
69+
is Step.AwaitingOtherDeviceResponse,
70+
Step.UseAnotherDevice,
71+
Step.Ready -> state.eventSink(VerifySelfSessionViewEvents.Cancel)
7072
is Step.Verifying -> {
7173
if (!step.state.isLoading()) {
7274
state.eventSink(VerifySelfSessionViewEvents.DeclineVerification)
@@ -159,16 +161,20 @@ fun VerifySelfSessionView(
159161
private fun VerifySelfSessionHeader(step: Step) {
160162
val iconStyle = when (step) {
161163
Step.Loading -> error("Should not happen")
162-
is Step.Initial, Step.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.LockSolid())
164+
is Step.Initial -> BigIcon.Style.Default(CompoundIcons.LockSolid())
165+
Step.UseAnotherDevice -> BigIcon.Style.Default(CompoundIcons.Devices())
166+
Step.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.Devices())
163167
Step.Canceled -> BigIcon.Style.AlertSolid
164168
Step.Ready, is Step.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction())
165169
Step.Completed -> BigIcon.Style.SuccessSolid
166170
is Step.Skipped -> return
167171
}
168172
val titleTextId = when (step) {
169173
Step.Loading -> error("Should not happen")
170-
is Step.Initial, Step.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_title
171-
Step.Canceled -> CommonStrings.common_verification_cancelled
174+
is Step.Initial -> R.string.screen_identity_confirmation_title
175+
Step.UseAnotherDevice -> R.string.screen_session_verification_use_another_device_title
176+
Step.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_another_device_title
177+
Step.Canceled -> CommonStrings.common_verification_failed
172178
Step.Ready -> R.string.screen_session_verification_compare_emojis_title
173179
Step.Completed -> R.string.screen_identity_confirmed_title
174180
is Step.Verifying -> when (step.data) {
@@ -179,8 +185,10 @@ private fun VerifySelfSessionHeader(step: Step) {
179185
}
180186
val subtitleTextId = when (step) {
181187
Step.Loading -> error("Should not happen")
182-
is Step.Initial, Step.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_subtitle
183-
Step.Canceled -> R.string.screen_session_verification_cancelled_subtitle
188+
is Step.Initial -> R.string.screen_identity_confirmation_subtitle
189+
Step.UseAnotherDevice -> R.string.screen_session_verification_use_another_device_subtitle
190+
Step.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_another_device_subtitle
191+
Step.Canceled -> R.string.screen_session_verification_failed_subtitle
184192
Step.Ready -> R.string.screen_session_verification_ready_subtitle
185193
Step.Completed -> R.string.screen_identity_confirmed_subtitle
186194
is Step.Verifying -> when (step.data) {
@@ -252,7 +260,7 @@ private fun VerifySelfSessionBottomMenu(
252260
Button(
253261
modifier = Modifier.fillMaxWidth(),
254262
text = stringResource(R.string.screen_identity_use_another_device),
255-
onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) },
263+
onClick = { eventSink(VerifySelfSessionViewEvents.UseAnotherDevice) },
256264
)
257265
}
258266
Button(
@@ -267,18 +275,26 @@ private fun VerifySelfSessionBottomMenu(
267275
)
268276
}
269277
}
270-
is Step.Canceled -> {
278+
is Step.UseAnotherDevice -> {
271279
VerificationBottomMenu {
272280
Button(
273281
modifier = Modifier.fillMaxWidth(),
274-
text = stringResource(R.string.screen_session_verification_positive_button_canceled),
282+
text = stringResource(CommonStrings.action_start_verification),
275283
onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) },
276284
)
277-
TextButton(
285+
// Placeholder so the 1st button keeps its vertical position
286+
Spacer(modifier = Modifier.height(40.dp))
287+
}
288+
}
289+
is Step.Canceled -> {
290+
VerificationBottomMenu {
291+
Button(
278292
modifier = Modifier.fillMaxWidth(),
279-
text = stringResource(CommonStrings.action_cancel),
293+
text = stringResource(CommonStrings.action_done),
280294
onClick = onCancelClick,
281295
)
296+
// Placeholder so the 1st button keeps its vertical position
297+
Spacer(modifier = Modifier.height(40.dp))
282298
}
283299
}
284300
is Step.Ready -> {
@@ -302,6 +318,7 @@ private fun VerifySelfSessionBottomMenu(
302318
text = stringResource(R.string.screen_identity_waiting_on_other_device),
303319
onClick = {},
304320
showProgress = true,
321+
enabled = false,
305322
)
306323
// Placeholder so the 1st button keeps its vertical position
307324
Spacer(modifier = Modifier.height(40.dp))

features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionViewEvents.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package io.element.android.features.verifysession.impl.outgoing
99

1010
sealed interface VerifySelfSessionViewEvents {
11+
data object UseAnotherDevice : VerifySelfSessionViewEvents
1112
data object RequestVerification : VerifySelfSessionViewEvents
1213
data object StartSasVerification : VerifySelfSessionViewEvents
1314
data object ConfirmVerification : VerifySelfSessionViewEvents

features/verifysession/impl/src/main/res/values/localazy.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
<string name="screen_session_verification_request_title">"Verification requested"</string>
3636
<string name="screen_session_verification_they_dont_match">"They don’t match"</string>
3737
<string name="screen_session_verification_they_match">"They match"</string>
38+
<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>
39+
<string name="screen_session_verification_use_another_device_title">"Open the app on another verified device"</string>
40+
<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>
41+
<string name="screen_session_verification_waiting_another_device_title">"Start verification on the other device"</string>
3842
<string name="screen_session_verification_waiting_to_accept_subtitle">"Accept the request to start the verification process in your other session to continue."</string>
3943
<string name="screen_session_verification_waiting_to_accept_title">"Waiting to accept request"</string>
4044
<string name="screen_signout_in_progress_dialog_content">"Signing out…"</string>

0 commit comments

Comments
 (0)