diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index fa161554cd..940e576a30 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -20,11 +20,20 @@ import androidx.lifecycle.repeatOnLifecycle import com.bumble.appyx.core.composable.PermanentChild import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.navigation.NavElements +import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.core.plugin.plugins import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.BackStack.State.ACTIVE +import com.bumble.appyx.navmodel.backstack.BackStack.State.CREATED +import com.bumble.appyx.navmodel.backstack.BackStack.State.STASHED +import com.bumble.appyx.navmodel.backstack.BackStackElement +import com.bumble.appyx.navmodel.backstack.BackStackElements +import com.bumble.appyx.navmodel.backstack.operation.BackStackOperation +import com.bumble.appyx.navmodel.backstack.operation.Push import com.bumble.appyx.navmodel.backstack.operation.pop import com.bumble.appyx.navmodel.backstack.operation.push import com.bumble.appyx.navmodel.backstack.operation.replace @@ -312,7 +321,7 @@ class LoggedInFlowNode @AssistedInject constructor( } override fun onForwardedToSingleRoom(roomId: RoomId) { - coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias()) } + coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias(), clearBackstack = false) } } override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) { @@ -472,21 +481,21 @@ class LoggedInFlowNode @AssistedInject constructor( serverNames: List = emptyList(), trigger: JoinedRoom.Trigger? = null, eventId: EventId? = null, + clearBackstack: Boolean, ) { waitForNavTargetAttached { navTarget -> navTarget is NavTarget.RoomList } attachChild { - backstack.push( - NavTarget.Room( - roomIdOrAlias = roomIdOrAlias, - serverNames = serverNames, - trigger = trigger, - initialElement = RoomNavigationTarget.Messages( - focusedEventId = eventId - ) + val roomNavTarget = NavTarget.Room( + roomIdOrAlias = roomIdOrAlias, + serverNames = serverNames, + trigger = trigger, + initialElement = RoomNavigationTarget.Messages( + focusedEventId = eventId ) ) + backstack.accept(AttachRoomOperation(roomNavTarget, clearBackstack)) } } @@ -531,3 +540,31 @@ class LoggedInFlowNode @AssistedInject constructor( @Assisted plugins: List, ) : Node(buildContext, plugins = plugins) } + +@Parcelize +private class AttachRoomOperation( + val roomTarget: LoggedInFlowNode.NavTarget.Room, + val clearBackstack: Boolean, +) : BackStackOperation { + override fun isApplicable(elements: NavElements) = true + + override fun invoke(elements: BackStackElements): BackStackElements { + return if (clearBackstack) { + // Makes sure the room list target is alone in the backstack and stashed + elements.mapNotNull { element -> + if (element.key.navTarget == LoggedInFlowNode.NavTarget.RoomList) { + element.transitionTo(STASHED, this) + } else { + null + } + } + BackStackElement( + key = NavKey(roomTarget), + fromState = CREATED, + targetState = ACTIVE, + operation = this + ) + } else { + Push(roomTarget).invoke(elements) + } + } +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index 53f6de6032..143595d934 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -303,6 +303,7 @@ class RootFlowNode @AssistedInject constructor( trigger = JoinedRoom.Trigger.MobilePermalink, serverNames = permalinkData.viaParameters, eventId = permalinkData.eventId, + clearBackstack = true ) } is PermalinkData.UserLink -> { @@ -318,7 +319,7 @@ class RootFlowNode @AssistedInject constructor( .apply { when (deeplinkData) { is DeeplinkData.Root -> Unit // The room list will always be shown, observing FtueState - is DeeplinkData.Room -> attachRoom(deeplinkData.roomId.toRoomIdOrAlias()) + is DeeplinkData.Room -> attachRoom(deeplinkData.roomId.toRoomIdOrAlias(), clearBackstack = true) } } }