Resolve RoomId in RoomFlowNode.

This commit is contained in:
Benoit Marty 2024-04-16 15:16:53 +02:00 committed by Benoit Marty
parent 09faa6d1c9
commit 235ef2a71b
9 changed files with 98 additions and 51 deletions

View file

@ -43,17 +43,19 @@ import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.designsystem.components.async.AsyncFailure
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient
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.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import timber.log.Timber
import java.util.Optional
@ -87,43 +89,72 @@ class RoomFlowNode @AssistedInject constructor(
data object Loading : NavTarget
@Parcelize
data object JoinRoom : NavTarget
data class JoinRoom(val roomId: RoomId) : NavTarget
@Parcelize
data class RoomAliasError(val roomAlias: RoomAlias) : NavTarget
@Parcelize
data class JoinedRoom(val roomId: RoomId) : NavTarget
}
private var roomMembershipJob: Job? = null
override fun onBuilt() {
super.onBuilt()
resolveRoomId()
}
private fun resolveRoomId() {
lifecycleScope.launch {
when (val i = inputs.roomIdOrAlias) {
is RoomIdOrAlias.Alias -> {
client.resolveRoomAlias(i.roomAlias)
.onFailure {
Timber.e(it, "Failed to resolve room alias")
backstack.newRoot(NavTarget.RoomAliasError(i.roomAlias))
}
.onSuccess {
subscribeToRoomInfoFlow(it)
}
}
is RoomIdOrAlias.Id -> {
subscribeToRoomInfoFlow(i.roomId)
}
}
}
}
private fun subscribeToRoomInfoFlow(roomId: RoomId) {
client.getRoomInfoFlow(
inputs.roomIdOrAlias
roomId
).onEach { roomInfo ->
Timber.d("Room membership: ${roomInfo.map { it.currentUserMembership }}")
val info = roomInfo.getOrNull()
if (info?.currentUserMembership == CurrentUserMembership.JOINED) {
backstack.newRoot(NavTarget.JoinedRoom(info.id))
// When leaving the room from this session only, navigate up.
roomMembershipJob?.cancel()
roomMembershipJob = roomMembershipObserver.updates
.filter { update -> update.roomId == info.id && !update.isUserInRoom }
.onEach {
navigateUp()
}
.launchIn(lifecycleScope)
backstack.newRoot(NavTarget.JoinedRoom(roomId))
} else {
backstack.newRoot(NavTarget.JoinRoom)
backstack.newRoot(NavTarget.JoinRoom(roomId))
}
}
.launchIn(lifecycleScope)
// When leaving the room from this session only, navigate up.
roomMembershipObserver.updates
.filter { update -> update.roomId == roomId && !update.isUserInRoom }
.onEach {
navigateUp()
}
.launchIn(lifecycleScope)
}
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.Loading -> loadingNode(buildContext)
NavTarget.JoinRoom -> {
val inputs = JoinRoomEntryPoint.Inputs(inputs.roomIdOrAlias, roomDescription = inputs.roomDescription)
is NavTarget.JoinRoom -> {
val inputs = JoinRoomEntryPoint.Inputs(
roomId = navTarget.roomId,
roomIdOrAlias = inputs.roomIdOrAlias,
roomDescription = inputs.roomDescription,
)
joinRoomEntryPoint.createNode(this, buildContext, inputs)
}
is NavTarget.JoinedRoom -> {
@ -131,6 +162,7 @@ class RoomFlowNode @AssistedInject constructor(
val inputs = JoinedRoomFlowNode.Inputs(navTarget.roomId, initialElement = inputs.initialElement)
createNode<JoinedRoomFlowNode>(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback)
}
is NavTarget.RoomAliasError -> roomAliasErrorNode(buildContext, navTarget.roomAlias)
}
}
@ -140,6 +172,15 @@ class RoomFlowNode @AssistedInject constructor(
}
}
private fun roomAliasErrorNode(buildContext: BuildContext, roomAlias: RoomAlias) = node(buildContext) {
Box(modifier = it.fillMaxSize(), contentAlignment = Alignment.Center) {
AsyncFailure(
throwable = Exception("Unable to resolve alias ${roomAlias.value}"),
onRetry = { resolveRoomId() },
)
}
}
@Composable
override fun View(modifier: Modifier) {
BackstackView(transitionHandler = JumpToEndTransitionHandler())