Room join : add presenter tests
This commit is contained in:
parent
fbb92f0c9a
commit
ab8c31541b
10 changed files with 410 additions and 88 deletions
|
|
@ -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.room.CurrentUserMembership
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import java.util.Optional
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
class JoinRoomPresenter @AssistedInject constructor(
|
||||
@Assisted private val roomId: RoomId,
|
||||
|
|
@ -49,8 +49,6 @@ class JoinRoomPresenter @AssistedInject constructor(
|
|||
@Composable
|
||||
override fun present(): JoinRoomState {
|
||||
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) {
|
||||
value = when {
|
||||
roomInfo.isPresent -> {
|
||||
|
|
@ -61,20 +59,25 @@ class JoinRoomPresenter @AssistedInject constructor(
|
|||
val contentState = roomDescription.get().toContentState()
|
||||
AsyncData.Success(contentState)
|
||||
}
|
||||
else -> AsyncData.Uninitialized
|
||||
else -> {
|
||||
AsyncData.Uninitialized
|
||||
}
|
||||
}
|
||||
}
|
||||
val acceptDeclineInviteState = acceptDeclineInvitePresenter.present()
|
||||
|
||||
fun handleEvents(event: JoinRoomEvents) {
|
||||
when (event) {
|
||||
JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> {
|
||||
val inviteData = contentState.toInviteData() ?: return
|
||||
acceptDeclineInviteState.eventSink(
|
||||
AcceptDeclineInviteEvents.AcceptInvite(contentState.toInviteData())
|
||||
AcceptDeclineInviteEvents.AcceptInvite(inviteData)
|
||||
)
|
||||
}
|
||||
JoinRoomEvents.DeclineInvite -> {
|
||||
val inviteData = contentState.toInviteData() ?: return
|
||||
acceptDeclineInviteState.eventSink(
|
||||
AcceptDeclineInviteEvents.DeclineInvite(contentState.toInviteData())
|
||||
AcceptDeclineInviteEvents.DeclineInvite(inviteData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -82,66 +85,69 @@ class JoinRoomPresenter @AssistedInject constructor(
|
|||
|
||||
return JoinRoomState(
|
||||
contentState = contentState,
|
||||
joinAuthorisationStatus = joinAuthorisationStatus,
|
||||
acceptDeclineInviteState = acceptDeclineInviteState,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun RoomDescription.toContentState(): ContentState {
|
||||
return ContentState(
|
||||
roomId = roomId,
|
||||
name = name,
|
||||
description = description,
|
||||
numberOfMembers = numberOfMembers,
|
||||
isDirect = false,
|
||||
roomAvatarUrl = avatarUrl
|
||||
)
|
||||
}
|
||||
|
||||
private fun MatrixRoomInfo.toContentState(): ContentState {
|
||||
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
|
||||
@VisibleForTesting
|
||||
internal fun RoomDescription.toContentState(): ContentState {
|
||||
return ContentState(
|
||||
roomId = roomId,
|
||||
name = name,
|
||||
description = description,
|
||||
numberOfMembers = numberOfMembers,
|
||||
isDirect = false,
|
||||
roomAvatarUrl = avatarUrl,
|
||||
joinAuthorisationStatus = when (joinRule) {
|
||||
RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock
|
||||
RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
|||
@Immutable
|
||||
data class JoinRoomState(
|
||||
val contentState: AsyncData<ContentState>,
|
||||
val joinAuthorisationStatus: JoinAuthorisationStatus,
|
||||
val acceptDeclineInviteState: AcceptDeclineInviteState,
|
||||
val eventSink: (JoinRoomEvents) -> Unit
|
||||
)
|
||||
) {
|
||||
val joinAuthorisationStatus = contentState.dataOrNull()?.joinAuthorisationStatus ?: JoinAuthorisationStatus.Unknown
|
||||
}
|
||||
|
||||
data class ContentState(
|
||||
val roomId: RoomId,
|
||||
|
|
@ -38,6 +39,7 @@ data class ContentState(
|
|||
val numberOfMembers: Long?,
|
||||
val isDirect: Boolean,
|
||||
val roomAvatarUrl: String?,
|
||||
val joinAuthorisationStatus: JoinAuthorisationStatus,
|
||||
) {
|
||||
|
||||
val showMemberCount = numberOfMembers != null
|
||||
|
|
|
|||
|
|
@ -29,34 +29,49 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
|
|||
contentState = AsyncData.Uninitialized
|
||||
),
|
||||
aJoinRoomState(
|
||||
joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin
|
||||
contentState = AsyncData.Success(
|
||||
aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin)
|
||||
)
|
||||
),
|
||||
aJoinRoomState(
|
||||
joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock
|
||||
contentState = AsyncData.Success(
|
||||
aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock)
|
||||
)
|
||||
),
|
||||
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(
|
||||
contentState: AsyncData<ContentState> = AsyncData.Success(
|
||||
ContentState(
|
||||
roomId = RoomId("@exa:matrix.org"),
|
||||
name = "Element x android",
|
||||
description = "#exa:matrix.org",
|
||||
numberOfMembers = null,
|
||||
isDirect = false,
|
||||
roomAvatarUrl = null
|
||||
)
|
||||
aContentState()
|
||||
),
|
||||
joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown,
|
||||
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
|
||||
eventSink: (JoinRoomEvents) -> Unit = {}
|
||||
) = JoinRoomState(
|
||||
contentState = contentState,
|
||||
joinAuthorisationStatus = joinAuthorisationStatus,
|
||||
acceptDeclineInviteState = acceptDeclineInviteState,
|
||||
eventSink = eventSink
|
||||
)
|
||||
|
|
|
|||
|
|
@ -109,8 +109,7 @@ private fun JoinRoomFooter(
|
|||
)
|
||||
}
|
||||
}
|
||||
// TODO handle all cases properly
|
||||
else -> {
|
||||
JoinAuthorisationStatus.CanJoin -> {
|
||||
Button(
|
||||
text = stringResource(CommonStrings.action_join),
|
||||
onClick = onJoinRoom,
|
||||
|
|
@ -118,6 +117,18 @@ private fun JoinRoomFooter(
|
|||
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(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 16.dp),
|
||||
.fillMaxWidth()
|
||||
.padding(all = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
when (asyncContentState) {
|
||||
|
|
@ -191,9 +202,9 @@ private fun JoinRoomMembersCount(memberCount: Long) {
|
|||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape)
|
||||
.widthIn(min = 48.dp)
|
||||
.padding(all = 2.dp),
|
||||
.background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape)
|
||||
.widthIn(min = 48.dp)
|
||||
.padding(all = 2.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue