diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt index eb1dfd3df6..fa296edc1c 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt @@ -12,6 +12,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo +import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.parcelize.Parcelize @Parcelize @@ -36,3 +37,11 @@ fun RoomInfo.toInviteData(): InviteData { isDm = isDm, ) } + +fun SpaceRoom.toInviteData(): InviteData { + return InviteData( + roomId = roomId, + roomName = name ?: roomId.value, + isDm = false, + ) +} diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 5fe12a42d9..c8a107eba4 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.Inject import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState @@ -41,18 +42,23 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias 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.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.RoomMember +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.isDm 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.preview.RoomPreviewInfo +import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import java.util.Optional +import kotlin.jvm.optionals.getOrNull @Inject class JoinRoomPresenter( @@ -80,6 +86,8 @@ class JoinRoomPresenter( ): JoinRoomPresenter } + private val spaceList = matrixClient.spaceService.spaceRoomList(roomId) + @Composable override fun present(): JoinRoomState { val coroutineScope = rememberCoroutineScope() @@ -87,6 +95,9 @@ class JoinRoomPresenter( val roomInfo by remember { matrixClient.getRoomInfoFlow(roomId) }.collectAsState(initial = Optional.empty()) + val spaceRoom by remember { + spaceList.currentSpaceFlow() + }.collectAsState() val joinAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val knockAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val cancelKnockAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } @@ -96,55 +107,41 @@ class JoinRoomPresenter( val hideInviteAvatars by matrixClient.rememberHideInvitesAvatar() val canReportRoom by produceState(false) { value = matrixClient.canReportRoom() } - val contentState by produceState( - initialValue = ContentState.Loading, - key1 = roomInfo, - key2 = retryCount, - key3 = isDismissingContent, - ) { + var contentState by remember { + mutableStateOf(ContentState.Loading) + } + LaunchedEffect(roomInfo, retryCount, isDismissingContent, spaceRoom) { when { - isDismissingContent -> value = ContentState.Dismissing + isDismissingContent -> contentState = ContentState.Dismissing roomInfo.isPresent -> { val notJoinedRoom = matrixClient.getRoomPreview(roomIdOrAlias, serverNames).getOrNull() - val (sender, reason) = when (roomInfo.get().currentUserMembership) { - CurrentUserMembership.BANNED -> { - // Workaround to get info about the sender for banned rooms - // TODO re-do this once we have a better API in the SDK - val membershipDetails = notJoinedRoom?.membershipDetails()?.getOrNull() - membershipDetails?.senderMember to membershipDetails?.currentUserMember?.membershipChangeReason - } - CurrentUserMembership.INVITED -> { - roomInfo.get().inviter to null - } - else -> null to null - } + val membershipDetails = notJoinedRoom?.membershipDetails()?.getOrNull() val joinedMembersCountOverride = notJoinedRoom?.previewInfo?.numberOfJoinedMembers - value = roomInfo.get().toContentState( - membershipSender = sender, + contentState = roomInfo.get().toContentState( joinedMembersCountOverride = joinedMembersCountOverride, - reason = reason, + membershipDetails = membershipDetails, + childrenCount = spaceRoom.getOrNull()?.childrenCount, ) } + spaceRoom.isPresent -> { + val spaceRoom = spaceRoom.get() + // Only use this state when space is not locally known + contentState = if (spaceRoom.state != null) { + ContentState.Loading + } else { + spaceRoom.toContentState() + } + } roomDescription.isPresent -> { - value = roomDescription.get().toContentState() + contentState = roomDescription.get().toContentState() } else -> { - value = ContentState.Loading + contentState = ContentState.Loading val result = matrixClient.getRoomPreview(roomIdOrAlias, serverNames) - value = result.fold( + contentState = result.fold( onSuccess = { preview -> - val membershipInfo = when (preview.previewInfo.membership) { - CurrentUserMembership.INVITED, - CurrentUserMembership.BANNED, - CurrentUserMembership.KNOCKED -> { - preview.membershipDetails().getOrNull() - } - else -> null - } - preview.previewInfo.toContentState( - senderMember = membershipInfo?.senderMember, - reason = membershipInfo?.currentUserMember?.membershipChangeReason, - ) + val membershipDetails = preview.membershipDetails().getOrNull() + preview.previewInfo.toContentState(membershipDetails) }, onFailure = { throwable -> if (throwable is ClientException.MatrixApi && (throwable.kind == ErrorKind.NotFound || throwable.kind == ErrorKind.Forbidden)) { @@ -223,6 +220,15 @@ class JoinRoomPresenter( } } + private suspend fun getRoomPreviewIfKnown(membership: CurrentUserMembership?): NotJoinedRoom? { + return when (membership) { + CurrentUserMembership.INVITED, + CurrentUserMembership.KNOCKED, + CurrentUserMembership.BANNED -> matrixClient.getRoomPreview(roomIdOrAlias, serverNames).getOrNull() + else -> null + } + } + private fun CoroutineScope.knockRoom(knockAction: MutableState>, message: String) = launch { knockAction.runUpdatingState { knockRoom(roomIdOrAlias, message, serverNames) @@ -252,7 +258,7 @@ class JoinRoomPresenter( } } -private fun RoomPreviewInfo.toContentState(senderMember: RoomMember?, reason: String?): ContentState { +private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDetails?): ContentState { return ContentState.Loaded( roomId = roomId, name = name, @@ -262,17 +268,37 @@ private fun RoomPreviewInfo.toContentState(senderMember: RoomMember?, reason: St isDm = false, roomType = roomType, roomAvatarUrl = avatarUrl, - joinAuthorisationStatus = when (membership) { - CurrentUserMembership.INVITED -> { - JoinAuthorisationStatus.IsInvited( - inviteData = toInviteData(), - inviteSender = senderMember?.toInviteSender() - ) - } - CurrentUserMembership.BANNED -> JoinAuthorisationStatus.IsBanned(senderMember?.toInviteSender(), reason) - CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked - else -> joinRule.toJoinAuthorisationStatus() - } + joinAuthorisationStatus = computeJoinAuthorisationStatus( + membership, + membershipDetails, + joinRule, + { toInviteData() } + ), + joinRule = joinRule, + childrenCount = null, + heroes = persistentListOf(), + ) +} + +private fun SpaceRoom.toContentState(): ContentState { + return ContentState.Loaded( + roomId = roomId, + name = name, + topic = topic, + alias = canonicalAlias, + numberOfMembers = numJoinedMembers.toLong(), + isDm = false, + roomType = roomType, + roomAvatarUrl = avatarUrl, + joinAuthorisationStatus = computeJoinAuthorisationStatus( + membership = state, + membershipDetails = null, + joinRule = joinRule, + inviteData = { toInviteData() } + ), + childrenCount = childrenCount, + joinRule = joinRule, + heroes = heroes.toPersistentList(), ) } @@ -291,15 +317,25 @@ internal fun RoomDescription.toContentState(): ContentState { 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 + RoomDescription.JoinRule.RESTRICTED -> JoinRule.Restricted(persistentListOf()) + RoomDescription.JoinRule.KNOCK_RESTRICTED -> JoinRule.KnockRestricted(persistentListOf()) + RoomDescription.JoinRule.INVITE -> JoinRule.Invite + RoomDescription.JoinRule.UNKNOWN -> null + }, + heroes = persistentListOf() ) } @VisibleForTesting internal fun RoomInfo.toContentState( - membershipSender: RoomMember?, joinedMembersCountOverride: Long?, - reason: String?, + membershipDetails: RoomMembershipDetails?, + childrenCount: Int?, ): ContentState { return ContentState.Loaded( roomId = id, @@ -310,21 +346,40 @@ internal fun RoomInfo.toContentState( isDm = isDm, roomType = if (isSpace) RoomType.Space else RoomType.Room, roomAvatarUrl = avatarUrl, - joinAuthorisationStatus = when (currentUserMembership) { - CurrentUserMembership.INVITED -> JoinAuthorisationStatus.IsInvited( - inviteData = toInviteData(), - inviteSender = membershipSender?.toInviteSender(), - ) - CurrentUserMembership.BANNED -> JoinAuthorisationStatus.IsBanned( - banSender = membershipSender?.toInviteSender(), - reason = reason, - ) - CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked - else -> joinRule.toJoinAuthorisationStatus() - } + joinAuthorisationStatus = computeJoinAuthorisationStatus( + membership = currentUserMembership, + membershipDetails = membershipDetails, + joinRule = joinRule, + inviteData = { toInviteData() } + ), + joinRule = joinRule, + childrenCount = childrenCount, + heroes = heroes ) } +private fun computeJoinAuthorisationStatus( + membership: CurrentUserMembership?, + membershipDetails: RoomMembershipDetails?, + joinRule: JoinRule?, + inviteData: () -> InviteData, +): JoinAuthorisationStatus { + return when (membership) { + CurrentUserMembership.INVITED -> { + JoinAuthorisationStatus.IsInvited( + inviteData = inviteData(), + inviteSender = membershipDetails?.senderMember?.toInviteSender() + ) + } + CurrentUserMembership.BANNED -> JoinAuthorisationStatus.IsBanned( + membershipDetails?.senderMember?.toInviteSender(), + membershipDetails?.membershipChangeReason + ) + CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked + else -> joinRule.toJoinAuthorisationStatus() + } +} + private fun JoinRule?.toJoinAuthorisationStatus(): JoinAuthorisationStatus { return when (this) { JoinRule.Knock, diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index 5b9f8007a3..36a74c813e 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -18,7 +18,10 @@ 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 import io.element.android.libraries.matrix.ui.model.InviteSender +import kotlinx.collections.immutable.ImmutableList internal const val MAX_KNOCK_MESSAGE_LENGTH = 500 @@ -41,9 +44,6 @@ data class JoinRoomState( val joinAuthorisationStatus = when (contentState) { is ContentState.Loaded -> { when { - contentState.roomType == RoomType.Space -> { - JoinAuthorisationStatus.IsSpace(applicationName) - } isJoinActionUnauthorized -> { JoinAuthorisationStatus.Unauthorized } @@ -81,8 +81,12 @@ sealed interface ContentState { val roomType: RoomType, val roomAvatarUrl: String?, val joinAuthorisationStatus: JoinAuthorisationStatus, + val joinRule: JoinRule?, + val childrenCount: Int?, + val heroes: ImmutableList, ) : ContentState { val showMemberCount = numberOfMembers != null + val isSpace = roomType is RoomType.Space fun avatarData(size: AvatarSize): AvatarData { return AvatarData( diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 8f891fe645..244cc0579d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -22,7 +22,10 @@ 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 import io.element.android.libraries.matrix.ui.model.InviteSender +import kotlinx.collections.immutable.toPersistentList open class JoinRoomStateProvider : PreviewParameterProvider { override val values: Sequence @@ -78,6 +81,7 @@ open class JoinRoomStateProvider : PreviewParameterProvider { alias = null, topic = "This is the topic of a space", roomType = RoomType.Space, + childrenCount = 42, ) ), aJoinRoomState( @@ -160,6 +164,9 @@ fun aLoadedContentState( roomType: RoomType = RoomType.Room, roomAvatarUrl: String? = null, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, + childrenCount: Int? = null, + joinRule : JoinRule? = null, + heroes: List = emptyList() ) = ContentState.Loaded( roomId = roomId, name = name, @@ -169,7 +176,10 @@ fun aLoadedContentState( isDm = isDm, roomType = roomType, roomAvatarUrl = roomAvatarUrl, - joinAuthorisationStatus = joinAuthorisationStatus + joinAuthorisationStatus = joinAuthorisationStatus, + childrenCount = childrenCount, + joinRule = joinRule, + heroes = heroes.toPersistentList() ) fun aJoinRoomState( diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt index cabab56802..5a6631146d 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt @@ -964,7 +964,7 @@ class JoinRoomPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.IsSpace("AppName")) + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.UnsupportedSpace("AppName")) } } } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index 95597371a6..3b07e06051 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -29,6 +29,8 @@ import kotlinx.collections.immutable.toPersistentSet import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import java.util.Optional +import kotlin.jvm.optionals.getOrNull @Inject class SpacePresenter( @@ -64,7 +66,7 @@ class SpacePresenter( } }.collectAsState() - val currentSpace by remember { spaceRoomList.currentSpaceFlow() }.collectAsState(null) + val currentSpace by remember { spaceRoomList.currentSpaceFlow() }.collectAsState(Optional.empty()) fun handleEvents(event: SpaceEvents) { when (event) { @@ -72,7 +74,7 @@ class SpacePresenter( } } return SpaceState( - currentSpace = currentSpace, + currentSpace = currentSpace.getOrNull(), children = children.toPersistentList(), seenSpaceInvites = seenSpaceInvites, hideInvitesAvatar = hideInvitesAvatar, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt index a591fc2537..e55e1b87bd 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.api.spaces import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +import java.util.Optional interface SpaceRoomList { sealed interface PaginationStatus { @@ -16,7 +17,7 @@ interface SpaceRoomList { data class Idle(val hasMoreToLoad: Boolean) : PaginationStatus } - fun currentSpaceFlow(): Flow + fun currentSpaceFlow(): StateFlow> val spaceRoomsFlow: Flow> val paginationStatusFlow: StateFlow diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt index e3f2132a2f..7e6a9f6afa 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -16,10 +16,12 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState +import java.util.Optional import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList class RustSpaceRoomList( @@ -31,7 +33,7 @@ class RustSpaceRoomList( ) : SpaceRoomList { private val inner = CompletableDeferred() - override fun currentSpaceFlow(): Flow { + override fun currentSpaceFlow(): StateFlow> { return spaceRoomCache.getSpaceRoomFlow(roomId) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt index 8b7d1f5e1b..f9d45e5ea6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -12,7 +12,9 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update +import java.util.Optional /** * An in memory cache of space rooms. @@ -20,8 +22,8 @@ import kotlinx.coroutines.flow.update */ class SpaceRoomCache { private val inMemoryCache = MutableStateFlow>(emptyMap()) - fun getSpaceRoomFlow(roomId: RoomId): Flow { - return inMemoryCache.mapState { it[roomId] } + fun getSpaceRoomFlow(roomId: RoomId): StateFlow> { + return inMemoryCache.mapState { Optional.ofNullable(it[roomId]) } } fun update(spaceRooms: List) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt index 0679ce1a33..061169c5e8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt @@ -21,7 +21,7 @@ class SpaceRoomCacheTest { fun `getSpaceRoomFlow emits items`() = runTest { val sut = SpaceRoomCache() sut.getSpaceRoomFlow(A_ROOM_ID).test { - assertThat(awaitItem()).isNull() + assertThat(awaitItem().isEmpty).isTrue() val room = aSpaceRoom( roomId = A_ROOM_ID, roomType = RoomType.Room, @@ -34,7 +34,7 @@ class SpaceRoomCacheTest { roomType = RoomType.Space, ) sut.update(listOf(space)) - assertThat(awaitItem()).isEqualTo(space) + assertThat(awaitItem().get()).isEqualTo(space) val spaceOther = aSpaceRoom( roomId = A_ROOM_ID_2, roomType = RoomType.Space, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt index eb71f33fa2..ca424eac11 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import java.util.Optional class FakeSpaceRoomList( initialSpaceFlowValue: SpaceRoom? = null, @@ -22,11 +23,11 @@ class FakeSpaceRoomList( initialSpaceRoomList: SpaceRoomList.PaginationStatus = SpaceRoomList.PaginationStatus.Loading, private val paginateResult: () -> Result = { lambdaError() }, ) : SpaceRoomList { - private val _currentSpaceFlow: MutableStateFlow = MutableStateFlow(initialSpaceFlowValue) - override fun currentSpaceFlow(): Flow = _currentSpaceFlow.asStateFlow() + private val _currentSpaceFlow: MutableStateFlow> = MutableStateFlow(Optional.ofNullable(initialSpaceFlowValue)) + override fun currentSpaceFlow() = _currentSpaceFlow.asStateFlow() fun emitCurrentSpace(value: SpaceRoom?) { - _currentSpaceFlow.value = value + _currentSpaceFlow.value = Optional.ofNullable(value) } private val _spaceRoomsFlow: MutableStateFlow> = MutableStateFlow(initialSpaceRoomsValue)