Created
December 2, 2022 16:41
-
-
Save dimsuz/bb2540c753c710a23a76eb9e39d57382 to your computer and use it in GitHub Desktop.
A sample code to reproduce https://github.com/bumble-tech/appyx/issues/293
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.kode.appyxplayground | |
import android.os.Bundle | |
import android.util.Log | |
import androidx.activity.ComponentActivity | |
import androidx.activity.compose.setContent | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.material.Button | |
import androidx.compose.material.MaterialTheme | |
import androidx.compose.material.Surface | |
import androidx.compose.material.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.ui.Modifier | |
import androidx.lifecycle.DefaultLifecycleObserver | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.LifecycleOwner | |
import com.bumble.appyx.core.composable.Children | |
import com.bumble.appyx.core.integration.NodeHost | |
import com.bumble.appyx.core.integrationpoint.ActivityIntegrationPoint | |
import com.bumble.appyx.core.modality.BuildContext | |
import com.bumble.appyx.core.node.Node | |
import com.bumble.appyx.core.node.ParentNode | |
import com.bumble.appyx.core.node.node | |
import com.bumble.appyx.core.plugin.NodeLifecycleAware | |
import com.bumble.appyx.navmodel.backstack.BackStack | |
import com.bumble.appyx.navmodel.backstack.operation.push | |
import com.bumble.appyx.navmodel.backstack.operation.singleTop | |
import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackSlider | |
sealed class AppFlowNavTarget { | |
object Login : AppFlowNavTarget() | |
object Main : AppFlowNavTarget() | |
} | |
class AppFlowNode internal constructor( | |
buildContext: BuildContext, | |
private val backStack: BackStack<AppFlowNavTarget> = BackStack( | |
initialElement = AppFlowNavTarget.Login, | |
savedStateMap = buildContext.savedStateMap | |
) | |
) : ParentNode<AppFlowNavTarget>( | |
navModel = backStack, | |
buildContext = buildContext, | |
) { | |
override fun resolve( | |
navTarget: AppFlowNavTarget, | |
buildContext: BuildContext | |
): Node { | |
return when (navTarget) { | |
AppFlowNavTarget.Login -> { | |
LoginFlowNode(buildContext, onReset = { backStack.singleTop(AppFlowNavTarget.Main) }) | |
} | |
AppFlowNavTarget.Main -> { | |
MainFlowNode(buildContext) | |
} | |
} | |
} | |
@Composable | |
override fun View(modifier: Modifier) { | |
Children(navModel = backStack) | |
} | |
} | |
class PermissionsFlowNode internal constructor( | |
buildContext: BuildContext, | |
private val onReset: () -> Unit, | |
private val backStack: BackStack<NavTarget> = BackStack( | |
initialElement = NavTarget.P1, | |
savedStateMap = buildContext.savedStateMap | |
) | |
) : ParentNode<PermissionsFlowNode.NavTarget>( | |
navModel = backStack, | |
buildContext = buildContext, | |
plugins = listOf(FlowDIComponentPlugin("Permissions")) | |
) { | |
enum class NavTarget { P1, P2 } | |
override fun resolve( | |
navTarget: NavTarget, | |
buildContext: BuildContext | |
): Node { | |
return when (navTarget) { | |
NavTarget.P1 -> { | |
node(buildContext) { | |
Column { | |
Text("Permissions1") | |
Button(onClick = { backStack.push(NavTarget.P2) }) { Text("Go to P2") } | |
} | |
} | |
} | |
NavTarget.P2 -> { | |
node(buildContext) { | |
Column { | |
Text("Permissions2") | |
Button(onClick = onReset) { Text(text = "Reset") } | |
} | |
} | |
} | |
} | |
} | |
@Composable | |
override fun View(modifier: Modifier) { | |
Children(navModel = backStack, transitionHandler = rememberBackstackSlider()) | |
} | |
} | |
class LoginFlowNode internal constructor( | |
buildContext: BuildContext, | |
private val onReset: () -> Unit, | |
private val backStack: BackStack<NavTarget> = BackStack( | |
initialElement = NavTarget.L1, | |
savedStateMap = buildContext.savedStateMap | |
) | |
) : ParentNode<LoginFlowNode.NavTarget>( | |
navModel = backStack, | |
buildContext = buildContext, | |
plugins = listOf(FlowDIComponentPlugin("Login")) | |
) { | |
enum class NavTarget { L1, P } | |
override fun resolve( | |
navTarget: NavTarget, | |
buildContext: BuildContext | |
): Node { | |
return when (navTarget) { | |
NavTarget.L1 -> { | |
node(buildContext) { | |
Column { | |
Text("Login1") | |
Button(onClick = { backStack.push(NavTarget.P) }) { Text("Go to P") } | |
} | |
} | |
} | |
NavTarget.P -> { | |
PermissionsFlowNode(buildContext, onReset) | |
} | |
} | |
} | |
@Composable | |
override fun View(modifier: Modifier) { | |
Children(navModel = backStack, transitionHandler = rememberBackstackSlider()) | |
} | |
} | |
class MainFlowNode internal constructor( | |
buildContext: BuildContext, | |
private val backStack: BackStack<NavTarget> = BackStack( | |
initialElement = NavTarget.M1, | |
savedStateMap = buildContext.savedStateMap | |
) | |
) : ParentNode<MainFlowNode.NavTarget>( | |
navModel = backStack, | |
buildContext = buildContext, | |
plugins = listOf(FlowDIComponentPlugin("Main")) | |
) { | |
enum class NavTarget { M1 } | |
override fun resolve( | |
navTarget: NavTarget, | |
buildContext: BuildContext | |
): Node { | |
return when (navTarget) { | |
NavTarget.M1 -> node(buildContext) { | |
Button(onClick = { }) { Text("Hey there, I'm Main") } | |
} | |
} | |
} | |
@Composable | |
override fun View(modifier: Modifier) { | |
Children(navModel = backStack, transitionHandler = rememberBackstackSlider()) | |
} | |
} | |
class MainActivity : ComponentActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContent { | |
MaterialTheme { | |
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { | |
NodeHost(integrationPoint = ActivityIntegrationPoint(this, savedInstanceState)) { | |
AppFlowNode(it) | |
} | |
} | |
} | |
} | |
} | |
} | |
class FlowDIComponentPlugin(val name: String) : NodeLifecycleAware { | |
override fun onCreate(lifecycle: Lifecycle) { | |
lifecycle.addObserver(object : DefaultLifecycleObserver { | |
override fun onCreate(owner: LifecycleOwner) { | |
super.onCreate(owner) | |
Log.d("Appyx-Playground", "[$name] node onCreate") | |
} | |
override fun onDestroy(owner: LifecycleOwner) { | |
super.onDestroy(owner) | |
Log.d("Appyx-Playground", "[$name] node onDestroy") | |
} | |
override fun onStart(owner: LifecycleOwner) { | |
super.onStart(owner) | |
Log.d("Appyx-Playground", "[$name] node onStart") | |
} | |
override fun onStop(owner: LifecycleOwner) { | |
super.onStop(owner) | |
Log.d("Appyx-Playground", "[$name] node onStop") | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment