Browse Source

BackstackParentNode now become BaseFlowNode and adds Overlay navModel into it.

pull/2059/head
ganfra 9 months ago
parent
commit
78bd6915c7
  1. 12
      appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
  2. 12
      appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt
  3. 11
      appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
  4. 10
      appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt
  5. 11
      appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt
  6. 11
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt
  7. 11
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt
  8. 11
      features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt
  9. 11
      features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/LockScreenFlowNode.kt
  10. 11
      features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsFlowNode.kt
  11. 11
      features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/LockScreenSetupFlowNode.kt
  12. 12
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt
  13. 36
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt
  14. 11
      features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryFlowNode.kt
  15. 11
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt
  16. 11
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
  17. 11
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt
  18. 57
      libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BackstackNode.kt
  19. 106
      libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BaseFlowNode.kt

12
appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt

@ -57,7 +57,8 @@ import io.element.android.features.preferences.api.PreferencesEntryPoint
import io.element.android.features.roomlist.api.RoomListEntryPoint import io.element.android.features.roomlist.api.RoomListEntryPoint
import io.element.android.features.securebackup.api.SecureBackupEntryPoint import io.element.android.features.securebackup.api.SecureBackupEntryPoint
import io.element.android.features.verifysession.api.VerifySessionEntryPoint import io.element.android.features.verifysession.api.VerifySessionEntryPoint
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.waitForChildAttached import io.element.android.libraries.architecture.waitForChildAttached
@ -100,7 +101,7 @@ class LoggedInFlowNode @AssistedInject constructor(
private val lockScreenStateService: LockScreenService, private val lockScreenStateService: LockScreenService,
private val matrixClient: MatrixClient, private val matrixClient: MatrixClient,
snackbarDispatcher: SnackbarDispatcher, snackbarDispatcher: SnackbarDispatcher,
) : BackstackNode<LoggedInFlowNode.NavTarget>( ) : BaseFlowNode<LoggedInFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.RoomList, initialElement = NavTarget.RoomList,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -384,12 +385,7 @@ class LoggedInFlowNode @AssistedInject constructor(
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Box(modifier = modifier) { Box(modifier = modifier) {
val lockScreenState by lockScreenStateService.lockState.collectAsState() val lockScreenState by lockScreenStateService.lockState.collectAsState()
Children( BackstackView()
navModel = backstack,
modifier = Modifier,
// Animate navigation to settings and to a room
transitionHandler = rememberDefaultTransitionHandler(),
)
val isFtueDisplayed by ftueState.shouldDisplayFlow.collectAsState() val isFtueDisplayed by ftueState.shouldDisplayFlow.collectAsState()
if (!isFtueDisplayed) { if (!isFtueDisplayed) {
PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LoggedInPermanent) PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LoggedInPermanent)

12
appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt

@ -33,7 +33,8 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.login.api.LoginEntryPoint
import io.element.android.features.onboarding.api.OnBoardingEntryPoint import io.element.android.features.onboarding.api.OnBoardingEntryPoint
import io.element.android.features.preferences.api.ConfigureTracingEntryPoint import io.element.android.features.preferences.api.ConfigureTracingEntryPoint
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.ui.media.NotLoggedInImageLoaderFactory import io.element.android.libraries.matrix.ui.media.NotLoggedInImageLoaderFactory
@ -47,7 +48,7 @@ class NotLoggedInFlowNode @AssistedInject constructor(
private val configureTracingEntryPoint: ConfigureTracingEntryPoint, private val configureTracingEntryPoint: ConfigureTracingEntryPoint,
private val loginEntryPoint: LoginEntryPoint, private val loginEntryPoint: LoginEntryPoint,
private val notLoggedInImageLoaderFactory: NotLoggedInImageLoaderFactory, private val notLoggedInImageLoaderFactory: NotLoggedInImageLoaderFactory,
) : BackstackNode<NotLoggedInFlowNode.NavTarget>( ) : BaseFlowNode<NotLoggedInFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.OnBoarding, initialElement = NavTarget.OnBoarding,
savedStateMap = buildContext.savedStateMap savedStateMap = buildContext.savedStateMap
@ -111,11 +112,6 @@ class NotLoggedInFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
// Animate navigation to login screen
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

11
appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt

@ -46,7 +46,8 @@ import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.api.oidc.OidcActionFlow import io.element.android.features.login.api.oidc.OidcActionFlow
import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint
import io.element.android.features.signedout.api.SignedOutEntryPoint import io.element.android.features.signedout.api.SignedOutEntryPoint
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.waitForChildAttached import io.element.android.libraries.architecture.waitForChildAttached
@ -74,7 +75,7 @@ class RootFlowNode @AssistedInject constructor(
private val signedOutEntryPoint: SignedOutEntryPoint, private val signedOutEntryPoint: SignedOutEntryPoint,
private val intentResolver: IntentResolver, private val intentResolver: IntentResolver,
private val oidcActionFlow: OidcActionFlow, private val oidcActionFlow: OidcActionFlow,
) : BackstackNode<RootFlowNode.NavTarget>( ) : BaseFlowNode<RootFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.SplashScreen, initialElement = NavTarget.SplashScreen,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -172,11 +173,7 @@ class RootFlowNode @AssistedInject constructor(
modifier = modifier, modifier = modifier,
onOpenBugReport = this::onOpenBugReport, onOpenBugReport = this::onOpenBugReport,
) { ) {
Children( BackstackView()
navModel = backstack,
// Animate opening the bug report screen
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

10
appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt

@ -38,7 +38,8 @@ import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkMonitor
import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.networkmonitor.api.NetworkStatus
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
@ -57,7 +58,7 @@ class RoomFlowNode @AssistedInject constructor(
loadingRoomStateFlowFactory: LoadingRoomStateFlowFactory, loadingRoomStateFlowFactory: LoadingRoomStateFlowFactory,
private val networkMonitor: NetworkMonitor, private val networkMonitor: NetworkMonitor,
) : ) :
BackstackNode<RoomFlowNode.NavTarget>( BaseFlowNode<RoomFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Loading, initialElement = NavTarget.Loading,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -130,10 +131,7 @@ class RoomFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
)
} }
} }

