feature (space) : start logic for joining space
This commit is contained in:
parent
4869c0b5d7
commit
e79281a78a
11 changed files with 167 additions and 81 deletions
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
||||
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
||||
val cancelKnockAction: MutableState<AsyncAction<Unit>> = 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<ContentState>(
|
||||
initialValue = ContentState.Loading,
|
||||
key1 = roomInfo,
|
||||
key2 = retryCount,
|
||||
key3 = isDismissingContent,
|
||||
) {
|
||||
var contentState by remember {
|
||||
mutableStateOf<ContentState>(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<AsyncAction<Unit>>, 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,
|
||||
|
|
|
|||
|
|
@ -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<MatrixUser>,
|
||||
) : ContentState {
|
||||
val showMemberCount = numberOfMembers != null
|
||||
val isSpace = roomType is RoomType.Space
|
||||
|
||||
fun avatarData(size: AvatarSize): AvatarData {
|
||||
return AvatarData(
|
||||
|
|
|
|||
|
|
@ -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<JoinRoomState> {
|
||||
override val values: Sequence<JoinRoomState>
|
||||
|
|
@ -78,6 +81,7 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
|
|||
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<MatrixUser> = 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(
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<SpaceRoom?>
|
||||
fun currentSpaceFlow(): StateFlow<Optional<SpaceRoom>>
|
||||
|
||||
val spaceRoomsFlow: Flow<List<SpaceRoom>>
|
||||
val paginationStatusFlow: StateFlow<PaginationStatus>
|
||||
|
|
|
|||
|
|
@ -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<InnerSpaceRoomList>()
|
||||
|
||||
override fun currentSpaceFlow(): Flow<SpaceRoom?> {
|
||||
override fun currentSpaceFlow(): StateFlow<Optional<SpaceRoom>> {
|
||||
return spaceRoomCache.getSpaceRoomFlow(roomId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Map<RoomId, SpaceRoom?>>(emptyMap())
|
||||
fun getSpaceRoomFlow(roomId: RoomId): Flow<SpaceRoom?> {
|
||||
return inMemoryCache.mapState { it[roomId] }
|
||||
fun getSpaceRoomFlow(roomId: RoomId): StateFlow<Optional<SpaceRoom>> {
|
||||
return inMemoryCache.mapState { Optional.ofNullable(it[roomId]) }
|
||||
}
|
||||
|
||||
fun update(spaceRooms: List<SpaceRoom>) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<Unit> = { lambdaError() },
|
||||
) : SpaceRoomList {
|
||||
private val _currentSpaceFlow: MutableStateFlow<SpaceRoom?> = MutableStateFlow(initialSpaceFlowValue)
|
||||
override fun currentSpaceFlow(): Flow<SpaceRoom?> = _currentSpaceFlow.asStateFlow()
|
||||
private val _currentSpaceFlow: MutableStateFlow<Optional<SpaceRoom>> = 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<List<SpaceRoom>> = MutableStateFlow(initialSpaceRoomsValue)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue