Merge pull request #4212 from element-hq/feature/fga/room_settings_security_privacy

Feature : room settings - security and privacy
This commit is contained in:
ganfra 2025-01-29 17:29:56 +01:00 committed by GitHub
commit c689809b55
125 changed files with 3387 additions and 347 deletions

View file

@ -8,6 +8,8 @@
package io.element.android.libraries.matrix.api.createroom
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import java.util.Optional
data class CreateRoomParameters(
@ -19,6 +21,6 @@ data class CreateRoomParameters(
val preset: RoomPreset,
val invite: List<UserId>? = null,
val avatar: String? = null,
val joinRuleOverride: JoinRuleOverride = JoinRuleOverride.None,
val joinRuleOverride: JoinRule? = null,
val roomAliasName: Optional<String> = Optional.empty(),
)

View file

@ -1,16 +0,0 @@
/*
* Copyright 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.libraries.matrix.api.createroom
/**
* Rules to override the default room join rules.
*/
sealed interface JoinRuleOverride {
data object Knock : JoinRuleOverride
data object None : JoinRuleOverride
}

View file

@ -1,12 +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.libraries.matrix.api.createroom
enum class RoomVisibility {
PUBLIC,
PRIVATE,
}

View file

@ -24,10 +24,13 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.knock.KnockRequest
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
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.timeline.item.event.EventOrTransactionId
@ -43,7 +46,7 @@ interface MatrixRoom : Closeable {
val sessionId: SessionId
val roomId: RoomId
val displayName: String
val alias: RoomAlias?
val canonicalAlias: RoomAlias?
val alternativeAliases: List<RoomAlias>
val topic: String?
val avatarUrl: String?
@ -403,4 +406,60 @@ interface MatrixRoom : Closeable {
suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle): Result<Unit>
override fun close() = destroy()
/**
* Update the canonical alias of the room.
*
* Note that publishing the alias in the room directory is done separately.
*/
suspend fun updateCanonicalAlias(
canonicalAlias: RoomAlias?,
alternativeAliases: List<RoomAlias>
): Result<Unit>
/**
* Update the room's visibility in the room directory.
*/
suspend fun updateRoomVisibility(roomVisibility: RoomVisibility): Result<Unit>
/**
* Update room history visibility for this room.
*/
suspend fun updateHistoryVisibility(historyVisibility: RoomHistoryVisibility): Result<Unit>
/**
* Returns the visibility for this room in the room directory.
* If the room is not published, the result will be [RoomVisibility.Private].
*/
suspend fun getRoomVisibility(): Result<RoomVisibility>
/**
* Publish a new room alias for this room in the room directory.
*
* Returns:
* - `true` if the room alias didn't exist and it's now published.
* - `false` if the room alias was already present so it couldn't be
* published.
*/
suspend fun publishRoomAliasInRoomDirectory(roomAlias: RoomAlias): Result<Boolean>
/**
* Remove an existing room alias for this room in the room directory.
*
* Returns:
* - `true` if the room alias was present and it's now removed from the
* room directory.
* - `false` if the room alias didn't exist so it couldn't be removed.
*/
suspend fun removeRoomAliasFromRoomDirectory(roomAlias: RoomAlias): Result<Boolean>
/**
* Enable End-to-end encryption in this room.
*/
suspend fun enableEncryption(): Result<Unit>
/**
* Update the join rule for this room.
*/
suspend fun updateJoinRule(joinRule: JoinRule): Result<Unit>
}

View file

@ -12,6 +12,7 @@ import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.ImmutableList
@ -71,6 +72,7 @@ data class MatrixRoomInfo(
val heroes: ImmutableList<MatrixUser>,
val pinnedEventIds: ImmutableList<EventId>,
val creator: UserId?,
val historyVisibility: RoomHistoryVisibility,
) {
val aliases: List<RoomAlias>
get() = listOfNotNull(canonicalAlias) + alternativeAliases

View file

@ -19,7 +19,7 @@ fun MatrixRoom.matches(roomIdOrAlias: RoomIdOrAlias): Boolean {
roomIdOrAlias.roomId == roomId
}
is RoomIdOrAlias.Alias -> {
roomIdOrAlias.roomAlias == alias || roomIdOrAlias.roomAlias in alternativeAliases
roomIdOrAlias.roomAlias == canonicalAlias || roomIdOrAlias.roomAlias in alternativeAliases
}
}
}

