mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-05 12:54:35 +00:00
Show the account receiving the incoming user verification request
This commit is contained in:
+31
-7
@@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationR
|
|||||||
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
||||||
|
import io.element.android.libraries.matrix.test.A_USER_ID_3
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||||
@@ -83,6 +84,23 @@ class IncomingVerificationRequestObserverTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `incoming user verification request of another session is emitted with its session id`() = runTest {
|
||||||
|
val matrixSessionCache = createMatrixSessionCache()
|
||||||
|
val observer = IncomingVerificationRequestObserver(
|
||||||
|
matrixSessionCache = matrixSessionCache,
|
||||||
|
appForegroundStateService = FakeAppForegroundStateService(),
|
||||||
|
)
|
||||||
|
observer.incomingVerificationRequests().test {
|
||||||
|
matrixSessionCache.getOrRestore(A_SESSION_ID)
|
||||||
|
matrixSessionCache.getOrRestore(A_SESSION_ID_2)
|
||||||
|
runCurrent()
|
||||||
|
val request = anIncomingUserVerificationRequest()
|
||||||
|
sessionVerificationService2.listener!!.onIncomingSessionRequest(request)
|
||||||
|
assertThat(awaitItem()).isEqualTo(IncomingVerificationRequestData(A_SESSION_ID_2, request))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `incoming verification request is emitted when the app goes to foreground`() = runTest {
|
fun `incoming verification request is emitted when the app goes to foreground`() = runTest {
|
||||||
val matrixSessionCache = createMatrixSessionCache()
|
val matrixSessionCache = createMatrixSessionCache()
|
||||||
@@ -156,12 +174,18 @@ class IncomingVerificationRequestObserverTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun anIncomingVerificationRequest() = VerificationRequest.Incoming.OtherSession(
|
private fun anIncomingVerificationRequest() = VerificationRequest.Incoming.OtherSession(
|
||||||
details = SessionVerificationRequestDetails(
|
details = aSessionVerificationRequestDetails(senderProfile = MatrixUser(A_SESSION_ID)),
|
||||||
senderProfile = MatrixUser(A_SESSION_ID),
|
)
|
||||||
flowId = FlowId("flowId"),
|
|
||||||
deviceId = DeviceId("deviceId"),
|
private fun anIncomingUserVerificationRequest() = VerificationRequest.Incoming.User(
|
||||||
deviceDisplayName = "a device name",
|
details = aSessionVerificationRequestDetails(senderProfile = MatrixUser(A_USER_ID_3)),
|
||||||
firstSeenTimestamp = 0,
|
)
|
||||||
)
|
|
||||||
|
private fun aSessionVerificationRequestDetails(senderProfile: MatrixUser) = SessionVerificationRequestDetails(
|
||||||
|
senderProfile = senderProfile,
|
||||||
|
flowId = FlowId("flowId"),
|
||||||
|
deviceId = DeviceId("deviceId"),
|
||||||
|
deviceDisplayName = "a device name",
|
||||||
|
firstSeenTimestamp = 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-20
@@ -33,7 +33,6 @@ import io.element.android.features.verifysession.impl.R
|
|||||||
import io.element.android.features.verifysession.impl.incoming.IncomingVerificationState.Step
|
import io.element.android.features.verifysession.impl.incoming.IncomingVerificationState.Step
|
||||||
import io.element.android.features.verifysession.impl.ui.VerificationBottomMenu
|
import io.element.android.features.verifysession.impl.ui.VerificationBottomMenu
|
||||||
import io.element.android.features.verifysession.impl.ui.VerificationContentVerifying
|
import io.element.android.features.verifysession.impl.ui.VerificationContentVerifying
|
||||||
import io.element.android.features.verifysession.impl.ui.VerificationUserProfileContent
|
|
||||||
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
|
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
|
||||||
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
|
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
|
||||||
import io.element.android.libraries.designsystem.components.BigIcon
|
import io.element.android.libraries.designsystem.components.BigIcon
|
||||||
@@ -41,6 +40,7 @@ import io.element.android.libraries.designsystem.components.button.BackButton
|
|||||||
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.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
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
@@ -169,12 +169,12 @@ private fun ContentInitial(
|
|||||||
stepInitial: Step.Initial,
|
stepInitial: Step.Initial,
|
||||||
request: VerificationRequest.Incoming,
|
request: VerificationRequest.Incoming,
|
||||||
) {
|
) {
|
||||||
when (request) {
|
Column(
|
||||||
is VerificationRequest.Incoming.OtherSession -> {
|
modifier = Modifier.fillMaxWidth(),
|
||||||
Column(
|
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||||
modifier = Modifier.fillMaxWidth(),
|
) {
|
||||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
when (request) {
|
||||||
) {
|
is VerificationRequest.Incoming.OtherSession -> {
|
||||||
AccountInfoCard(
|
AccountInfoCard(
|
||||||
state = AccountInfoCardState(
|
state = AccountInfoCardState(
|
||||||
matrixUser = stepInitial.currentUser,
|
matrixUser = stepInitial.currentUser,
|
||||||
@@ -194,15 +194,15 @@ private fun ContentInitial(
|
|||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
is VerificationRequest.Incoming.User -> {
|
||||||
is VerificationRequest.Incoming.User -> {
|
AccountInfoCard(
|
||||||
Column(
|
state = AccountInfoCardState(
|
||||||
modifier = Modifier
|
matrixUser = stepInitial.currentUser,
|
||||||
.fillMaxWidth()
|
mode = AccountInfoCardMode.UserVerification(
|
||||||
.padding(top = 24.dp),
|
otherUser = request.details.senderProfile,
|
||||||
) {
|
hint = stringResource(R.string.screen_session_verification_user_requesting_verification),
|
||||||
VerificationUserProfileContent(
|
),
|
||||||
user = request.details.senderProfile,
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ private fun IncomingVerificationBottomMenu(
|
|||||||
showProgress = step.isWaiting,
|
showProgress = step.isWaiting,
|
||||||
onClick = { eventSink(IncomingVerificationViewEvent.StartVerification) },
|
onClick = { eventSink(IncomingVerificationViewEvent.StartVerification) },
|
||||||
)
|
)
|
||||||
TextButton(
|
OutlinedButton(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = stringResource(CommonStrings.action_ignore),
|
text = stringResource(CommonStrings.action_ignore),
|
||||||
enabled = !step.isWaiting,
|
enabled = !step.isWaiting,
|
||||||
@@ -269,9 +269,9 @@ private fun IncomingVerificationBottomMenu(
|
|||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun IncomingVerificationViewPreview(@PreviewParameter(
|
internal fun IncomingVerificationViewPreview(
|
||||||
IncomingVerificationStatePreviewParam::class
|
@PreviewParameter(IncomingVerificationStatePreviewParam::class) state: IncomingVerificationState
|
||||||
) state: IncomingVerificationState) = ElementPreview {
|
) = ElementPreview {
|
||||||
IncomingVerificationView(
|
IncomingVerificationView(
|
||||||
state = state,
|
state = state,
|
||||||
)
|
)
|
||||||
|
|||||||
-94
@@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2025 Element Creations Ltd.
|
|
||||||
* Copyright 2025 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.ui
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import io.element.android.compound.theme.ElementTheme
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarType
|
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
|
||||||
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
|
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
|
||||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
|
||||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
|
||||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ref: https://www.figma.com/design/lMrKOhS8BEb75GXVq7FnNI/ER-96--User-Verification-by-Emoji?node-id=116-52049
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun VerificationUserProfileContent(
|
|
||||||
user: MatrixUser,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
|
||||||
val avatarData = remember(user) {
|
|
||||||
user.getAvatarData(AvatarSize.UserVerification)
|
|
||||||
}
|
|
||||||
Row(
|
|
||||||
modifier = modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clip(RoundedCornerShape(8.dp))
|
|
||||||
.background(ElementTheme.colors.bgSubtleSecondary)
|
|
||||||
.padding(12.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
Avatar(
|
|
||||||
avatarData = avatarData,
|
|
||||||
avatarType = AvatarType.User,
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
|
||||||
Text(
|
|
||||||
text = user.getBestName(),
|
|
||||||
style = ElementTheme.typography.fontBodyLgMedium,
|
|
||||||
color = ElementTheme.colors.textPrimary,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (user.displayName.isNullOrEmpty().not()) {
|
|
||||||
Text(
|
|
||||||
text = user.userId.value,
|
|
||||||
style = ElementTheme.typography.fontBodyMdRegular,
|
|
||||||
color = ElementTheme.colors.textSecondary,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreviewsDayNight
|
|
||||||
@Composable
|
|
||||||
internal fun VerificationUserProfileContentPreview() = ElementPreview(
|
|
||||||
drawableFallbackForImages = CommonDrawables.sample_avatar
|
|
||||||
) {
|
|
||||||
VerificationUserProfileContent(
|
|
||||||
user = MatrixUser(
|
|
||||||
userId = UserId("@alice:example.com"),
|
|
||||||
displayName = USER_NAME_ALICE,
|
|
||||||
avatarUrl = "https://example.com/avatar.png",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
<string name="screen_session_verification_use_another_device_title">"Open the app on another verified device"</string>
|
<string name="screen_session_verification_use_another_device_title">"Open the app on another verified device"</string>
|
||||||
<string name="screen_session_verification_user_initiator_subtitle">"For extra security, verify this user by comparing a set of emojis on your devices. Do this by using a trusted way to communicate."</string>
|
<string name="screen_session_verification_user_initiator_subtitle">"For extra security, verify this user by comparing a set of emojis on your devices. Do this by using a trusted way to communicate."</string>
|
||||||
<string name="screen_session_verification_user_initiator_title">"Verify this user?"</string>
|
<string name="screen_session_verification_user_initiator_title">"Verify this user?"</string>
|
||||||
|
<string name="screen_session_verification_user_requesting_verification">"User requesting verification:"</string>
|
||||||
<string name="screen_session_verification_user_responder_subtitle">"For extra security, another user wants to verify your digital identity. You’ll be shown a set of emojis to compare."</string>
|
<string name="screen_session_verification_user_responder_subtitle">"For extra security, another user wants to verify your digital identity. You’ll be shown a set of emojis to compare."</string>
|
||||||
<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>
|
<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>
|
||||||
<string name="screen_session_verification_waiting_another_device_title">"Start verification on the other device"</string>
|
<string name="screen_session_verification_waiting_another_device_title">"Start verification on the other device"</string>
|
||||||
|
|||||||
+27
@@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.test.A_DEVICE_ID
|
|||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.A_TIMESTAMP
|
import io.element.android.libraries.matrix.test.A_TIMESTAMP
|
||||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||||
|
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||||
@@ -49,7 +50,19 @@ class IncomingVerificationPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - the current user is built from the stored session`() = runTest {
|
fun `present - the current user is built from the stored session`() = runTest {
|
||||||
|
assertCurrentUserIsBuiltFromStoredSession(anIncomingSessionVerificationRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - incoming user verification - the current user is built from the stored session`() = runTest {
|
||||||
|
assertCurrentUserIsBuiltFromStoredSession(anIncomingUserVerificationRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun TestScope.assertCurrentUserIsBuiltFromStoredSession(
|
||||||
|
verificationRequest: VerificationRequest.Incoming,
|
||||||
|
) {
|
||||||
createPresenter(
|
createPresenter(
|
||||||
|
verificationRequest = verificationRequest,
|
||||||
service = FakeSessionVerificationService(
|
service = FakeSessionVerificationService(
|
||||||
acknowledgeVerificationRequestLambda = { },
|
acknowledgeVerificationRequestLambda = { },
|
||||||
resetLambda = { },
|
resetLambda = { },
|
||||||
@@ -353,6 +366,20 @@ private val anIncomingSessionVerificationRequest = VerificationRequest.Incoming.
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val anIncomingUserVerificationRequest = VerificationRequest.Incoming.User(
|
||||||
|
details = SessionVerificationRequestDetails(
|
||||||
|
senderProfile = MatrixUser(
|
||||||
|
userId = A_USER_ID_2,
|
||||||
|
displayName = "another user name",
|
||||||
|
avatarUrl = null,
|
||||||
|
),
|
||||||
|
flowId = FlowId("flowId"),
|
||||||
|
deviceId = A_DEVICE_ID,
|
||||||
|
deviceDisplayName = "a device name",
|
||||||
|
firstSeenTimestamp = A_TIMESTAMP,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
internal fun TestScope.createPresenter(
|
internal fun TestScope.createPresenter(
|
||||||
verificationRequest: VerificationRequest.Incoming = anIncomingSessionVerificationRequest,
|
verificationRequest: VerificationRequest.Incoming = anIncomingSessionVerificationRequest,
|
||||||
navigator: IncomingVerificationNavigator = IncomingVerificationNavigator { lambdaError() },
|
navigator: IncomingVerificationNavigator = IncomingVerificationNavigator { lambdaError() },
|
||||||
|
|||||||
-2
@@ -73,8 +73,6 @@ enum class AvatarSize(val dp: Dp) {
|
|||||||
|
|
||||||
DmCreationConfirmation(64.dp),
|
DmCreationConfirmation(64.dp),
|
||||||
|
|
||||||
UserVerification(52.dp),
|
|
||||||
|
|
||||||
OrganizationHeader(64.dp),
|
OrganizationHeader(64.dp),
|
||||||
SpaceHeader(64.dp),
|
SpaceHeader(64.dp),
|
||||||
RoomPreviewHeader(64.dp),
|
RoomPreviewHeader(64.dp),
|
||||||
|
|||||||
+6
-13
@@ -58,19 +58,6 @@ fun AccountInfoCard(
|
|||||||
.border(1.dp, ElementTheme.colors.borderDisabled, RoundedCornerShape(8.dp))
|
.border(1.dp, ElementTheme.colors.borderDisabled, RoundedCornerShape(8.dp))
|
||||||
.padding(20.dp),
|
.padding(20.dp),
|
||||||
) {
|
) {
|
||||||
when (state.mode) {
|
|
||||||
AccountInfoCardMode.Simple -> Unit
|
|
||||||
is AccountInfoCardMode.DeviceVerification -> Unit
|
|
||||||
is AccountInfoCardMode.UserVerification -> {
|
|
||||||
Text(
|
|
||||||
// TODO
|
|
||||||
text = "User requesting verification:",
|
|
||||||
style = ElementTheme.typography.fontBodySmRegular,
|
|
||||||
color = ElementTheme.colors.textSecondary,
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AccountInfoCardUser(
|
AccountInfoCardUser(
|
||||||
matrixUser = state.matrixUser,
|
matrixUser = state.matrixUser,
|
||||||
)
|
)
|
||||||
@@ -82,6 +69,12 @@ fun AccountInfoCard(
|
|||||||
}
|
}
|
||||||
is AccountInfoCardMode.UserVerification -> {
|
is AccountInfoCardMode.UserVerification -> {
|
||||||
AccountInfoSeparator()
|
AccountInfoSeparator()
|
||||||
|
Text(
|
||||||
|
text = state.mode.hint,
|
||||||
|
style = ElementTheme.typography.fontBodySmRegular,
|
||||||
|
color = ElementTheme.colors.textSecondary,
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
AccountInfoCardUser(
|
AccountInfoCardUser(
|
||||||
matrixUser = state.mode.otherUser,
|
matrixUser = state.mode.otherUser,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -22,6 +22,7 @@ sealed interface AccountInfoCardMode {
|
|||||||
|
|
||||||
data class UserVerification(
|
data class UserVerification(
|
||||||
val otherUser: MatrixUser,
|
val otherUser: MatrixUser,
|
||||||
|
val hint: String,
|
||||||
) : AccountInfoCardMode
|
) : AccountInfoCardMode
|
||||||
|
|
||||||
data class DeviceVerification(
|
data class DeviceVerification(
|
||||||
|
|||||||
+1
@@ -20,6 +20,7 @@ open class AccountInfoCardStatePreviewParam : PreviewParameterProvider<AccountIn
|
|||||||
anAccountInfoCardState(
|
anAccountInfoCardState(
|
||||||
mode = AccountInfoCardMode.UserVerification(
|
mode = AccountInfoCardMode.UserVerification(
|
||||||
otherUser = aMatrixUser(displayName = "Other User"),
|
otherUser = aMatrixUser(displayName = "Other User"),
|
||||||
|
hint = "User request verification hint",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
anAccountInfoCardState(
|
anAccountInfoCardState(
|
||||||
|
|||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user