11
appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt

@ -35,7 +35,8 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.appnav.di.RoomComponentFactory import io.element.android.appnav.di.RoomComponentFactory
import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.messages.api.MessagesEntryPoint
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
@ -64,7 +65,7 @@ class RoomLoadedFlowNode @AssistedInject constructor(
private val appCoroutineScope: CoroutineScope, private val appCoroutineScope: CoroutineScope,
roomComponentFactory: RoomComponentFactory, roomComponentFactory: RoomComponentFactory,
roomMembershipObserver: RoomMembershipObserver, roomMembershipObserver: RoomMembershipObserver,
) : BackstackNode<RoomLoadedFlowNode.NavTarget>( ) : BaseFlowNode<RoomLoadedFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = plugins.filterIsInstance(Inputs::class.java).first().initialElement, initialElement = plugins.filterIsInstance(Inputs::class.java).first().initialElement,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -202,10 +203,6 @@ class RoomLoadedFlowNode @AssistedInject constructor(
} }
} }
} }
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

11
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt

@ -32,7 +32,8 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.createroom.impl.addpeople.AddPeopleNode import io.element.android.features.createroom.impl.addpeople.AddPeopleNode
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
import io.element.android.features.createroom.impl.di.CreateRoomComponent import io.element.android.features.createroom.impl.di.CreateRoomComponent
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.bindings import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
@ -45,7 +46,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
) : DaggerComponentOwner, ) : DaggerComponentOwner,
BackstackNode<ConfigureRoomFlowNode.NavTarget>( BaseFlowNode<ConfigureRoomFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Root, initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -88,10 +89,6 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler()
)
} }
} }

11
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt

@ -32,7 +32,8 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.createroom.api.CreateRoomEntryPoint
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
import io.element.android.features.createroom.impl.root.CreateRoomRootNode import io.element.android.features.createroom.impl.root.CreateRoomRootNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ -43,7 +44,7 @@ import kotlinx.parcelize.Parcelize
class CreateRoomFlowNode @AssistedInject constructor( class CreateRoomFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
) : BackstackNode<CreateRoomFlowNode.NavTarget>( ) : BaseFlowNode<CreateRoomFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Root, initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -87,10 +88,6 @@ class CreateRoomFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler()
)
} }
} }

11
features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt

