Merge pull request #2059 from element-hq/feature/fga/appyx_overlay
Appyx Overlay
This commit is contained in:
commit
7d33409810
26 changed files with 404 additions and 216 deletions
|
|
@ -25,7 +25,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.bumble.appyx.core.composable.Children
|
|
||||||
import com.bumble.appyx.core.composable.PermanentChild
|
import com.bumble.appyx.core.composable.PermanentChild
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
|
@ -57,8 +56,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.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.waitForChildAttached
|
import io.element.android.libraries.architecture.waitForChildAttached
|
||||||
import io.element.android.libraries.deeplink.DeeplinkData
|
import io.element.android.libraries.deeplink.DeeplinkData
|
||||||
|
|
@ -100,7 +99,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 +383,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)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ 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 coil.Coil
|
import coil.Coil
|
||||||
import com.bumble.appyx.core.composable.Children
|
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
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
|
||||||
|
|
@ -33,8 +32,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.animation.rememberDefaultTransitionHandler
|
import io.element.android.libraries.architecture.BaseFlowNode
|
||||||
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
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -47,7 +46,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 +110,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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
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.node.node
|
||||||
|
|
@ -46,8 +45,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.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.waitForChildAttached
|
import io.element.android.libraries.architecture.waitForChildAttached
|
||||||
import io.element.android.libraries.deeplink.DeeplinkData
|
import io.element.android.libraries.deeplink.DeeplinkData
|
||||||
|
|
@ -74,7 +73,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 +171,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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
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.node.node
|
||||||
|
|
@ -38,7 +37,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 +57,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 +130,7 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
Children(
|
BackstackView()
|
||||||
navModel = backstack,
|
|
||||||
modifier = modifier,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.bumble.appyx.core.composable.Children
|
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
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
|
||||||
|
|
@ -35,9 +34,9 @@ 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.inputs
|
import io.element.android.libraries.architecture.inputs
|
||||||
import io.element.android.libraries.di.DaggerComponentOwner
|
import io.element.android.libraries.di.DaggerComponentOwner
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
|
@ -64,7 +63,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 +201,6 @@ class RoomLoadedFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Children(
|
BackstackView()
|
||||||
navModel = backstack,
|
|
||||||
modifier = modifier,
|
|
||||||
transitionHandler = rememberDefaultTransitionHandler(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.createroom.impl
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -32,8 +31,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.animation.rememberDefaultTransitionHandler
|
import io.element.android.libraries.architecture.BaseFlowNode
|
||||||
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
|
||||||
import io.element.android.libraries.di.DaggerComponentOwner
|
import io.element.android.libraries.di.DaggerComponentOwner
|
||||||
|
|
@ -45,7 +44,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 +87,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()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.createroom.impl
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -32,8 +31,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.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.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
@ -43,7 +42,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 +86,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()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ 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 androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.bumble.appyx.core.composable.Children
|
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy
|
import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy
|
||||||
|
|
@ -40,8 +39,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.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.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
|
@ -62,7 +61,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 +180,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)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.lockscreen.impl
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -32,9 +31,9 @@ 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.createNode
|
import io.element.android.libraries.architecture.createNode
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -43,7 +42,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 +92,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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ 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 androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.bumble.appyx.core.composable.Children
|
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
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
|
||||||
|
|
@ -36,8 +35,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.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.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
@ -49,7 +48,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 +131,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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.lockscreen.impl.setup
|
||||||
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.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
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
|
||||||
|
|
@ -34,8 +33,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.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.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -45,7 +44,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 +105,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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.bumble.appyx.core.composable.Children
|
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
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
|
||||||
|
|
@ -48,9 +47,9 @@ 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.createNode
|
import io.element.android.libraries.architecture.createNode
|
||||||
import io.element.android.libraries.architecture.inputs
|
import io.element.android.libraries.architecture.inputs
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
|
|
@ -68,7 +67,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 +216,6 @@ class LoginFlowNode @AssistedInject constructor(
|
||||||
accountProviderDataSource.reset()
|
accountProviderDataSource.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Children(
|
BackstackView()
|
||||||
navModel = backstack,
|
|
||||||
modifier = modifier,
|
|
||||||
// Animate transition to change server screen
|
|
||||||
transitionHandler = rememberDefaultTransitionHandler(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.poll.impl.history
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -30,8 +29,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.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.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
|
@ -42,7 +41,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 +81,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()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.preferences.impl
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -41,8 +40,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.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.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
@ -55,7 +54,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 +209,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()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.roomdetails.impl
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -37,8 +36,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.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.core.mimetype.MimeTypes
|
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||||
import io.element.android.libraries.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
|
|
@ -54,7 +53,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 +195,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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package io.element.android.features.securebackup.impl
|
||||||
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.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -33,8 +32,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.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.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -43,7 +42,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 +123,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()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-compose-library")
|
id("io.element.android-compose-library")
|
||||||
|
id("kotlin-parcelize")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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.overlay
|
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElements
|
||||||
|
import io.element.android.libraries.architecture.overlay.operation.Hide
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
class HideOverlayBackPressHandler<NavTarget : Any>
|
||||||
|
: BaseBackPressHandlerStrategy<NavTarget, BackStack.State>() {
|
||||||
|
|
||||||
|
override val canHandleBackPressFlow: Flow<Boolean> by lazy {
|
||||||
|
navModel.elements.map(::areThereElements)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun areThereElements(elements: BackStackElements<NavTarget>) =
|
||||||
|
elements.isNotEmpty()
|
||||||
|
|
||||||
|
override fun onBackPressed() {
|
||||||
|
navModel.accept(Hide())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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.overlay
|
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.BaseNavModel
|
||||||
|
import com.bumble.appyx.core.navigation.NavElements
|
||||||
|
import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BackPressHandlerStrategy
|
||||||
|
import com.bumble.appyx.core.navigation.onscreen.OnScreenStateResolver
|
||||||
|
import com.bumble.appyx.core.navigation.operationstrategies.ExecuteImmediately
|
||||||
|
import com.bumble.appyx.core.navigation.operationstrategies.OperationStrategy
|
||||||
|
import com.bumble.appyx.core.state.SavedStateMap
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackOnScreenResolver
|
||||||
|
|
||||||
|
class Overlay<NavTarget : Any>(
|
||||||
|
savedStateMap: SavedStateMap?,
|
||||||
|
key: String = requireNotNull(Overlay::class.qualifiedName),
|
||||||
|
backPressHandler: BackPressHandlerStrategy<NavTarget, BackStack.State> = HideOverlayBackPressHandler(),
|
||||||
|
operationStrategy: OperationStrategy<NavTarget, BackStack.State> = ExecuteImmediately(),
|
||||||
|
screenResolver: OnScreenStateResolver<BackStack.State> = BackStackOnScreenResolver,
|
||||||
|
) : BaseNavModel<NavTarget, BackStack.State>(
|
||||||
|
backPressHandler = backPressHandler,
|
||||||
|
screenResolver = screenResolver,
|
||||||
|
operationStrategy = operationStrategy,
|
||||||
|
finalState = BackStack.State.DESTROYED,
|
||||||
|
savedStateMap = savedStateMap,
|
||||||
|
key = key,
|
||||||
|
) {
|
||||||
|
|
||||||
|
override val initialElements: NavElements<NavTarget, BackStack.State>
|
||||||
|
get() = emptyList()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.overlay.operation
|
||||||
|
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElements
|
||||||
|
import com.bumble.appyx.navmodel.backstack.activeIndex
|
||||||
|
import io.element.android.libraries.architecture.overlay.Overlay
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class Hide<T : Any> : OverlayOperation<T> {
|
||||||
|
|
||||||
|
override fun isApplicable(elements: BackStackElements<T>): Boolean =
|
||||||
|
elements.any { it.targetState == BackStack.State.ACTIVE }
|
||||||
|
|
||||||
|
override fun invoke(
|
||||||
|
elements: BackStackElements<T>
|
||||||
|
): BackStackElements<T> {
|
||||||
|
val hideIndex = elements.activeIndex
|
||||||
|
require(hideIndex != -1) { "Nothing to hide, state=$elements" }
|
||||||
|
return elements.mapIndexed { index, element ->
|
||||||
|
when (index) {
|
||||||
|
hideIndex -> element.transitionTo(
|
||||||
|
newTargetState = BackStack.State.DESTROYED,
|
||||||
|
operation = this
|
||||||
|
)
|
||||||
|
else -> element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = this.javaClass == other?.javaClass
|
||||||
|
|
||||||
|
override fun hashCode(): Int = this.javaClass.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> Overlay<T>.hide() {
|
||||||
|
accept(Hide())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.overlay.operation
|
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.Operation
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
|
|
||||||
|
interface OverlayOperation<T> : Operation<T, BackStack.State>
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.overlay.operation
|
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.NavKey
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElement
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElements
|
||||||
|
import com.bumble.appyx.navmodel.backstack.activeElement
|
||||||
|
import io.element.android.libraries.architecture.overlay.Overlay
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import kotlinx.parcelize.RawValue
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class Show<T : Any>(
|
||||||
|
private val element: @RawValue T
|
||||||
|
) : OverlayOperation<T> {
|
||||||
|
|
||||||
|
override fun isApplicable(elements: BackStackElements<T>): Boolean =
|
||||||
|
element != elements.activeElement
|
||||||
|
|
||||||
|
override fun invoke(elements: BackStackElements<T>): BackStackElements<T> = listOf(
|
||||||
|
BackStackElement(
|
||||||
|
key = NavKey(element),
|
||||||
|
fromState = BackStack.State.CREATED,
|
||||||
|
targetState = BackStack.State.ACTIVE,
|
||||||
|
operation = this
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> Overlay<T>.show(element: T) {
|
||||||
|
accept(Show(element))
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf
|
||||||
import com.lemonappdev.konsist.api.ext.list.withTopLevel
|
import com.lemonappdev.konsist.api.ext.list.withTopLevel
|
||||||
import com.lemonappdev.konsist.api.ext.list.withoutName
|
import com.lemonappdev.konsist.api.ext.list.withoutName
|
||||||
import com.lemonappdev.konsist.api.ext.list.withoutNameEndingWith
|
import com.lemonappdev.konsist.api.ext.list.withoutNameEndingWith
|
||||||
|
import com.lemonappdev.konsist.api.ext.list.withoutReceiverType
|
||||||
import com.lemonappdev.konsist.api.verify.assertTrue
|
import com.lemonappdev.konsist.api.verify.assertTrue
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -37,6 +38,7 @@ class KonsistComposableTest {
|
||||||
.withoutModifier(KoModifier.PRIVATE)
|
.withoutModifier(KoModifier.PRIVATE)
|
||||||
.withoutNameEndingWith("Preview")
|
.withoutNameEndingWith("Preview")
|
||||||
.withAllAnnotationsOf(Composable::class)
|
.withAllAnnotationsOf(Composable::class)
|
||||||
|
.withoutReceiverType()
|
||||||
.withoutName(
|
.withoutName(
|
||||||
// Add some exceptions...
|
// Add some exceptions...
|
||||||
"OutlinedButton",
|
"OutlinedButton",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue