Introduce LoadedDetails, different for Room and Space.

This commit is contained in:
Benoit Marty
2025-09-22 16:26:33 +02:00
parent 1ba474e3d8
commit b51c421e29
6 changed files with 71 additions and 56 deletions

View File

@@ -255,8 +255,6 @@ private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDeta
topic = topic, topic = topic,
alias = canonicalAlias, alias = canonicalAlias,
numberOfMembers = numberOfJoinedMembers, numberOfMembers = numberOfJoinedMembers,
isDm = false,
roomType = roomType,
roomAvatarUrl = avatarUrl, roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = computeJoinAuthorisationStatus( joinAuthorisationStatus = computeJoinAuthorisationStatus(
membership, membership,
@@ -265,8 +263,16 @@ private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDeta
{ toInviteData() } { toInviteData() }
), ),
joinRule = joinRule, joinRule = joinRule,
childrenCount = null, details = when (roomType) {
heroes = persistentListOf(), is RoomType.Other,
RoomType.Room -> LoadedDetails.Room(
isDm = false,
)
RoomType.Space -> LoadedDetails.Space(
childrenCount = 0,
heroes = persistentListOf(),
)
}
) )
} }
@@ -277,8 +283,6 @@ private fun SpaceRoom.toContentState(): ContentState {
topic = topic, topic = topic,
alias = canonicalAlias, alias = canonicalAlias,
numberOfMembers = numJoinedMembers.toLong(), numberOfMembers = numJoinedMembers.toLong(),
isDm = false,
roomType = roomType,
roomAvatarUrl = avatarUrl, roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = computeJoinAuthorisationStatus( joinAuthorisationStatus = computeJoinAuthorisationStatus(
membership = state, membership = state,
@@ -286,9 +290,11 @@ private fun SpaceRoom.toContentState(): ContentState {
joinRule = joinRule, joinRule = joinRule,
inviteData = { toInviteData() } inviteData = { toInviteData() }
), ),
childrenCount = childrenCount,
joinRule = joinRule, joinRule = joinRule,
heroes = heroes.toPersistentList(), details = LoadedDetails.Space(
childrenCount = childrenCount,
heroes = heroes.toPersistentList(),
)
) )
} }
@@ -300,15 +306,12 @@ internal fun RoomDescription.toContentState(): ContentState {
topic = topic, topic = topic,
alias = alias, alias = alias,
numberOfMembers = numberOfMembers, numberOfMembers = numberOfMembers,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = avatarUrl, roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = when (joinRule) { joinAuthorisationStatus = when (joinRule) {
RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock
RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin
else -> JoinAuthorisationStatus.Unknown else -> JoinAuthorisationStatus.Unknown
}, },
childrenCount = null,
joinRule = when (joinRule) { joinRule = when (joinRule) {
RoomDescription.JoinRule.KNOCK -> JoinRule.Knock RoomDescription.JoinRule.KNOCK -> JoinRule.Knock
RoomDescription.JoinRule.PUBLIC -> JoinRule.Public RoomDescription.JoinRule.PUBLIC -> JoinRule.Public
@@ -317,7 +320,7 @@ internal fun RoomDescription.toContentState(): ContentState {
RoomDescription.JoinRule.INVITE -> JoinRule.Invite RoomDescription.JoinRule.INVITE -> JoinRule.Invite
RoomDescription.JoinRule.UNKNOWN -> null RoomDescription.JoinRule.UNKNOWN -> null
}, },
heroes = persistentListOf() details = LoadedDetails.Room(isDm = false)
) )
} }
@@ -333,8 +336,6 @@ internal fun RoomInfo.toContentState(
topic = topic, topic = topic,
alias = canonicalAlias, alias = canonicalAlias,
numberOfMembers = joinedMembersCountOverride ?: joinedMembersCount, numberOfMembers = joinedMembersCountOverride ?: joinedMembersCount,
isDm = isDm,
roomType = if (isSpace) RoomType.Space else RoomType.Room,
roomAvatarUrl = avatarUrl, roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = computeJoinAuthorisationStatus( joinAuthorisationStatus = computeJoinAuthorisationStatus(
membership = currentUserMembership, membership = currentUserMembership,
@@ -343,8 +344,16 @@ internal fun RoomInfo.toContentState(
inviteData = { toInviteData() } inviteData = { toInviteData() }
), ),
joinRule = joinRule, joinRule = joinRule,
childrenCount = childrenCount, details = if (isSpace) {
heroes = heroes LoadedDetails.Space(
childrenCount = childrenCount ?: 0,
heroes = heroes,
)
} else {
LoadedDetails.Room(
isDm = isDm,
)
},
) )
} }

View File

@@ -16,7 +16,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.core.RoomAlias 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.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule 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.api.user.MatrixUser
@@ -77,16 +76,13 @@ sealed interface ContentState {
val topic: String?, val topic: String?,
val alias: RoomAlias?, val alias: RoomAlias?,
val numberOfMembers: Long?, val numberOfMembers: Long?,
val isDm: Boolean,
val roomType: RoomType,
val roomAvatarUrl: String?, val roomAvatarUrl: String?,
val joinAuthorisationStatus: JoinAuthorisationStatus, val joinAuthorisationStatus: JoinAuthorisationStatus,
val joinRule: JoinRule?, val joinRule: JoinRule?,
val childrenCount: Int?, val details: LoadedDetails,
val heroes: ImmutableList<MatrixUser>,
) : ContentState { ) : ContentState {
val showMemberCount = numberOfMembers != null val showMemberCount = numberOfMembers != null
val isSpace = roomType is RoomType.Space val isSpace = details is LoadedDetails.Space
fun avatarData(size: AvatarSize): AvatarData { fun avatarData(size: AvatarSize): AvatarData {
return AvatarData( return AvatarData(
@@ -99,6 +95,18 @@ sealed interface ContentState {
} }
} }
@Immutable
sealed interface LoadedDetails {
data class Room(
val isDm: Boolean,
) : LoadedDetails
data class Space(
val childrenCount: Int,
val heroes: ImmutableList<MatrixUser>,
) : LoadedDetails
}
sealed interface JoinAuthorisationStatus { sealed interface JoinAuthorisationStatus {
data object None : JoinAuthorisationStatus data object None : JoinAuthorisationStatus
data class IsInvited(val inviteData: InviteData, val inviteSender: InviteSender?) : JoinAuthorisationStatus data class IsInvited(val inviteData: InviteData, val inviteSender: InviteSender?) : JoinAuthorisationStatus

View File

@@ -20,7 +20,6 @@ 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.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.exception.ClientException
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule 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.api.user.MatrixUser
@@ -80,14 +79,17 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
name = "A space", name = "A space",
alias = null, alias = null,
topic = "This is the topic of a space", topic = "This is the topic of a space",
roomType = RoomType.Space, details = aLoadedDetailsSpace(
childrenCount = 42, childrenCount = 42,
),
) )
), ),
aJoinRoomState( aJoinRoomState(
contentState = aLoadedContentState( contentState = aLoadedContentState(
name = "A DM", name = "A DM",
isDm = true, details = aLoadedDetailsRoom(
isDm = true,
),
) )
), ),
aJoinRoomState( aJoinRoomState(
@@ -160,25 +162,33 @@ fun aLoadedContentState(
alias: RoomAlias? = RoomAlias("#exa:matrix.org"), alias: RoomAlias? = RoomAlias("#exa:matrix.org"),
topic: String? = "Element X is a secure, private and decentralized messenger.", topic: String? = "Element X is a secure, private and decentralized messenger.",
numberOfMembers: Long? = null, numberOfMembers: Long? = null,
isDm: Boolean = false,
roomType: RoomType = RoomType.Room,
roomAvatarUrl: String? = null, roomAvatarUrl: String? = null,
joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown,
childrenCount: Int? = null,
joinRule: JoinRule? = null, joinRule: JoinRule? = null,
heroes: List<MatrixUser> = emptyList() details: LoadedDetails = aLoadedDetailsRoom(isDm = false),
) = ContentState.Loaded( ) = ContentState.Loaded(
roomId = roomId, roomId = roomId,
name = name, name = name,
alias = alias, alias = alias,
topic = topic, topic = topic,
numberOfMembers = numberOfMembers, numberOfMembers = numberOfMembers,
isDm = isDm,
roomType = roomType,
roomAvatarUrl = roomAvatarUrl, roomAvatarUrl = roomAvatarUrl,
joinAuthorisationStatus = joinAuthorisationStatus, joinAuthorisationStatus = joinAuthorisationStatus,
childrenCount = childrenCount,
joinRule = joinRule, joinRule = joinRule,
details = details,
)
fun aLoadedDetailsRoom(
isDm: Boolean = false,
) = LoadedDetails.Room(
isDm = isDm
)
fun aLoadedDetailsSpace(
childrenCount: Int = 0,
heroes: List<MatrixUser> = emptyList(),
) = LoadedDetails.Space(
childrenCount = childrenCount,
heroes = heroes.toPersistentList() heroes = heroes.toPersistentList()
) )

View File

@@ -566,10 +566,10 @@ private fun DefaultLoadedContent(
}, },
subtitle = { subtitle = {
when { when {
contentState.isSpace -> { contentState.details is LoadedDetails.Space -> {
SpaceInfoRow( SpaceInfoRow(
joinRule = contentState.joinRule ?: JoinRule.Public, joinRule = contentState.joinRule ?: JoinRule.Public,
numberOfRooms = contentState.childrenCount ?: 0, numberOfRooms = contentState.details.childrenCount,
) )
} }
contentState.alias != null -> { contentState.alias != null -> {

View File

@@ -33,7 +33,6 @@ import io.element.android.libraries.matrix.api.exception.ClientException
import io.element.android.libraries.matrix.api.exception.ErrorKind import io.element.android.libraries.matrix.api.exception.ErrorKind
import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.AN_EXCEPTION
@@ -111,7 +110,7 @@ class JoinRoomPresenterTest {
assertThat(contentState.topic).isEqualTo(roomInfo.topic) assertThat(contentState.topic).isEqualTo(roomInfo.topic)
assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias) assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias)
assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.joinedMembersCount) assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.joinedMembersCount)
assertThat(contentState.isDm).isEqualTo(roomInfo.isDirect) assertThat(contentState.details).isEqualTo(aLoadedDetailsRoom(isDm = roomInfo.isDirect))
assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl) assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl)
} }
} }
@@ -464,7 +463,7 @@ class JoinRoomPresenterTest {
assertThat(contentState.topic).isEqualTo(roomDescription.topic) assertThat(contentState.topic).isEqualTo(roomDescription.topic)
assertThat(contentState.alias).isEqualTo(roomDescription.alias) assertThat(contentState.alias).isEqualTo(roomDescription.alias)
assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers) assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers)
assertThat(contentState.isDm).isFalse() assertThat(contentState.details).isEqualTo(aLoadedDetailsRoom(isDm = false))
assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl) assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl)
} }
} }
@@ -708,13 +707,10 @@ class JoinRoomPresenterTest {
topic = "Room topic", topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"), alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2, numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl", roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin, joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin,
joinRule = JoinRule.Public, joinRule = JoinRule.Public,
childrenCount = null, details = aLoadedDetailsRoom(isDm = false),
heroes = persistentListOf()
) )
) )
} }
@@ -762,8 +758,6 @@ class JoinRoomPresenterTest {
topic = "Room topic", topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"), alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2, numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl", roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited( joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(
inviteData = InviteData( inviteData = InviteData(
@@ -783,8 +777,7 @@ class JoinRoomPresenterTest {
), ),
), ),
joinRule = JoinRule.Public, joinRule = JoinRule.Public,
childrenCount = null, details = aLoadedDetailsRoom(isDm = false),
heroes = persistentListOf()
) )
) )
} }
@@ -834,8 +827,6 @@ class JoinRoomPresenterTest {
topic = "Room topic", topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"), alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2, numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl", roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned( joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned(
banSender = InviteSender( banSender = InviteSender(
@@ -851,8 +842,7 @@ class JoinRoomPresenterTest {
reason = null, reason = null,
), ),
joinRule = JoinRule.Public, joinRule = JoinRule.Public,
childrenCount = null, details = aLoadedDetailsRoom(isDm = false),
heroes = persistentListOf()
) )
) )
} }
@@ -900,13 +890,10 @@ class JoinRoomPresenterTest {
topic = "Room topic", topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"), alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2, numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl", roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked, joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked,
joinRule = JoinRule.Public, joinRule = JoinRule.Public,
childrenCount = null, details = aLoadedDetailsRoom(isDm = false),
heroes = persistentListOf()
) )
) )
} }

View File

@@ -26,6 +26,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
import org.matrix.rustcomponents.sdk.SpaceListUpdate import org.matrix.rustcomponents.sdk.SpaceListUpdate
import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState
import kotlin.jvm.optionals.getOrNull
import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList
class RustSpaceRoomListTest { class RustSpaceRoomListTest {
@@ -93,10 +94,10 @@ class RustSpaceRoomListTest {
spaceRoomCache = spaceRoomCache, spaceRoomCache = spaceRoomCache,
) )
sut.currentSpaceFlow().test { sut.currentSpaceFlow().test {
assertThat(awaitItem()).isNull() assertThat(awaitItem().getOrNull()).isNull()
val spaceRoom = aSpaceRoom(roomId = A_ROOM_ID) val spaceRoom = aSpaceRoom(roomId = A_ROOM_ID)
spaceRoomCache.update(listOf(spaceRoom)) spaceRoomCache.update(listOf(spaceRoom))
assertThat(awaitItem()).isEqualTo(spaceRoom) assertThat(awaitItem().getOrNull()).isEqualTo(spaceRoom)
} }
} }