@ -40,7 +40,8 @@ import io.element.android.features.ftue.impl.state.DefaultFtueState
import io.element.android.features.ftue.impl.state.FtueStep import io.element.android.features.ftue.impl.state.FtueStep
import io.element.android.features.ftue.impl.welcome.WelcomeNode import io.element.android.features.ftue.impl.welcome.WelcomeNode
import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.features.lockscreen.api.LockScreenEntryPoint
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
@ -62,7 +63,7 @@ class FtueFlowNode @AssistedInject constructor(
private val analyticsEntryPoint: AnalyticsEntryPoint, private val analyticsEntryPoint: AnalyticsEntryPoint,
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
private val lockScreenEntryPoint: LockScreenEntryPoint, private val lockScreenEntryPoint: LockScreenEntryPoint,
) : BackstackNode<FtueFlowNode.NavTarget>( ) : BaseFlowNode<FtueFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Placeholder, initialElement = NavTarget.Placeholder,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -181,11 +182,7 @@ class FtueFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)

11
features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/LockScreenFlowNode.kt

@ -32,7 +32,8 @@ import io.element.android.features.lockscreen.api.LockScreenEntryPoint
import io.element.android.features.lockscreen.impl.settings.LockScreenSettingsFlowNode import io.element.android.features.lockscreen.impl.settings.LockScreenSettingsFlowNode
import io.element.android.features.lockscreen.impl.setup.LockScreenSetupFlowNode import io.element.android.features.lockscreen.impl.setup.LockScreenSetupFlowNode
import io.element.android.features.lockscreen.impl.unlock.PinUnlockNode import io.element.android.features.lockscreen.impl.unlock.PinUnlockNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
@ -43,7 +44,7 @@ import kotlinx.parcelize.Parcelize
class LockScreenFlowNode @AssistedInject constructor( class LockScreenFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
) : BackstackNode<LockScreenFlowNode.NavTarget>( ) : BaseFlowNode<LockScreenFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = plugins.filterIsInstance(Inputs::class.java).first().initialNavTarget, initialElement = plugins.filterIsInstance(Inputs::class.java).first().initialNavTarget,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -93,10 +94,6 @@ class LockScreenFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

11
features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsFlowNode.kt

@ -36,7 +36,8 @@ import io.element.android.features.lockscreen.impl.pin.DefaultPinCodeManagerCall
import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.PinCodeManager
import io.element.android.features.lockscreen.impl.setup.pin.SetupPinNode import io.element.android.features.lockscreen.impl.setup.pin.SetupPinNode
import io.element.android.features.lockscreen.impl.unlock.PinUnlockNode import io.element.android.features.lockscreen.impl.unlock.PinUnlockNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ -49,7 +50,7 @@ class LockScreenSettingsFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val pinCodeManager: PinCodeManager, private val pinCodeManager: PinCodeManager,
) : BackstackNode<LockScreenSettingsFlowNode.NavTarget>( ) : BaseFlowNode<LockScreenSettingsFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Unknown, initialElement = NavTarget.Unknown,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -132,10 +133,6 @@ class LockScreenSettingsFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

11
features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/LockScreenSetupFlowNode.kt

@ -34,7 +34,8 @@ import io.element.android.features.lockscreen.impl.pin.DefaultPinCodeManagerCall
import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.PinCodeManager
import io.element.android.features.lockscreen.impl.setup.biometric.SetupBiometricNode import io.element.android.features.lockscreen.impl.setup.biometric.SetupBiometricNode
import io.element.android.features.lockscreen.impl.setup.pin.SetupPinNode import io.element.android.features.lockscreen.impl.setup.pin.SetupPinNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ -45,7 +46,7 @@ class LockScreenSetupFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val pinCodeManager: PinCodeManager, private val pinCodeManager: PinCodeManager,
) : BackstackNode<LockScreenSetupFlowNode.NavTarget>( ) : BaseFlowNode<LockScreenSetupFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Pin, initialElement = NavTarget.Pin,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -106,10 +107,6 @@ class LockScreenSetupFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

12
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt

