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,
alias = canonicalAlias,
numberOfMembers = numberOfJoinedMembers,
isDm = false,
roomType = roomType,
roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = computeJoinAuthorisationStatus(
membership,
@@ -265,10 +263,18 @@ private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDeta
{ toInviteData() }
),
joinRule = joinRule,
childrenCount = null,
details = when (roomType) {
is RoomType.Other,
RoomType.Room -> LoadedDetails.Room(
isDm = false,
)
RoomType.Space -> LoadedDetails.Space(
childrenCount = 0,
heroes = persistentListOf(),
)
}
)
}
private fun SpaceRoom.toContentState(): ContentState {
return ContentState.Loaded(
@@ -277,8 +283,6 @@ private fun SpaceRoom.toContentState(): ContentState {
topic = topic,
alias = canonicalAlias,
numberOfMembers = numJoinedMembers.toLong(),
isDm = false,
roomType = roomType,
roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = computeJoinAuthorisationStatus(
membership = state,
@@ -286,10 +290,12 @@ private fun SpaceRoom.toContentState(): ContentState {
joinRule = joinRule,
inviteData = { toInviteData() }
),
childrenCount = childrenCount,
joinRule = joinRule,
details = LoadedDetails.Space(
childrenCount = childrenCount,
heroes = heroes.toPersistentList(),
)
)
}
@VisibleForTesting
@@ -300,15 +306,12 @@ internal fun RoomDescription.toContentState(): ContentState {
topic = topic,
alias = alias,
numberOfMembers = numberOfMembers,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = when (joinRule) {
RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock
RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin
else -> JoinAuthorisationStatus.Unknown
},
childrenCount = null,
joinRule = when (joinRule) {
RoomDescription.JoinRule.KNOCK -> JoinRule.Knock
RoomDescription.JoinRule.PUBLIC -> JoinRule.Public
@@ -317,7 +320,7 @@ internal fun RoomDescription.toContentState(): ContentState {
RoomDescription.JoinRule.INVITE -> JoinRule.Invite
RoomDescription.JoinRule.UNKNOWN -> null
},
heroes = persistentListOf()
details = LoadedDetails.Room(isDm = false)
)
}
@@ -333,8 +336,6 @@ internal fun RoomInfo.toContentState(
topic = topic,
alias = canonicalAlias,
numberOfMembers = joinedMembersCountOverride ?: joinedMembersCount,
isDm = isDm,
roomType = if (isSpace) RoomType.Space else RoomType.Room,
roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = computeJoinAuthorisationStatus(
membership = currentUserMembership,
@@ -343,8 +344,16 @@ internal fun RoomInfo.toContentState(
inviteData = { toInviteData() }
),
joinRule = joinRule,
childrenCount = childrenCount,
heroes = heroes
details = if (isSpace) {
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.RoomId
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.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -77,16 +76,13 @@ sealed interface ContentState {
val topic: String?,
val alias: RoomAlias?,
val numberOfMembers: Long?,
val isDm: Boolean,
val roomType: RoomType,
val roomAvatarUrl: String?,
val joinAuthorisationStatus: JoinAuthorisationStatus,
val joinRule: JoinRule?,
val childrenCount: Int?,
val heroes: ImmutableList<MatrixUser>,
val details: LoadedDetails,
) : ContentState {
val showMemberCount = numberOfMembers != null
val isSpace = roomType is RoomType.Space
val isSpace = details is LoadedDetails.Space
fun avatarData(size: AvatarSize): 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 {
data object None : 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.toRoomIdOrAlias
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.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -80,14 +79,17 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
name = "A space",
alias = null,
topic = "This is the topic of a space",
roomType = RoomType.Space,
details = aLoadedDetailsSpace(
childrenCount = 42,
),
)
),
aJoinRoomState(
contentState = aLoadedContentState(
name = "A DM",
details = aLoadedDetailsRoom(
isDm = true,
),
)
),
aJoinRoomState(
@@ -160,25 +162,33 @@ fun aLoadedContentState(
alias: RoomAlias? = RoomAlias("#exa:matrix.org"),
topic: String? = "Element X is a secure, private and decentralized messenger.",
numberOfMembers: Long? = null,
isDm: Boolean = false,
roomType: RoomType = RoomType.Room,
roomAvatarUrl: String? = null,
joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown,
childrenCount: Int? = null,
joinRule: JoinRule? = null,
heroes: List<MatrixUser> = emptyList()
details: LoadedDetails = aLoadedDetailsRoom(isDm = false),
) = ContentState.Loaded(
roomId = roomId,
name = name,
alias = alias,
topic = topic,
numberOfMembers = numberOfMembers,
isDm = isDm,
roomType = roomType,
roomAvatarUrl = roomAvatarUrl,
joinAuthorisationStatus = joinAuthorisationStatus,
childrenCount = childrenCount,
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()
)

View File

@@ -566,10 +566,10 @@ private fun DefaultLoadedContent(
},
subtitle = {
when {
contentState.isSpace -> {
contentState.details is LoadedDetails.Space -> {
SpaceInfoRow(
joinRule = contentState.joinRule ?: JoinRule.Public,
numberOfRooms = contentState.childrenCount ?: 0,
numberOfRooms = contentState.details.childrenCount,
)
}
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.room.CurrentUserMembership
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.JoinRule
import io.element.android.libraries.matrix.test.AN_EXCEPTION
@@ -111,7 +110,7 @@ class JoinRoomPresenterTest {
assertThat(contentState.topic).isEqualTo(roomInfo.topic)
assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias)
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)
}
}
@@ -464,7 +463,7 @@ class JoinRoomPresenterTest {
assertThat(contentState.topic).isEqualTo(roomDescription.topic)
assertThat(contentState.alias).isEqualTo(roomDescription.alias)
assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers)
assertThat(contentState.isDm).isFalse()
assertThat(contentState.details).isEqualTo(aLoadedDetailsRoom(isDm = false))
assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl)
}
}
@@ -708,13 +707,10 @@ class JoinRoomPresenterTest {
topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin,
joinRule = JoinRule.Public,
childrenCount = null,
heroes = persistentListOf()
details = aLoadedDetailsRoom(isDm = false),
)
)
}
@@ -762,8 +758,6 @@ class JoinRoomPresenterTest {
topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(
inviteData = InviteData(
@@ -783,8 +777,7 @@ class JoinRoomPresenterTest {
),
),
joinRule = JoinRule.Public,
childrenCount = null,
heroes = persistentListOf()
details = aLoadedDetailsRoom(isDm = false),
)
)
}
@@ -834,8 +827,6 @@ class JoinRoomPresenterTest {
topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned(
banSender = InviteSender(
@@ -851,8 +842,7 @@ class JoinRoomPresenterTest {
reason = null,
),
joinRule = JoinRule.Public,
childrenCount = null,
heroes = persistentListOf()
details = aLoadedDetailsRoom(isDm = false),
)
)
}
@@ -900,13 +890,10 @@ class JoinRoomPresenterTest {
topic = "Room topic",
alias = RoomAlias("#alias:matrix.org"),
numberOfMembers = 2,
isDm = false,
roomType = RoomType.Room,
roomAvatarUrl = "avatarUrl",
joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked,
joinRule = JoinRule.Public,
childrenCount = null,
heroes = persistentListOf()
details = aLoadedDetailsRoom(isDm = false),
)
)
}

View File

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