Update regarding SDK change on verification data
This commit is contained in:
parent
de9645e514
commit
78ce22d458
8 changed files with 105 additions and 48 deletions
|
|
@ -97,7 +97,7 @@ class VerifySelfSessionPresenter @Inject constructor(
|
||||||
is StateMachineState.Verifying.Replying -> Async.Loading()
|
is StateMachineState.Verifying.Replying -> Async.Loading()
|
||||||
else -> Async.Uninitialized
|
else -> Async.Uninitialized
|
||||||
}
|
}
|
||||||
VerifySelfSessionState.VerificationStep.Verifying(machineState.emojis, async)
|
VerifySelfSessionState.VerificationStep.Verifying(machineState.data, async)
|
||||||
}
|
}
|
||||||
|
|
||||||
StateMachineState.Completed -> {
|
StateMachineState.Completed -> {
|
||||||
|
|
@ -116,7 +116,7 @@ class VerifySelfSessionPresenter @Inject constructor(
|
||||||
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidStartSasVerification)
|
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidStartSasVerification)
|
||||||
}
|
}
|
||||||
is VerificationFlowState.ReceivedVerificationData -> {
|
is VerificationFlowState.ReceivedVerificationData -> {
|
||||||
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidReceiveChallenge(verificationAttemptState.emoji))
|
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidReceiveChallenge(verificationAttemptState.data))
|
||||||
}
|
}
|
||||||
VerificationFlowState.Finished -> {
|
VerificationFlowState.Finished -> {
|
||||||
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidAcceptChallenge)
|
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidAcceptChallenge)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.verifysession.impl
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class VerifySelfSessionState(
|
data class VerifySelfSessionState(
|
||||||
|
|
@ -33,7 +33,7 @@ data class VerifySelfSessionState(
|
||||||
data object Canceled : VerificationStep
|
data object Canceled : VerificationStep
|
||||||
data object AwaitingOtherDeviceResponse : VerificationStep
|
data object AwaitingOtherDeviceResponse : VerificationStep
|
||||||
data object Ready : VerificationStep
|
data object Ready : VerificationStep
|
||||||
data class Verifying(val emojiList: List<VerificationEmoji>, val state: Async<Unit>) : VerificationStep
|
data class Verifying(val data: SessionVerificationData, val state: Async<Unit>) : VerificationStep
|
||||||
data object Completed : VerificationStep
|
data object Completed : VerificationStep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@
|
||||||
package io.element.android.features.verifysession.impl
|
package io.element.android.features.verifysession.impl
|
||||||
|
|
||||||
import com.freeletics.flowredux.dsl.FlowReduxStateMachine
|
import com.freeletics.flowredux.dsl.FlowReduxStateMachine
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
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.VerificationEmoji
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import com.freeletics.flowredux.dsl.State as MachineState
|
import com.freeletics.flowredux.dsl.State as MachineState
|
||||||
|
|
@ -70,15 +70,15 @@ class VerifySelfSessionStateMachine @Inject constructor(
|
||||||
}
|
}
|
||||||
inState<State.SasVerificationStarted> {
|
inState<State.SasVerificationStarted> {
|
||||||
on { event: Event.DidReceiveChallenge, state: MachineState<State.SasVerificationStarted> ->
|
on { event: Event.DidReceiveChallenge, state: MachineState<State.SasVerificationStarted> ->
|
||||||
state.override { State.Verifying.ChallengeReceived(event.emojis) }
|
state.override { State.Verifying.ChallengeReceived(event.data) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inState<State.Verifying.ChallengeReceived> {
|
inState<State.Verifying.ChallengeReceived> {
|
||||||
on { _: Event.AcceptChallenge, state: MachineState<State.Verifying.ChallengeReceived> ->
|
on { _: Event.AcceptChallenge, state: MachineState<State.Verifying.ChallengeReceived> ->
|
||||||
state.override { State.Verifying.Replying(state.snapshot.emojis, accept = true) }
|
state.override { State.Verifying.Replying(state.snapshot.data, accept = true) }
|
||||||
}
|
}
|
||||||
on { _: Event.DeclineChallenge, state: MachineState<State.Verifying.ChallengeReceived> ->
|
on { _: Event.DeclineChallenge, state: MachineState<State.Verifying.ChallengeReceived> ->
|
||||||
state.override { State.Verifying.Replying(state.snapshot.emojis, accept = false) }
|
state.override { State.Verifying.Replying(state.snapshot.data, accept = false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inState<State.Verifying.Replying> {
|
inState<State.Verifying.Replying> {
|
||||||
|
|
@ -139,12 +139,12 @@ class VerifySelfSessionStateMachine @Inject constructor(
|
||||||
/** A SaS verification flow has been started. */
|
/** A SaS verification flow has been started. */
|
||||||
data object SasVerificationStarted : State
|
data object SasVerificationStarted : State
|
||||||
|
|
||||||
sealed class Verifying(open val emojis: List<VerificationEmoji>) : State {
|
sealed class Verifying(open val data: SessionVerificationData) : State {
|
||||||
/** Verification accepted and emojis received. */
|
/** Verification accepted and emojis received. */
|
||||||
data class ChallengeReceived(override val emojis: List<VerificationEmoji>) : Verifying(emojis)
|
data class ChallengeReceived(override val data: SessionVerificationData) : Verifying(data)
|
||||||
|
|
||||||
/** Replying to a verification challenge. */
|
/** Replying to a verification challenge. */
|
||||||
data class Replying(override val emojis: List<VerificationEmoji>, val accept: Boolean) : Verifying(emojis)
|
data class Replying(override val data: SessionVerificationData, val accept: Boolean) : Verifying(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The verification is being canceled. */
|
/** The verification is being canceled. */
|
||||||
|
|
@ -170,8 +170,8 @@ class VerifySelfSessionStateMachine @Inject constructor(
|
||||||
/** Started a SaS verification flow. */
|
/** Started a SaS verification flow. */
|
||||||
data object DidStartSasVerification : Event
|
data object DidStartSasVerification : Event
|
||||||
|
|
||||||
/** Has received emojis. */
|
/** Has received data. */
|
||||||
data class DidReceiveChallenge(val emojis: List<VerificationEmoji>) : Event
|
data class DidReceiveChallenge(val data: SessionVerificationData) : Event
|
||||||
|
|
||||||
/** Emojis match. */
|
/** Emojis match. */
|
||||||
data object AcceptChallenge : Event
|
data object AcceptChallenge : Event
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package io.element.android.features.verifysession.impl
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
||||||
|
|
||||||
open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfSessionState> {
|
open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfSessionState> {
|
||||||
|
|
@ -28,10 +29,10 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
|
||||||
verificationFlowStep = VerifySelfSessionState.VerificationStep.AwaitingOtherDeviceResponse
|
verificationFlowStep = VerifySelfSessionState.VerificationStep.AwaitingOtherDeviceResponse
|
||||||
),
|
),
|
||||||
aVerifySelfSessionState().copy(
|
aVerifySelfSessionState().copy(
|
||||||
verificationFlowStep = VerifySelfSessionState.VerificationStep.Verifying(aVerificationEmojiList(), Async.Uninitialized)
|
verificationFlowStep = VerifySelfSessionState.VerificationStep.Verifying(aSessionVerificationData(), Async.Uninitialized)
|
||||||
),
|
),
|
||||||
aVerifySelfSessionState().copy(
|
aVerifySelfSessionState().copy(
|
||||||
verificationFlowStep = VerifySelfSessionState.VerificationStep.Verifying(aVerificationEmojiList(), Async.Loading())
|
verificationFlowStep = VerifySelfSessionState.VerificationStep.Verifying(aSessionVerificationData(), Async.Loading())
|
||||||
),
|
),
|
||||||
aVerifySelfSessionState().copy(
|
aVerifySelfSessionState().copy(
|
||||||
verificationFlowStep = VerifySelfSessionState.VerificationStep.Canceled
|
verificationFlowStep = VerifySelfSessionState.VerificationStep.Canceled
|
||||||
|
|
@ -43,17 +44,28 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider<VerifySelfS
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun aVerifySelfSessionState() = VerifySelfSessionState(
|
private fun aSessionVerificationData(
|
||||||
|
emojiList: List<VerificationEmoji> = aVerificationEmojiList(),
|
||||||
|
decimals: List<Int> = emptyList(),
|
||||||
|
): SessionVerificationData {
|
||||||
|
return if (emojiList.isEmpty()) {
|
||||||
|
SessionVerificationData.Decimals(decimals)
|
||||||
|
} else {
|
||||||
|
SessionVerificationData.Emojis(emojiList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun aVerifySelfSessionState() = VerifySelfSessionState(
|
||||||
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial,
|
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial,
|
||||||
eventSink = {},
|
eventSink = {},
|
||||||
)
|
)
|
||||||
|
|
||||||
fun aVerificationEmojiList() = listOf(
|
private fun aVerificationEmojiList() = listOf(
|
||||||
VerificationEmoji(27, "Pizza"),
|
VerificationEmoji(number = 27, emoji = "🍕", description = "Pizza"),
|
||||||
VerificationEmoji(54, "Rocket"),
|
VerificationEmoji(number = 54, emoji = "🚀", description = "Rocket"),
|
||||||
VerificationEmoji(54, "Rocket"),
|
VerificationEmoji(number = 54, emoji = "🚀", description = "Rocket"),
|
||||||
VerificationEmoji(42, "Book"),
|
VerificationEmoji(number = 42, emoji = "📕", description = "Book"),
|
||||||
VerificationEmoji(48, "Hammer"),
|
VerificationEmoji(number = 48, emoji = "🔨", description = "Hammer"),
|
||||||
VerificationEmoji(48, "Hammer"),
|
VerificationEmoji(number = 48, emoji = "🔨", description = "Hammer"),
|
||||||
VerificationEmoji(63, "Pin"),
|
VerificationEmoji(number = 63, emoji = "📌", description = "Pin"),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ 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.CircularProgressIndicator
|
||||||
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
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep as FlowStep
|
import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep as FlowStep
|
||||||
|
|
@ -141,17 +142,22 @@ private fun ContentWaiting(modifier: Modifier = Modifier) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) {
|
private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) {
|
||||||
// We want each row to have up to 4 emojis
|
when (verificationFlowStep.data) {
|
||||||
val rows = verificationFlowStep.emojiList.chunked(4)
|
is SessionVerificationData.Decimals -> Unit // TODO Render decimals
|
||||||
Column(modifier = modifier.fillMaxWidth()) {
|
is SessionVerificationData.Emojis -> {
|
||||||
for ((rowIndex, emojis) in rows.withIndex()) {
|
// We want each row to have up to 4 emojis
|
||||||
// Vertical spacing between rows
|
val rows = verificationFlowStep.data.emojis.chunked(4)
|
||||||
if (rowIndex > 0) {
|
Column(modifier = modifier.fillMaxWidth()) {
|
||||||
Spacer(modifier = Modifier.height(40.dp))
|
for ((rowIndex, emojis) in rows.withIndex()) {
|
||||||
}
|
// Vertical spacing between rows
|
||||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
|
if (rowIndex > 0) {
|
||||||
for (emoji in emojis) {
|
Spacer(modifier = Modifier.height(40.dp))
|
||||||
EmojiItemView(emoji = emoji, modifier = Modifier.widthIn(max = 60.dp))
|
}
|
||||||
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
|
||||||
|
for (emoji in emojis) {
|
||||||
|
EmojiItemView(emoji = emoji, modifier = Modifier.widthIn(max = 60.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +166,7 @@ private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier:
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) {
|
private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) {
|
||||||
val emojiResource = emoji.code.toEmojiResource()
|
val emojiResource = emoji.number.toEmojiResource()
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.size(48.dp),
|
modifier = Modifier.size(48.dp),
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,24 @@
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.api.verification
|
package io.element.android.libraries.matrix.api.verification
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
sealed interface SessionVerificationData {
|
||||||
|
data class Emojis(
|
||||||
|
// 7 emojis
|
||||||
|
val emojis: List<VerificationEmoji>,
|
||||||
|
) : SessionVerificationData
|
||||||
|
|
||||||
|
data class Decimals(
|
||||||
|
// 3 numbers
|
||||||
|
val decimals: List<Int>,
|
||||||
|
) : SessionVerificationData
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://spec.matrix.org/unstable/client-server-api/#sas-method-emoji
|
||||||
data class VerificationEmoji(
|
data class VerificationEmoji(
|
||||||
val code: Int,
|
val number: Int,
|
||||||
val name: String,
|
val emoji: String,
|
||||||
|
val description: String,
|
||||||
)
|
)
|
||||||
|
|
@ -101,8 +101,8 @@ sealed interface VerificationFlowState {
|
||||||
/** Short Authentication String (SAS) verification started between the 2 devices. */
|
/** Short Authentication String (SAS) verification started between the 2 devices. */
|
||||||
data object StartedSasVerification : VerificationFlowState
|
data object StartedSasVerification : VerificationFlowState
|
||||||
|
|
||||||
/** Verification data for the SAS verification (emojis) received. */
|
/** Verification data for the SAS verification received. */
|
||||||
data class ReceivedVerificationData(val emoji: ImmutableList<VerificationEmoji>) : VerificationFlowState
|
data class ReceivedVerificationData(val data: SessionVerificationData) : VerificationFlowState
|
||||||
|
|
||||||
/** Verification completed successfully. */
|
/** Verification completed successfully. */
|
||||||
data object Finished : VerificationFlowState
|
data object Finished : VerificationFlowState
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@ package io.element.android.libraries.matrix.impl.verification
|
||||||
|
|
||||||
import io.element.android.libraries.core.data.tryOrNull
|
import io.element.android.libraries.core.data.tryOrNull
|
||||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
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.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||||
import io.element.android.libraries.matrix.impl.sync.RustSyncService
|
import io.element.android.libraries.matrix.impl.sync.RustSyncService
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -33,7 +33,8 @@ import kotlinx.coroutines.launch
|
||||||
import org.matrix.rustcomponents.sdk.SessionVerificationController
|
import org.matrix.rustcomponents.sdk.SessionVerificationController
|
||||||
import org.matrix.rustcomponents.sdk.SessionVerificationControllerDelegate
|
import org.matrix.rustcomponents.sdk.SessionVerificationControllerDelegate
|
||||||
import org.matrix.rustcomponents.sdk.SessionVerificationControllerInterface
|
import org.matrix.rustcomponents.sdk.SessionVerificationControllerInterface
|
||||||
import org.matrix.rustcomponents.sdk.SessionVerificationEmoji
|
import org.matrix.rustcomponents.sdk.use
|
||||||
|
import org.matrix.rustcomponents.sdk.SessionVerificationData as RustSessionVerificationData
|
||||||
|
|
||||||
class RustSessionVerificationService(
|
class RustSessionVerificationService(
|
||||||
private val syncService: RustSyncService,
|
private val syncService: RustSyncService,
|
||||||
|
|
@ -105,12 +106,8 @@ class RustSessionVerificationService(
|
||||||
updateVerificationStatus(isVerified = true)
|
updateVerificationStatus(isVerified = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun didReceiveVerificationData(data: List<SessionVerificationEmoji>) {
|
override fun didReceiveVerificationData(data: RustSessionVerificationData) {
|
||||||
val emojis = data.map { emoji ->
|
_verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(data.map())
|
||||||
emoji.use { VerificationEmoji(it.code(), it.description()) }
|
|
||||||
}
|
|
||||||
.toImmutableList()
|
|
||||||
_verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(emojis)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the actual SAS verification starts
|
// When the actual SAS verification starts
|
||||||
|
|
@ -142,3 +139,28 @@ class RustSessionVerificationService(
|
||||||
_sessionVerifiedStatus.value = newValue
|
_sessionVerifiedStatus.value = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun RustSessionVerificationData.map(): SessionVerificationData {
|
||||||
|
return use { sessionVerificationData ->
|
||||||
|
when (sessionVerificationData) {
|
||||||
|
is RustSessionVerificationData.Emojis -> {
|
||||||
|
SessionVerificationData.Emojis(
|
||||||
|
emojis = sessionVerificationData.emojis.mapIndexed { index, emoji ->
|
||||||
|
emoji.use { sessionVerificationEmoji ->
|
||||||
|
VerificationEmoji(
|
||||||
|
number = sessionVerificationData.indices[index].toInt(),
|
||||||
|
emoji = sessionVerificationEmoji.symbol(),
|
||||||
|
description = sessionVerificationEmoji.description(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is RustSessionVerificationData.Decimals -> {
|
||||||
|
SessionVerificationData.Decimals(
|
||||||
|
decimals = sessionVerificationData.values.map { it.toInt() },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue