Browse Source

Properly skip the FTUE verification screen if verification is not needed.

pull/3395/head
Benoit Marty 2 weeks ago committed by Benoit Marty
parent
commit
f32e7c7e02
  1. 7
      features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/FtueSessionVerificationFlowNode.kt
  2. 4
      features/verifysession/api/src/main/kotlin/io/element/android/features/verifysession/api/VerifySessionEntryPoint.kt
  3. 5
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/DefaultVerifySessionEntryPoint.kt
  4. 7
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionNode.kt
  5. 37
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt
  6. 1
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt
  7. 6
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt
  8. 21
      features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt
  9. 29
      features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTest.kt

7
features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/FtueSessionVerificationFlowNode.kt

@ -46,7 +46,7 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor(
private val secureBackupEntryPoint: SecureBackupEntryPoint, private val secureBackupEntryPoint: SecureBackupEntryPoint,
) : BaseFlowNode<FtueSessionVerificationFlowNode.NavTarget>( ) : BaseFlowNode<FtueSessionVerificationFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Root, initialElement = NavTarget.Root(showDeviceVerifiedScreen = false),
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
), ),
buildContext = buildContext, buildContext = buildContext,
@ -54,7 +54,7 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor(
) { ) {
sealed interface NavTarget : Parcelable { sealed interface NavTarget : Parcelable {
@Parcelize @Parcelize
data object Root : NavTarget data class Root(val showDeviceVerifiedScreen: Boolean) : NavTarget
@Parcelize @Parcelize
data object EnterRecoveryKey : NavTarget data object EnterRecoveryKey : NavTarget
@ -71,7 +71,7 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor(
override fun onDone() { override fun onDone() {
lifecycleScope.launch { lifecycleScope.launch {
// Move to the completed state view in the verification flow // Move to the completed state view in the verification flow
backstack.newRoot(NavTarget.Root) backstack.newRoot(NavTarget.Root(showDeviceVerifiedScreen = true))
} }
} }
} }
@ -80,6 +80,7 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor(
return when (navTarget) { return when (navTarget) {
is NavTarget.Root -> { is NavTarget.Root -> {
verifySessionEntryPoint.nodeBuilder(this, buildContext) verifySessionEntryPoint.nodeBuilder(this, buildContext)
.params(VerifySessionEntryPoint.Params(navTarget.showDeviceVerifiedScreen))
.callback(object : VerifySessionEntryPoint.Callback { .callback(object : VerifySessionEntryPoint.Callback {
override fun onEnterRecoveryKey() { override fun onEnterRecoveryKey() {
backstack.push(NavTarget.EnterRecoveryKey) backstack.push(NavTarget.EnterRecoveryKey)

4
features/verifysession/api/src/main/kotlin/io/element/android/features/verifysession/api/VerifySessionEntryPoint.kt

@ -20,12 +20,16 @@ import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.core.plugin.Plugin
import io.element.android.libraries.architecture.FeatureEntryPoint import io.element.android.libraries.architecture.FeatureEntryPoint
import io.element.android.libraries.architecture.NodeInputs
interface VerifySessionEntryPoint : FeatureEntryPoint { interface VerifySessionEntryPoint : FeatureEntryPoint {
data class Params(val showDeviceVerifiedScreen: Boolean) : NodeInputs
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
interface NodeBuilder { interface NodeBuilder {
fun callback(callback: Callback): NodeBuilder fun callback(callback: Callback): NodeBuilder
fun params(params: Params): NodeBuilder
fun build(): Node fun build(): Node
} }

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

@ -36,6 +36,11 @@ class DefaultVerifySessionEntryPoint @Inject constructor() : VerifySessionEntryP
return this return this
} }
override fun params(params: VerifySessionEntryPoint.Params): VerifySessionEntryPoint.NodeBuilder {
plugins += params
return this
}
override fun build(): Node { override fun build(): Node {
return parentNode.createNode<VerifySelfSessionNode>(buildContext, plugins) return parentNode.createNode<VerifySelfSessionNode>(buildContext, plugins)
} }

7
features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionNode.kt

@ -30,16 +30,21 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.features.logout.api.util.onSuccessLogout import io.element.android.features.logout.api.util.onSuccessLogout
import io.element.android.features.verifysession.api.VerifySessionEntryPoint import io.element.android.features.verifysession.api.VerifySessionEntryPoint
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ContributesNode(SessionScope::class) @ContributesNode(SessionScope::class)
class VerifySelfSessionNode @AssistedInject constructor( class VerifySelfSessionNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val presenter: VerifySelfSessionPresenter, presenterFactory: VerifySelfSessionPresenter.Factory,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
private val callback = plugins<VerifySessionEntryPoint.Callback>().first() private val callback = plugins<VerifySessionEntryPoint.Callback>().first()
private val presenter = presenterFactory.create(
showDeviceVerifiedScreen = inputs<VerifySessionEntryPoint.Params>().showDeviceVerifiedScreen,
)
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state = presenter.present() val state = presenter.present()

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

@ -28,6 +28,9 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import com.freeletics.flowredux.compose.rememberStateAndDispatch import com.freeletics.flowredux.compose.rememberStateAndDispatch
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.element.android.features.logout.api.LogoutUseCase import io.element.android.features.logout.api.LogoutUseCase
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
@ -37,6 +40,7 @@ import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.matrix.api.verification.VerificationFlowState import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -44,11 +48,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
import io.element.android.features.verifysession.impl.VerifySelfSessionStateMachine.Event as StateMachineEvent import io.element.android.features.verifysession.impl.VerifySelfSessionStateMachine.Event as StateMachineEvent
import io.element.android.features.verifysession.impl.VerifySelfSessionStateMachine.State as StateMachineState import io.element.android.features.verifysession.impl.VerifySelfSessionStateMachine.State as StateMachineState
class VerifySelfSessionPresenter @Inject constructor( class VerifySelfSessionPresenter @AssistedInject constructor(
@Assisted private val showDeviceVerifiedScreen: Boolean,
private val sessionVerificationService: SessionVerificationService, private val sessionVerificationService: SessionVerificationService,
private val encryptionService: EncryptionService, private val encryptionService: EncryptionService,
private val stateMachine: VerifySelfSessionStateMachine, private val stateMachine: VerifySelfSessionStateMachine,
@ -56,6 +60,11 @@ class VerifySelfSessionPresenter @Inject constructor(
private val sessionPreferencesStore: SessionPreferencesStore, private val sessionPreferencesStore: SessionPreferencesStore,
private val logoutUseCase: LogoutUseCase, private val logoutUseCase: LogoutUseCase,
) : Presenter<VerifySelfSessionState> { ) : Presenter<VerifySelfSessionState> {
@AssistedFactory
interface Factory {
fun create(showDeviceVerifiedScreen: Boolean): VerifySelfSessionPresenter
}
@Composable @Composable
override fun present(): VerifySelfSessionState { override fun present(): VerifySelfSessionState {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
@ -66,18 +75,32 @@ class VerifySelfSessionPresenter @Inject constructor(
val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState() val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState()
val stateAndDispatch = stateMachine.rememberStateAndDispatch() val stateAndDispatch = stateMachine.rememberStateAndDispatch()
val skipVerification by sessionPreferencesStore.isSessionVerificationSkipped().collectAsState(initial = false) val skipVerification by sessionPreferencesStore.isSessionVerificationSkipped().collectAsState(initial = false)
val needsVerification by sessionVerificationService.needsSessionVerification.collectAsState(initial = true) val sessionVerifiedStatus by sessionVerificationService.sessionVerifiedStatus.collectAsState()
val signOutAction = remember { val signOutAction = remember {
mutableStateOf<AsyncAction<String?>>(AsyncAction.Uninitialized) mutableStateOf<AsyncAction<String?>>(AsyncAction.Uninitialized)
} }
val verificationFlowStep by remember { val verificationFlowStep by remember {
derivedStateOf { derivedStateOf {
when { if (skipVerification) {
skipVerification -> VerifySelfSessionState.VerificationStep.Skipped VerifySelfSessionState.VerificationStep.Skipped
needsVerification -> stateAndDispatch.state.value.toVerificationStep( } else {
when (sessionVerifiedStatus) {
SessionVerifiedStatus.Unknown -> VerifySelfSessionState.VerificationStep.Loading
SessionVerifiedStatus.NotVerified -> {
stateAndDispatch.state.value.toVerificationStep(
canEnterRecoveryKey = recoveryState == RecoveryState.INCOMPLETE canEnterRecoveryKey = recoveryState == RecoveryState.INCOMPLETE
) )
else -> VerifySelfSessionState.VerificationStep.Completed }
SessionVerifiedStatus.Verified -> {
if (stateAndDispatch.state.value != StateMachineState.Initial || showDeviceVerifiedScreen) {
// The user has verified the session, we need to show the success screen
VerifySelfSessionState.VerificationStep.Completed
} else {
// Automatic verification, which can happen on freshly created account, in this case, skip the screen
VerifySelfSessionState.VerificationStep.Skipped
}
}
}
} }
} }
} }

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

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

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

@ -59,6 +59,12 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
signOutAction = AsyncAction.Loading, signOutAction = AsyncAction.Loading,
displaySkipButton = true, displaySkipButton = true,
), ),
aVerifySelfSessionState(
verificationFlowStep = VerificationStep.Loading
),
aVerifySelfSessionState(
verificationFlowStep = VerificationStep.Skipped
),
// Add other state here // Add other state here
) )
} }

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

@ -19,11 +19,13 @@ package io.element.android.features.verifysession.impl
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@ -57,6 +59,7 @@ import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
@ -99,13 +102,24 @@ fun VerifySelfSessionView(
} }
} }
val verificationFlowStep = state.verificationFlowStep val verificationFlowStep = state.verificationFlowStep
if (state.verificationFlowStep is FlowStep.Loading ||
state.verificationFlowStep is FlowStep.Skipped) {
// Just display a loader in this case, to avoid UI glitch.
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator()
}
} else {
HeaderFooterPage( HeaderFooterPage(
modifier = modifier, modifier = modifier,
topBar = { topBar = {
TopAppBar( TopAppBar(
title = {}, title = {},
actions = { actions = {
if (state.verificationFlowStep != FlowStep.Completed && if (state.verificationFlowStep !is FlowStep.Completed &&
state.displaySkipButton && state.displaySkipButton &&
LocalInspectionMode.current.not()) { LocalInspectionMode.current.not()) {
TextButton( TextButton(
@ -137,6 +151,7 @@ fun VerifySelfSessionView(
) { ) {
Content(flowState = verificationFlowStep) Content(flowState = verificationFlowStep)
} }
}
when (state.signOutAction) { when (state.signOutAction) {
AsyncAction.Loading -> { AsyncAction.Loading -> {
@ -157,6 +172,7 @@ fun VerifySelfSessionView(
@Composable @Composable
private fun HeaderContent(verificationFlowStep: FlowStep) { private fun HeaderContent(verificationFlowStep: FlowStep) {
val iconStyle = when (verificationFlowStep) { val iconStyle = when (verificationFlowStep) {
VerifySelfSessionState.VerificationStep.Loading -> error("Should not happen")
is FlowStep.Initial, FlowStep.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.LockSolid()) is FlowStep.Initial, FlowStep.AwaitingOtherDeviceResponse -> BigIcon.Style.Default(CompoundIcons.LockSolid())
FlowStep.Canceled -> BigIcon.Style.AlertSolid FlowStep.Canceled -> BigIcon.Style.AlertSolid
FlowStep.Ready, is FlowStep.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction()) FlowStep.Ready, is FlowStep.Verifying -> BigIcon.Style.Default(CompoundIcons.Reaction())
@ -164,6 +180,7 @@ private fun HeaderContent(verificationFlowStep: FlowStep) {
is FlowStep.Skipped -> return is FlowStep.Skipped -> return
} }
val titleTextId = when (verificationFlowStep) { val titleTextId = when (verificationFlowStep) {
VerifySelfSessionState.VerificationStep.Loading -> error("Should not happen")
is FlowStep.Initial, FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_title is FlowStep.Initial, FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_title
FlowStep.Canceled -> CommonStrings.common_verification_cancelled FlowStep.Canceled -> CommonStrings.common_verification_cancelled
FlowStep.Ready -> R.string.screen_session_verification_compare_emojis_title FlowStep.Ready -> R.string.screen_session_verification_compare_emojis_title
@ -175,6 +192,7 @@ private fun HeaderContent(verificationFlowStep: FlowStep) {
is FlowStep.Skipped -> return is FlowStep.Skipped -> return
} }
val subtitleTextId = when (verificationFlowStep) { val subtitleTextId = when (verificationFlowStep) {
VerifySelfSessionState.VerificationStep.Loading -> error("Should not happen")
is FlowStep.Initial, FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_subtitle is FlowStep.Initial, FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_identity_confirmation_subtitle
FlowStep.Canceled -> R.string.screen_session_verification_cancelled_subtitle FlowStep.Canceled -> R.string.screen_session_verification_cancelled_subtitle
FlowStep.Ready -> R.string.screen_session_verification_ready_subtitle FlowStep.Ready -> R.string.screen_session_verification_ready_subtitle
@ -268,6 +286,7 @@ private fun BottomMenu(
val isVerifying = (verificationViewState as? FlowStep.Verifying)?.state is AsyncData.Loading<Unit> val isVerifying = (verificationViewState as? FlowStep.Verifying)?.state is AsyncData.Loading<Unit>
when (verificationViewState) { when (verificationViewState) {
VerifySelfSessionState.VerificationStep.Loading -> error("Should not happen")
is FlowStep.Initial -> { is FlowStep.Initial -> {
BottomMenu { BottomMenu {
if (verificationViewState.isLastDevice) { if (verificationViewState.isLastDevice) {

29
features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTest.kt

@ -298,21 +298,42 @@ class VerifySelfSessionPresenterTest {
} }
@Test @Test
fun `present - When verification is not needed, the flow is completed`() = runTest { fun `present - When verification is done using recovery key, the flow is completed`() = runTest {
val service = FakeSessionVerificationService().apply { val service = FakeSessionVerificationService().apply {
givenNeedsSessionVerification(false) givenNeedsSessionVerification(false)
givenVerifiedStatus(SessionVerifiedStatus.Verified) givenVerifiedStatus(SessionVerifiedStatus.Verified)
givenVerificationFlowState(VerificationFlowState.Finished) givenVerificationFlowState(VerificationFlowState.Finished)
} }
val presenter = createVerifySelfSessionPresenter(service) val presenter = createVerifySelfSessionPresenter(
service = service,
showDeviceVerifiedScreen = true,
)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
skipItems(1)
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Completed) assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Completed)
} }
} }
@Test
fun `present - When verification is not needed, the flow is skipped`() = runTest {
val service = FakeSessionVerificationService().apply {
givenNeedsSessionVerification(false)
givenVerifiedStatus(SessionVerifiedStatus.Verified)
givenVerificationFlowState(VerificationFlowState.Finished)
}
val presenter = createVerifySelfSessionPresenter(
service = service,
showDeviceVerifiedScreen = false,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Skipped)
}
}
@Test @Test
fun `present - When user request to sign out, the sign out use case is invoked`() = runTest { fun `present - When user request to sign out, the sign out use case is invoked`() = runTest {
val service = FakeSessionVerificationService().apply { val service = FakeSessionVerificationService().apply {
@ -374,8 +395,10 @@ class VerifySelfSessionPresenterTest {
buildMeta: BuildMeta = aBuildMeta(), buildMeta: BuildMeta = aBuildMeta(),
sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(),
logoutUseCase: LogoutUseCase = FakeLogoutUseCase(), logoutUseCase: LogoutUseCase = FakeLogoutUseCase(),
showDeviceVerifiedScreen: Boolean = false,
): VerifySelfSessionPresenter { ): VerifySelfSessionPresenter {
return VerifySelfSessionPresenter( return VerifySelfSessionPresenter(
showDeviceVerifiedScreen = showDeviceVerifiedScreen,
sessionVerificationService = service, sessionVerificationService = service,
encryptionService = encryptionService, encryptionService = encryptionService,
stateMachine = VerifySelfSessionStateMachine(service, encryptionService), stateMachine = VerifySelfSessionStateMachine(service, encryptionService),

Loading…
Cancel
Save