@ -48,7 +48,8 @@ import io.element.android.features.login.impl.screens.loginpassword.LoginFormSta
import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordNode import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordNode
import io.element.android.features.login.impl.screens.searchaccountprovider.SearchAccountProviderNode import io.element.android.features.login.impl.screens.searchaccountprovider.SearchAccountProviderNode
import io.element.android.features.login.impl.screens.waitlistscreen.WaitListNode import io.element.android.features.login.impl.screens.waitlistscreen.WaitListNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
@ -68,7 +69,7 @@ class LoginFlowNode @AssistedInject constructor(
private val accountProviderDataSource: AccountProviderDataSource, private val accountProviderDataSource: AccountProviderDataSource,
private val defaultLoginUserStory: DefaultLoginUserStory, private val defaultLoginUserStory: DefaultLoginUserStory,
private val oidcActionFlow: OidcActionFlow, private val oidcActionFlow: OidcActionFlow,
) : BackstackNode<LoginFlowNode.NavTarget>( ) : BaseFlowNode<LoginFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.ConfirmAccountProvider, initialElement = NavTarget.ConfirmAccountProvider,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -217,11 +218,6 @@ class LoginFlowNode @AssistedInject constructor(
accountProviderDataSource.reset() accountProviderDataSource.reset()
} }
} }
Children( BackstackView()
navModel = backstack,
modifier = modifier,
// Animate transition to change server screen
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

36
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt

@ -20,9 +20,9 @@ import android.content.Context
import android.os.Parcelable import android.os.Parcelable
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.composable.Children
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.node.node
import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStack
@ -49,9 +49,11 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
import io.element.android.features.poll.api.create.CreatePollEntryPoint import io.element.android.features.poll.api.create.CreatePollEntryPoint
import io.element.android.features.poll.api.create.CreatePollMode import io.element.android.features.poll.api.create.CreatePollMode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackWithOverlayBox
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.overlay.Overlay
import io.element.android.libraries.architecture.overlay.operation.show
import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
@ -74,16 +76,23 @@ class MessagesFlowNode @AssistedInject constructor(
private val sendLocationEntryPoint: SendLocationEntryPoint, private val sendLocationEntryPoint: SendLocationEntryPoint,
private val showLocationEntryPoint: ShowLocationEntryPoint, private val showLocationEntryPoint: ShowLocationEntryPoint,
private val createPollEntryPoint: CreatePollEntryPoint, private val createPollEntryPoint: CreatePollEntryPoint,
) : BackstackNode<MessagesFlowNode.NavTarget>( ) : BaseFlowNode<MessagesFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Messages, initialElement = NavTarget.Messages,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
), ),
overlay = Overlay(
savedStateMap = buildContext.savedStateMap,
),
buildContext = buildContext, buildContext = buildContext,
plugins = plugins plugins = plugins
) { ) {
sealed interface NavTarget : Parcelable { sealed interface NavTarget : Parcelable {
@Parcelize
data object Empty : NavTarget
@Parcelize @Parcelize
data object Messages : NavTarget data object Messages : NavTarget
@ -223,6 +232,9 @@ class MessagesFlowNode @AssistedInject constructor(
.params(CreatePollEntryPoint.Params(mode = CreatePollMode.EditPoll(eventId = navTarget.eventId))) .params(CreatePollEntryPoint.Params(mode = CreatePollMode.EditPoll(eventId = navTarget.eventId)))
.build() .build()
} }
NavTarget.Empty -> {
node(buildContext) {}
}
} }
} }
@ -239,7 +251,7 @@ class MessagesFlowNode @AssistedInject constructor(
mediaSource = event.content.mediaSource, mediaSource = event.content.mediaSource,
thumbnailSource = event.content.thumbnailSource, thumbnailSource = event.content.thumbnailSource,
) )
backstack.push(navTarget) overlay.show(navTarget)
} }
is TimelineItemVideoContent -> { is TimelineItemVideoContent -> {
val navTarget = NavTarget.MediaViewer( val navTarget = NavTarget.MediaViewer(
@ -252,7 +264,7 @@ class MessagesFlowNode @AssistedInject constructor(
mediaSource = event.content.videoSource, mediaSource = event.content.videoSource,
thumbnailSource = event.content.thumbnailSource, thumbnailSource = event.content.thumbnailSource,
) )
backstack.push(navTarget) overlay.show(navTarget)
} }
is TimelineItemFileContent -> { is TimelineItemFileContent -> {
val navTarget = NavTarget.MediaViewer( val navTarget = NavTarget.MediaViewer(
@ -265,7 +277,7 @@ class MessagesFlowNode @AssistedInject constructor(
mediaSource = event.content.fileSource, mediaSource = event.content.fileSource,
thumbnailSource = event.content.thumbnailSource, thumbnailSource = event.content.thumbnailSource,
) )
backstack.push(navTarget) overlay.show(navTarget)
} }
is TimelineItemAudioContent -> { is TimelineItemAudioContent -> {
val navTarget = NavTarget.MediaViewer( val navTarget = NavTarget.MediaViewer(
@ -278,14 +290,14 @@ class MessagesFlowNode @AssistedInject constructor(
mediaSource = event.content.mediaSource, mediaSource = event.content.mediaSource,
thumbnailSource = null, thumbnailSource = null,
) )
backstack.push(navTarget) overlay.show(navTarget)
} }
is TimelineItemLocationContent -> { is TimelineItemLocationContent -> {
val navTarget = NavTarget.LocationViewer( val navTarget = NavTarget.LocationViewer(
location = event.content.location, location = event.content.location,
description = event.content.description, description = event.content.description,
) )
backstack.push(navTarget) overlay.show(navTarget)
} }
else -> Unit else -> Unit
} }
@ -293,10 +305,6 @@ class MessagesFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackWithOverlayBox(modifier)
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

11
features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryFlowNode.kt

@ -30,7 +30,8 @@ import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.poll.api.create.CreatePollEntryPoint import io.element.android.features.poll.api.create.CreatePollEntryPoint
import io.element.android.features.poll.api.create.CreatePollMode import io.element.android.features.poll.api.create.CreatePollMode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
@ -42,7 +43,7 @@ class PollHistoryFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val createPollEntryPoint: CreatePollEntryPoint, private val createPollEntryPoint: CreatePollEntryPoint,
) : BackstackNode<PollHistoryFlowNode.NavTarget>( ) : BaseFlowNode<PollHistoryFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Root, initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -82,11 +83,7 @@ class PollHistoryFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler()
)
} }
} }

11
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt

@ -41,7 +41,8 @@ import io.element.android.features.preferences.impl.notifications.NotificationSe
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingNode import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingNode
import io.element.android.features.preferences.impl.root.PreferencesRootNode import io.element.android.features.preferences.impl.root.PreferencesRootNode
import io.element.android.features.preferences.impl.user.editprofile.EditUserProfileNode import io.element.android.features.preferences.impl.user.editprofile.EditUserProfileNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ -55,7 +56,7 @@ class PreferencesFlowNode @AssistedInject constructor(
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val lockScreenEntryPoint: LockScreenEntryPoint, private val lockScreenEntryPoint: LockScreenEntryPoint,
private val logoutEntryPoint: LogoutEntryPoint, private val logoutEntryPoint: LogoutEntryPoint,
) : BackstackNode<PreferencesFlowNode.NavTarget>( ) : BaseFlowNode<PreferencesFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = plugins.filterIsInstance<PreferencesEntryPoint.Params>().first().initialElement.toNavTarget(), initialElement = plugins.filterIsInstance<PreferencesEntryPoint.Params>().first().initialElement.toNavTarget(),
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -210,10 +211,6 @@ class PreferencesFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler()
)
} }
} }

11
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt

@ -37,7 +37,8 @@ import io.element.android.features.roomdetails.impl.members.RoomMemberListNode
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsNode import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsNode
import io.element.android.features.roomdetails.impl.members.details.avatar.AvatarPreviewNode import io.element.android.features.roomdetails.impl.members.details.avatar.AvatarPreviewNode
import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsNode import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes
@ -54,7 +55,7 @@ class RoomDetailsFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val pollHistoryEntryPoint: PollHistoryEntryPoint, private val pollHistoryEntryPoint: PollHistoryEntryPoint,
) : BackstackNode<RoomDetailsFlowNode.NavTarget>( ) : BaseFlowNode<RoomDetailsFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = plugins.filterIsInstance<RoomDetailsEntryPoint.Params>().first().initialElement.toNavTarget(), initialElement = plugins.filterIsInstance<RoomDetailsEntryPoint.Params>().first().initialElement.toNavTarget(),
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -196,10 +197,6 @@ class RoomDetailsFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler(),
)
} }
} }

11
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt

@ -33,7 +33,8 @@ import io.element.android.features.securebackup.impl.enable.SecureBackupEnableNo
import io.element.android.features.securebackup.impl.enter.SecureBackupEnterRecoveryKeyNode import io.element.android.features.securebackup.impl.enter.SecureBackupEnterRecoveryKeyNode
import io.element.android.features.securebackup.impl.root.SecureBackupRootNode import io.element.android.features.securebackup.impl.root.SecureBackupRootNode
import io.element.android.features.securebackup.impl.setup.SecureBackupSetupNode import io.element.android.features.securebackup.impl.setup.SecureBackupSetupNode
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ -43,7 +44,7 @@ import kotlinx.parcelize.Parcelize
class SecureBackupFlowNode @AssistedInject constructor( class SecureBackupFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
) : BackstackNode<SecureBackupFlowNode.NavTarget>( ) : BaseFlowNode<SecureBackupFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.Root, initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap, savedStateMap = buildContext.savedStateMap,
@ -124,10 +125,6 @@ class SecureBackupFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Children( BackstackView()
navModel = backstack,
modifier = modifier,
transitionHandler = rememberDefaultTransitionHandler()
)
} }
} }

