diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionPresenter.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionPresenter.kt index 360bf64875..97778b322b 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionPresenter.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionPresenter.kt @@ -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) @@ -134,6 +135,9 @@ class VerifySelfSessionPresenter @AssistedInject constructor( isLastDevice = encryptionService.isLastDevice.value ) } + VerifySelfSessionStateMachine.State.UseAnotherDevice -> { + VerifySelfSessionState.Step.UseAnotherDevice + } StateMachineState.RequestingVerification, StateMachineState.StartingSasVerification, StateMachineState.SasVerificationStarted, diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionState.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionState.kt index e763305caa..32664b347f 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionState.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionState.kt @@ -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 diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateMachine.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateMachine.kt index f423b14aae..09f18538d0 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateMachine.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateMachine.kt @@ -38,12 +38,14 @@ class VerifySelfSessionStateMachine @Inject constructor( init { spec { inState { + on { _: Event.UseAnotherDevice, state -> + state.override { State.UseAnotherDevice.andLogStateChange() } + } + } + inState { on { _: Event.RequestVerification, state -> state.override { State.RequestingVerification.andLogStateChange() } } - on { _: Event.StartSasVerification, state -> - state.override { State.StartingSasVerification.andLogStateChange() } - } } inState { onEnterEffect { @@ -119,6 +121,7 @@ class VerifySelfSessionStateMachine @Inject constructor( on { _: Event.Cancel, state: MachineState -> 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 -> { @@ -144,6 +147,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 @@ -175,6 +181,9 @@ class VerifySelfSessionStateMachine @Inject constructor( } sealed interface Event { + /** User wants to use another session. */ + data object UseAnotherDevice : Event + /** Request verification. */ data object RequestVerification : Event diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateProvider.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateProvider.kt index 8cb60a822f..b9de96aae4 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateProvider.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionStateProvider.kt @@ -56,6 +56,9 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider 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) @@ -159,6 +161,7 @@ fun VerifySelfSessionView( private fun VerifySelfSessionHeader(step: Step) { val iconStyle = when (step) { Step.Loading -> error("Should not happen") + Step.UseAnotherDevice -> BigIcon.Style.Default(CompoundIcons.Devices()) is Step.Initial, Step.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.LockSolid()) Step.Canceled -> BigIcon.Style.AlertSolid Step.Ready, is Step.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction()) @@ -167,6 +170,7 @@ private fun VerifySelfSessionHeader(step: Step) { } val titleTextId = when (step) { Step.Loading -> error("Should not happen") + Step.UseAnotherDevice -> R.string.screen_session_verification_use_another_device_title is Step.Initial, Step.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_title Step.Canceled -> CommonStrings.common_verification_cancelled Step.Ready -> R.string.screen_session_verification_compare_emojis_title @@ -179,6 +183,7 @@ private fun VerifySelfSessionHeader(step: Step) { } val subtitleTextId = when (step) { Step.Loading -> error("Should not happen") + Step.UseAnotherDevice -> R.string.screen_session_verification_use_another_device_subtitle is Step.Initial, Step.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_subtitle Step.Canceled -> R.string.screen_session_verification_cancelled_subtitle Step.Ready -> R.string.screen_session_verification_ready_subtitle @@ -252,7 +257,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( @@ -267,6 +272,17 @@ private fun VerifySelfSessionBottomMenu( ) } } + is Step.UseAnotherDevice -> { + VerificationBottomMenu { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_start_verification), + onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) }, + ) + // Placeholder so the 1st button keeps its vertical position + Spacer(modifier = Modifier.height(40.dp)) + } + } is Step.Canceled -> { VerificationBottomMenu { Button( diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionViewEvents.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionViewEvents.kt index 869bdc7051..b4af38f780 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionViewEvents.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/VerifySelfSessionViewEvents.kt @@ -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 diff --git a/features/verifysession/impl/src/main/res/values/localazy.xml b/features/verifysession/impl/src/main/res/values/localazy.xml index f67a2024b9..85fa3b8246 100644 --- a/features/verifysession/impl/src/main/res/values/localazy.xml +++ b/features/verifysession/impl/src/main/res/values/localazy.xml @@ -35,6 +35,8 @@ "Verification requested" "They don’t match" "They match" + "Make sure you have the app open in the other device before starting verification from here." + "Open the app on another verified device" "Accept the request to start the verification process in your other session to continue." "Waiting to accept request" "Signing out…"