Update "Learn more" link (#4686)

* Update target link for "Learn more".

* Rename VerifySelfSession* to OutgoingVerification*

* Optimize import

* Refactor to avoid long line

* Update screenshots

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Benoit Marty 2025-05-09 11:10:30 +02:00 committed by GitHub
parent 8f484c322f
commit 3391e7cc55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 194 additions and 196 deletions

View file

@ -11,29 +11,29 @@ import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.verifysession.api.VerifySessionEntryPoint
import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.AppScope
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultVerifySessionEntryPoint @Inject constructor() : VerifySessionEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): VerifySessionEntryPoint.NodeBuilder {
class DefaultOutgoingVerificationEntryPoint @Inject constructor() : OutgoingVerificationEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): OutgoingVerificationEntryPoint.NodeBuilder {
val plugins = ArrayList<Plugin>()
return object : VerifySessionEntryPoint.NodeBuilder {
override fun callback(callback: VerifySessionEntryPoint.Callback): VerifySessionEntryPoint.NodeBuilder {
return object : OutgoingVerificationEntryPoint.NodeBuilder {
override fun callback(callback: OutgoingVerificationEntryPoint.Callback): OutgoingVerificationEntryPoint.NodeBuilder {
plugins += callback
return this
}
override fun params(params: VerifySessionEntryPoint.Params): VerifySessionEntryPoint.NodeBuilder {
override fun params(params: OutgoingVerificationEntryPoint.Params): OutgoingVerificationEntryPoint.NodeBuilder {
plugins += params
return this
}
override fun build(): Node {
return parentNode.createNode<VerifySelfSessionNode>(buildContext, plugins)
return parentNode.createNode<OutgoingVerificationNode>(buildContext, plugins)
}
}
}

View file

@ -16,19 +16,19 @@ import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.verifysession.api.VerifySessionEntryPoint
import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.SessionScope
@ContributesNode(SessionScope::class)
class VerifySelfSessionNode @AssistedInject constructor(
class OutgoingVerificationNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
presenterFactory: VerifySelfSessionPresenter.Factory,
presenterFactory: OutgoingVerificationPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
private val callback = plugins<VerifySessionEntryPoint.Callback>().first()
private val callback = plugins<OutgoingVerificationEntryPoint.Callback>().first()
private val inputs = inputs<VerifySessionEntryPoint.Params>()
private val inputs = inputs<OutgoingVerificationEntryPoint.Params>()
private val presenter = presenterFactory.create(
showDeviceVerifiedScreen = inputs.showDeviceVerifiedScreen,
@ -38,7 +38,7 @@ class VerifySelfSessionNode @AssistedInject constructor(
@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
VerifySelfSessionView(
OutgoingVerificationView(
state = state,
modifier = modifier,
onLearnMoreClick = callback::onLearnMoreAboutEncryption,

View file

@ -31,30 +31,30 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import io.element.android.features.verifysession.impl.outgoing.VerifySelfSessionStateMachine.Event as StateMachineEvent
import io.element.android.features.verifysession.impl.outgoing.VerifySelfSessionStateMachine.State as StateMachineState
import io.element.android.features.verifysession.impl.outgoing.OutgoingVerificationStateMachine.Event as StateMachineEvent
import io.element.android.features.verifysession.impl.outgoing.OutgoingVerificationStateMachine.State as StateMachineState
class VerifySelfSessionPresenter @AssistedInject constructor(
class OutgoingVerificationPresenter @AssistedInject constructor(
@Assisted private val showDeviceVerifiedScreen: Boolean,
@Assisted private val verificationRequest: VerificationRequest.Outgoing,
private val sessionVerificationService: SessionVerificationService,
private val encryptionService: EncryptionService,
) : Presenter<VerifySelfSessionState> {
) : Presenter<OutgoingVerificationState> {
@AssistedFactory
interface Factory {
fun create(
verificationRequest: VerificationRequest.Outgoing,
showDeviceVerifiedScreen: Boolean,
): VerifySelfSessionPresenter
): OutgoingVerificationPresenter
}
private val stateMachine = VerifySelfSessionStateMachine(
private val stateMachine = OutgoingVerificationStateMachine(
sessionVerificationService = sessionVerificationService,
encryptionService = encryptionService,
)
@Composable
override fun present(): VerifySelfSessionState {
override fun present(): OutgoingVerificationState {
val stateAndDispatch = stateMachine.rememberStateAndDispatch()
val sessionVerifiedStatus by sessionVerificationService.sessionVerifiedStatus.collectAsState()
@ -63,17 +63,17 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
when (verificationRequest) {
is VerificationRequest.Outgoing.CurrentSession -> {
when (sessionVerifiedStatus) {
SessionVerifiedStatus.Unknown -> VerifySelfSessionState.Step.Loading
SessionVerifiedStatus.Unknown -> OutgoingVerificationState.Step.Loading
SessionVerifiedStatus.NotVerified -> {
stateAndDispatch.state.value.toVerificationStep()
}
SessionVerifiedStatus.Verified -> {
if (stateAndDispatch.state.value != StateMachineState.Initial || showDeviceVerifiedScreen) {
// The user has verified the session, we need to show the success screen
VerifySelfSessionState.Step.Completed
OutgoingVerificationState.Step.Completed
} else {
// Automatic verification, which can happen on freshly created account, in this case, skip the screen
VerifySelfSessionState.Step.Exit
OutgoingVerificationState.Step.Exit
}
}
}
@ -91,42 +91,44 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
observeVerificationService()
}
fun handleEvents(event: VerifySelfSessionViewEvents) {
fun handleEvents(event: OutgoingVerificationViewEvents) {
Timber.d("Verification user action: ${event::class.simpleName}")
when (event) {
// Just relay the event to the state machine
VerifySelfSessionViewEvents.RequestVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.RequestVerification(verificationRequest))
VerifySelfSessionViewEvents.StartSasVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.StartSasVerification)
VerifySelfSessionViewEvents.ConfirmVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.AcceptChallenge)
VerifySelfSessionViewEvents.DeclineVerification -> stateAndDispatch.dispatchAction(StateMachineEvent.DeclineChallenge)
VerifySelfSessionViewEvents.Cancel -> stateAndDispatch.dispatchAction(StateMachineEvent.Cancel)
VerifySelfSessionViewEvents.Reset -> stateAndDispatch.dispatchAction(StateMachineEvent.Reset)
OutgoingVerificationViewEvents.RequestVerification -> StateMachineEvent.RequestVerification(verificationRequest)
OutgoingVerificationViewEvents.StartSasVerification -> StateMachineEvent.StartSasVerification
OutgoingVerificationViewEvents.ConfirmVerification -> StateMachineEvent.AcceptChallenge
OutgoingVerificationViewEvents.DeclineVerification -> StateMachineEvent.DeclineChallenge
OutgoingVerificationViewEvents.Cancel -> StateMachineEvent.Cancel
OutgoingVerificationViewEvents.Reset -> StateMachineEvent.Reset
}.let { stateMachineEvent ->
stateAndDispatch.dispatchAction(stateMachineEvent)
}
}
return VerifySelfSessionState(
return OutgoingVerificationState(
step = step,
request = verificationRequest,
eventSink = ::handleEvents,
)
}
private fun StateMachineState?.toVerificationStep(): VerifySelfSessionState.Step =
private fun StateMachineState?.toVerificationStep(): OutgoingVerificationState.Step =
when (val machineState = this) {
StateMachineState.Initial, null -> {
VerifySelfSessionState.Step.Initial
OutgoingVerificationState.Step.Initial
}
is StateMachineState.RequestingVerification,
is StateMachineState.StartingSasVerification,
StateMachineState.SasVerificationStarted -> {
VerifySelfSessionState.Step.AwaitingOtherDeviceResponse
OutgoingVerificationState.Step.AwaitingOtherDeviceResponse
}
StateMachineState.VerificationRequestAccepted -> {
VerifySelfSessionState.Step.Ready
OutgoingVerificationState.Step.Ready
}
is StateMachineState.Canceled -> {
VerifySelfSessionState.Step.Canceled
OutgoingVerificationState.Step.Canceled
}
is StateMachineState.Verifying -> {
@ -134,15 +136,15 @@ class VerifySelfSessionPresenter @AssistedInject constructor(
is StateMachineState.Verifying.Replying -> AsyncData.Loading()
else -> AsyncData.Uninitialized
}
VerifySelfSessionState.Step.Verifying(machineState.data, async)
OutgoingVerificationState.Step.Verifying(machineState.data, async)
}
StateMachineState.Completed -> {
VerifySelfSessionState.Step.Completed
OutgoingVerificationState.Step.Completed
}
StateMachineState.Exit -> {
VerifySelfSessionState.Step.Exit
OutgoingVerificationState.Step.Exit
}
}

View file

@ -14,10 +14,10 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationD
import io.element.android.libraries.matrix.api.verification.VerificationRequest
@Immutable
data class VerifySelfSessionState(
data class OutgoingVerificationState(
val step: Step,
val request: VerificationRequest.Outgoing,
val eventSink: (VerifySelfSessionViewEvents) -> Unit,
val eventSink: (OutgoingVerificationViewEvents) -> Unit,
) {
@Stable
sealed interface Step {

View file

@ -29,10 +29,10 @@ import kotlin.time.Duration.Companion.seconds
import com.freeletics.flowredux.dsl.State as MachineState
@OptIn(FlowPreview::class)
class VerifySelfSessionStateMachine(
class OutgoingVerificationStateMachine(
private val sessionVerificationService: SessionVerificationService,
private val encryptionService: EncryptionService,
) : FlowReduxStateMachine<VerifySelfSessionStateMachine.State, VerifySelfSessionStateMachine.Event>(
) : FlowReduxStateMachine<OutgoingVerificationStateMachine.State, OutgoingVerificationStateMachine.Event>(
initialState = State.Initial,
) {
init {

View file

@ -8,64 +8,64 @@
package io.element.android.features.verifysession.impl.outgoing
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.verifysession.impl.outgoing.VerifySelfSessionState.Step
import io.element.android.features.verifysession.impl.outgoing.OutgoingVerificationState.Step
import io.element.android.features.verifysession.impl.ui.aDecimalsSessionVerificationData
import io.element.android.features.verifysession.impl.ui.aEmojisSessionVerificationData
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.verification.VerificationRequest
open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfSessionState> {
override val values: Sequence<VerifySelfSessionState>
open class OutgoingVerificationStateProvider : PreviewParameterProvider<OutgoingVerificationState> {
override val values: Sequence<OutgoingVerificationState>
get() = sequenceOf(
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Initial,
request = anOutgoingSessionVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Initial,
request = anOutgoingUserVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.AwaitingOtherDeviceResponse,
request = anOutgoingSessionVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.AwaitingOtherDeviceResponse,
request = anOutgoingUserVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Verifying(aEmojisSessionVerificationData(), AsyncData.Uninitialized),
request = anOutgoingSessionVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Verifying(aEmojisSessionVerificationData(), AsyncData.Uninitialized),
request = anOutgoingUserVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Verifying(aEmojisSessionVerificationData(), AsyncData.Loading())
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Canceled
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Ready
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Verifying(aDecimalsSessionVerificationData(), AsyncData.Uninitialized)
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Completed,
request = anOutgoingSessionVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Completed,
request = anOutgoingUserVerificationRequest(),
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Loading
),
aVerifySelfSessionState(
anOutgoingVerificationState(
step = Step.Exit
),
// Add other state here
@ -75,11 +75,11 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
internal fun anOutgoingUserVerificationRequest() = VerificationRequest.Outgoing.User(userId = UserId("@alice:example.com"))
internal fun anOutgoingSessionVerificationRequest() = VerificationRequest.Outgoing.CurrentSession
internal fun aVerifySelfSessionState(
internal fun anOutgoingVerificationState(
step: Step = Step.Initial,
request: VerificationRequest.Outgoing = anOutgoingSessionVerificationRequest(),
eventSink: (VerifySelfSessionViewEvents) -> Unit = {},
) = VerifySelfSessionState(
eventSink: (OutgoingVerificationViewEvents) -> Unit = {},
) = OutgoingVerificationState(
step = step,
request = request,
eventSink = eventSink,

View file

@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.verifysession.impl.R
import io.element.android.features.verifysession.impl.outgoing.VerifySelfSessionState.Step
import io.element.android.features.verifysession.impl.outgoing.OutgoingVerificationState.Step
import io.element.android.features.verifysession.impl.ui.VerificationBottomMenu
import io.element.android.features.verifysession.impl.ui.VerificationContentVerifying
import io.element.android.libraries.architecture.AsyncData
@ -49,8 +49,8 @@ import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun VerifySelfSessionView(
state: VerifySelfSessionState,
fun OutgoingVerificationView(
state: OutgoingVerificationState,
onLearnMoreClick: () -> Unit,
onFinish: () -> Unit,
onBack: () -> Unit,
@ -59,12 +59,12 @@ fun VerifySelfSessionView(
val step = state.step
fun cancelOrResetFlow() {
when (step) {
is Step.Canceled -> state.eventSink(VerifySelfSessionViewEvents.Reset)
is Step.Canceled -> state.eventSink(OutgoingVerificationViewEvents.Reset)
Step.Initial, Step.Completed -> onBack()
Step.Ready, is Step.AwaitingOtherDeviceResponse -> state.eventSink(VerifySelfSessionViewEvents.Cancel)
Step.Ready, is Step.AwaitingOtherDeviceResponse -> state.eventSink(OutgoingVerificationViewEvents.Cancel)
is Step.Verifying -> {
if (!step.state.isLoading()) {
state.eventSink(VerifySelfSessionViewEvents.DeclineVerification)
state.eventSink(OutgoingVerificationViewEvents.DeclineVerification)
}
}
else -> Unit
@ -98,10 +98,10 @@ fun VerifySelfSessionView(
)
},
header = {
VerifySelfSessionHeader(step = step, request = state.request)
OutgoingVerificationHeader(step = step, request = state.request)
},
footer = {
VerifySelfSessionBottomMenu(
OutgoingVerificationViewBottomMenu(
screenState = state,
onCancelClick = ::cancelOrResetFlow,
onContinueClick = onFinish,
@ -109,7 +109,7 @@ fun VerifySelfSessionView(
},
isScrollable = true,
) {
VerifySelfSessionContent(
OutgoingVerificationContent(
flowState = step,
request = state.request,
onLearnMoreClick = onLearnMoreClick,
@ -119,7 +119,7 @@ fun VerifySelfSessionView(
}
@Composable
private fun VerifySelfSessionHeader(step: Step, request: VerificationRequest.Outgoing) {
private fun OutgoingVerificationHeader(step: Step, request: VerificationRequest.Outgoing) {
val iconStyle = when (step) {
Step.Loading -> error("Should not happen")
Step.Initial -> when (request) {
@ -189,7 +189,7 @@ private fun VerifySelfSessionHeader(step: Step, request: VerificationRequest.Out
}
@Composable
private fun VerifySelfSessionContent(
private fun OutgoingVerificationContent(
flowState: Step,
request: VerificationRequest.Outgoing,
onLearnMoreClick: () -> Unit,
@ -227,8 +227,8 @@ private fun ContentInitial(
}
@Composable
private fun VerifySelfSessionBottomMenu(
screenState: VerifySelfSessionState,
private fun OutgoingVerificationViewBottomMenu(
screenState: OutgoingVerificationState,
onCancelClick: () -> Unit,
onContinueClick: () -> Unit,
) {
@ -244,7 +244,7 @@ private fun VerifySelfSessionBottomMenu(
Button(
modifier = Modifier.fillMaxWidth(),
text = stringResource(CommonStrings.action_start_verification),
onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) },
onClick = { eventSink(OutgoingVerificationViewEvents.RequestVerification) },
)
InvisibleButton()
}
@ -264,7 +264,7 @@ private fun VerifySelfSessionBottomMenu(
Button(
modifier = Modifier.fillMaxWidth(),
text = stringResource(CommonStrings.action_start),
onClick = { eventSink(VerifySelfSessionViewEvents.StartSasVerification) },
onClick = { eventSink(OutgoingVerificationViewEvents.StartSasVerification) },
)
TextButton(
modifier = Modifier.fillMaxWidth(),
@ -287,14 +287,14 @@ private fun VerifySelfSessionBottomMenu(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.screen_session_verification_they_match),
onClick = {
eventSink(VerifySelfSessionViewEvents.ConfirmVerification)
eventSink(OutgoingVerificationViewEvents.ConfirmVerification)
},
)
TextButton(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.screen_session_verification_they_dont_match),
onClick = { eventSink(VerifySelfSessionViewEvents.DeclineVerification) },
onClick = { eventSink(OutgoingVerificationViewEvents.DeclineVerification) },
)
}
}
@ -315,8 +315,8 @@ private fun VerifySelfSessionBottomMenu(
@PreviewsDayNight
@Composable
internal fun VerifySelfSessionViewPreview(@PreviewParameter(VerifySelfSessionStateProvider::class) state: VerifySelfSessionState) = ElementPreview {
VerifySelfSessionView(
internal fun OutgoingVerificationViewPreview(@PreviewParameter(OutgoingVerificationStateProvider::class) state: OutgoingVerificationState) = ElementPreview {
OutgoingVerificationView(
state = state,
onLearnMoreClick = {},
onFinish = {},

View file

@ -0,0 +1,17 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.verifysession.impl.outgoing
sealed interface OutgoingVerificationViewEvents {
data object RequestVerification : OutgoingVerificationViewEvents
data object StartSasVerification : OutgoingVerificationViewEvents
data object ConfirmVerification : OutgoingVerificationViewEvents
data object DeclineVerification : OutgoingVerificationViewEvents
data object Cancel : OutgoingVerificationViewEvents
data object Reset : OutgoingVerificationViewEvents
}

View file

@ -1,17 +0,0 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.verifysession.impl.outgoing
sealed interface VerifySelfSessionViewEvents {
data object RequestVerification : VerifySelfSessionViewEvents
data object StartSasVerification : VerifySelfSessionViewEvents
data object ConfirmVerification : VerifySelfSessionViewEvents
data object DeclineVerification : VerifySelfSessionViewEvents
data object Cancel : VerifySelfSessionViewEvents
data object Reset : VerifySelfSessionViewEvents
}