Alias permalink navigation - WIP

This commit is contained in:
Benoit Marty 2024-04-16 12:20:25 +02:00 committed by Benoit Marty
parent a602849ec5
commit c1188ebb2d
12 changed files with 137 additions and 68 deletions

View file

@ -66,6 +66,8 @@ import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.MAIN_SPACE
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.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.sync.SyncState
import io.element.android.services.appnavstate.api.AppNavigationStateService
@ -190,7 +192,7 @@ class LoggedInFlowNode @AssistedInject constructor(
@Parcelize
data class Room(
val roomId: RoomId,
val roomIdOrAlias: RoomIdOrAlias,
val roomDescription: RoomDescription? = null,
val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages(null)
) : NavTarget
@ -229,7 +231,7 @@ class LoggedInFlowNode @AssistedInject constructor(
NavTarget.RoomList -> {
val callback = object : RoomListEntryPoint.Callback {
override fun onRoomClicked(roomId: RoomId) {
backstack.push(NavTarget.Room(roomId))
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
}
override fun onSettingsClicked() {
@ -245,7 +247,7 @@ class LoggedInFlowNode @AssistedInject constructor(
}
override fun onRoomSettingsClicked(roomId: RoomId) {
backstack.push(NavTarget.Room(roomId, initialElement = RoomNavigationTarget.Details))
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), initialElement = RoomNavigationTarget.Details))
}
override fun onReportBugClicked() {
@ -264,7 +266,7 @@ class LoggedInFlowNode @AssistedInject constructor(
is NavTarget.Room -> {
val callback = object : JoinedRoomLoadedFlowNode.Callback {
override fun onOpenRoom(roomId: RoomId) {
backstack.push(NavTarget.Room(roomId))
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
}
override fun onForwardedToSingleRoom(roomId: RoomId) {
@ -279,20 +281,23 @@ class LoggedInFlowNode @AssistedInject constructor(
Timber.e("User link clicked: ${data.userId}. TODO Add a user profile screen")
}
is PermalinkData.RoomIdLink -> {
backstack.push(NavTarget.Room(data.roomId))
backstack.push(NavTarget.Room(data.roomId.toRoomIdOrAlias()))
}
is PermalinkData.RoomAliasLink -> {
// FIXME Implement room alias navigation
Timber.e("Room alias link clicked: ${data.roomAlias}. TODO Handle a room alias navigation")
backstack.push(NavTarget.Room(data.roomAlias.toRoomIdOrAlias()))
}
is PermalinkData.EventIdAliasLink -> {
// FIXME Implement event alias navigation
Timber.e("Event with room alias link clicked: ${data.eventId}. TODO Handle an event with room alias navigation")
backstack.push(
NavTarget.Room(
data.roomAlias.toRoomIdOrAlias(),
initialElement = RoomNavigationTarget.Messages(data.eventId)
)
)
}
is PermalinkData.EventIdLink -> {
backstack.push(
NavTarget.Room(
data.roomId,
data.roomId.toRoomIdOrAlias(),
initialElement = RoomNavigationTarget.Messages(data.eventId)
)
)
@ -310,7 +315,7 @@ class LoggedInFlowNode @AssistedInject constructor(
}
}
val inputs = RoomFlowNode.Inputs(
roomId = navTarget.roomId,
roomIdOrAlias = navTarget.roomIdOrAlias,
roomDescription = Optional.ofNullable(navTarget.roomDescription),
initialElement = navTarget.initialElement
)
@ -327,7 +332,7 @@ class LoggedInFlowNode @AssistedInject constructor(
}
override fun onOpenRoomNotificationSettings(roomId: RoomId) {
backstack.push(NavTarget.Room(roomId, initialElement = RoomNavigationTarget.NotificationSettings))
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), initialElement = RoomNavigationTarget.NotificationSettings))
}
}
val inputs = PreferencesEntryPoint.Params(navTarget.initialElement)
@ -339,7 +344,7 @@ class LoggedInFlowNode @AssistedInject constructor(
NavTarget.CreateRoom -> {
val callback = object : CreateRoomEntryPoint.Callback {
override fun onSuccess(roomId: RoomId) {
backstack.replace(NavTarget.Room(roomId))
backstack.replace(NavTarget.Room(roomId.toRoomIdOrAlias()))
}
}
@ -366,11 +371,11 @@ class LoggedInFlowNode @AssistedInject constructor(
roomDirectoryEntryPoint.nodeBuilder(this, buildContext)
.callback(object : RoomDirectoryEntryPoint.Callback {
override fun onRoomJoined(roomId: RoomId) {
backstack.push(NavTarget.Room(roomId))
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
}
override fun onResultClicked(roomDescription: RoomDescription) {
backstack.push(NavTarget.Room(roomDescription.roomId, roomDescription))
backstack.push(NavTarget.Room(roomDescription.roomId.toRoomIdOrAlias(), roomDescription))
}
})
.build()
@ -389,7 +394,7 @@ class LoggedInFlowNode @AssistedInject constructor(
if (!canShowRoomList()) return
attachChild<RoomFlowNode> {
backstack.singleTop(NavTarget.RoomList)
backstack.push(NavTarget.Room(roomId))
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
}
}

View file

@ -47,8 +47,10 @@ import io.element.android.libraries.designsystem.theme.components.CircularProgre
import io.element.android.libraries.di.SessionScope
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.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
@ -73,7 +75,7 @@ class RoomFlowNode @AssistedInject constructor(
plugins = plugins
) {
data class Inputs(
val roomId: RoomId,
val roomIdOrAlias: RoomIdOrAlias,
val roomDescription: Optional<RoomDescription>,
val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages(),
) : NodeInputs
@ -88,42 +90,45 @@ class RoomFlowNode @AssistedInject constructor(
data object JoinRoom : NavTarget
@Parcelize
data object JoinedRoom : NavTarget
data class JoinedRoom(val roomId: RoomId) : NavTarget
}
private var roomMembershipJob: Job? = null
override fun onBuilt() {
super.onBuilt()
client.getRoomInfoFlow(
inputs.roomId
inputs.roomIdOrAlias
).onEach { roomInfo ->
Timber.d("Room membership: ${roomInfo.map { it.currentUserMembership }}")
if (roomInfo.getOrNull()?.currentUserMembership == CurrentUserMembership.JOINED) {
backstack.newRoot(NavTarget.JoinedRoom)
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)
} else {
backstack.newRoot(NavTarget.JoinRoom)
}
}
.launchIn(lifecycleScope)
// When leaving the room from this session only, navigate up.
roomMembershipObserver.updates
.filter { update -> update.roomId == inputs.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.roomId, roomDescription = inputs.roomDescription)
val inputs = JoinRoomEntryPoint.Inputs(inputs.roomIdOrAlias, roomDescription = inputs.roomDescription)
joinRoomEntryPoint.createNode(this, buildContext, inputs)
}
NavTarget.JoinedRoom -> {
is NavTarget.JoinedRoom -> {
val roomFlowNodeCallback = plugins<JoinedRoomLoadedFlowNode.Callback>()
val inputs = JoinedRoomFlowNode.Inputs(inputs.roomId, initialElement = inputs.initialElement)
val inputs = JoinedRoomFlowNode.Inputs(navTarget.roomId, initialElement = inputs.initialElement)
createNode<JoinedRoomFlowNode>(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback)
}
}