diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e8ffe949..8b31bae32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ - [#670](https://github.com/bumble-tech/appyx/pull/670) - Fixes ios lifecycle - [#673](https://github.com/bumble-tech/appyx/pull/673) – Fix canHandeBackPress typo +### Enhancement + +- [#679](https://github.com/bumble-tech/appyx/pull/679) – Simple api for backStackNode and spotlightNode + --- ## 2.0.0-alpha10 diff --git a/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/android/BackStackTest.kt b/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/android/BackStackTest.kt index fff61af86..1ae2e568f 100644 --- a/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/android/BackStackTest.kt +++ b/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/android/BackStackTest.kt @@ -14,7 +14,7 @@ import com.bumble.appyx.components.backstack.ui.stack3d.BackStack3D import com.bumble.appyx.interactions.core.model.transition.Operation import com.bumble.appyx.interactions.core.ui.Visualisation import com.bumble.appyx.interactions.core.ui.context.UiContext -import com.bumble.appyx.interactions.testing.InteractionTarget +import com.bumble.appyx.interactions.testing.TestTarget import com.bumble.appyx.interactions.testing.setupAppyxComponent import com.bumble.appyx.interactions.testing.waitUntilAnimationEnded import com.bumble.appyx.interactions.testing.waitUntilAnimationStarted @@ -32,11 +32,11 @@ class BackStackTest(private val testParam: TestParam) { @get:Rule val composeTestRule = createComposeRule() - private lateinit var backStack: BackStack + private lateinit var backStack: BackStack companion object { data class TestParam( - val visualisation: (UiContext) -> Visualisation> + val visualisation: (UiContext) -> Visualisation> ) @JvmStatic @@ -55,9 +55,9 @@ class BackStackTest(private val testParam: TestParam) { composeTestRule.setupAppyxComponent(backStack) val tweenTwoSec = tween(durationMillis = 2000) - backStack.push(interactionTarget = InteractionTarget.Child2) - backStack.push(interactionTarget = InteractionTarget.Child3) - backStack.push(interactionTarget = InteractionTarget.Child4) + backStack.push(navTarget = TestTarget.Child2) + backStack.push(navTarget = TestTarget.Child3) + backStack.push(navTarget = TestTarget.Child4) backStack.pop(animationSpec = tweenTwoSec) // all operations finished @@ -73,9 +73,9 @@ class BackStackTest(private val testParam: TestParam) { composeTestRule.setupAppyxComponent(backStack) val tweenTwoSec = tween(durationMillis = 2000) - backStack.push(interactionTarget = InteractionTarget.Child2) - backStack.push(interactionTarget = InteractionTarget.Child3) - backStack.push(interactionTarget = InteractionTarget.Child4) + backStack.push(navTarget = TestTarget.Child2) + backStack.push(navTarget = TestTarget.Child3) + backStack.push(navTarget = TestTarget.Child4) backStack.pop(animationSpec = tweenTwoSec) // last operation is not finished. advanced time < 2000 (last operation animation spec) @@ -89,9 +89,9 @@ class BackStackTest(private val testParam: TestParam) { createBackStack(disableAnimations = true, testParam.visualisation) composeTestRule.setupAppyxComponent(backStack) - backStack.push(interactionTarget = InteractionTarget.Child2) - backStack.push(interactionTarget = InteractionTarget.Child3) - backStack.push(interactionTarget = InteractionTarget.Child4) + backStack.push(navTarget = TestTarget.Child2) + backStack.push(navTarget = TestTarget.Child3) + backStack.push(navTarget = TestTarget.Child4) backStack.pop() Assert.assertEquals(3, backStack.elements.value.all.size) @@ -106,17 +106,17 @@ class BackStackTest(private val testParam: TestParam) { val popSpringSpec = spring(stiffness = 10f) backStack.push( - interactionTarget = InteractionTarget.Child2, + navTarget = TestTarget.Child2, mode = Operation.Mode.IMMEDIATE, animationSpec = pushSpringSpec ) // all subsequent operations will be in IMMEDIATE mode until settled backStack.push( - interactionTarget = InteractionTarget.Child3, + navTarget = TestTarget.Child3, animationSpec = pushSpringSpec ) backStack.push( - interactionTarget = InteractionTarget.Child4, + navTarget = TestTarget.Child4, animationSpec = pushSpringSpec ) backStack.pop(animationSpec = popSpringSpec) @@ -133,11 +133,11 @@ class BackStackTest(private val testParam: TestParam) { private fun createBackStack( disableAnimations: Boolean, - visualisation: (UiContext) -> Visualisation> + visualisation: (UiContext) -> Visualisation> ) { backStack = BackStack( model = BackStackModel( - initialTargets = listOf(InteractionTarget.Child1), + initialTargets = listOf(TestTarget.Child1), savedStateMap = null ), visualisation = visualisation, diff --git a/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallaxTest.kt b/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallaxTest.kt index f62be2325..93f9a09c9 100644 --- a/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallaxTest.kt +++ b/appyx-components/standard/backstack/android/src/androidTest/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallaxTest.kt @@ -5,7 +5,7 @@ import com.bumble.appyx.components.backstack.BackStack import com.bumble.appyx.components.backstack.BackStackModel import com.bumble.appyx.components.backstack.operation.push import com.bumble.appyx.interactions.core.model.transition.Update -import com.bumble.appyx.interactions.testing.InteractionTarget +import com.bumble.appyx.interactions.testing.TestTarget import com.bumble.appyx.interactions.testing.setupAppyxComponent import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -18,22 +18,22 @@ class BackStackParallaxTest { @get:Rule val composeTestRule = createComposeRule() - private lateinit var backStack: BackStack - private lateinit var backStackModel: BackStackModel - private lateinit var visualisation: BackStackParallax + private lateinit var backStack: BackStack + private lateinit var backStackModel: BackStackModel + private lateinit var visualisation: BackStackParallax @Test fun backStackParallax_resolves_visibility_to_false_when_element_is_not_top_most_stashed_one() { createBackStack() composeTestRule.setupAppyxComponent(backStack) - backStack.push(interactionTarget = InteractionTarget.Child2) - backStack.push(interactionTarget = InteractionTarget.Child3) - backStack.push(interactionTarget = InteractionTarget.Child4) + backStack.push(navTarget = TestTarget.Child2) + backStack.push(navTarget = TestTarget.Child3) + backStack.push(navTarget = TestTarget.Child4) composeTestRule.waitForIdle() - with(visualisation.mapUpdate(backStackModel.output.value as Update>)) { + with(visualisation.mapUpdate(backStackModel.output.value as Update>)) { Assert.assertFalse(get(0).visibleState.value) // Child #1 should be false Assert.assertFalse(get(1).visibleState.value) // Child #2 should be false Assert.assertFalse(get(2).visibleState.value) // Child #3 should be false @@ -43,13 +43,13 @@ class BackStackParallaxTest { private fun createBackStack() { backStackModel = BackStackModel( - initialTargets = listOf(InteractionTarget.Child1), + initialTargets = listOf(TestTarget.Child1), savedStateMap = null ) backStack = BackStack( model = backStackModel, visualisation = { uiContext -> - BackStackParallax(uiContext).also { + BackStackParallax(uiContext).also { visualisation = it } }, diff --git a/appyx-components/standard/backstack/common/build.gradle.kts b/appyx-components/standard/backstack/common/build.gradle.kts index 516de08fc..ae4cd61cd 100644 --- a/appyx-components/standard/backstack/common/build.gradle.kts +++ b/appyx-components/standard/backstack/common/build.gradle.kts @@ -33,7 +33,7 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - implementation(project(":appyx-interactions:appyx-interactions")) + implementation(project(":appyx-navigation:appyx-navigation")) api(compose.runtime) api(compose.foundation) api(compose.material) diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStack.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStack.kt index bd25093fa..3a298b2fd 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStack.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStack.kt @@ -14,19 +14,19 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -class BackStack( +class BackStack( scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main), - val model: BackStackModel, - visualisation: (UiContext) -> Visualisation>, + val model: BackStackModel, + visualisation: (UiContext) -> Visualisation>, animationSpec: AnimationSpec = spring(), - gestureFactory: (TransitionBounds) -> GestureFactory> = { + gestureFactory: (TransitionBounds) -> GestureFactory> = { GestureFactory.Noop() }, gestureSettleConfig: GestureSettleConfig = GestureSettleConfig(), - backPressStrategy: BackPressHandlerStrategy> = + backPressStrategy: BackPressHandlerStrategy> = PopBackstackStrategy(scope), disableAnimations: Boolean = false, -) : BaseAppyxComponent>( +) : BaseAppyxComponent>( scope = scope, model = model, visualisation = visualisation, diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModel.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModel.kt index e9e95d03e..033032b55 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModel.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModel.kt @@ -9,56 +9,56 @@ import com.bumble.appyx.utils.multiplatform.Parcelable import com.bumble.appyx.utils.multiplatform.Parcelize import com.bumble.appyx.utils.multiplatform.SavedStateMap -class BackStackModel( - initialTargets: List, +class BackStackModel( + initialTargets: List, savedStateMap: SavedStateMap?, -) : BaseTransitionModel>( +) : BaseTransitionModel>( savedStateMap = savedStateMap, ) { @Parcelize - data class State( + data class State( /** * Elements that have been created, but not yet moved to an active state */ - val created: Elements = listOf(), + val created: Elements = listOf(), /** * The currently active element. * There should be only one such element in the stack. */ - val active: Element, + val active: Element, /** * Elements stashed in the back stack (history). */ - val stashed: Elements = listOf(), + val stashed: Elements = listOf(), /** * Elements that will be destroyed after reaching this state. */ - val destroyed: Elements = listOf(), + val destroyed: Elements = listOf(), ) : Parcelable constructor( - initialTarget: InteractionTarget, + initialTarget: NavTarget, savedStateMap: SavedStateMap?, ) : this( initialTargets = listOf(initialTarget), savedStateMap = savedStateMap ) - override fun State.availableElements(): Set> = + override fun State.availableElements(): Set> = (created + active + stashed + destroyed).toSet() - override fun State.destroyedElements(): Set> = + override fun State.destroyedElements(): Set> = destroyed.toSet() - override fun State.removeDestroyedElement( - element: Element - ): State = + override fun State.removeDestroyedElement( + element: Element + ): State = copy(destroyed = destroyed.filterNot { it == element }) - override fun State.removeDestroyedElements(): State = + override fun State.removeDestroyedElements(): State = copy(destroyed = emptyList()) override val initialState = State( diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModelExt.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModelExt.kt index 8a44378c1..dfbb1610f 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModelExt.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/BackStackModelExt.kt @@ -5,5 +5,5 @@ import com.bumble.appyx.interactions.core.Element val BackStackModel.activeElement: Element get() = output.value.currentTargetState.active -val BackStackModel.activeInteractionTarget: T +val BackStackModel.activeTarget: T get() = activeElement.interactionTarget diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/backpresshandler/PopBackstackStrategy.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/backpresshandler/PopBackstackStrategy.kt index ed2c2ba67..abb19ac78 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/backpresshandler/PopBackstackStrategy.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/backpresshandler/PopBackstackStrategy.kt @@ -8,11 +8,11 @@ import com.bumble.appyx.mapState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow -class PopBackstackStrategy( +class PopBackstackStrategy( val scope: CoroutineScope, val animationSpec: AnimationSpec? = null ) : - BaseBackPressHandlerStrategy>() { + BaseBackPressHandlerStrategy>() { override val canHandleBackPress: StateFlow by lazy { transitionModel.output.mapState(scope) { output -> @@ -21,7 +21,7 @@ class PopBackstackStrategy( } override fun handleBackPress(): Boolean { - val pop = Pop() + val pop = Pop() //todo find a better way to check if operation is applicable return if (pop.isApplicable(transitionModel.output.value.currentTargetState)) { appyxComponent.operation(operation = Pop(), animationSpec) diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/node/backStackNode.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/node/backStackNode.kt new file mode 100644 index 000000000..79a3a5439 --- /dev/null +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/node/backStackNode.kt @@ -0,0 +1,51 @@ +package com.bumble.appyx.components.backstack.node + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.components.backstack.BackStack +import com.bumble.appyx.components.backstack.BackStackModel +import com.bumble.appyx.components.backstack.BackStackModel.State +import com.bumble.appyx.components.backstack.ui.fader.BackStackFader +import com.bumble.appyx.interactions.core.ui.Visualisation +import com.bumble.appyx.interactions.core.ui.context.TransitionBounds +import com.bumble.appyx.interactions.core.ui.context.UiContext +import com.bumble.appyx.interactions.core.ui.gesture.GestureFactory +import com.bumble.appyx.navigation.composable.AppyxNavigationContainer +import com.bumble.appyx.navigation.modality.NodeContext +import com.bumble.appyx.navigation.node.ComponentNode +import com.bumble.appyx.navigation.node.Node + +/** + * A simplified way of creating a Node with back stack navigation, allowing you to + * quickly sketch out your navigation. + * + * In more complex scenarios you'll probably want to create your own Node class, but in many + * cases this should offer a simple api to reduce the amount of code required. + */ +fun backStackNode( + nodeContext: NodeContext, + initialTarget: T, + mappings: (BackStack, T, NodeContext) -> Node<*>, + visualisation: (UiContext) -> Visualisation> = { BackStackFader(it) }, + gestureFactory: (TransitionBounds) -> GestureFactory> = { + GestureFactory.Noop() + }, + content: @Composable (BackStack, Modifier) -> Unit = { backStack, modifier -> + AppyxNavigationContainer( + appyxComponent = backStack, + modifier = modifier + ) + } +) = ComponentNode( + nodeContext = nodeContext, + component = BackStack( + model = BackStackModel( + initialTarget = initialTarget, + savedStateMap = nodeContext.savedStateMap + ), + visualisation = visualisation, + gestureFactory = gestureFactory + ), + mappings = mappings, + content = content +) diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/NewRoot.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/NewRoot.kt index 2d4f746fe..3f510c269 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/NewRoot.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/NewRoot.kt @@ -15,23 +15,23 @@ import com.bumble.appyx.utils.multiplatform.RawValue * [A, B, C] + NewRoot(D) = [ D ] */ @Parcelize -data class NewRoot( - private val interactionTarget: @RawValue InteractionTarget, +data class NewRoot( + private val navTarget: @RawValue NavTarget, override var mode: Operation.Mode = Operation.Mode.KEYFRAME -) : BaseOperation>() { - override fun isApplicable(state: BackStackModel.State): Boolean = +) : BaseOperation>() { + override fun isApplicable(state: BackStackModel.State): Boolean = true override fun createFromState( - baseLineState: BackStackModel.State - ): BackStackModel.State = + baseLineState: BackStackModel.State + ): BackStackModel.State = baseLineState.copy( - created = baseLineState.created + interactionTarget.asElement() + created = baseLineState.created + navTarget.asElement() ) override fun createTargetState( - fromState: BackStackModel.State - ): BackStackModel.State = + fromState: BackStackModel.State + ): BackStackModel.State = fromState.copy( active = fromState.created.last(), created = fromState.created.dropLast(1), @@ -40,10 +40,10 @@ data class NewRoot( ) } -fun BackStack.newRoot( - interactionTarget: InteractionTarget, +fun BackStack.newRoot( + navTarget: NavTarget, mode: Operation.Mode = Operation.Mode.KEYFRAME, animationSpec: AnimationSpec? = null ) { - operation(operation = NewRoot(interactionTarget, mode), animationSpec = animationSpec) + operation(operation = NewRoot(navTarget, mode), animationSpec = animationSpec) } diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Pop.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Pop.kt index afa263e96..36247362b 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Pop.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Pop.kt @@ -13,17 +13,17 @@ import com.bumble.appyx.utils.multiplatform.Parcelize * [A, B, C] + Pop = [A, B] */ @Parcelize -class Pop( +class Pop( override var mode: Operation.Mode = Operation.Mode.KEYFRAME -) : BaseOperation>() { - override fun isApplicable(state: State): Boolean = +) : BaseOperation>() { + override fun isApplicable(state: State): Boolean = state.stashed.isNotEmpty() - override fun createFromState(baseLineState: State): State = + override fun createFromState(baseLineState: State): State = baseLineState - override fun createTargetState(fromState: State): State = + override fun createTargetState(fromState: State): State = fromState.copy( active = fromState.stashed.last(), destroyed = fromState.destroyed + fromState.active, @@ -35,7 +35,7 @@ class Pop( override fun hashCode(): Int = this::class.hashCode() } -fun BackStack.pop( +fun BackStack.pop( mode: Operation.Mode = Operation.Mode.KEYFRAME, animationSpec: AnimationSpec? = null ) { diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Push.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Push.kt index c5d943e1e..36f91d73c 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Push.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Push.kt @@ -15,24 +15,24 @@ import com.bumble.appyx.utils.multiplatform.RawValue * [A, B, C] + Push(D) = [A, B, C, D] */ @Parcelize -data class Push( - private val interactionTarget: @RawValue InteractionTarget, +data class Push( + private val navTarget: @RawValue NavTarget, override var mode: Operation.Mode = Operation.Mode.KEYFRAME -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: BackStackModel.State): Boolean = - interactionTarget != state.active.interactionTarget + override fun isApplicable(state: BackStackModel.State): Boolean = + navTarget != state.active.interactionTarget override fun createFromState( - baseLineState: BackStackModel.State - ): BackStackModel.State = + baseLineState: BackStackModel.State + ): BackStackModel.State = baseLineState.copy( - created = baseLineState.created + interactionTarget.asElement() + created = baseLineState.created + navTarget.asElement() ) override fun createTargetState( - fromState: BackStackModel.State - ): BackStackModel.State = + fromState: BackStackModel.State + ): BackStackModel.State = fromState.copy( active = fromState.created.last(), created = fromState.created.dropLast(1), @@ -40,10 +40,10 @@ data class Push( ) } -fun BackStack.push( - interactionTarget: InteractionTarget, +fun BackStack.push( + navTarget: NavTarget, mode: Operation.Mode = Operation.Mode.KEYFRAME, animationSpec: AnimationSpec? = null ) { - operation(operation = Push(interactionTarget, mode), animationSpec = animationSpec) + operation(operation = Push(navTarget, mode), animationSpec = animationSpec) } diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Replace.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Replace.kt index 09767bb84..01de2f41f 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Replace.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/operation/Replace.kt @@ -16,19 +16,19 @@ import com.bumble.appyx.utils.multiplatform.RawValue * [A, B, C] + Replace(D) = [A, B, D] */ @Parcelize -data class Replace( - private val interactionTarget: @RawValue InteractionTarget, +data class Replace( + private val navTarget: @RawValue NavTarget, override var mode: Operation.Mode = Operation.Mode.KEYFRAME -) : BaseOperation>() { - override fun isApplicable(state: State): Boolean = - interactionTarget != state.active.interactionTarget +) : BaseOperation>() { + override fun isApplicable(state: State): Boolean = + navTarget != state.active.interactionTarget - override fun createFromState(baseLineState: State): State = + override fun createFromState(baseLineState: State): State = baseLineState.copy( - created = baseLineState.created + interactionTarget.asElement() + created = baseLineState.created + navTarget.asElement() ) - override fun createTargetState(fromState: State): State = + override fun createTargetState(fromState: State): State = fromState.copy( active = fromState.created.last(), created = fromState.created.dropLast(1), @@ -36,10 +36,10 @@ data class Replace( ) } -fun BackStack.replace( - target: InteractionTarget, +fun BackStack.replace( + navTarget: NavTarget, mode: Operation.Mode = Operation.Mode.KEYFRAME, animationSpec: AnimationSpec? = null ) { - operation(operation = Replace(target, mode), animationSpec = animationSpec) + operation(operation = Replace(navTarget, mode), animationSpec = animationSpec) } diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/fader/BackStackFader.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/fader/BackStackFader.kt index fc9510fbc..ddeddfec4 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/fader/BackStackFader.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/fader/BackStackFader.kt @@ -8,10 +8,10 @@ import com.bumble.appyx.interactions.core.ui.property.impl.Alpha import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation -class BackStackFader( +class BackStackFader( uiContext: UiContext, defaultAnimationSpec: SpringSpec = DefaultAnimationSpec -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext, defaultAnimationSpec = defaultAnimationSpec, ) { @@ -23,8 +23,8 @@ class BackStackFader( alpha = Alpha.Target(0f) ) - override fun BackStackModel.State.toUiTargets(): - List> = + override fun BackStackModel.State.toUiTargets(): + List> = listOf( MatchedTargetUiState(active, visible) ) + (created + stashed + destroyed).map { diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallax.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallax.kt index d40c85ac2..cb34cfe92 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallax.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/parallax/BackStackParallax.kt @@ -20,10 +20,10 @@ import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation @Suppress("MagicNumber") -class BackStackParallax( +class BackStackParallax( uiContext: UiContext, defaultAnimationSpec: SpringSpec = DefaultAnimationSpec -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext, defaultAnimationSpec = defaultAnimationSpec, ) { @@ -51,7 +51,7 @@ class BackStackParallax( alpha = Alpha.Target(value = 1f, easing = { fraction -> if (fraction == 0f) 0f else 1f }) ) - override fun State.toUiTargets(): List> { + override fun State.toUiTargets(): List> { val stashed = stashed.mapIndexed { index, element -> MatchedTargetUiState( element = element, @@ -78,17 +78,17 @@ class BackStackParallax( ): MutableUiState = targetUiState.toMutableUiState(uiContext) - class Gestures( + class Gestures( private val transitionBounds: TransitionBounds, - ) : GestureFactory> { + ) : GestureFactory> { override val isContinuous: Boolean = false override fun createGesture( - state: State, + state: State, delta: Offset, density: Density - ): Gesture> { + ): Gesture> { return if (dragHorizontalDirection(delta) == Drag.HorizontalDirection.RIGHT) { Gesture( diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/slider/BackStackSlider.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/slider/BackStackSlider.kt index 07e8c779a..dd13c35c7 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/slider/BackStackSlider.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/slider/BackStackSlider.kt @@ -8,9 +8,9 @@ import com.bumble.appyx.interactions.core.ui.property.impl.position.PositionAlig import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation -class BackStackSlider( +class BackStackSlider( uiContext: UiContext, -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext, ) { @@ -26,8 +26,8 @@ class BackStackSlider( alpha = Alpha.Target(1f), ) - override fun BackStackModel.State.toUiTargets( - ): List> = + override fun BackStackModel.State.toUiTargets( + ): List> = created.map { MatchedTargetUiState(it, visible.toOutsideRight()) } + listOf(active).map { MatchedTargetUiState(it, visible.toNoOffset()) } + stashed.mapIndexed { index, element -> diff --git a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/stack3d/BackStack3D.kt b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/stack3d/BackStack3D.kt index c6e5f4448..6cd978dd9 100644 --- a/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/stack3d/BackStack3D.kt +++ b/appyx-components/standard/backstack/common/src/commonMain/kotlin/com/bumble/appyx/components/backstack/ui/stack3d/BackStack3D.kt @@ -25,10 +25,10 @@ import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation @Suppress("MagicNumber") -class BackStack3D( +class BackStack3D( uiContext: UiContext, private val itemsInStack: Int = 3, -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext, ) { @@ -65,7 +65,7 @@ class BackStack3D( zIndex = ZIndex.Target(itemsInStack + 1f), ) - override fun State.toUiTargets(): List> = + override fun State.toUiTargets(): List> = created.mapIndexed { _, element -> MatchedTargetUiState(element, incoming) } + listOf(active).map { MatchedTargetUiState(it, topMost) } + stashed.mapIndexed { index, element -> @@ -82,19 +82,19 @@ class BackStack3D( ): MutableUiState = targetUiState.toMutableUiState(uiContext) - class Gestures( + class Gestures( transitionBounds: TransitionBounds, - ) : GestureFactory> { + ) : GestureFactory> { override val isContinuous: Boolean = false private val height = transitionBounds.screenHeightDp override fun createGesture( - state: State, + state: State, delta: Offset, density: Density, - ): Gesture> { + ): Gesture> { val heightInPx = with(density) { height.toPx() } return if (dragVerticalDirection(delta) == Drag.VerticalDirection.DOWN) { diff --git a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/InteractionTarget.kt b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/TestTarget.kt similarity index 77% rename from appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/InteractionTarget.kt rename to appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/TestTarget.kt index cf43be733..97079bfe1 100644 --- a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/InteractionTarget.kt +++ b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/TestTarget.kt @@ -1,5 +1,5 @@ package com.bumble.appyx.components.stable.backstack -enum class InteractionTarget { +enum class TestTarget { Child1, Child2, Child3, Child4, Child5, Child6; } diff --git a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/NewRootTest.kt b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/NewRootTest.kt index e32e45afd..2323887a7 100644 --- a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/NewRootTest.kt +++ b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/NewRootTest.kt @@ -1,10 +1,10 @@ package com.bumble.appyx.components.stable.backstack.operation -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child1 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child2 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child3 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child4 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child5 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child1 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child2 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child3 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child4 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child5 import com.bumble.appyx.interactions.core.asElement import com.bumble.appyx.components.backstack.BackStackModel import com.bumble.appyx.components.backstack.operation.NewRoot diff --git a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PopTest.kt b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PopTest.kt index dd02d0a77..87a26690c 100644 --- a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PopTest.kt +++ b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PopTest.kt @@ -2,9 +2,9 @@ package com.bumble.appyx.components.stable.backstack.operation import com.bumble.appyx.components.backstack.operation.Pop import com.bumble.appyx.components.backstack.BackStackModel -import com.bumble.appyx.components.stable.backstack.InteractionTarget -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child1 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child2 +import com.bumble.appyx.components.stable.backstack.TestTarget +import com.bumble.appyx.components.stable.backstack.TestTarget.Child1 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child2 import com.bumble.appyx.interactions.core.Element import kotlin.test.Test import kotlin.test.assertEquals @@ -16,7 +16,7 @@ class PopTest { fun GIVEN_no_stashed_elements_THEN_it_is_not_applicable() { val state = BackStackModel.State(active = Element(Child1)) - val pop = Pop() + val pop = Pop() assertFalse(pop.isApplicable(state)) } @@ -28,7 +28,7 @@ class PopTest { stashed = listOf(Element(Child2)) ) - val pop = Pop() + val pop = Pop() val actual = pop.invoke(state) diff --git a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PushTest.kt b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PushTest.kt index d6a98410c..9595462cf 100644 --- a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PushTest.kt +++ b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/PushTest.kt @@ -2,8 +2,8 @@ package com.bumble.appyx.components.stable.backstack.operation import com.bumble.appyx.components.backstack.BackStackModel import com.bumble.appyx.components.backstack.operation.Push -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child1 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child2 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child1 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child2 import com.bumble.appyx.interactions.core.asElement import kotlin.test.Test import kotlin.test.assertEquals diff --git a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/ReplaceTest.kt b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/ReplaceTest.kt index 3b2fc645c..ff186ae3c 100644 --- a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/ReplaceTest.kt +++ b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/operation/ReplaceTest.kt @@ -2,10 +2,10 @@ package com.bumble.appyx.components.stable.backstack.operation import com.bumble.appyx.components.backstack.BackStackModel import com.bumble.appyx.components.backstack.operation.Replace -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child1 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child2 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child3 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child4 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child1 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child2 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child3 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child4 import com.bumble.appyx.interactions.core.asElement import kotlin.test.Test import kotlin.test.assertEquals diff --git a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/restore/BackstackRestoreTest.kt b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/restore/BackstackRestoreTest.kt index 1518b2e6d..e5d6587fc 100644 --- a/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/restore/BackstackRestoreTest.kt +++ b/appyx-components/standard/backstack/common/src/commonTest/kotlin/com/bumble/appyx/components/stable/backstack/restore/BackstackRestoreTest.kt @@ -1,8 +1,8 @@ package com.bumble.appyx.components.stable.backstack.restore import com.bumble.appyx.components.backstack.BackStackModel -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child1 -import com.bumble.appyx.components.stable.backstack.InteractionTarget.Child2 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child1 +import com.bumble.appyx.components.stable.backstack.TestTarget.Child2 import com.bumble.appyx.components.backstack.operation.Push import com.bumble.appyx.interactions.core.state.MutableSavedStateMapImpl import kotlin.test.Test diff --git a/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/SpotlightTest.kt b/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/SpotlightTest.kt index 8fb5f99b3..ff712a336 100644 --- a/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/SpotlightTest.kt +++ b/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/SpotlightTest.kt @@ -7,7 +7,7 @@ import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.operation.last import com.bumble.appyx.components.spotlight.ui.slider.SpotlightSlider import com.bumble.appyx.interactions.core.model.transition.Operation -import com.bumble.appyx.interactions.testing.InteractionTarget +import com.bumble.appyx.interactions.testing.TestTarget import com.bumble.appyx.interactions.testing.setupAppyxComponent import com.bumble.appyx.interactions.testing.waitUntilAnimationEnded import kotlinx.coroutines.CoroutineScope @@ -24,7 +24,7 @@ class SpotlightTest(private val testParam: TestParam) { @get:Rule val composeTestRule = createComposeRule() - private lateinit var spotlight: Spotlight + private lateinit var spotlight: Spotlight companion object { @@ -45,7 +45,7 @@ class SpotlightTest(private val testParam: TestParam) { fun spotlight_calculates_visible_elements_correctly_when_clipToBounds_is_false() { createSpotlightSlider(initialActiveIndex = 1f) composeTestRule.setupAppyxComponent(spotlight, 0.67f, clipToBounds = false) - checkInteractionTargetsOnScreen(setOf(InteractionTarget.Child1, InteractionTarget.Child2, InteractionTarget.Child3)) + checkTargetsOnScreen(setOf(TestTarget.Child1, TestTarget.Child2, TestTarget.Child3)) if (testParam.operationMode == Operation.Mode.KEYFRAME) { val animationDuration = 1000 @@ -58,7 +58,7 @@ class SpotlightTest(private val testParam: TestParam) { composeTestRule.waitForIdle() - checkInteractionTargetsOnScreen(setOf(InteractionTarget.Child5, InteractionTarget.Child4)) + checkTargetsOnScreen(setOf(TestTarget.Child5, TestTarget.Child4)) } @Test @@ -77,19 +77,19 @@ class SpotlightTest(private val testParam: TestParam) { composeTestRule.waitForIdle() - checkInteractionTargetsOnScreen(setOf(InteractionTarget.Child5)) + checkTargetsOnScreen(setOf(TestTarget.Child5)) } - private fun checkInteractionTargetsOnScreen(interactionTargets: Set) { + private fun checkTargetsOnScreen(targets: Set) { assertEquals( - interactionTargets, + targets, spotlight.elements.value.onScreen.map { it.interactionTarget }.toSet() ) } - private fun checkInteractionTargetsOffScreen(interactionTargets: Set) { + private fun checkTargetsOffScreen(targets: Set) { assertEquals( - interactionTargets, + targets, spotlight.elements.value.offScreen.map { it.interactionTarget }.toSet() ) } @@ -100,11 +100,11 @@ class SpotlightTest(private val testParam: TestParam) { ) { val model = SpotlightModel( items = listOf( - InteractionTarget.Child1, - InteractionTarget.Child2, - InteractionTarget.Child3, - InteractionTarget.Child4, - InteractionTarget.Child5 + TestTarget.Child1, + TestTarget.Child2, + TestTarget.Child3, + TestTarget.Child4, + TestTarget.Child5 ), initialActiveIndex = initialActiveIndex, savedStateMap = null diff --git a/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/utils/SpotlightUtils.kt b/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/utils/SpotlightUtils.kt index cac81bc52..394a1cb0d 100644 --- a/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/utils/SpotlightUtils.kt +++ b/appyx-components/standard/spotlight/android/src/androidTest/kotlin/com/bumble/appyx/components/spotlight/android/utils/SpotlightUtils.kt @@ -43,8 +43,8 @@ fun ComposeContentTestRule.createSpotlight( ).also { setupSpotlight(it) } } -fun ComposeContentTestRule.setupSpotlight( - spotlight: Spotlight, +fun ComposeContentTestRule.setupSpotlight( + spotlight: Spotlight, ) { setContent { Surface( @@ -62,8 +62,8 @@ fun ComposeContentTestRule.setupSpotlight( } @Composable -fun SpotlightUi( - spotlight: Spotlight, +fun SpotlightUi( + spotlight: Spotlight, modifier: Modifier = Modifier, color: Color = Color.Unspecified ) { diff --git a/appyx-components/standard/spotlight/common/build.gradle.kts b/appyx-components/standard/spotlight/common/build.gradle.kts index 9ea36f025..2b56f8952 100644 --- a/appyx-components/standard/spotlight/common/build.gradle.kts +++ b/appyx-components/standard/spotlight/common/build.gradle.kts @@ -33,7 +33,7 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - api(project(":appyx-interactions:appyx-interactions")) + api(project(":appyx-navigation:appyx-navigation")) api(compose.runtime) api(compose.foundation) api(compose.material) diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/Spotlight.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/Spotlight.kt index 1f742a2b4..d95621849 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/Spotlight.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/Spotlight.kt @@ -14,11 +14,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.StateFlow -open class Spotlight( +open class Spotlight( scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main), - model: SpotlightModel, - visualisation: (UiContext) -> Visualisation>, - gestureFactory: (TransitionBounds) -> GestureFactory> = { + model: SpotlightModel, + visualisation: (UiContext) -> Visualisation>, + gestureFactory: (TransitionBounds) -> GestureFactory> = { GestureFactory.Noop() }, animationSpec: AnimationSpec = spring(), @@ -28,7 +28,7 @@ open class Spotlight( revertGestureSpec = animationSpec, ), disableAnimations: Boolean = false, -) : BaseAppyxComponent>( +) : BaseAppyxComponent>( scope = scope, model = model, visualisation = visualisation, @@ -40,6 +40,6 @@ open class Spotlight( val activeIndex: StateFlow = model.output .mapState(scope) { it.currentTargetState.activeIndex } - val activeElement: StateFlow = model.output + val activeElement: StateFlow = model.output .mapState(scope) { it.currentTargetState.activeElement } } diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/SpotlightModel.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/SpotlightModel.kt index 2a15ff5b7..969ba6199 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/SpotlightModel.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/SpotlightModel.kt @@ -11,23 +11,23 @@ import com.bumble.appyx.utils.multiplatform.Parcelize import com.bumble.appyx.utils.multiplatform.RawValue import com.bumble.appyx.utils.multiplatform.SavedStateMap -class SpotlightModel( - items: List, +class SpotlightModel( + items: List, initialActiveIndex: Float = 0f, savedStateMap: SavedStateMap?, -) : BaseTransitionModel>( +) : BaseTransitionModel>( savedStateMap = savedStateMap ) { @Parcelize - data class State( - val positions: @RawValue List>, + data class State( + val positions: @RawValue List>, val activeIndex: Float ) : Parcelable { @Parcelize - data class Position( - val elements: Map, ElementState> = mapOf() + data class Position( + val elements: Map, ElementState> = mapOf() ) : Parcelable enum class ElementState { @@ -40,11 +40,11 @@ class SpotlightModel( fun hasNext(): Boolean = activeIndex <= positions.lastIndex - 1 - val activeElement: InteractionTarget? = + val activeElement: NavTarget? = positions.getOrNull(activeIndex.toInt())?.elements?.firstNotNullOf { it.key.interactionTarget } } - override val initialState: State = + override val initialState: State = State( positions = items.map { State.Position( @@ -54,12 +54,12 @@ class SpotlightModel( activeIndex = initialActiveIndex ) - val currentState: State + val currentState: State get() = output.value.currentTargetState - override fun State.removeDestroyedElement( - element: Element - ): State { + override fun State.removeDestroyedElement( + element: Element + ): State { val newPositions = positions.map { position -> val newElements = position .elements @@ -72,7 +72,7 @@ class SpotlightModel( return copy(positions = newPositions) } - override fun State.removeDestroyedElements(): State { + override fun State.removeDestroyedElements(): State { val newPositions = positions.map { position -> val newElements = position .elements @@ -85,14 +85,14 @@ class SpotlightModel( return copy(positions = newPositions) } - override fun State.availableElements(): Set> = + override fun State.availableElements(): Set> = positions .flatMap { it.elements.entries } .filter { it.value != DESTROYED } .map { it.key } .toSet() - override fun State.destroyedElements(): Set> = + override fun State.destroyedElements(): Set> = positions .flatMap { it.elements.entries } .filter { it.value == DESTROYED } diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/node/spotlightNode.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/node/spotlightNode.kt new file mode 100644 index 000000000..b83a512f7 --- /dev/null +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/node/spotlightNode.kt @@ -0,0 +1,55 @@ +package com.bumble.appyx.components.spotlight.node + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.components.spotlight.Spotlight +import com.bumble.appyx.components.spotlight.SpotlightModel +import com.bumble.appyx.components.spotlight.SpotlightModel.State +import com.bumble.appyx.components.spotlight.ui.slider.SpotlightSlider +import com.bumble.appyx.interactions.core.ui.Visualisation +import com.bumble.appyx.interactions.core.ui.context.TransitionBounds +import com.bumble.appyx.interactions.core.ui.context.UiContext +import com.bumble.appyx.interactions.core.ui.gesture.GestureFactory +import com.bumble.appyx.navigation.composable.AppyxNavigationContainer +import com.bumble.appyx.navigation.modality.NodeContext +import com.bumble.appyx.navigation.node.ComponentNode +import com.bumble.appyx.navigation.node.Node + +/** + * A simplified way of creating a Node with a pager/carousel-like navigation, allowing you to + * quickly sketch out your navigation. + * + * In more complex scenarios you'll probably want to create your own Node class, but in many + * cases this should offer a simple api to reduce the amount of code required. + */ +fun spotlightNode( + nodeContext: NodeContext, + items: List, + mappings: (Spotlight, T, NodeContext) -> Node<*>, + model: SpotlightModel = SpotlightModel( + items = items, + savedStateMap = nodeContext.savedStateMap + ), + visualisation: (UiContext) -> Visualisation> = { SpotlightSlider(it, model.currentState) }, + gestureFactory: (TransitionBounds) -> GestureFactory> = { + SpotlightSlider.Gestures(it) + }, + content: @Composable (Spotlight, Modifier) -> Unit = { spotlight, modifier -> + AppyxNavigationContainer( + appyxComponent = spotlight, + modifier = modifier + ) + } +) = ComponentNode( + nodeContext = nodeContext, + component = Spotlight( + model = SpotlightModel( + items = items, + savedStateMap = nodeContext.savedStateMap + ), + visualisation = visualisation, + gestureFactory = gestureFactory + ), + mappings = mappings, + content = content +) diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Activate.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Activate.kt index 2774d10df..4731725f3 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Activate.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Activate.kt @@ -8,29 +8,29 @@ import com.bumble.appyx.interactions.core.model.transition.Operation import com.bumble.appyx.utils.multiplatform.Parcelize @Parcelize -class Activate( +class Activate( private val index: Float, override var mode: Operation.Mode = Operation.Mode.IMPOSED -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: SpotlightModel.State): Boolean = + override fun isApplicable(state: SpotlightModel.State): Boolean = index != state.activeIndex && (index in 0f..state.positions.lastIndex.toFloat()) override fun createFromState( - baseLineState: SpotlightModel.State - ): SpotlightModel.State = + baseLineState: SpotlightModel.State + ): SpotlightModel.State = baseLineState override fun createTargetState( - fromState: SpotlightModel.State - ): SpotlightModel.State = + fromState: SpotlightModel.State + ): SpotlightModel.State = fromState.copy( activeIndex = index, ) } -fun Spotlight.activate( +fun Spotlight.activate( index: Float, animationSpec: AnimationSpec = defaultAnimationSpec, mode: Operation.Mode = Operation.Mode.IMPOSED diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/First.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/First.kt index 2d29dd922..4e798bfd4 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/First.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/First.kt @@ -9,27 +9,27 @@ import com.bumble.appyx.utils.multiplatform.Parcelize @Parcelize -class First( +class First( override var mode: Operation.Mode = Operation.Mode.IMPOSED -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: SpotlightModel.State): Boolean = + override fun isApplicable(state: SpotlightModel.State): Boolean = true override fun createFromState( - baseLineState: SpotlightModel.State - ): SpotlightModel.State = + baseLineState: SpotlightModel.State + ): SpotlightModel.State = baseLineState override fun createTargetState( - fromState: SpotlightModel.State - ): SpotlightModel.State = + fromState: SpotlightModel.State + ): SpotlightModel.State = fromState.copy( activeIndex = 0f, ) } -fun Spotlight.first( +fun Spotlight.first( animationSpec: AnimationSpec = defaultAnimationSpec, mode: Operation.Mode = Operation.Mode.IMPOSED ) { diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Last.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Last.kt index 8a46e6984..ca443d8e5 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Last.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Last.kt @@ -9,27 +9,27 @@ import com.bumble.appyx.utils.multiplatform.Parcelize @Parcelize -class Last( +class Last( override var mode: Operation.Mode = Operation.Mode.IMPOSED -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: SpotlightModel.State): Boolean = + override fun isApplicable(state: SpotlightModel.State): Boolean = true override fun createFromState( - baseLineState: SpotlightModel.State - ): SpotlightModel.State = + baseLineState: SpotlightModel.State + ): SpotlightModel.State = baseLineState override fun createTargetState( - fromState: SpotlightModel.State - ): SpotlightModel.State = + fromState: SpotlightModel.State + ): SpotlightModel.State = fromState.copy( activeIndex = fromState.positions.lastIndex.toFloat(), ) } -fun Spotlight.last( +fun Spotlight.last( animationSpec: AnimationSpec = defaultAnimationSpec, mode: Operation.Mode = Operation.Mode.IMPOSED ) { diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Next.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Next.kt index 1c3a977a6..4ea1c5bfb 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Next.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Next.kt @@ -8,27 +8,27 @@ import com.bumble.appyx.interactions.core.model.transition.Operation import com.bumble.appyx.utils.multiplatform.Parcelize @Parcelize -class Next( +class Next( override var mode: Operation.Mode = Operation.Mode.IMPOSED -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: SpotlightModel.State): Boolean = + override fun isApplicable(state: SpotlightModel.State): Boolean = state.hasNext() override fun createFromState( - baseLineState: SpotlightModel.State - ): SpotlightModel.State = + baseLineState: SpotlightModel.State + ): SpotlightModel.State = baseLineState override fun createTargetState( - fromState: SpotlightModel.State - ): SpotlightModel.State = + fromState: SpotlightModel.State + ): SpotlightModel.State = fromState.copy( activeIndex = fromState.activeIndex + 1f ) } -fun Spotlight.next( +fun Spotlight.next( animationSpec: AnimationSpec = defaultAnimationSpec, mode: Operation.Mode = Operation.Mode.IMPOSED ) { diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Previous.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Previous.kt index 09d5e262d..cbc0942d8 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Previous.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/Previous.kt @@ -9,27 +9,27 @@ import com.bumble.appyx.utils.multiplatform.Parcelize @Parcelize -class Previous( +class Previous( override var mode: Operation.Mode = Operation.Mode.IMPOSED -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: SpotlightModel.State): Boolean = + override fun isApplicable(state: SpotlightModel.State): Boolean = state.hasPrevious() override fun createFromState( - baseLineState: SpotlightModel.State - ): SpotlightModel.State = + baseLineState: SpotlightModel.State + ): SpotlightModel.State = baseLineState override fun createTargetState( - fromState: SpotlightModel.State - ): SpotlightModel.State = + fromState: SpotlightModel.State + ): SpotlightModel.State = fromState.copy( activeIndex = fromState.activeIndex - 1f, ) } -fun Spotlight.previous( +fun Spotlight.previous( animationSpec: AnimationSpec = defaultAnimationSpec, mode: Operation.Mode = Operation.Mode.IMPOSED ) { diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElements.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElements.kt index 4c8a21df0..773bdb9a8 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElements.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElements.kt @@ -17,24 +17,24 @@ import kotlin.math.max @Parcelize // TODO cleanup SpotlightModel.State.positions if a position doesn't contain more elements -class UpdateElements( - private val items: @RawValue List, +class UpdateElements( + private val items: @RawValue List, private val initialActiveIndex: Float? = null, override var mode: Operation.Mode = Operation.Mode.KEYFRAME -) : BaseOperation>() { +) : BaseOperation>() { - override fun isApplicable(state: SpotlightModel.State): Boolean = + override fun isApplicable(state: SpotlightModel.State): Boolean = true override fun createFromState( - baseLineState: SpotlightModel.State - ): SpotlightModel.State { + baseLineState: SpotlightModel.State + ): SpotlightModel.State { val positions = baseLineState.positions val newSize = max(positions.size, items.size) - val newPositions = ArrayList>(newSize) + val newPositions = ArrayList>(newSize) for (i in 0 until newSize) { val elementsForPosition = - mutableMapOf, SpotlightModel.State.ElementState>() + mutableMapOf, SpotlightModel.State.ElementState>() if (i < positions.size) { elementsForPosition += positions[i].elements } @@ -47,8 +47,8 @@ class UpdateElements( } override fun createTargetState( - fromState: SpotlightModel.State - ): SpotlightModel.State = + fromState: SpotlightModel.State + ): SpotlightModel.State = fromState.copy( positions = fromState.positions.map { position -> position.copy( @@ -65,8 +65,8 @@ class UpdateElements( ) } -fun Spotlight.updateElements( - items: List, +fun Spotlight.updateElements( + items: List, initialActiveIndex: Float? = null, animationSpec: AnimationSpec = defaultAnimationSpec, mode: Operation.Mode = Operation.Mode.KEYFRAME diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/fader/SpotlightFader.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/fader/SpotlightFader.kt index 3a3d26986..70cd3a2e3 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/fader/SpotlightFader.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/fader/SpotlightFader.kt @@ -12,10 +12,10 @@ import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation -class SpotlightFader( +class SpotlightFader( uiContext: UiContext, defaultAnimationSpec: SpringSpec = DefaultAnimationSpec -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext, defaultAnimationSpec = defaultAnimationSpec ) { @@ -27,8 +27,8 @@ class SpotlightFader( alpha = Alpha.Target(1f), ) - override fun SpotlightModel.State.toUiTargets(): - List> { + override fun SpotlightModel.State.toUiTargets(): + List> { return positions.flatMapIndexed { index, position -> position.elements.map { MatchedTargetUiState( diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/slider/SpotlightSlider.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/slider/SpotlightSlider.kt index b1e3261fc..6e87e6d48 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/slider/SpotlightSlider.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/slider/SpotlightSlider.kt @@ -27,21 +27,21 @@ import com.bumble.appyx.interactions.core.ui.property.impl.position.PositionAlig import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation -class SpotlightSlider( +class SpotlightSlider( uiContext: UiContext, - initialState: State, + initialState: State, @Suppress("UnusedPrivateMember") private val orientation: Orientation = Orientation.Horizontal, // TODO support RTL -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext ) { private val scrollX = GenericFloatProperty( coroutineScope = uiContext.coroutineScope, target = Target(initialState.activeIndex), ) - override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = + override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = listOf( - { state: State -> state.activeIndex } to scrollX + { state: State -> state.activeIndex } to scrollX ) private val created: TargetUiState = TargetUiState( @@ -62,7 +62,7 @@ class SpotlightSlider( alpha = Alpha.Target(0f), ) - override fun State.toUiTargets(): List> { + override fun State.toUiTargets(): List> { return positions.flatMapIndexed { index, position -> position.elements.map { MatchedTargetUiState( @@ -87,19 +87,19 @@ class SpotlightSlider( targetUiState.toMutableUiState(uiContext, scrollX.renderValueFlow) - class Gestures( + class Gestures( transitionBounds: TransitionBounds, private val orientation: Orientation = Orientation.Horizontal, private val reverseOrientation: Boolean = false, - ) : GestureFactory> { + ) : GestureFactory> { private val width = transitionBounds.widthPx.toFloat() private val height = transitionBounds.heightPx.toFloat() override fun createGesture( - state: State, + state: State, delta: Offset, density: Density - ): Gesture> = when (orientation) { + ): Gesture> = when (orientation) { Orientation.Horizontal -> { when (dragHorizontalDirection(delta)) { Drag.HorizontalDirection.LEFT -> Gesture( diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderrotation/SpotlightSliderRotation.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderrotation/SpotlightSliderRotation.kt index 7128ad8e9..ae4179d6a 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderrotation/SpotlightSliderRotation.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderrotation/SpotlightSliderRotation.kt @@ -18,21 +18,21 @@ import com.bumble.appyx.interactions.core.ui.property.impl.position.BiasAlignmen import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation -class SpotlightSliderRotation( +class SpotlightSliderRotation( uiContext: UiContext, - initialState: State, + initialState: State, @Suppress("UnusedPrivateMember") private val orientation: Orientation = Orientation.Horizontal, // TODO support RTL -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext ) { private val scrollX = GenericFloatProperty( coroutineScope = uiContext.coroutineScope, target = Target(initialState.activeIndex), ) - override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = + override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = listOf( - { state: State -> state.activeIndex } to scrollX + { state: State -> state.activeIndex } to scrollX ) private val created: TargetUiState = TargetUiState( @@ -56,7 +56,7 @@ class SpotlightSliderRotation( alpha = Alpha.Target(0f), ) - override fun State.toUiTargets(): List> { + override fun State.toUiTargets(): List> { return positions.flatMapIndexed { index, position -> position.elements.map { MatchedTargetUiState( diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderscale/SpotlightSliderScale.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderscale/SpotlightSliderScale.kt index 7c2482eae..39d14d859 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderscale/SpotlightSliderScale.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/sliderscale/SpotlightSliderScale.kt @@ -16,12 +16,12 @@ import com.bumble.appyx.interactions.core.ui.property.impl.position.PositionAlig import com.bumble.appyx.interactions.core.ui.state.MatchedTargetUiState import com.bumble.appyx.transitionmodel.BaseVisualisation -class SpotlightSliderScale( +class SpotlightSliderScale( uiContext: UiContext, - initialState: State, + initialState: State, @Suppress("UnusedPrivateMember") private val orientation: Orientation = Orientation.Horizontal, // TODO support RTL -) : BaseVisualisation, TargetUiState, MutableUiState>( +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext ) { @Suppress("MaxLineLength") @@ -29,9 +29,9 @@ class SpotlightSliderScale( coroutineScope = uiContext.coroutineScope, target = Target(initialState.activeIndex), ) - override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = + override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = listOf( - { state: State -> state.activeIndex } to scrollX + { state: State -> state.activeIndex } to scrollX ) private val created: TargetUiState = TargetUiState( @@ -49,7 +49,7 @@ class SpotlightSliderScale( scale = Scale.Target(0f), ) - override fun State.toUiTargets(): List> { + override fun State.toUiTargets(): List> { return positions.flatMapIndexed { index, position -> position.elements.map { MatchedTargetUiState( diff --git a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/stack3d/SpotlightStack3D.kt b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/stack3d/SpotlightStack3D.kt index 453704d06..05e1e5770 100644 --- a/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/stack3d/SpotlightStack3D.kt +++ b/appyx-components/standard/spotlight/common/src/commonMain/kotlin/com/bumble/appyx/components/spotlight/ui/stack3d/SpotlightStack3D.kt @@ -23,10 +23,10 @@ import com.bumble.appyx.mapState import com.bumble.appyx.transitionmodel.BaseVisualisation @Suppress("MagicNumber") -class SpotlightStack3D( +class SpotlightStack3D( uiContext: UiContext, - initialState: State, -) : BaseVisualisation, TargetUiState, MutableUiState>( + initialState: State, +) : BaseVisualisation, TargetUiState, MutableUiState>( uiContext = uiContext, ) { private var width: Dp = 0.dp @@ -42,9 +42,9 @@ class SpotlightStack3D( coroutineScope = uiContext.coroutineScope, target = GenericFloatProperty.Target(initialState.activeIndex), ) - override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = + override val viewpointDimensions: List) -> Float, GenericFloatProperty>> = listOf( - { state: State -> state.activeIndex } to scrollY + { state: State -> state.activeIndex } to scrollY ) private val created: TargetUiState = TargetUiState( @@ -71,7 +71,7 @@ class SpotlightStack3D( zIndex = ZIndex.Target(0f), ) - override fun State.toUiTargets(): List> = + override fun State.toUiTargets(): List> = positions.flatMapIndexed { index, position -> position.elements.map { MatchedTargetUiState( diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/InteractionTarget.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/TestTarget.kt similarity index 76% rename from appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/InteractionTarget.kt rename to appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/TestTarget.kt index 0e94847f8..55620ec73 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/InteractionTarget.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/TestTarget.kt @@ -1,5 +1,5 @@ package com.bumble.appyx.components.spotlight -enum class InteractionTarget { +enum class TestTarget { Child1, Child2, Child3, Child4, Child5, Child6; } diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/model/SpotlightModelTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/model/SpotlightModelTest.kt index f9effaa16..fc5c70c61 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/model/SpotlightModelTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/model/SpotlightModelTest.kt @@ -1,8 +1,8 @@ package com.bumble.appyx.components.spotlight.model -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child3 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child3 import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.operation.Next import com.bumble.appyx.components.spotlight.operation.UpdateElements diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/ActivateTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/ActivateTest.kt index 8bab17a50..183773623 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/ActivateTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/ActivateTest.kt @@ -1,13 +1,13 @@ package com.bumble.appyx.components.spotlight.operation -import com.bumble.appyx.components.spotlight.InteractionTarget -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child3 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child3 import com.bumble.appyx.interactions.core.asElement import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.SpotlightModel.State.ElementState.STANDARD import com.bumble.appyx.components.spotlight.SpotlightModel.State.Position +import com.bumble.appyx.components.spotlight.TestTarget import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -24,7 +24,7 @@ class ActivateTest { activeIndex = 0f, ) - val activate = Activate(0f) + val activate = Activate(0f) assertFalse(activate.isApplicable(state)) } @@ -39,7 +39,7 @@ class ActivateTest { activeIndex = 0f ) - val activate = Activate(2f) + val activate = Activate(2f) assertFalse(activate.isApplicable(state)) } @@ -55,7 +55,7 @@ class ActivateTest { activeIndex = 0f ) - val activate = Activate(1f) + val activate = Activate(1f) assertEquals( actual = activate.invoke(state).targetState.activeIndex, diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/FirstTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/FirstTest.kt index d82afdc90..903fc4cbd 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/FirstTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/FirstTest.kt @@ -1,11 +1,11 @@ package com.bumble.appyx.components.spotlight.operation -import com.bumble.appyx.components.spotlight.InteractionTarget -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.SpotlightModel.State.ElementState.STANDARD import com.bumble.appyx.components.spotlight.SpotlightModel.State.Position +import com.bumble.appyx.components.spotlight.TestTarget import com.bumble.appyx.interactions.core.asElement import kotlin.test.Test import kotlin.test.assertEquals @@ -21,7 +21,7 @@ class FirstTest { ), activeIndex = 1f ) - val first = First() + val first = First() assertEquals( actual = first.invoke(state).targetState.activeIndex, diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/LastTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/LastTest.kt index fea4ba24c..0d074ecda 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/LastTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/LastTest.kt @@ -1,12 +1,12 @@ package com.bumble.appyx.components.spotlight.operation -import com.bumble.appyx.components.spotlight.InteractionTarget -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 import com.bumble.appyx.interactions.core.asElement import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.SpotlightModel.State.ElementState.STANDARD import com.bumble.appyx.components.spotlight.SpotlightModel.State.Position +import com.bumble.appyx.components.spotlight.TestTarget import kotlin.test.Test import kotlin.test.assertEquals @@ -21,7 +21,7 @@ class LastTest { ), activeIndex = 0f ) - val last = Last() + val last = Last() assertEquals( actual = last.invoke(state).targetState.activeIndex, diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/NextTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/NextTest.kt index a8f844ea2..e59de147e 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/NextTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/NextTest.kt @@ -1,13 +1,13 @@ package com.bumble.appyx.components.spotlight.operation -import com.bumble.appyx.components.spotlight.InteractionTarget -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child3 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child3 import com.bumble.appyx.interactions.core.asElement import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.SpotlightModel.State.ElementState.STANDARD import com.bumble.appyx.components.spotlight.SpotlightModel.State.Position +import com.bumble.appyx.components.spotlight.TestTarget import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -25,7 +25,7 @@ class NextTest { activeIndex = 2f ) - val next = Next() + val next = Next() assertFalse(next.isApplicable(state)) } @@ -41,7 +41,7 @@ class NextTest { activeIndex = 0f ) - val next = Next() + val next = Next() assertEquals( actual = next.invoke(state).targetState.activeIndex, diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/PreviousTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/PreviousTest.kt index e20ddda61..48f078ac1 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/PreviousTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/PreviousTest.kt @@ -1,14 +1,14 @@ package com.bumble.appyx.components.spotlight.operation -import com.bumble.appyx.components.spotlight.InteractionTarget -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child3 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child4 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child5 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child6 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child3 +import com.bumble.appyx.components.spotlight.TestTarget.Child4 +import com.bumble.appyx.components.spotlight.TestTarget.Child5 +import com.bumble.appyx.components.spotlight.TestTarget.Child6 import com.bumble.appyx.interactions.core.asElement import com.bumble.appyx.components.spotlight.SpotlightModel +import com.bumble.appyx.components.spotlight.TestTarget import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -37,7 +37,7 @@ class PreviousTest { activeIndex = 0f ) - val previous = Previous() + val previous = Previous() assertFalse(previous.isApplicable(state)) } @@ -64,7 +64,7 @@ class PreviousTest { activeIndex = 2f ) - val previous = Previous() + val previous = Previous() assertEquals( actual = previous.invoke(state).targetState.activeIndex, diff --git a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElementsTest.kt b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElementsTest.kt index ec0f3f613..cd433c0c4 100644 --- a/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElementsTest.kt +++ b/appyx-components/standard/spotlight/common/src/commonTest/kotlin/com/bumble/appyx/components/spotlight/operation/UpdateElementsTest.kt @@ -1,11 +1,11 @@ package com.bumble.appyx.components.spotlight.operation -import com.bumble.appyx.components.spotlight.InteractionTarget.Child1 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child2 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child3 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child4 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child5 -import com.bumble.appyx.components.spotlight.InteractionTarget.Child6 +import com.bumble.appyx.components.spotlight.TestTarget.Child1 +import com.bumble.appyx.components.spotlight.TestTarget.Child2 +import com.bumble.appyx.components.spotlight.TestTarget.Child3 +import com.bumble.appyx.components.spotlight.TestTarget.Child4 +import com.bumble.appyx.components.spotlight.TestTarget.Child5 +import com.bumble.appyx.components.spotlight.TestTarget.Child6 import com.bumble.appyx.components.spotlight.SpotlightModel import com.bumble.appyx.components.spotlight.SpotlightModel.State.ElementState.DESTROYED import com.bumble.appyx.components.spotlight.SpotlightModel.State.ElementState.STANDARD diff --git a/appyx-interactions/android/src/main/kotlin/com/bumble/appyx/interactions/testing/InteractionTarget.kt b/appyx-interactions/android/src/main/kotlin/com/bumble/appyx/interactions/testing/TestTarget.kt similarity index 81% rename from appyx-interactions/android/src/main/kotlin/com/bumble/appyx/interactions/testing/InteractionTarget.kt rename to appyx-interactions/android/src/main/kotlin/com/bumble/appyx/interactions/testing/TestTarget.kt index b8b4fb588..f46d9648d 100644 --- a/appyx-interactions/android/src/main/kotlin/com/bumble/appyx/interactions/testing/InteractionTarget.kt +++ b/appyx-interactions/android/src/main/kotlin/com/bumble/appyx/interactions/testing/TestTarget.kt @@ -1,5 +1,5 @@ package com.bumble.appyx.interactions.testing -enum class InteractionTarget { +enum class TestTarget { Child1, Child2, Child3, Child4, Child5, Child6, Child7, Child8, Child9, Child10 } diff --git a/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/navigation/node/ComponentNode.kt b/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/navigation/node/ComponentNode.kt new file mode 100644 index 000000000..4f280e715 --- /dev/null +++ b/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/navigation/node/ComponentNode.kt @@ -0,0 +1,27 @@ +package com.bumble.appyx.navigation.node + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.interactions.core.model.AppyxComponent +import com.bumble.appyx.navigation.modality.NodeContext + +/** + * A pre-wired node to build component-specific helper methods on. + */ +open class ComponentNode>( + nodeContext: NodeContext, + private val component: C, + private val mappings: (C, T, NodeContext) -> Node<*>, + private val content: @Composable (C, Modifier) -> Unit +) : Node( + appyxComponent = component, + nodeContext = nodeContext +) { + override fun buildChildNode(navTarget: T, nodeContext: NodeContext): Node<*> = + mappings(component, navTarget, nodeContext) + + @Composable + override fun Content(modifier: Modifier) { + content(component, modifier) + } +} diff --git a/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/checkout/CheckoutNode.kt b/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/checkout/CheckoutNode.kt index 2be9ce819..b2adf090c 100644 --- a/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/checkout/CheckoutNode.kt +++ b/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/checkout/CheckoutNode.kt @@ -1,97 +1,61 @@ package com.bumble.appyx.demos.navigation.node.checkout -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.bumble.appyx.components.backstack.BackStack -import com.bumble.appyx.components.backstack.BackStackModel +import com.bumble.appyx.components.backstack.node.backStackNode import com.bumble.appyx.components.backstack.operation.newRoot import com.bumble.appyx.components.backstack.operation.push import com.bumble.appyx.components.backstack.ui.parallax.BackStackParallax import com.bumble.appyx.components.backstack.ui.slider.BackStackSlider import com.bumble.appyx.demos.navigation.node.cart.Cart -import com.bumble.appyx.demos.navigation.node.checkout.CheckoutNode.NavTarget -import com.bumble.appyx.demos.navigation.platform.IOS_PLATFORM_NAME -import com.bumble.appyx.demos.navigation.platform.getPlatformName +import com.bumble.appyx.demos.navigation.node.checkout.NavTarget.Address +import com.bumble.appyx.demos.navigation.node.checkout.NavTarget.CartItems +import com.bumble.appyx.demos.navigation.node.checkout.NavTarget.Payment +import com.bumble.appyx.demos.navigation.node.checkout.NavTarget.Shipping +import com.bumble.appyx.demos.navigation.node.checkout.NavTarget.Success import com.bumble.appyx.interactions.core.ui.gesture.GestureFactory -import com.bumble.appyx.navigation.composable.AppyxNavigationContainer import com.bumble.appyx.navigation.modality.NodeContext import com.bumble.appyx.navigation.node.Node -import com.bumble.appyx.utils.multiplatform.Parcelable -import com.bumble.appyx.utils.multiplatform.Parcelize +import com.bumble.appyx.demos.navigation.platform.IOS_PLATFORM_NAME as IOS +import com.bumble.appyx.demos.navigation.platform.getPlatformName as platform + +private enum class NavTarget { + CartItems, + Address, + Shipping, + Payment, + Success +} -class CheckoutNode( - nodeContext: NodeContext, - private val cart: Cart, - private val backStack: BackStack = BackStack( - model = BackStackModel( - initialTargets = listOf(NavTarget.CartItems), - savedStateMap = nodeContext.savedStateMap, - ), - visualisation = { - if (getPlatformName() == IOS_PLATFORM_NAME) { - BackStackParallax(it) - } else { - BackStackSlider(it) +fun checkoutNode(nodeContext: NodeContext, cart: Cart): Node<*> = + backStackNode( + nodeContext = nodeContext, + initialTarget = CartItems, + mappings = { backStack, navTarget, childContext -> + with(backStack) { + when (navTarget) { + CartItems -> CartItemsNode(childContext, cart) { + push(Address) + } + Address -> AddressNode(childContext) { + push(Shipping) + } + Shipping -> ShippingDetailsNode(childContext) { + push(Payment) + } + Payment -> PaymentNode(childContext) { + cart.clear() + newRoot(Success) + } + Success -> OrderConfirmedNode(childContext) { + newRoot(CartItems) + } + } } }, + visualisation = { + if (platform() == IOS) BackStackParallax(it) else BackStackSlider(it) + }, gestureFactory = { - if (getPlatformName() == IOS_PLATFORM_NAME) { - BackStackParallax.Gestures(it) - } else { - GestureFactory.Noop() - } + if (platform() == IOS) BackStackParallax.Gestures(it) else GestureFactory.Noop() } ) -) : Node( - nodeContext = nodeContext, - appyxComponent = backStack -) { - sealed class NavTarget : Parcelable { - @Parcelize - object CartItems : NavTarget() - - @Parcelize - object Address : NavTarget() - - @Parcelize - object Shipping : NavTarget() - - @Parcelize - object Payment : NavTarget() - - @Parcelize - object Success : NavTarget() - } - - override fun buildChildNode(navTarget: NavTarget, nodeContext: NodeContext): Node<*> = - when (navTarget) { - is NavTarget.CartItems -> CartItemsNode(nodeContext, cart) { - backStack.push(NavTarget.Address) - } - is NavTarget.Address -> AddressNode(nodeContext) { - backStack.push(NavTarget.Shipping) - } - - is NavTarget.Shipping -> ShippingDetailsNode(nodeContext) { - backStack.push(NavTarget.Payment) - } - - is NavTarget.Payment -> PaymentNode(nodeContext) { - cart.clear() - backStack.newRoot(NavTarget.Success) - } - - is NavTarget.Success -> OrderConfirmedNode(nodeContext) { - backStack.newRoot(NavTarget.CartItems) - } - } - - @Composable - override fun Content(modifier: Modifier) { - AppyxNavigationContainer( - appyxComponent = backStack, - modifier = Modifier - ) - } -} diff --git a/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/main/MainNavItem.kt b/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/main/MainNavItem.kt index 6454ac711..0752d007d 100644 --- a/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/main/MainNavItem.kt +++ b/demos/appyx-navigation/common/src/commonMain/kotlin/com/bumble/appyx/demos/navigation/node/main/MainNavItem.kt @@ -12,7 +12,7 @@ import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.ShoppingCart import com.bumble.appyx.demos.navigation.node.cakes.CakeListNode import com.bumble.appyx.demos.navigation.node.cart.Cart -import com.bumble.appyx.demos.navigation.node.checkout.CheckoutNode +import com.bumble.appyx.demos.navigation.node.checkout.checkoutNode import com.bumble.appyx.demos.navigation.node.home.HomeNode import com.bumble.appyx.demos.navigation.node.profile.ProfileNode import com.bumble.appyx.demos.navigation.node.profile.User @@ -65,7 +65,7 @@ enum class MainNavItem : Parcelable { null } }, - node = { CheckoutNode(it, cart) } + node = { checkoutNode(it, cart) } ) } } diff --git a/demos/mkdocs/appyx-components/common/src/commonMain/kotlin/com/bumble/appyx/demos/common/AppyxWebSample.kt b/demos/mkdocs/appyx-components/common/src/commonMain/kotlin/com/bumble/appyx/demos/common/AppyxWebSample.kt index 46da9b3ec..0f6c716fb 100644 --- a/demos/mkdocs/appyx-components/common/src/commonMain/kotlin/com/bumble/appyx/demos/common/AppyxWebSample.kt +++ b/demos/mkdocs/appyx-components/common/src/commonMain/kotlin/com/bumble/appyx/demos/common/AppyxWebSample.kt @@ -29,6 +29,7 @@ import com.bumble.appyx.interactions.core.Element import com.bumble.appyx.interactions.core.model.BaseAppyxComponent import com.bumble.appyx.interactions.core.ui.helper.AppyxComponentSetup import kotlin.random.Random +import com.bumble.appyx.demos.common.InteractionTarget.Element as SampleElement sealed class InteractionTarget { data class Element(val idx: Int = Random.nextInt(1, 100)) : InteractionTarget() { @@ -136,7 +137,7 @@ fun ModalUi( .padding(if (isChildMaxSize) 0.dp else 8.dp) .background( color = when (val target = element.interactionTarget) { - is com.bumble.appyx.demos.common.InteractionTarget.Element -> colors.getOrElse(target.idx % colors.size) { Color.Cyan } + is SampleElement -> colors.getOrElse(target.idx % colors.size) { Color.Cyan } else -> { Color.Cyan }