Room join : add presenter tests

This commit is contained in:
ganfra 2024-04-11 21:07:10 +02:00
parent 79c6385edb
commit 038d8e3334
10 changed files with 410 additions and 88 deletions

View file

@ -50,6 +50,8 @@ dependencies {
testImplementation(libs.test.truth) testImplementation(libs.test.truth)
testImplementation(libs.test.turbine) testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.features.invite.test)
testImplementation(projects.tests.testutils)
ksp(libs.showkase.processor) ksp(libs.showkase.processor)
} }

View file

@ -32,8 +32,8 @@ import io.element.android.libraries.matrix.api.MatrixClient
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.room.CurrentUserMembership 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.MatrixRoomInfo
import org.jetbrains.annotations.VisibleForTesting
import java.util.Optional import java.util.Optional
import kotlin.jvm.optionals.getOrNull
class JoinRoomPresenter @AssistedInject constructor( class JoinRoomPresenter @AssistedInject constructor(
@Assisted private val roomId: RoomId, @Assisted private val roomId: RoomId,
@ -49,8 +49,6 @@ class JoinRoomPresenter @AssistedInject constructor(
@Composable @Composable
override fun present(): JoinRoomState { override fun present(): JoinRoomState {
val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty())
val joinAuthorisationStatus = joinAuthorisationStatus(roomInfo)
val acceptDeclineInviteState = acceptDeclineInvitePresenter.present()
val contentState by produceState<AsyncData<ContentState>>(initialValue = AsyncData.Uninitialized, key1 = roomInfo) { val contentState by produceState<AsyncData<ContentState>>(initialValue = AsyncData.Uninitialized, key1 = roomInfo) {
value = when { value = when {
roomInfo.isPresent -> { roomInfo.isPresent -> {
@ -61,20 +59,25 @@ class JoinRoomPresenter @AssistedInject constructor(
val contentState = roomDescription.get().toContentState() val contentState = roomDescription.get().toContentState()
AsyncData.Success(contentState) AsyncData.Success(contentState)
} }
else -> AsyncData.Uninitialized else -> {
AsyncData.Uninitialized
}
} }
} }
val acceptDeclineInviteState = acceptDeclineInvitePresenter.present()
fun handleEvents(event: JoinRoomEvents) { fun handleEvents(event: JoinRoomEvents) {
when (event) { when (event) {
JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> { JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> {
val inviteData = contentState.toInviteData() ?: return
acceptDeclineInviteState.eventSink( acceptDeclineInviteState.eventSink(
AcceptDeclineInviteEvents.AcceptInvite(contentState.toInviteData()) AcceptDeclineInviteEvents.AcceptInvite(inviteData)
) )
} }
JoinRoomEvents.DeclineInvite -> { JoinRoomEvents.DeclineInvite -> {
val inviteData = contentState.toInviteData() ?: return
acceptDeclineInviteState.eventSink( acceptDeclineInviteState.eventSink(
AcceptDeclineInviteEvents.DeclineInvite(contentState.toInviteData()) AcceptDeclineInviteEvents.DeclineInvite(inviteData)
) )
} }
} }
@ -82,66 +85,69 @@ class JoinRoomPresenter @AssistedInject constructor(
return JoinRoomState( return JoinRoomState(
contentState = contentState, contentState = contentState,
joinAuthorisationStatus = joinAuthorisationStatus,
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
eventSink = ::handleEvents eventSink = ::handleEvents
) )
} }
}
private fun RoomDescription.toContentState(): ContentState { @VisibleForTesting
return ContentState( internal fun RoomDescription.toContentState(): ContentState {
roomId = roomId, return ContentState(
name = name, roomId = roomId,
description = description, name = name,
numberOfMembers = numberOfMembers, description = description,
isDirect = false, numberOfMembers = numberOfMembers,
roomAvatarUrl = avatarUrl isDirect = false,
) roomAvatarUrl = avatarUrl,
} joinAuthorisationStatus = when (joinRule) {
RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock
private fun MatrixRoomInfo.toContentState(): ContentState { RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin
fun title(): String {
return name ?: canonicalAlias ?: roomId.value
}
fun description(): String? {
val topic = topic
val alias = canonicalAlias
val name = name
return when {
topic != null -> topic
name != null && alias != null -> alias
name == null && alias == null -> null
else -> roomId.value
}
}
return ContentState(
roomId = roomId,
name = title(),
description = description(),
numberOfMembers = activeMembersCount,
isDirect = isDirect,
roomAvatarUrl = avatarUrl
)
}
private fun AsyncData<ContentState>.toInviteData(): InviteData {
return dataOrNull().let {
InviteData(
roomId = roomId,
roomName = it?.name ?: "",
isDirect = it?.isDirect ?: false
)
}
}
@Composable
private fun joinAuthorisationStatus(roomInfo: Optional<MatrixRoomInfo>): JoinAuthorisationStatus {
val userMembership = roomInfo.getOrNull()?.currentUserMembership
return when {
userMembership == CurrentUserMembership.INVITED -> return JoinAuthorisationStatus.IsInvited
else -> JoinAuthorisationStatus.Unknown else -> JoinAuthorisationStatus.Unknown
} }
)
}
@VisibleForTesting
internal fun MatrixRoomInfo.toContentState(): ContentState {
fun title(): String {
return name ?: canonicalAlias ?: id
}
fun description(): String? {
val topic = topic
val alias = canonicalAlias
val name = name
return when {
topic != null -> topic
name != null && alias != null -> alias
name == null && alias == null -> null
else -> id
}
}
return ContentState(
roomId = RoomId(id),
name = title(),
description = description(),
numberOfMembers = activeMembersCount,
isDirect = isDirect,
roomAvatarUrl = avatarUrl,
joinAuthorisationStatus = when {
currentUserMembership == CurrentUserMembership.INVITED -> JoinAuthorisationStatus.IsInvited
isPublic -> JoinAuthorisationStatus.CanJoin
else -> JoinAuthorisationStatus.Unknown
}
)
}
@VisibleForTesting
internal fun AsyncData<ContentState>.toInviteData(): InviteData? {
return dataOrNull()?.let { contentState ->
InviteData(
roomId = contentState.roomId,
roomName = contentState.name,
isDirect = contentState.isDirect
)
} }
} }

View file

@ -26,10 +26,11 @@ import io.element.android.libraries.matrix.api.core.RoomId
@Immutable @Immutable
data class JoinRoomState( data class JoinRoomState(
val contentState: AsyncData<ContentState>, val contentState: AsyncData<ContentState>,
val joinAuthorisationStatus: JoinAuthorisationStatus,
val acceptDeclineInviteState: AcceptDeclineInviteState, val acceptDeclineInviteState: AcceptDeclineInviteState,
val eventSink: (JoinRoomEvents) -> Unit val eventSink: (JoinRoomEvents) -> Unit
) ) {
val joinAuthorisationStatus = contentState.dataOrNull()?.joinAuthorisationStatus ?: JoinAuthorisationStatus.Unknown
}
data class ContentState( data class ContentState(
val roomId: RoomId, val roomId: RoomId,
@ -38,6 +39,7 @@ data class ContentState(
val numberOfMembers: Long?, val numberOfMembers: Long?,
val isDirect: Boolean, val isDirect: Boolean,
val roomAvatarUrl: String?, val roomAvatarUrl: String?,
val joinAuthorisationStatus: JoinAuthorisationStatus,
) { ) {
val showMemberCount = numberOfMembers != null val showMemberCount = numberOfMembers != null

View file

@ -29,34 +29,49 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
contentState = AsyncData.Uninitialized contentState = AsyncData.Uninitialized
), ),
aJoinRoomState( aJoinRoomState(
joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin contentState = AsyncData.Success(
aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin)
)
), ),
aJoinRoomState( aJoinRoomState(
joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock contentState = AsyncData.Success(
aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock)
)
), ),
aJoinRoomState( aJoinRoomState(
joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited contentState = AsyncData.Success(
aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited)
)
), ),
) )
} }
fun aContentState(
roomId: RoomId = RoomId("@exa:matrix.org"),
name: String = "Element x android",
description: String? = "#exa:matrix.org",
numberOfMembers: Long? = null,
isDirect: Boolean = false,
roomAvatarUrl: String? = null,
joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown
) = ContentState(
roomId = roomId,
name = name,
description = description,
numberOfMembers = numberOfMembers,
isDirect = isDirect,
roomAvatarUrl = roomAvatarUrl,
joinAuthorisationStatus = joinAuthorisationStatus
)
fun aJoinRoomState( fun aJoinRoomState(
contentState: AsyncData<ContentState> = AsyncData.Success( contentState: AsyncData<ContentState> = AsyncData.Success(
ContentState( aContentState()
roomId = RoomId("@exa:matrix.org"),
name = "Element x android",
description = "#exa:matrix.org",
numberOfMembers = null,
isDirect = false,
roomAvatarUrl = null
)
), ),
joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown,
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
eventSink: (JoinRoomEvents) -> Unit = {} eventSink: (JoinRoomEvents) -> Unit = {}
) = JoinRoomState( ) = JoinRoomState(
contentState = contentState, contentState = contentState,
joinAuthorisationStatus = joinAuthorisationStatus,
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
eventSink = eventSink eventSink = eventSink
) )