View file

@ -0,0 +1,47 @@
/*
* 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.libraries.matrix.api.room.history
sealed interface RoomHistoryVisibility {
/**
* Previous events are accessible to newly joined members from the point
* they were invited onwards.
*
* Events stop being accessible when the member's state changes to
* something other than *invite* or *join*.
*/
data object Invited : RoomHistoryVisibility
/**
* Previous events are accessible to newly joined members from the point
* they joined the room onwards.
* Events stop being accessible when the member's state changes to
* something other than *join*.
*/
data object Joined : RoomHistoryVisibility
/**
* Previous events are always accessible to newly joined members.
*
* All events in the room are accessible, even those sent when the member
* was not a part of the room.
*/
data object Shared : RoomHistoryVisibility
/**
* All events while this is the `HistoryVisibility` value may be shared by
* any participating homeserver with anyone, regardless of whether they
* have ever joined the room.
*/
data object WorldReadable : RoomHistoryVisibility
/**
* A custom visibility value.
*/
data class Custom(val value: String) : RoomHistoryVisibility
}

View file

@ -0,0 +1,28 @@
/*
* 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.libraries.matrix.api.roomdirectory
/**
* Enum class representing the visibility of a room in the room directory.
*/
sealed interface RoomVisibility {
/**
* Indicates that the room will be shown in the published room list.
*/
data object Public : RoomVisibility
/**
* Indicates that the room will not be shown in the published room list.
*/
data object Private : RoomVisibility
/**
* A custom value that's not present in the spec.
*/
data class Custom(val value: String) : RoomVisibility
}

View file