57
libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BackstackNode.kt

@ -1,57 +0,0 @@
/*
* Copyright (c) 2023 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.libraries.architecture
import androidx.compose.runtime.Stable
import com.bumble.appyx.core.children.ChildEntry
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.navigation.model.combined.plus
import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.node.ParentNode
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.navmodel.backstack.BackStack
/**
* This class is just an helper for configuring a backstack directly in the constructor.
* With this we can more easily use constructor injection without having a secondary constructor to create the [BackStack] instance.
* Can be used instead of [ParentNode] in flow nodes.
*/
@Stable
abstract class BackstackNode<NavTarget : Any>(
val backstack: BackStack<NavTarget>,
buildContext: BuildContext,
plugins: List<Plugin>,
val permanentNavModel: PermanentNavModel<NavTarget> = PermanentNavModel(emptySet(), null),
childKeepMode: ChildEntry.KeepMode = ChildEntry.KeepMode.KEEP,
) : ParentNode<NavTarget>(
navModel = backstack + permanentNavModel,
buildContext = buildContext,
plugins = plugins,
childKeepMode = childKeepMode,
) {
override fun onBuilt() {
super.onBuilt()
lifecycle.logLifecycle(this::class.java.simpleName)
whenChildAttached<Node> { _, child ->
// BackstackNode will be logged by their parent.
if (child !is BackstackNode<*>) {
child.lifecycle.logLifecycle(child::class.java.simpleName)
}
}
}
}

106
libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BaseFlowNode.kt

@ -0,0 +1,106 @@
/*
* Copyright (c) 2023 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.libraries.architecture
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.children.ChildEntry
import com.bumble.appyx.core.composable.Children
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.navigation.model.combined.plus
import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel
import com.bumble.appyx.core.navigation.transition.TransitionHandler
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.node.ParentNode
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.navmodel.backstack.BackStack
import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackFader
import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackSlider
import io.element.android.libraries.architecture.overlay.Overlay
/**
* This class is a [ParentNode] that contains a [BackStack] and an [Overlay]. It is used to represent a flow in the app.
* Should be used instead of [ParentNode] in flow nodes.
*/
@Stable
abstract class BaseFlowNode<NavTarget : Any>(
val backstack: BackStack<NavTarget>,
buildContext: BuildContext,
plugins: List<Plugin>,
val overlay: Overlay<NavTarget> = Overlay(null),
val permanentNavModel: PermanentNavModel<NavTarget> = PermanentNavModel(emptySet(), null),
childKeepMode: ChildEntry.KeepMode = ChildEntry.KeepMode.KEEP,
) : ParentNode<NavTarget>(
navModel = overlay + backstack + permanentNavModel,
buildContext = buildContext,
plugins = plugins,
childKeepMode = childKeepMode,
) {
override fun onBuilt() {
super.onBuilt()
lifecycle.logLifecycle(this::class.java.simpleName)
whenChildAttached<Node> { _, child ->
// BackstackNode will be logged by their parent.
if (child !is BaseFlowNode<*>) {
child.lifecycle.logLifecycle(child::class.java.simpleName)
}
}
}
}
@Composable
inline fun <reified NavTarget : Any> BaseFlowNode<NavTarget>.BackstackView(
modifier: Modifier = Modifier,
transitionHandler: TransitionHandler<NavTarget, BackStack.State> = rememberBackstackSlider(
transitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) },
),
) {
Children(
modifier = modifier,
navModel = backstack,
transitionHandler = transitionHandler,
)
}
@Composable
inline fun <reified NavTarget : Any> BaseFlowNode<NavTarget>.OverlayView(
modifier: Modifier = Modifier,
transitionHandler: TransitionHandler<NavTarget, BackStack.State> = rememberBackstackFader(),
) {
Children(
modifier = modifier,
navModel = overlay,
transitionHandler = transitionHandler,
)
}
@Composable
inline fun <reified NavTarget : Any> BaseFlowNode<NavTarget>.BackstackWithOverlayBox(
modifier: Modifier = Modifier,
content: @Composable BoxScope.() -> Unit = {},
) {
Box(modifier = modifier) {
BackstackView()
OverlayView()
content()
}
}
Loading…
Cancel
Save