View file

@ -109,8 +109,7 @@ private fun JoinRoomFooter(
) )
} }
} }
// TODO handle all cases properly JoinAuthorisationStatus.CanJoin -> {
else -> {
Button( Button(
text = stringResource(CommonStrings.action_join), text = stringResource(CommonStrings.action_join),
onClick = onJoinRoom, onClick = onJoinRoom,
@ -118,6 +117,18 @@ private fun JoinRoomFooter(
size = ButtonSize.Medium, size = ButtonSize.Medium,
) )
} }
JoinAuthorisationStatus.CanKnock -> {
//TODO knock
/*
Button(
text = stringResource(CommonStrings.action_knock),
onClick = onJoinRoom,
modifier = modifier.fillMaxWidth(),
size = ButtonSize.Medium,
)
*/
}
JoinAuthorisationStatus.Unknown -> Unit
} }
} }
@ -154,8 +165,8 @@ private fun JoinRoomContent(
Column( Column(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(all = 16.dp), .padding(all = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
when (asyncContentState) { when (asyncContentState) {
@ -191,9 +202,9 @@ private fun JoinRoomMembersCount(memberCount: Long) {
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Row( Row(
modifier = Modifier modifier = Modifier
.background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape)
.widthIn(min = 48.dp) .widthIn(min = 48.dp)
.padding(all = 2.dp), .padding(all = 2.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp) horizontalArrangement = Arrangement.spacedBy(4.dp)
) { ) {

View file

@ -0,0 +1,274 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.joinroom.impl
import com.google.common.truth.Truth.assertThat
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
import io.element.android.features.invite.api.response.anAcceptDeclineInviteState
import io.element.android.features.roomdirectory.api.RoomDescription
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.assert
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import java.util.Optional
class JoinRoomPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@Test
fun `present - initial state`() = runTest {
val presenter = createJoinRoomPresenter()
presenter.test {
awaitItem().also { state ->
assertThat(state.contentState).isInstanceOf(AsyncData.Uninitialized::class.java)
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown)
assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState())
}
}
}
@Test
fun `present - when room is joined then content state is filled with his data`() = runTest {
val roomInfo = aRoomInfo()
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
}
}
val presenter = createJoinRoomPresenter(
matrixClient = matrixClient
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java)
val contentState = state.contentState.dataOrNull()!!
assertThat(contentState.roomId).isEqualTo(A_ROOM_ID)
assertThat(contentState.name).isEqualTo(roomInfo.name)
assertThat(contentState.description).isEqualTo(roomInfo.topic)
assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.activeMembersCount)
assertThat(contentState.isDirect).isEqualTo(roomInfo.isDirect)
assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl)
}
}
}
@Test
fun `present - when room is invited then join authorization is equal to invited`() = runTest {
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
}
}
val presenter = createJoinRoomPresenter(
matrixClient = matrixClient
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.IsInvited)
}
}
}
@Test
fun `present - when room is invited then accept and decline events are sent to acceptDeclinePresenter`() = runTest {
val eventSinkRecorder = lambdaRecorder { _: AcceptDeclineInviteEvents -> }
val acceptDeclinePresenter = Presenter {
anAcceptDeclineInviteState(eventSink = eventSinkRecorder)
}
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
}
}
val presenter = createJoinRoomPresenter(
matrixClient = matrixClient,
acceptDeclineInvitePresenter = acceptDeclinePresenter
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.AcceptInvite)
state.eventSink(JoinRoomEvents.DeclineInvite)
val inviteData = state.contentState.toInviteData()!!
assert(eventSinkRecorder)
.isCalledExactly(2)
.withSequence(
listOf(value(AcceptDeclineInviteEvents.AcceptInvite(inviteData))),
listOf(value(AcceptDeclineInviteEvents.DeclineInvite(inviteData))),
)
}
}
}
@Test
fun `present - when room is left and public then join authorization is equal to canJoin`() = runTest {
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, isPublic = true)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
}
}
val presenter = createJoinRoomPresenter(
matrixClient = matrixClient
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.CanJoin)
}
}
}
@Test
fun `present - when room is left and not public then join authorization is equal to unknown`() = runTest {
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, isPublic = false)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
}
}
val presenter = createJoinRoomPresenter(
matrixClient = matrixClient
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown)
}
}
}
@Test
fun `present - when room description is provided and room is not found then content state is filled with data`() = runTest {
val roomDescription = aRoomDescription()
val presenter = createJoinRoomPresenter(
roomDescription = Optional.of(roomDescription)
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java)
val contentState = state.contentState.dataOrNull()!!
assertThat(contentState.roomId).isEqualTo(A_ROOM_ID)
assertThat(contentState.name).isEqualTo(roomDescription.name)
assertThat(contentState.description).isEqualTo(roomDescription.description)
assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers)
assertThat(contentState.isDirect).isFalse()
assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl)
}
}
}
@Test
fun `present - when room description join rule is Knock then join authorization is equal to canKnock`() = runTest {
val roomDescription = aRoomDescription(joinRule = RoomDescription.JoinRule.KNOCK)
val presenter = createJoinRoomPresenter(
roomDescription = Optional.of(roomDescription)
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.CanKnock)
}
}
}
@Test
fun `present - when room description join rule is Public then join authorization is equal to canJoin`() = runTest {
val roomDescription = aRoomDescription(joinRule = RoomDescription.JoinRule.PUBLIC)
val presenter = createJoinRoomPresenter(
roomDescription = Optional.of(roomDescription)
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.CanJoin)
}
}
}
@Test
fun `present - when room description join rule is Unknown then join authorization is equal to unknown`() = runTest {
val roomDescription = aRoomDescription(joinRule = RoomDescription.JoinRule.UNKNOWN)
val presenter = createJoinRoomPresenter(
roomDescription = Optional.of(roomDescription)
)
presenter.test {
skipItems(1)
awaitItem().also { state ->
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown)
}
}
}
private fun createJoinRoomPresenter(
roomId: RoomId = A_ROOM_ID,
roomDescription: Optional<RoomDescription> = Optional.empty(),
matrixClient: MatrixClient = FakeMatrixClient(),
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() }
): JoinRoomPresenter {
return JoinRoomPresenter(
roomId = roomId,
roomDescription = roomDescription,
matrixClient = matrixClient,
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter
)
}
private fun aRoomDescription(
roomId: RoomId = A_ROOM_ID,
name: String = A_ROOM_NAME,
description: String = "A room about something",
avatarUrl: String? = null,
joinRule: RoomDescription.JoinRule = RoomDescription.JoinRule.UNKNOWN,
numberOfMembers: Long = 2L
): RoomDescription {
return RoomDescription(
roomId = roomId,
name = name,
description = description,
avatarUrl = avatarUrl,
joinRule = joinRule,
numberOfMembers = numberOfMembers
)
}
}

