Render PinViolation above the composer.

This commit is contained in:
Benoit Marty 2024-10-01 17:35:42 +02:00 committed by Benoit Marty
parent 81fc52dcfa
commit c69e5f47e5
18 changed files with 509 additions and 1 deletions

View file

@ -0,0 +1,34 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.api.encryption.identity
enum class IdentityState {
/** The user is verified with us */
Verified,
/**
* Either this is the first identity we have seen for this user, or the
* user has acknowledged a change of identity explicitly e.g. by
* clicking OK on a notification.
*/
Pinned,
/**
* The user's identity has changed since it was pinned. The user should be
* notified about this and given the opportunity to acknowledge the
* change, which will make the new identity pinned.
*/
PinViolation,
/**
* The user's identity has changed, and before that it was verified. This
* is a serious problem. The user can either verify again to make this
* identity verified, or withdraw verification to make it pinned.
*/
VerificationViolation,
}

View file

@ -0,0 +1,15 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.api.encryption.identity
import io.element.android.libraries.matrix.api.core.UserId
data class IdentityStateChange(
val userId: UserId,
val identityState: IdentityState,
)

View file

@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.media.AudioInfo
import io.element.android.libraries.matrix.api.media.FileInfo
import io.element.android.libraries.matrix.api.media.ImageInfo
@ -52,6 +53,7 @@ interface MatrixRoom : Closeable {
val roomInfoFlow: Flow<MatrixRoomInfo>
val roomTypingMembersFlow: Flow<List<UserId>>
val identityStateChangesFlow: Flow<List<IdentityStateChange>>
/**
* A one-to-one is a room with exactly 2 members.

View file

@ -0,0 +1,18 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.mapper
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import org.matrix.rustcomponents.sdk.IdentityState as RustIdentityState
fun RustIdentityState.map(): IdentityState = when (this) {
RustIdentityState.VERIFIED -> IdentityState.Verified
RustIdentityState.PINNED -> IdentityState.Pinned
RustIdentityState.PIN_VIOLATION -> IdentityState.PinViolation
RustIdentityState.VERIFICATION_VIOLATION -> IdentityState.VerificationViolation
}

View file

@ -19,6 +19,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.media.AudioInfo
import io.element.android.libraries.matrix.api.media.FileInfo
import io.element.android.libraries.matrix.api.media.ImageInfo
@ -43,6 +44,7 @@ import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
import io.element.android.libraries.matrix.impl.mapper.map
import io.element.android.libraries.matrix.impl.room.draft.into
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
@ -69,6 +71,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.IdentityStatusChangeListener
import org.matrix.rustcomponents.sdk.RoomInfo
import org.matrix.rustcomponents.sdk.RoomInfoListener
import org.matrix.rustcomponents.sdk.RoomListItem
@ -82,6 +85,7 @@ import timber.log.Timber
import uniffi.matrix_sdk.RoomPowerLevelChanges
import java.io.File
import kotlin.coroutines.cancellation.CancellationException
import org.matrix.rustcomponents.sdk.IdentityStatusChange as RustIdentityStateChange
import org.matrix.rustcomponents.sdk.Room as InnerRoom
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
@ -130,6 +134,23 @@ class RustMatrixRoom(
})
}
override val identityStateChangesFlow: Flow<List<IdentityStateChange>> = mxCallbackFlow {
val initial = emptyList<IdentityStateChange>()
channel.trySend(initial)
innerRoom.subscribeToIdentityStatusChanges(object : IdentityStatusChangeListener {
override fun call(identityStatusChange: List<RustIdentityStateChange>) {
channel.trySend(
identityStatusChange.map {
IdentityStateChange(
userId = UserId(it.userId),
identityState = it.changedTo.map(),
)
}
)
}
})
}
// Create a dispatcher for all room methods...
private val roomDispatcher = coroutineDispatchers.io.limitedParallelism(32)

View file

@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.media.AudioInfo
import io.element.android.libraries.matrix.api.media.FileInfo
import io.element.android.libraries.matrix.api.media.ImageInfo
@ -137,7 +138,7 @@ class FakeMatrixRoom(
private val subscribeToSyncLambda: () -> Unit = { lambdaError() },
private val ignoreDeviceTrustAndResendResult: (Map<UserId, List<DeviceId>>, TransactionId) -> Result<Unit> = { _, _ -> lambdaError() },
private val withdrawVerificationAndResendResult: (List<UserId>, TransactionId) -> Result<Unit> = { _, _ -> lambdaError() },
) : MatrixRoom {
) : MatrixRoom {
private val _roomInfoFlow: MutableSharedFlow<MatrixRoomInfo> = MutableSharedFlow(replay = 1)
override val roomInfoFlow: Flow<MatrixRoomInfo> = _roomInfoFlow
@ -152,6 +153,13 @@ class FakeMatrixRoom(
_roomTypingMembersFlow.tryEmit(typingMembers)
}
private val _identityStateChangesFlow: MutableSharedFlow<List<IdentityStateChange>> = MutableSharedFlow(replay = 1)
override val identityStateChangesFlow: Flow<List<IdentityStateChange>> = _identityStateChangesFlow
fun emitIdentityStateChanges(identityStateChanges: List<IdentityStateChange>) {
_identityStateChangesFlow.tryEmit(identityStateChanges)
}
override val membersStateFlow: MutableStateFlow<MatrixRoomMembersState> = MutableStateFlow(MatrixRoomMembersState.Unknown)
override val roomNotificationSettingsStateFlow: MutableStateFlow<MatrixRoomNotificationSettingsState> =