@ -23,9 +23,7 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride
import io.element.android.libraries.matrix.api.createroom.RoomPreset
import io.element.android.libraries.matrix.api.createroom.RoomVisibility
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.notification.NotificationService
@ -38,8 +36,10 @@ import io.element.android.libraries.matrix.api.room.PendingRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
@ -59,8 +59,10 @@ import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber
import io.element.android.libraries.matrix.impl.room.RustRoomFactory
import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper
import io.element.android.libraries.matrix.impl.roomdirectory.RustRoomDirectoryService
import io.element.android.libraries.matrix.impl.roomdirectory.map
import io.element.android.libraries.matrix.impl.roomlist.RoomListFactory
import io.element.android.libraries.matrix.impl.roomlist.RustRoomListService
import io.element.android.libraries.matrix.impl.sync.RustSyncService
@ -112,9 +114,7 @@ import kotlin.jvm.optionals.getOrNull
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParameters
import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset
import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService
class RustMatrixClient(
@ -310,36 +310,23 @@ class RustMatrixClient(
topic = createRoomParams.topic,
isEncrypted = createRoomParams.isEncrypted,
isDirect = createRoomParams.isDirect,
visibility = when (createRoomParams.visibility) {
RoomVisibility.PUBLIC -> RustRoomVisibility.Public
RoomVisibility.PRIVATE -> RustRoomVisibility.Private
},
preset = when (createRoomParams.visibility) {
RoomVisibility.PRIVATE -> {
if (createRoomParams.isDirect) {
RustRoomPreset.TRUSTED_PRIVATE_CHAT
} else {
RustRoomPreset.PRIVATE_CHAT
}
}
RoomVisibility.PUBLIC -> {
RustRoomPreset.PUBLIC_CHAT
}
visibility = createRoomParams.visibility.map(),
preset = when (createRoomParams.preset) {
RoomPreset.PRIVATE_CHAT -> RustRoomPreset.PRIVATE_CHAT
RoomPreset.TRUSTED_PRIVATE_CHAT -> RustRoomPreset.TRUSTED_PRIVATE_CHAT
RoomPreset.PUBLIC_CHAT -> RustRoomPreset.PUBLIC_CHAT
},
invite = createRoomParams.invite?.map { it.value },
avatar = createRoomParams.avatar,
powerLevelContentOverride = defaultRoomCreationPowerLevels.copy(
invite = if (createRoomParams.joinRuleOverride == JoinRuleOverride.Knock) {
invite = if (createRoomParams.joinRuleOverride == JoinRule.Knock) {
// override the invite power level so it's the same as kick.
RoomMember.Role.MODERATOR.powerLevel.toInt()
} else {
null
}
),
joinRuleOverride = when (createRoomParams.joinRuleOverride) {
JoinRuleOverride.Knock -> RustJoinRule.Knock
JoinRuleOverride.None -> null
},
joinRuleOverride = createRoomParams.joinRuleOverride?.map(),
canonicalAlias = createRoomParams.roomAliasName.getOrNull(),
)
val roomId = RoomId(innerClient.createRoom(rustParams))
@ -358,7 +345,7 @@ class RustMatrixClient(
name = null,
isEncrypted = true,
isDirect = true,
visibility = RoomVisibility.PRIVATE,
visibility = RoomVisibility.Private,
preset = RoomPreset.TRUSTED_PRIVATE_CHAT,
invite = listOf(userId),
)

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.room.history.map
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import kotlinx.collections.immutable.ImmutableMap
@ -60,6 +61,7 @@ class MatrixRoomInfoMapper {
numUnreadMessages = it.numUnreadMessages.toLong(),
numUnreadMentions = it.numUnreadMentions.toLong(),
numUnreadNotifications = it.numUnreadNotifications.toLong(),
historyVisibility = it.historyVisibility.map(),
)
}
}

View file

@ -38,11 +38,14 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.knock.KnockRequest
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
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.timeline.item.event.EventOrTransactionId
@ -51,10 +54,13 @@ import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
import io.element.android.libraries.matrix.impl.core.RustSendHandle
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.history.map
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.knock.RustKnockRequest
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsMapper
import io.element.android.libraries.matrix.impl.roomdirectory.map
import io.element.android.libraries.matrix.impl.timeline.RustTimeline
import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType
import io.element.android.libraries.matrix.impl.util.MessageEventContent
@ -101,6 +107,7 @@ import org.matrix.rustcomponents.sdk.KnockRequest as InnerKnockRequest
import org.matrix.rustcomponents.sdk.Room as InnerRoom
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
@Suppress("LargeClass")
class RustMatrixRoom(
override val sessionId: SessionId,
private val deviceId: DeviceId,
@ -306,7 +313,7 @@ class RustMatrixRoom(
override val isEncrypted: Boolean
get() = runCatching { innerRoom.isEncrypted() }.getOrDefault(false)
override val alias: RoomAlias?
override val canonicalAlias: RoomAlias?
get() = runCatching { innerRoom.canonicalAlias()?.let(::RoomAlias) }.getOrDefault(null)
override val alternativeAliases: List<RoomAlias>
@ -805,6 +812,54 @@ class RustMatrixRoom(
}
}
override suspend fun updateCanonicalAlias(canonicalAlias: RoomAlias?, alternativeAliases: List<RoomAlias>): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateCanonicalAlias(canonicalAlias?.value, alternativeAliases.map { it.value })
}
}
override suspend fun publishRoomAliasInRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = withContext(roomDispatcher) {
runCatching {
innerRoom.publishRoomAliasInRoomDirectory(roomAlias.value)
}
}
override suspend fun removeRoomAliasFromRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = withContext(roomDispatcher) {
runCatching {
innerRoom.removeRoomAliasFromRoomDirectory(roomAlias.value)
}
}
override suspend fun updateRoomVisibility(roomVisibility: RoomVisibility): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateRoomVisibility(roomVisibility.map())
}
}
override suspend fun updateHistoryVisibility(historyVisibility: RoomHistoryVisibility): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateHistoryVisibility(historyVisibility.map())
}
}
override suspend fun getRoomVisibility(): Result<RoomVisibility> = withContext(roomDispatcher) {
runCatching {
innerRoom.getRoomVisibility().map()
}
}
override suspend fun enableEncryption(): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.enableEncryption()
}
}
override suspend fun updateJoinRule(joinRule: JoinRule): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateJoinRules(joinRule.map())
}
}
private fun createTimeline(
timeline: InnerTimeline,
mode: Timeline.Mode,

View file

@ -0,0 +1,31 @@
/*
* 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.libraries.matrix.impl.room.history
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
fun RoomHistoryVisibility.map(): RustRoomHistoryVisibility {
return when (this) {
RoomHistoryVisibility.WorldReadable -> RustRoomHistoryVisibility.WorldReadable
RoomHistoryVisibility.Invited -> RustRoomHistoryVisibility.Invited
RoomHistoryVisibility.Joined -> RustRoomHistoryVisibility.Joined
RoomHistoryVisibility.Shared -> RustRoomHistoryVisibility.Shared
is RoomHistoryVisibility.Custom -> RustRoomHistoryVisibility.Custom(value)
}
}
fun RustRoomHistoryVisibility.map(): RoomHistoryVisibility {
return when (this) {
RustRoomHistoryVisibility.WorldReadable -> RoomHistoryVisibility.WorldReadable
RustRoomHistoryVisibility.Invited -> RoomHistoryVisibility.Invited
RustRoomHistoryVisibility.Joined -> RoomHistoryVisibility.Joined
RustRoomHistoryVisibility.Shared -> RoomHistoryVisibility.Shared
is RustRoomHistoryVisibility.Custom -> RoomHistoryVisibility.Custom(value)
}
}

View file

@ -17,3 +17,10 @@ fun RustAllowRule.map(): AllowRule {
is RustAllowRule.Custom -> AllowRule.Custom(json)
}
}
fun AllowRule.map(): RustAllowRule {
return when (this) {
is AllowRule.RoomMembership -> RustAllowRule.RoomMembership(roomId.toString())
is AllowRule.Custom -> RustAllowRule.Custom(json)
}
}

View file

@ -21,3 +21,15 @@ fun RustJoinRule.map(): JoinRule {
is RustJoinRule.KnockRestricted -> JoinRule.KnockRestricted(rules.map { it.map() })
}
}
fun JoinRule.map(): RustJoinRule {
return when (this) {
JoinRule.Public -> RustJoinRule.Public
JoinRule.Private -> RustJoinRule.Private
JoinRule.Knock -> RustJoinRule.Knock
JoinRule.Invite -> RustJoinRule.Invite
is JoinRule.Restricted -> RustJoinRule.Restricted(rules.map { it.map() })
is JoinRule.Custom -> RustJoinRule.Custom(value)
is JoinRule.KnockRestricted -> RustJoinRule.KnockRestricted(rules.map { it.map() })
}
}

View file

@ -0,0 +1,27 @@
/*
* 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.libraries.matrix.impl.roomdirectory
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
fun RoomVisibility.map(): RustRoomVisibility {
return when (this) {
RoomVisibility.Public -> RustRoomVisibility.Public
RoomVisibility.Private -> RustRoomVisibility.Private
is RoomVisibility.Custom -> RustRoomVisibility.Custom(value)
}
}
fun RustRoomVisibility.map(): RoomVisibility {
return when (this) {
RustRoomVisibility.Public -> RoomVisibility.Public
RustRoomVisibility.Private -> RoomVisibility.Private
is RustRoomVisibility.Custom -> RoomVisibility.Custom(value)
}
}

View file

@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero
@ -33,6 +34,7 @@ import kotlinx.collections.immutable.toPersistentList
import org.junit.Test
import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
class MatrixRoomInfoMapperTest {
@ -72,6 +74,7 @@ class MatrixRoomInfoMapperTest {
numUnreadMentions = 14uL,
pinnedEventIds = listOf(AN_EVENT_ID.value),
roomCreator = A_USER_ID,
historyVisibility = RustRoomHistoryVisibility.Joined,
)
)
).isEqualTo(
@ -113,6 +116,7 @@ class MatrixRoomInfoMapperTest {
numUnreadMessages = 12L,
numUnreadNotifications = 13L,
numUnreadMentions = 14L,
historyVisibility = RoomHistoryVisibility.Joined,
)
)
}
@ -188,6 +192,7 @@ class MatrixRoomInfoMapperTest {
numUnreadMessages = 12L,
numUnreadNotifications = 13L,
numUnreadMentions = 14L,
historyVisibility = RoomHistoryVisibility.Joined,
)
)
}

View file

@ -33,10 +33,13 @@ import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.knock.KnockRequest
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
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.timeline.item.event.EventOrTransactionId
@ -66,7 +69,7 @@ class FakeMatrixRoom(
override val topic: String? = null,
override val avatarUrl: String? = null,
override var isEncrypted: Boolean = false,
override val alias: RoomAlias? = null,
override val canonicalAlias: RoomAlias? = null,
override val alternativeAliases: List<RoomAlias> = emptyList(),
override val isPublic: Boolean = true,
override val isSpace: Boolean = false,
@ -145,6 +148,14 @@ class FakeMatrixRoom(
private val subscribeToSyncLambda: () -> Unit = { lambdaError() },
private val ignoreDeviceTrustAndResendResult: (Map<UserId, List<DeviceId>>, SendHandle) -> Result<Unit> = { _, _ -> lambdaError() },
private val withdrawVerificationAndResendResult: (List<UserId>, SendHandle) -> Result<Unit> = { _, _ -> lambdaError() },
private val updateCanonicalAliasResult: (RoomAlias?, List<RoomAlias>) -> Result<Unit> = { _, _ -> lambdaError() },
private val updateRoomVisibilityResult: (RoomVisibility) -> Result<Unit> = { lambdaError() },
private val updateRoomHistoryVisibilityResult: (RoomHistoryVisibility) -> Result<Unit> = { lambdaError() },
private val roomVisibilityResult: () -> Result<RoomVisibility> = { lambdaError() },
private val publishRoomAliasInRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
private val removeRoomAliasFromRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
private val enableEncryptionResult: () -> Result<Unit> = { lambdaError() },
private val updateJoinRuleResult: (JoinRule) -> Result<Unit> = { lambdaError() },
) : MatrixRoom {
private val _roomInfoFlow: MutableSharedFlow<MatrixRoomInfo> = MutableSharedFlow(replay = 1)
override val roomInfoFlow: Flow<MatrixRoomInfo> = _roomInfoFlow
@ -195,9 +206,11 @@ class FakeMatrixRoom(
return Result.success(Unit)
}
fun enableEncryption() {
isEncrypted = true
emitSyncUpdate()
override suspend fun enableEncryption(): Result<Unit> = simulateLongTask {
enableEncryptionResult().onSuccess {
isEncrypted = true
emitSyncUpdate()
}
}
private val _syncUpdateFlow = MutableStateFlow(0L)
@ -582,6 +595,34 @@ class FakeMatrixRoom(
return withdrawVerificationAndResendResult(userIds, sendHandle)
}
override suspend fun updateCanonicalAlias(canonicalAlias: RoomAlias?, alternativeAliases: List<RoomAlias>): Result<Unit> = simulateLongTask {
updateCanonicalAliasResult(canonicalAlias, alternativeAliases)
}
override suspend fun updateRoomVisibility(roomVisibility: RoomVisibility): Result<Unit> = simulateLongTask {
updateRoomVisibilityResult(roomVisibility)
}
override suspend fun updateHistoryVisibility(historyVisibility: RoomHistoryVisibility): Result<Unit> = simulateLongTask {
updateRoomHistoryVisibilityResult(historyVisibility)
}
override suspend fun getRoomVisibility(): Result<RoomVisibility> = simulateLongTask {
roomVisibilityResult()
}
override suspend fun publishRoomAliasInRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = simulateLongTask {
publishRoomAliasInRoomDirectoryResult(roomAlias)
}
override suspend fun removeRoomAliasFromRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = simulateLongTask {
removeRoomAliasFromRoomDirectoryResult(roomAlias)
}
override suspend fun updateJoinRule(joinRule: JoinRule): Result<Unit> = simulateLongTask {
updateJoinRuleResult(joinRule)
}
fun givenRoomMembersState(state: MatrixRoomMembersState) {
membersStateFlow.value = state
}

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
@ -58,6 +59,7 @@ fun aRoomInfo(
numUnreadMessages: Long = 0,
numUnreadNotifications: Long = 0,
numUnreadMentions: Long = 0,
historyVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Joined,
) = MatrixRoomInfo(
id = id,
name = name,
@ -90,4 +92,5 @@ fun aRoomInfo(
numUnreadMessages = numUnreadMessages,
numUnreadNotifications = numUnreadNotifications,
numUnreadMentions = numUnreadMentions,
historyVisibility = historyVisibility,
)

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.message.RoomMessage
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
@ -71,6 +72,7 @@ fun aRoomSummary(
numUnreadMessages: Long = 0,
numUnreadNotifications: Long = 0,
numUnreadMentions: Long = 0,
historyVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Joined,
lastMessage: RoomMessage? = aRoomMessage(),
) = RoomSummary(
info = MatrixRoomInfo(
@ -105,6 +107,7 @@ fun aRoomSummary(
numUnreadMessages = numUnreadMessages,
numUnreadNotifications = numUnreadNotifications,
numUnreadMentions = numUnreadMentions,
historyVisibility = historyVisibility,
),
lastMessage = lastMessage,
)