View file

@ -28,10 +28,18 @@ data class RoomDescription(
val name: String, val name: String,
val description: String, val description: String,
val avatarUrl: String?, val avatarUrl: String?,
val canBeJoined: Boolean, val joinRule: JoinRule,
val numberOfMembers: Long, val numberOfMembers: Long,
) : Parcelable { ) : Parcelable {
enum class JoinRule {
PUBLIC,
KNOCK,
UNKNOWN
}
fun canBeJoined() = joinRule == JoinRule.PUBLIC || joinRule == JoinRule.KNOCK
fun avatarData(size: AvatarSize) = AvatarData( fun avatarData(size: AvatarSize) = AvatarData(
id = roomId.value, id = roomId.value,
name = name, name = name,

View file

@ -70,7 +70,7 @@ fun aRoomDescriptionList(): ImmutableList<RoomDescription> {
name = "Element X Android", name = "Element X Android",
description = "Element X is a secure, private and decentralized messenger.", description = "Element X is a secure, private and decentralized messenger.",
avatarUrl = null, avatarUrl = null,
canBeJoined = true, joinRule = RoomDescription.JoinRule.PUBLIC,
numberOfMembers = 2765, numberOfMembers = 2765,
), ),
RoomDescription( RoomDescription(
@ -78,7 +78,7 @@ fun aRoomDescriptionList(): ImmutableList<RoomDescription> {
name = "Element X iOS", name = "Element X iOS",
description = "Element X is a secure, private and decentralized messenger.", description = "Element X is a secure, private and decentralized messenger.",
avatarUrl = null, avatarUrl = null,
canBeJoined = false, joinRule = RoomDescription.JoinRule.UNKNOWN,
numberOfMembers = 356, numberOfMembers = 356,
) )
) )

View file

@ -274,7 +274,7 @@ private fun RoomDirectoryRoomRow(
Row( Row(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.clickable(enabled = roomDescription.canBeJoined, onClick = onClick) .clickable(onClick = onClick)
.padding( .padding(
top = 12.dp, top = 12.dp,
bottom = 12.dp, bottom = 12.dp,
@ -306,7 +306,7 @@ private fun RoomDirectoryRoomRow(
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
} }
if (roomDescription.canBeJoined) { if (roomDescription.canBeJoined()) {
Text( Text(
text = stringResource(id = CommonStrings.action_join), text = stringResource(id = CommonStrings.action_join),
color = ElementTheme.colors.textSuccessPrimary, color = ElementTheme.colors.textSuccessPrimary,

View file

@ -44,6 +44,10 @@ fun MatrixRoomDescription.toFeatureModel(): RoomDescription {
description = description(), description = description(),
avatarUrl = avatarUrl, avatarUrl = avatarUrl,
numberOfMembers = numberOfMembers, numberOfMembers = numberOfMembers,
canBeJoined = joinRule == MatrixRoomDescription.JoinRule.PUBLIC, joinRule = when (joinRule) {
MatrixRoomDescription.JoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC
MatrixRoomDescription.JoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK
MatrixRoomDescription.JoinRule.UNKNOWN -> RoomDescription.JoinRule.UNKNOWN
}
) )
} }