diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d0bd33a9..e52b5faff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Pending changes +- [#311](https://github.com/bumble-tech/appyx/pull/311) – **Breaking change**: `NavTarget` and `State` are now explicitly `Parcelable`. Please see this PR to see approaches to resolve any compilation issues you may notice. - [#287](https://github.com/bumble-tech/appyx/pull/287) – **Added**: Introduced a new `rememberCombinedHandler` implementation that takes an immutable list to avoid non-skippable compositions. The previous implementation is now deprecated. - [#287](https://github.com/bumble-tech/appyx/pull/287) – **Added**: `ImmutableList` has been added to avoid non-skippable compositions. - [#289](https://github.com/bumble-tech/appyx/issues/289) – **Added**: Introduced `interop-rx3` for RxJava 3 support. This has identical functionality to `interop-rx2`. diff --git a/documentation/navmodel/backstack.md b/documentation/navmodel/backstack.md index a63bba753..de616e8fd 100644 --- a/documentation/navmodel/backstack.md +++ b/documentation/navmodel/backstack.md @@ -16,7 +16,8 @@ The back stack also supports different back press and operation strategies (see ## States ```kotlin -enum class State { +@Parcelize +enum class State : Parcelable { CREATED, ACTIVE, STASHED, DESTROYED, } ``` @@ -33,7 +34,7 @@ Check out the apps in our [Coding challenges](../how-to-use-appyx/coding-challen As the back stack can never be empty, it's required to define an initial target. ```kotlin -class BackStack( +class BackStack( initialElement: NavTarget, savedStateMap: SavedStateMap?, // Optional parameters are omitted @@ -131,7 +132,7 @@ Effect on stack: depends on the contents of the stack: You can override the default strategy in the constructor. You're not limited to using the provided classes, feel free to implement your own. ```kotlin -class BackStack( +class BackStack( /* ... */ backPressHandler: BackPressHandlerStrategy = PopBackPressHandler(), /* ... */ @@ -152,7 +153,7 @@ Serves as a no-op. You can override the default strategy in the constructor. You're not limited to using the provided classes, feel free to implement your own. ```kotlin -class BackStack( +class BackStack( /* ... */ operationStrategy: OperationStrategy = ExecuteImmediately(), /* ... */ diff --git a/documentation/navmodel/cards.md b/documentation/navmodel/cards.md index ce2d8f8b6..de3df07f4 100644 --- a/documentation/navmodel/cards.md +++ b/documentation/navmodel/cards.md @@ -15,13 +15,20 @@ The `Cards` NavModel is not currently published, however you can try it in `:sam ## States ```kotlin -sealed class State { +sealed class State: Parcelable { + @Parcelize data class Queued(val queueNumber: Int) : State() + @Parcelize object Bottom : State() + @Parcelize object Top : State() + @Parcelize object IndicateLike : State() + @Parcelize object IndicatePass : State() + @Parcelize object VoteLike : State() + @Parcelize object VotePass : State() } ``` @@ -35,7 +42,7 @@ sealed class State { Requires defining items that will be converted to profile cards. The first one in the list will become a `Top` card, the second one a `Bottom` card, the rest will be `Queued`. ```kotlin -class Cards( +class Cards( initialItems: List = listOf(), ) : BaseNavModel( screenResolver = CardsOnScreenResolver, diff --git a/documentation/navmodel/custom.md b/documentation/navmodel/custom.md index 40be939ae..73afec43c 100644 --- a/documentation/navmodel/custom.md +++ b/documentation/navmodel/custom.md @@ -7,7 +7,7 @@ A step-by-step guide. You can also take a look at other existing examples to see Create the class; define your possible states; define your initial state. ```kotlin -class Foo( +class Foo( initialItems: List = listOf(), savedStateMap: SavedStateMap? ) : BaseNavModel( @@ -17,7 +17,8 @@ class Foo( ) { // Your possible states for any single navigation target - enum class State { + @Parcelize + enum class State : Parcelable { CREATED, FOO, BAR, BAZ, DESTROYED; } @@ -54,7 +55,7 @@ Define one or more operations. ```kotlin @Parcelize -class SomeOperation : FooOperation { +class SomeOperation : FooOperation { override fun isApplicable(elements: FooElements): Boolean = TODO("Define whether this operation is applicable given the current state") @@ -74,7 +75,7 @@ class SomeOperation : FooOperation { } // You can add an extension method for a leaner API -fun Foo.someOperation() { +fun Foo.someOperation() { accept(FooOperation()) } ``` diff --git a/documentation/navmodel/promoter.md b/documentation/navmodel/promoter.md index 78b5fe8a3..a496f7c84 100644 --- a/documentation/navmodel/promoter.md +++ b/documentation/navmodel/promoter.md @@ -12,7 +12,8 @@ If you feel that this functionality should be part of the main library, please l ## States ```kotlin -enum class State { +@Parcelize +enum class State : Parcelable { CREATED, STAGE1, STAGE2, STAGE3, STAGE4, SELECTED, DESTROYED } ``` diff --git a/documentation/navmodel/spotlight.md b/documentation/navmodel/spotlight.md index 27ebc105e..275a8703b 100644 --- a/documentation/navmodel/spotlight.md +++ b/documentation/navmodel/spotlight.md @@ -9,7 +9,8 @@ It's great for flows or tabbed containers. ## States ```kotlin -enum class State { +@Parcelize +enum class State : Parcelable { INACTIVE_BEFORE, ACTIVE, INACTIVE_AFTER; } ``` @@ -19,7 +20,7 @@ enum class State { Requires defining items and an active index. ```kotlin -class Spotlight( +class Spotlight( items: List, initialActiveIndex: Int = 0, savedStateMap: SavedStateMap?, @@ -95,7 +96,7 @@ Replaces elements held by the spotlight instance with a new list. Transitions ne You can override the default strategy in the constructor. You're not limited to using the provided classes, feel free to implement your own. ```kotlin -class Spotlight( +class Spotlight( /* ... */ backPressHandler: BackPressHandlerStrategy = GoToDefault( initialActiveIndex @@ -118,7 +119,7 @@ Runs a `Previous` operation. You can override the default strategy in the constructor. You're not limited to using the provided classes, feel free to implement your own. ```kotlin -class Spotlight( +class Spotlight( /* ... */ operationStrategy: OperationStrategy = ExecuteImmediately(), /* ... */ diff --git a/documentation/navmodel/tiles.md b/documentation/navmodel/tiles.md index 6f98aec44..085f57085 100644 --- a/documentation/navmodel/tiles.md +++ b/documentation/navmodel/tiles.md @@ -12,7 +12,8 @@ If you feel that this functionality should be part of the main library, please l ## States ```kotlin -enum class State { +@Parcelize +enum class State : Parcelable { CREATED, STANDARD, SELECTED, DESTROYED } ``` diff --git a/documentation/ui/children-view.md b/documentation/ui/children-view.md index 3265c24b2..b1bdf1ccf 100644 --- a/documentation/ui/children-view.md +++ b/documentation/ui/children-view.md @@ -84,7 +84,7 @@ override fun View(modifier: Modifier) { } @Composable -private fun GridExample(elements: List>) { +private fun GridExample(elements: List>) { LazyVerticalGrid( columns = Fixed(2), modifier = Modifier.fillMaxSize(), diff --git a/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt b/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt index 3298e7286..c464055a6 100644 --- a/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt +++ b/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt @@ -13,6 +13,7 @@ import com.bumble.appyx.core.AppyxTestScenario import com.bumble.appyx.core.children.nodeOrNull import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.navigation.EmptyNavModel +import com.bumble.appyx.core.navigation.EmptyState import kotlinx.parcelize.Parcelize import org.junit.Assert.assertEquals import org.junit.Rule @@ -50,7 +51,7 @@ class PermanentChildTest { buildContext: BuildContext, ) : ParentNode( buildContext = buildContext, - navModel = EmptyNavModel(), + navModel = EmptyNavModel(), ) { @Parcelize diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntry.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntry.kt index cd36ef971..a900406e7 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntry.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntry.kt @@ -1,11 +1,12 @@ package com.bumble.appyx.core.children +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.state.SavedStateMap // custom equals/hashCode for MutableStateFlow and equality checks -sealed class ChildEntry { +sealed class ChildEntry { abstract val key: NavKey override fun equals(other: Any?): Boolean = @@ -18,12 +19,12 @@ sealed class ChildEntry { "$key@${javaClass.simpleName}" /** All public APIs should return this type of child which is ready to work with. */ - class Initialized( + class Initialized( override val key: NavKey, val node: Node, ) : ChildEntry() - class Suspended( + class Suspended( override val key: NavKey, val savedState: SavedStateMap?, ) : ChildEntry() diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntryExt.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntryExt.kt index d5ee48a42..bef7beee0 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntryExt.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildEntryExt.kt @@ -1,8 +1,9 @@ package com.bumble.appyx.core.children +import android.os.Parcelable import com.bumble.appyx.core.node.Node -val ChildEntry.nodeOrNull: Node? +val ChildEntry.nodeOrNull: Node? get() = when (this) { is ChildEntry.Initialized -> node diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildNodeCreationManager.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildNodeCreationManager.kt index 1b020aa96..59b312db5 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildNodeCreationManager.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/children/ChildNodeCreationManager.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.children +import android.os.Parcelable import androidx.lifecycle.coroutineScope import com.bumble.appyx.core.modality.AncestryInfo import com.bumble.appyx.core.modality.BuildContext @@ -21,7 +22,7 @@ import kotlinx.coroutines.launch * * Lifecycle of these nodes is managed in [com.bumble.appyx.core.lifecycle.ChildNodeLifecycleManager]. */ -internal class ChildNodeCreationManager( +internal class ChildNodeCreationManager( private var savedStateMap: SavedStateMap?, private val customisations: NodeCustomisationDirectory, private val keepMode: ChildEntry.KeepMode, diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Child.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Child.kt index 39f9ff9ca..c8fe862de 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Child.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Child.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.composable +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable @@ -32,7 +33,7 @@ import com.bumble.appyx.core.navigation.transition.TransitionParams import kotlinx.coroutines.flow.map @Composable -fun ParentNode.Child( +fun ParentNode.Child( navElement: NavElement, saveableStateHolder: SaveableStateHolder, transitionParams: TransitionParams, @@ -87,7 +88,7 @@ private class ChildRendererImpl( } @Composable -fun ParentNode.Child( +fun ParentNode.Child( navElement: NavElement, modifier: Modifier = Modifier, transitionHandler: TransitionHandler = JumpToEndTransitionHandler(), @@ -125,7 +126,7 @@ fun ParentNode.Child( } } -private fun NavElement.createDescriptor( +private fun NavElement.createDescriptor( transitionParams: TransitionParams ) = TransitionDescriptor( @@ -137,7 +138,7 @@ private fun NavElement.createDescript ) @Composable -fun NavModel?.childrenAsState(): State> = +fun NavModel?.childrenAsState(): State> = if (this != null) { elements.collectAsState() } else { @@ -145,7 +146,7 @@ fun NavModel?.childrenAsState(): State> = } @Composable -fun NavModel?.visibleChildrenAsState(): State> = +fun NavModel?.visibleChildrenAsState(): State> = if (this != null) { val visibleElementsFlow = remember { screenState.map { it.onScreen } } visibleElementsFlow.collectAsState(emptyList()) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Children.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Children.kt index 55937df26..b7e22e5c4 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Children.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/Children.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.composable +import android.os.Parcelable import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -26,7 +27,7 @@ import kotlinx.coroutines.flow.map import kotlin.reflect.KClass @Composable -inline fun ParentNode.Children( +inline fun ParentNode.Children( navModel: NavModel, modifier: Modifier = Modifier, transitionHandler: TransitionHandler = JumpToEndTransitionHandler(), @@ -63,7 +64,7 @@ inline fun ParentNode.Children( } } -class ChildrenTransitionScope( +class ChildrenTransitionScope( private val transitionHandler: TransitionHandler, private val transitionParams: TransitionParams, private val navModel: NavModel diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/lifecycle/ChildNodeLifecycleManager.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/lifecycle/ChildNodeLifecycleManager.kt index 59d6996fa..637ed6e81 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/lifecycle/ChildNodeLifecycleManager.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/lifecycle/ChildNodeLifecycleManager.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.lifecycle +import android.os.Parcelable import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleRegistry import com.bumble.appyx.core.children.ChildEntry @@ -23,7 +24,7 @@ import kotlinx.coroutines.launch * Hosts [LifecycleRegistry] to manage the current node lifecycle * and updates lifecycle of children nodes when updated. */ -internal class ChildNodeLifecycleManager( +internal class ChildNodeLifecycleManager( private val navModel: NavModel, private val children: StateFlow>, private val coroutineScope: CoroutineScope, @@ -86,7 +87,7 @@ internal class ChildNodeLifecycleManager( } } - private fun Flow>.keys() = + private fun Flow>.keys() = this .map { screenState -> ScreenState( @@ -100,7 +101,7 @@ internal class ChildNodeLifecycleManager( nodeOrNull?.updateLifecycleState(state) } - private data class ScreenState( + private data class ScreenState( val onScreen: List> = emptyList(), val offScreen: List> = emptyList(), ) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/BaseNavModel.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/BaseNavModel.kt index 82546b455..df5a00faf 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/BaseNavModel.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/BaseNavModel.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation +import android.os.Parcelable import androidx.activity.OnBackPressedCallback import com.bumble.appyx.core.mapState import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BackPressHandlerStrategy @@ -28,7 +29,7 @@ import kotlin.coroutines.EmptyCoroutineContext * * If more granular configuration is required, you should inherit NavModel interface instead. */ -abstract class BaseNavModel( +abstract class BaseNavModel( private val backPressHandler: BackPressHandlerStrategy = DontHandleBackPress(), private val operationStrategy: OperationStrategy = ExecuteImmediately(), private val screenResolver: OnScreenStateResolver, diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyNavModel.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyNavModel.kt index 330d8c517..0e9804e48 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyNavModel.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyNavModel.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation +import android.os.Parcelable import com.bumble.appyx.core.navigation.onscreen.OnScreenStateResolver /** @@ -7,7 +8,7 @@ import com.bumble.appyx.core.navigation.onscreen.OnScreenStateResolver * This is potentially useful if your ParentNode only uses * [com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel] */ -class EmptyNavModel : BaseNavModel( +class EmptyNavModel : BaseNavModel( savedStateMap = null, finalState = null, screenResolver = OnScreenStateResolver { true } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyState.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyState.kt new file mode 100644 index 000000000..43caa8f85 --- /dev/null +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/EmptyState.kt @@ -0,0 +1,16 @@ +package com.bumble.appyx.core.navigation + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +/** + * There are cases where you may need to have a NavModel without state. + * As state is [Parcelable] this class can be used to meet the contract. + */ +@Suppress("PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY") +@Parcelize +class EmptyState internal constructor() : Parcelable { + companion object { + val INSTANCE = EmptyState() + } +} diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavElement.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavElement.kt index 2a06ceb48..a9977e9f3 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavElement.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavElement.kt @@ -7,18 +7,18 @@ import kotlinx.parcelize.RawValue @Parcelize @Immutable -class NavElement private constructor( - val key: @RawValue NavKey, - val fromState: @RawValue State, - val targetState: @RawValue State, - val operation: @RawValue Operation, +class NavElement private constructor( + val key: NavKey, + val fromState: State, + val targetState: State, + val operation: Operation, val transitionHistory: List> ) : Parcelable { constructor( - key: @RawValue NavKey, - fromState: @RawValue State, - targetState: @RawValue State, - operation: @RawValue Operation, + key: NavKey, + fromState: State, + targetState: State, + operation: Operation, ) : this( key, fromState, diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavKey.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavKey.kt index 138a6c5ff..9e2869df7 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavKey.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavKey.kt @@ -8,12 +8,12 @@ import java.util.UUID @Parcelize @Immutable -class NavKey private constructor( - val navTarget: @RawValue NavTarget, +class NavKey private constructor( + val navTarget: NavTarget, val id: String ) : Parcelable { - constructor(navTarget: @RawValue NavTarget) : this( + constructor(navTarget: NavTarget) : this( navTarget = navTarget, id = UUID.randomUUID().toString() ) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModel.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModel.kt index 1e9453f5e..ed541f179 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModel.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModel.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation +import android.os.Parcelable import androidx.compose.runtime.Stable import com.bumble.appyx.core.plugin.BackPressHandler import com.bumble.appyx.core.plugin.SavesInstanceState @@ -7,7 +8,7 @@ import com.bumble.appyx.core.plugin.UpNavigationHandler import kotlinx.coroutines.flow.StateFlow @Stable -interface NavModel : NavModelAdapter, +interface NavModel : NavModelAdapter, UpNavigationHandler, SavesInstanceState, BackPressHandler { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModelAdapter.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModelAdapter.kt index ca524a2cb..b07a59849 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModelAdapter.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/NavModelAdapter.kt @@ -1,14 +1,15 @@ package com.bumble.appyx.core.navigation +import android.os.Parcelable import androidx.compose.runtime.Stable import kotlinx.coroutines.flow.StateFlow @Stable -interface NavModelAdapter { +interface NavModelAdapter { val screenState: StateFlow> - data class ScreenState( + data class ScreenState( val onScreen: NavElements = emptyList(), val offScreen: NavElements = emptyList(), ) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt index 53f42e32e..496e87ac8 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt @@ -3,7 +3,7 @@ package com.bumble.appyx.core.navigation import android.os.Parcelable import kotlinx.parcelize.Parcelize -interface Operation : +interface Operation : (NavElements) -> NavElements, Parcelable { fun isApplicable(elements: NavElements): Boolean @@ -67,7 +67,7 @@ interface Operation : } @Parcelize - class Noop : Operation { + class Noop : Operation { override fun isApplicable(elements: NavElements) = false diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BackPressHandlerStrategy.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BackPressHandlerStrategy.kt index a0a1b6ef4..ea383b14a 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BackPressHandlerStrategy.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BackPressHandlerStrategy.kt @@ -1,10 +1,11 @@ package com.bumble.appyx.core.navigation.backpresshandlerstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow -interface BackPressHandlerStrategy { +interface BackPressHandlerStrategy { fun init(navModel: BaseNavModel, scope: CoroutineScope) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BaseBackPressHandlerStrategy.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BaseBackPressHandlerStrategy.kt index 42dfb6dcf..21848c0c1 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BaseBackPressHandlerStrategy.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/BaseBackPressHandlerStrategy.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation.backpresshandlerstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow @@ -7,7 +8,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn -abstract class BaseBackPressHandlerStrategy +abstract class BaseBackPressHandlerStrategy : BackPressHandlerStrategy { protected lateinit var scope: CoroutineScope diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/DontHandleBackPress.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/DontHandleBackPress.kt index 6ad8f5463..ca5553093 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/DontHandleBackPress.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/backpresshandlerstrategies/DontHandleBackPress.kt @@ -1,9 +1,10 @@ package com.bumble.appyx.core.navigation.backpresshandlerstrategies +import android.os.Parcelable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf -class DontHandleBackPress : +class DontHandleBackPress : BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow = diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/CombinedNavModel.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/CombinedNavModel.kt index f7e31836c..572b7a8c8 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/CombinedNavModel.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/CombinedNavModel.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation.model.combined +import android.os.Parcelable import androidx.activity.OnBackPressedCallback import com.bumble.appyx.core.combineState import com.bumble.appyx.core.navigation.NavElements @@ -14,9 +15,9 @@ import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.StateFlow import kotlin.coroutines.EmptyCoroutineContext -class CombinedNavModel( +class CombinedNavModel( val navModels: List>, -) : NavModel, Destroyable { +) : NavModel, Destroyable { constructor(vararg navModels: NavModel) : this(navModels.toList()) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/NavModelExt.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/NavModelExt.kt index 692f4a05a..25ede220a 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/NavModelExt.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/combined/NavModelExt.kt @@ -1,8 +1,9 @@ package com.bumble.appyx.core.navigation.model.combined +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavModel -operator fun NavModel.plus( +operator fun NavModel.plus( other: NavModel, ): CombinedNavModel { val currentModels = if (this is CombinedNavModel) navModels else listOf(this) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElement.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElement.kt index dda0fc620..107f97d69 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElement.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElement.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation.model.permanent +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.NavElement -typealias PermanentElement = NavElement +typealias PermanentElement = NavElement diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElements.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElements.kt index 71ece421f..5337e0303 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElements.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentElements.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation.model.permanent +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.NavElements -typealias PermanentElements = NavElements +typealias PermanentElements = NavElements diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentNavModel.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentNavModel.kt index a5e680024..13cadf933 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentNavModel.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/PermanentNavModel.kt @@ -1,6 +1,8 @@ package com.bumble.appyx.core.navigation.model.permanent +import android.os.Parcelable import com.bumble.appyx.core.mapState +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.NavElement import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.core.navigation.NavModel @@ -15,11 +17,11 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlin.coroutines.EmptyCoroutineContext -class PermanentNavModel( +class PermanentNavModel( navTargets: Set = emptySet(), savedStateMap: SavedStateMap?, private val key: String = requireNotNull(PermanentNavModel::class.qualifiedName), -) : NavModel { +) : NavModel { private val scope: CoroutineScope = CoroutineScope(EmptyCoroutineContext + Dispatchers.Unconfined) @@ -37,8 +39,8 @@ class PermanentNavModel( savedStateMap.restore() ?: navTargets.map { key -> PermanentElement( key = NavKey(navTarget = key), - fromState = 0, - targetState = 0, + fromState = EmptyState.INSTANCE, + targetState = EmptyState.INSTANCE, operation = Operation.Noop() ) } @@ -47,7 +49,7 @@ class PermanentNavModel( override val elements: StateFlow> get() = state - override val screenState: StateFlow> by lazy { + override val screenState: StateFlow> by lazy { state.mapState(scope) { NavModelAdapter.ScreenState(onScreen = it) } } @@ -55,7 +57,7 @@ class PermanentNavModel( // no-op } - override fun accept(operation: Operation) { + override fun accept(operation: Operation) { if (operation.isApplicable(state.value)) { state.update { operation(it) } } @@ -65,7 +67,7 @@ class PermanentNavModel( state[key] = this.state.value } - private fun SavedStateMap?.restore(): List>? = + private fun SavedStateMap?.restore(): List>? = (this?.get(key) as? PermanentElements) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/Add.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/Add.kt index 9fd6642aa..c7cc73fb5 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/Add.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/Add.kt @@ -1,5 +1,7 @@ package com.bumble.appyx.core.navigation.model.permanent.operation +import android.os.Parcelable +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.NavElement import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey @@ -7,28 +9,28 @@ import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel import kotlinx.parcelize.Parcelize @Parcelize -data class Add( +data class Add( private val key: NavKey ) : PermanentOperation { - override fun isApplicable(elements: NavElements): Boolean = + override fun isApplicable(elements: NavElements): Boolean = !elements.any { it.key == key } override fun invoke( - elements: NavElements - ): NavElements = + elements: NavElements + ): NavElements = if (elements.any { it.key == key }) { elements } else { elements + NavElement( key = key, - fromState = 0, - targetState = 0, + fromState = EmptyState.INSTANCE, + targetState = EmptyState.INSTANCE, operation = this, ) } } -fun PermanentNavModel.add(navKey: NavKey) { +fun PermanentNavModel.add(navKey: NavKey) { accept(Add(navKey)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/AddUnique.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/AddUnique.kt index 287bd4711..1430e80cd 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/AddUnique.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/AddUnique.kt @@ -1,5 +1,7 @@ package com.bumble.appyx.core.navigation.model.permanent.operation +import android.os.Parcelable +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.NavElement import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey @@ -11,28 +13,28 @@ import kotlinx.parcelize.RawValue * Adds [NavTarget] into [PermanentNavModel] only if it is not there yet. */ @Parcelize -data class AddUnique( - private val navTarget: @RawValue NavTarget, +data class AddUnique( + private val navTarget: NavTarget, ) : PermanentOperation { - override fun isApplicable(elements: NavElements): Boolean = + override fun isApplicable(elements: NavElements): Boolean = !elements.any { it.key.navTarget == navTarget } override fun invoke( - elements: NavElements - ): NavElements = + elements: NavElements + ): NavElements = if (elements.any { it.key.navTarget == navTarget }) { elements } else { elements + NavElement( key = NavKey(navTarget), - fromState = 0, - targetState = 0, + fromState = EmptyState.INSTANCE, + targetState = EmptyState.INSTANCE, operation = this, ) } } -fun PermanentNavModel.addUnique(navTarget: NavTarget) { +fun PermanentNavModel.addUnique(navTarget: NavTarget) { accept(AddUnique(navTarget)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/PermanentOperation.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/PermanentOperation.kt index 364b7c481..a04997948 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/PermanentOperation.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/model/permanent/operation/PermanentOperation.kt @@ -1,5 +1,7 @@ package com.bumble.appyx.core.navigation.model.permanent.operation +import android.os.Parcelable +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.Operation -interface PermanentOperation : Operation +interface PermanentOperation : Operation diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/onscreen/OnScreenStateResolverExt.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/onscreen/OnScreenStateResolverExt.kt index ea12b891c..d10a3f970 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/onscreen/OnScreenStateResolverExt.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/onscreen/OnScreenStateResolverExt.kt @@ -1,8 +1,9 @@ package com.bumble.appyx.core.navigation.onscreen +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElement -fun OnScreenStateResolver.isOnScreen(element: NavElement<*, out State>): Boolean = +fun OnScreenStateResolver.isOnScreen(element: NavElement<*, out State>): Boolean = if (element.transitionHistory.isEmpty()) { isOnScreen(element.fromState) || isOnScreen(element.targetState) } else { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/BaseOperationStrategy.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/BaseOperationStrategy.kt index 8f5a645af..c2f5548ab 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/BaseOperationStrategy.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/BaseOperationStrategy.kt @@ -1,10 +1,11 @@ package com.bumble.appyx.core.navigation.operationstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.core.navigation.NavModel import kotlinx.coroutines.CoroutineScope -abstract class BaseOperationStrategy : OperationStrategy { +abstract class BaseOperationStrategy : OperationStrategy { protected lateinit var scope: CoroutineScope protected lateinit var navModel: NavModel diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/ExecuteImmediately.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/ExecuteImmediately.kt index e70177e05..3ef25fb5c 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/ExecuteImmediately.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/ExecuteImmediately.kt @@ -1,8 +1,9 @@ package com.bumble.appyx.core.navigation.operationstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation -class ExecuteImmediately : BaseOperationStrategy() { +class ExecuteImmediately : BaseOperationStrategy() { override fun accept(operation: Operation) { executeOperation(operation) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/FinishTransitionsOnNewOperation.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/FinishTransitionsOnNewOperation.kt index 4da87da04..0e58e5714 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/FinishTransitionsOnNewOperation.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/FinishTransitionsOnNewOperation.kt @@ -1,10 +1,12 @@ package com.bumble.appyx.core.navigation.operationstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.core.navigation.isTransitioning -class FinishTransitionsOnNewOperation : BaseOperationStrategy() { +class FinishTransitionsOnNewOperation : + BaseOperationStrategy() { override fun accept(operation: Operation) { finishUnfinishedTransitions() diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/IgnoreIfThereAreUnfinishedTransitions.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/IgnoreIfThereAreUnfinishedTransitions.kt index 92e4f2d92..206f5ae8e 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/IgnoreIfThereAreUnfinishedTransitions.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/IgnoreIfThereAreUnfinishedTransitions.kt @@ -1,9 +1,11 @@ package com.bumble.appyx.core.navigation.operationstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.core.navigation.isTransitioning -class IgnoreIfThereAreUnfinishedTransitions : BaseOperationStrategy() { +class IgnoreIfThereAreUnfinishedTransitions : + BaseOperationStrategy() { override fun accept(operation: Operation) { if (hasNoUnfinishedTransitions()) { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/OperationStrategy.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/OperationStrategy.kt index 761cea9f6..0ab1a7605 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/OperationStrategy.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/OperationStrategy.kt @@ -1,10 +1,11 @@ package com.bumble.appyx.core.navigation.operationstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.core.navigation.NavModel import kotlinx.coroutines.CoroutineScope -interface OperationStrategy { +interface OperationStrategy { fun init( navModel: NavModel, diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/QueueOperations.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/QueueOperations.kt index cc5667045..d2aa7b617 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/QueueOperations.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/operationstrategies/QueueOperations.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation.operationstrategies +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.isTransitioning @@ -7,7 +8,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.launch import java.util.LinkedList -class QueueOperations : BaseOperationStrategy() { +class QueueOperations : BaseOperationStrategy() { private val operationQueue = LinkedList>() private lateinit var collectJob: Job diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/CombinedHandler.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/CombinedHandler.kt index f11c5af6d..99a9b74f4 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/CombinedHandler.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/CombinedHandler.kt @@ -1,13 +1,14 @@ package com.bumble.appyx.core.navigation.transition import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import com.bumble.appyx.core.collections.ImmutableList -class CombinedHandler( +class CombinedHandler( private val handlers: List> ) : ModifierTransitionHandler() { @@ -33,11 +34,13 @@ class CombinedHandler( ) ) @Composable -fun rememberCombinedHandler(handlers: List>): ModifierTransitionHandler = +fun rememberCombinedHandler( + handlers: List> +): ModifierTransitionHandler = remember { CombinedHandler(handlers = handlers) } @Composable -fun rememberCombinedHandler( +fun rememberCombinedHandler( handlers: ImmutableList> ): ModifierTransitionHandler = remember(handlers) { CombinedHandler(handlers = handlers) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/JumpToEndTransitionHandler.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/JumpToEndTransitionHandler.kt index 80b4365b9..1af4c9a19 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/JumpToEndTransitionHandler.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/JumpToEndTransitionHandler.kt @@ -1,11 +1,12 @@ package com.bumble.appyx.core.navigation.transition import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.ui.Modifier @Suppress("TransitionPropertiesLabel") -class JumpToEndTransitionHandler : ModifierTransitionHandler() { +class JumpToEndTransitionHandler : ModifierTransitionHandler() { @SuppressLint("ModifierFactoryExtensionFunction") override fun createModifier( diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/ModifierTransitionHandler.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/ModifierTransitionHandler.kt index 85878c0fc..8b77a30d2 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/ModifierTransitionHandler.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/ModifierTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.core.navigation.transition import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.Transition import androidx.compose.animation.core.updateTransition @@ -12,7 +13,7 @@ import androidx.compose.ui.draw.clipToBounds import com.bumble.appyx.core.composable.ChildTransitionScope import com.bumble.appyx.core.composable.ChildTransitionScopeImpl -abstract class ModifierTransitionHandler(open val clipToBounds: Boolean = false) : +abstract class ModifierTransitionHandler(open val clipToBounds: Boolean = false) : TransitionHandler { private val clipToBoundsModifier: Modifier by lazy(LazyThreadSafetyMode.NONE) { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionDescriptor.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionDescriptor.kt index cb76eab0a..0740660d6 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionDescriptor.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionDescriptor.kt @@ -1,10 +1,11 @@ package com.bumble.appyx.core.navigation.transition +import android.os.Parcelable import androidx.compose.runtime.Immutable import com.bumble.appyx.core.navigation.Operation @Immutable -data class TransitionDescriptor( +data class TransitionDescriptor( val params: TransitionParams, val operation: Operation, val element: NavTarget, diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionHandler.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionHandler.kt index 32dc4a114..0e843f0c6 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionHandler.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/navigation/transition/TransitionHandler.kt @@ -1,11 +1,12 @@ package com.bumble.appyx.core.navigation.transition +import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import com.bumble.appyx.core.composable.ChildTransitionScope @Stable -interface TransitionHandler { +interface TransitionHandler { @Composable fun handle( diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/EmptyNodeViews.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/EmptyNodeViews.kt index bcbde45ca..a52023d42 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/EmptyNodeViews.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/EmptyNodeViews.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.node +import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -9,7 +10,7 @@ object EmptyNodeView : NodeView { override fun View(modifier: Modifier) = Unit } -class EmptyParentNodeView : ParentNodeView { +class EmptyParentNodeView : ParentNodeView { @Composable override fun ParentNode.NodeView(modifier: Modifier) = Unit diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNode.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNode.kt index 8d2611771..83b59e6ab 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNode.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNode.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.node +import android.os.Parcelable import androidx.annotation.CallSuper import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable @@ -49,7 +50,7 @@ import kotlin.reflect.KClass @Suppress("TooManyFunctions") @Stable -abstract class ParentNode( +abstract class ParentNode( navModel: NavModel, buildContext: BuildContext, view: ParentNodeView = EmptyParentNodeView(), diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNodeView.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNodeView.kt index d91e2cb1d..9c27adef4 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNodeView.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/node/ParentNodeView.kt @@ -1,9 +1,10 @@ package com.bumble.appyx.core.node +import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -interface ParentNodeView : NodeView { +interface ParentNodeView : NodeView { @Composable fun ParentNode.NodeView(modifier: Modifier) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStack.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStack.kt index 8b001d25e..dd41087a7 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStack.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStack.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavKey @@ -12,8 +13,9 @@ import com.bumble.appyx.navmodel.backstack.BackStack.State.DESTROYED import com.bumble.appyx.navmodel.backstack.backpresshandler.PopBackPressHandler import com.bumble.appyx.core.state.SavedStateMap import com.bumble.appyx.navmodel.backstack.BackStack.State.ACTIVE +import kotlinx.parcelize.Parcelize -class BackStack( +class BackStack( initialElement: NavTarget, savedStateMap: SavedStateMap?, key: String = KEY_NAV_MODEL, @@ -29,7 +31,8 @@ class BackStack( key = key, ) { - enum class State { + @Parcelize + enum class State : Parcelable { CREATED, ACTIVE, STASHED, DESTROYED, } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStackExt.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStackExt.kt index 7e9b184de..2338d8a66 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStackExt.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/BackStackExt.kt @@ -1,18 +1,19 @@ package com.bumble.appyx.navmodel.backstack +import android.os.Parcelable import com.bumble.appyx.navmodel.backstack.BackStack.State.ACTIVE -val BackStackElements.active: BackStackElement? +val BackStackElements.active: BackStackElement? get() = lastOrNull { it.targetState == ACTIVE } -val BackStack.active: BackStackElement? +val BackStack.active: BackStackElement? get() = elements.value.active -val BackStackElements.activeElement: T? +val BackStackElements.activeElement: T? get() = active?.key?.navTarget -val BackStack.activeElement: T? +val BackStack.activeElement: T? get() = elements.value.activeElement -val BackStackElements.activeIndex: Int +val BackStackElements.activeIndex: Int get() = indexOfLast { it.targetState == ACTIVE } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/backpresshandler/PopBackPressHandler.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/backpresshandler/PopBackPressHandler.kt index 666206b20..d1e072d23 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/backpresshandler/PopBackPressHandler.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/backpresshandler/PopBackPressHandler.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStackElements @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.backstack.operation.Pop import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class PopBackPressHandler : +class PopBackPressHandler : BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow by lazy { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/BackStackOperation.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/BackStackOperation.kt index 2ad7830ef..2e8d9476d 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/BackStackOperation.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/BackStackOperation.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.navmodel.backstack.BackStack -interface BackStackOperation : Operation +interface BackStackOperation : Operation diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/NewRoot.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/NewRoot.kt index 691ad3401..1f106c9b7 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/NewRoot.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/NewRoot.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStackElement @@ -16,8 +17,8 @@ import kotlinx.parcelize.RawValue * [A, B, C] + NewRoot(D) = [ D ] */ @Parcelize -data class NewRoot( - private val element: @RawValue T +data class NewRoot( + private val element: T ) : BackStackOperation { override fun isApplicable(elements: BackStackElements): Boolean = true @@ -48,6 +49,6 @@ data class NewRoot( } } -fun BackStack.newRoot(element: T) { +fun BackStack.newRoot(element: T) { accept(NewRoot(element)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Pop.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Pop.kt index 39f0ddc08..4c320b5c8 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Pop.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Pop.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStackElements import com.bumble.appyx.navmodel.backstack.activeIndex @@ -11,7 +12,7 @@ import kotlinx.parcelize.Parcelize * [A, B, C] + Pop = [A, B] */ @Parcelize -class Pop : BackStackOperation { +class Pop : BackStackOperation { override fun isApplicable(elements: BackStackElements): Boolean = elements.any { it.targetState == BackStack.State.ACTIVE } && @@ -46,6 +47,6 @@ class Pop : BackStackOperation { override fun hashCode(): Int = this.javaClass.hashCode() } -fun BackStack.pop() { +fun BackStack.pop() { accept(Pop()) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt index a2c3f82b3..439a8b833 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStackElement @@ -17,8 +18,8 @@ import kotlinx.parcelize.RawValue * [A, B, C] + Push(D) = [A, B, C, D] */ @Parcelize -data class Push( - private val element: @RawValue T +data class Push( + private val element: T ) : BackStackOperation { override fun isApplicable(elements: BackStackElements): Boolean = @@ -35,6 +36,6 @@ data class Push( ) } -fun BackStack.push(element: T) { +fun BackStack.push(element: T) { accept(Push(element)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Remove.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Remove.kt index f365332b2..674beebc0 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Remove.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Remove.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStackElements @@ -12,7 +13,7 @@ import kotlinx.parcelize.Parcelize * [A, B, C] + Remove(id of B) = [A, C] */ @Parcelize -data class Remove( +data class Remove( private val key: NavKey ) : BackStackOperation { @@ -61,6 +62,6 @@ data class Remove( } } -fun BackStack.remove(key: NavKey) { +fun BackStack.remove(key: NavKey) { accept(Remove(key)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt index ecde3a821..9ef70f6e5 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStack.State.ACTIVE @@ -18,8 +19,8 @@ import kotlinx.parcelize.RawValue * [A, B, C] + Replace(D) = [A, B, D] */ @Parcelize -data class Replace( - private val element: @RawValue T +data class Replace( + private val element: T ) : BackStackOperation { override fun isApplicable(elements: BackStackElements): Boolean = @@ -41,6 +42,6 @@ data class Replace( } } -fun BackStack.replace(element: T) { +fun BackStack.replace(element: T) { accept(Replace(element)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt index 32b1941bc..d91fb05ce 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.BackStackElement @@ -18,11 +19,11 @@ import kotlinx.parcelize.RawValue * [A, B, C, D] + SingleTop(B') = [A, B'] // of same type but not equals, acts as n * Pop + Replace * [A, B, C, D] + SingleTop(E) = [A, B, C, D, E] // not found, acts as Push */ -sealed class SingleTop : BackStackOperation { +sealed class SingleTop : BackStackOperation { @Parcelize - class SingleTopReactivateBackStackOperation( - private val element: @RawValue T, + class SingleTopReactivateBackStackOperation( + private val element: T, private val position: Int ) : SingleTop() { @@ -52,8 +53,8 @@ sealed class SingleTop : BackStackOperation { } @Parcelize - class SingleTopReplaceBackStackOperation( - private val element: @RawValue T, + class SingleTopReplaceBackStackOperation( + private val element: T, private val position: Int, ) : SingleTop() { @@ -85,7 +86,7 @@ sealed class SingleTop : BackStackOperation { companion object { - fun init( + fun init( element: T, elements: BackStackElements ): BackStackOperation { @@ -112,6 +113,6 @@ sealed class SingleTop : BackStackOperation { } } -fun BackStack.singleTop(element: T) { +fun BackStack.singleTop(element: T) { accept(SingleTop.init(element, elements.value)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackFader.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackFader.kt index b781fccb1..8f0513882 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackFader.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackFader.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.backstack.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.spring @@ -15,7 +16,7 @@ import com.bumble.appyx.core.navigation.transition.TransitionSpec import com.bumble.appyx.navmodel.backstack.BackStack @Suppress("TransitionPropertiesLabel") -class BackStackFader( +class BackStackFader( private val transitionSpec: TransitionSpec = { spring() } ) : ModifierTransitionHandler() { @@ -39,7 +40,7 @@ class BackStackFader( } @Composable -fun rememberBackstackFader( +fun rememberBackstackFader( transitionSpec: TransitionSpec = { spring() } ): ModifierTransitionHandler = remember { BackStackFader(transitionSpec = transitionSpec) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackSlider.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackSlider.kt index abfa73fb0..4bbc70c32 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackSlider.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/transitionhandler/BackStackSlider.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.backstack.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateOffset @@ -27,7 +28,7 @@ import com.bumble.appyx.navmodel.backstack.operation.SingleTop.SingleTopReplaceB import com.bumble.appyx.navmodel.toIntOffset @Suppress("TransitionPropertiesLabel") -class BackStackSlider( +class BackStackSlider( private val transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) }, @@ -77,7 +78,7 @@ class BackStackSlider( } @Composable -fun rememberBackstackSlider( +fun rememberBackstackSlider( transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) }, clipToBounds: Boolean = false ): ModifierTransitionHandler = remember { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/Spotlight.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/Spotlight.kt index ac8317193..a8e75c875 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/Spotlight.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/Spotlight.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BackPressHandlerStrategy import com.bumble.appyx.core.navigation.onscreen.OnScreenStateResolver @@ -9,8 +10,9 @@ import com.bumble.appyx.core.state.SavedStateMap import com.bumble.appyx.navmodel.spotlight.Spotlight.State import com.bumble.appyx.navmodel.spotlight.backpresshandler.GoToDefault import com.bumble.appyx.navmodel.spotlight.operation.toSpotlightElements +import kotlinx.parcelize.Parcelize -class Spotlight( +class Spotlight( items: List, initialActiveIndex: Int = 0, savedStateMap: SavedStateMap?, @@ -29,7 +31,8 @@ class Spotlight( key = key, ) { - enum class State { + @Parcelize + enum class State : Parcelable { INACTIVE_BEFORE, ACTIVE, INACTIVE_AFTER; } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightElementExt.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightElementExt.kt index 4bf5a184c..bc06a8a9d 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightElementExt.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightElementExt.kt @@ -1,9 +1,10 @@ package com.bumble.appyx.navmodel.spotlight +import android.os.Parcelable import com.bumble.appyx.navmodel.spotlight.Spotlight.State.ACTIVE -val SpotlightElements.current: SpotlightElement? +val SpotlightElements.current: SpotlightElement? get() = this.lastOrNull { it.targetState == ACTIVE } -val SpotlightElements.currentIndex: Int +val SpotlightElements.currentIndex: Int get() = this.indexOfLast { it.targetState == ACTIVE } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightExt.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightExt.kt index ffaa66bc1..0f5e40540 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightExt.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/SpotlightExt.kt @@ -1,18 +1,19 @@ package com.bumble.appyx.navmodel.spotlight +import android.os.Parcelable import kotlinx.coroutines.flow.map -fun Spotlight.hasNext() = +fun Spotlight.hasNext() = elements.map { value -> value.lastIndex != elements.value.currentIndex } -fun Spotlight.hasPrevious() = +fun Spotlight.hasPrevious() = elements.map { value -> value.currentIndex != 0 } -fun Spotlight.activeIndex() = +fun Spotlight.activeIndex() = elements.map { value -> value.currentIndex } -fun Spotlight.current() = +fun Spotlight.current() = elements.map { value -> value.current?.key?.navTarget } -fun Spotlight.elementsCount() = +fun Spotlight.elementsCount() = elements.value.size diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToDefault.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToDefault.kt index 0e85f9555..8d8e95002 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToDefault.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToDefault.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.spotlight.Spotlight.State.ACTIVE @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.spotlight.operation.Activate import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class GoToDefault( +class GoToDefault( private val defaultElementIndex: Int = 0 ) : BaseBackPressHandlerStrategy() { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToPrevious.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToPrevious.kt index 604d86134..faa669afb 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToPrevious.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/GoToPrevious.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.spotlight.SpotlightElements @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.spotlight.operation.Previous import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class GoToPrevious : +class GoToPrevious : BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow by lazy { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/UndoHistory.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/UndoHistory.kt index 53b52a665..232aca6b1 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/UndoHistory.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/backpresshandler/UndoHistory.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.spotlight.Spotlight.State.ACTIVE @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.spotlight.operation.Activate import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class UndoHistory( +class UndoHistory( private val historyLimit: Int = 10 ) : BaseBackPressHandlerStrategy() { diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Activate.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Activate.kt index 13e08c5f5..62ddec5f0 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Activate.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Activate.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.spotlight.Spotlight.State @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.spotlight.currentIndex import kotlinx.parcelize.Parcelize @Parcelize -class Activate( +class Activate( private val index: Int ) : SpotlightOperation { @@ -43,6 +44,6 @@ class Activate( } -fun Spotlight.activate(index: Int) { +fun Spotlight.activate(index: Int) { accept(Activate(index)) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Next.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Next.kt index 7a629b59d..0f9fd6d11 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Next.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Next.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.spotlight.Spotlight.State @@ -9,7 +10,7 @@ import com.bumble.appyx.navmodel.spotlight.Spotlight.State.INACTIVE_BEFORE import kotlinx.parcelize.Parcelize @Parcelize -class Next : SpotlightOperation { +class Next : SpotlightOperation { override fun isApplicable(elements: NavElements) = elements.any { it.fromState == INACTIVE_AFTER && it.targetState == INACTIVE_AFTER } @@ -40,7 +41,7 @@ class Next : SpotlightOperation { } } -fun Spotlight.next() { +fun Spotlight.next() { accept(Next()) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Previous.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Previous.kt index 7a8b13863..125b44eee 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Previous.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/Previous.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.spotlight.Spotlight.State.ACTIVE @@ -9,7 +10,7 @@ import kotlinx.parcelize.Parcelize @Parcelize -class Previous : SpotlightOperation { +class Previous : SpotlightOperation { override fun isApplicable(elements: NavElements) = elements.any { it.fromState == INACTIVE_BEFORE && it.targetState == INACTIVE_BEFORE } @@ -42,7 +43,7 @@ class Previous : SpotlightOperation { } } -fun Spotlight.previous() { +fun Spotlight.previous() { accept(Previous()) } diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/UpdateElements.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/UpdateElements.kt index 336c42eed..63dab3eff 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/UpdateElements.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/operation/UpdateElements.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlight.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey @@ -14,8 +15,8 @@ import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @Parcelize -class UpdateElements( - private val elements: @RawValue List, +class UpdateElements( + private val elements: List, private val initialActiveIndex: Int? = null, ) : SpotlightOperation { @@ -46,14 +47,14 @@ class UpdateElements( } } -fun Spotlight.updateElements( +fun Spotlight.updateElements( items: List, initialActiveItem: Int? = null ) { accept(UpdateElements(items, initialActiveItem)) } -internal fun List.toSpotlightElements(activeIndex: Int): SpotlightElements = +internal fun List.toSpotlightElements(activeIndex: Int): SpotlightElements = mapIndexed { index, item -> val state = when { index < activeIndex -> INACTIVE_BEFORE diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightFader.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightFader.kt index 0299f4317..51b133699 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightFader.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightFader.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.spotlight.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.spring @@ -16,7 +17,7 @@ import com.bumble.appyx.navmodel.spotlight.Spotlight @Suppress("TransitionPropertiesLabel") -class SpotlightFader( +class SpotlightFader( private val transitionSpec: TransitionSpec = { spring() } ) : ModifierTransitionHandler() { @@ -40,7 +41,7 @@ class SpotlightFader( } @Composable -fun rememberSpotlightFader( +fun rememberSpotlightFader( transitionSpec: TransitionSpec = { spring() } ): ModifierTransitionHandler = remember { SpotlightFader(transitionSpec = transitionSpec) diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightSlider.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightSlider.kt index 9bdb12c04..d4322837b 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightSlider.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/navmodel/spotlight/transitionhandler/SpotlightSlider.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.spotlight.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateOffset @@ -19,7 +20,7 @@ import com.bumble.appyx.navmodel.spotlight.Spotlight import com.bumble.appyx.navmodel.toIntOffset @Suppress("TransitionPropertiesLabel") -class SpotlightSlider( +class SpotlightSlider( private val transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) }, @@ -57,7 +58,7 @@ class SpotlightSlider( } @Composable -fun rememberSpotlightSlider( +fun rememberSpotlightSlider( transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) }, clipToBounds: Boolean = false ): ModifierTransitionHandler = remember { diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildAwareTestBase.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildAwareTestBase.kt index 10ca5604b..d698f479b 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildAwareTestBase.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildAwareTestBase.kt @@ -1,9 +1,11 @@ package com.bumble.appyx.core.children +import android.os.Parcelable import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.navigation.NavModel import com.bumble.appyx.core.navigation.NavModelAdapter import com.bumble.appyx.core.navigation.Operation @@ -22,6 +24,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update +import kotlinx.parcelize.Parcelize import org.junit.Before import org.junit.Rule import kotlin.coroutines.EmptyCoroutineContext @@ -53,11 +56,16 @@ open class ChildAwareTestBase { .mapNotNull { it.nodeOrNull } } - sealed class Configuration : Comparable { + sealed class Configuration : Comparable, Parcelable { abstract val id: Int + @Parcelize data class Child1(override val id: Int = 0) : Configuration() + + @Parcelize data class Child2(override val id: Int = 0) : Configuration() + + @Parcelize data class Child3(override val id: Int = 0) : Configuration() override fun compareTo(other: Configuration): Int { @@ -118,13 +126,13 @@ open class ChildAwareTestBase { } } - class TestNavModel : NavModel { + class TestNavModel : NavModel { private val scope = CoroutineScope(EmptyCoroutineContext + Dispatchers.Unconfined) - private val state = MutableStateFlow(emptyList>()) - override val elements: StateFlow> + private val state = MutableStateFlow(emptyList>()) + override val elements: StateFlow> get() = state - override val screenState: StateFlow> + override val screenState: StateFlow> get() = state.map { NavModelAdapter.ScreenState(onScreen = it) } .stateIn(scope, SharingStarted.Eagerly, NavModelAdapter.ScreenState()) @@ -146,8 +154,8 @@ open class ChildAwareTestBase { list + key.map { NavElement( key = it, - fromState = 0, - targetState = 0, + fromState = EmptyState.INSTANCE, + targetState = EmptyState.INSTANCE, operation = Operation.Noop(), ) } diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildCreationTest.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildCreationTest.kt index ee8b5f690..973d46800 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildCreationTest.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/core/children/ChildCreationTest.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.children +import android.os.Parcelable import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.navigation.BaseNavModel @@ -13,6 +14,7 @@ import com.bumble.appyx.core.node.ParentNode import com.bumble.appyx.core.node.build import com.bumble.appyx.core.state.MutableSavedStateMap import com.bumble.appyx.testing.junit4.util.MainDispatcherRule +import kotlinx.parcelize.Parcelize import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull @@ -152,16 +154,17 @@ class ChildCreationTest { // region Setup - private class TestNavModel : BaseNavModel( + private class TestNavModel : BaseNavModel( screenResolver = OnScreenStateResolver { it == State.ON_SCREEN }, finalState = State.DESTROYED, savedStateMap = null, ) { - enum class State { ON_SCREEN, OFF_SCREEN, DESTROYED } + @Parcelize + enum class State: Parcelable { ON_SCREEN, OFF_SCREEN, DESTROYED } - override val initialElements: NavElements = listOf( + override val initialElements: NavElements = listOf( NavElement( - key = NavKey("initial"), + key = NavKey(StringNavTarget("initial")), fromState = State.ON_SCREEN, targetState = State.ON_SCREEN, operation = Operation.Noop(), @@ -171,7 +174,7 @@ class ChildCreationTest { fun add(navTarget: String, state: State) { updateState { it + NavElement( - key = NavKey(navTarget), + key = NavKey(StringNavTarget(navTarget)), fromState = state, targetState = state, operation = Operation.Noop(), @@ -180,15 +183,17 @@ class ChildCreationTest { } fun remove(navTarget: String) { + val stringNavTarget = StringNavTarget(navTarget) updateState { - it.filterNot { it.key.navTarget == navTarget } + it.filterNot { it.key.navTarget == stringNavTarget } } } fun suspend(navTarget: String) { + val stringNavTarget = StringNavTarget(navTarget) updateState { list -> list.map { - if (it.key.navTarget == navTarget) { + if (it.key.navTarget == stringNavTarget) { it.transitionTo(State.OFF_SCREEN, Operation.Noop()) } else { it @@ -198,9 +203,10 @@ class ChildCreationTest { } fun unsuspend(navTarget: String) { + val stringNavTarget = StringNavTarget(navTarget) updateState { list -> list.map { - if (it.key.navTarget == navTarget) { + if (it.key.navTarget == stringNavTarget) { it.transitionTo(State.ON_SCREEN, Operation.Noop()) } else { it @@ -215,7 +221,7 @@ class ChildCreationTest { keepMode: ChildEntry.KeepMode = ChildEntry.KeepMode.KEEP, buildContext: BuildContext = BuildContext.root(null), val testNavModel: TestNavModel = TestNavModel(), - ) : ParentNode( + ) : ParentNode( buildContext = buildContext, navModel = testNavModel, childKeepMode = keepMode, @@ -225,14 +231,16 @@ class ChildCreationTest { manageTransitionsInTest() } - override fun resolve(navTarget: String, buildContext: BuildContext): Node = + override fun resolve(navTarget: StringNavTarget, buildContext: BuildContext): Node = Child(buildContext) - fun key(navTarget: String): NavKey? = + fun key(navTarget: StringNavTarget): NavKey? = children.value.keys.find { it.navTarget == navTarget } - fun child(navTarget: String): Child? = - children.value.values.find { it.key.navTarget == navTarget }?.nodeOrNull as Child? + fun child(navTarget: String): Child? { + val stringNavTarget = StringNavTarget(navTarget) + return children.value.values.find { it.key.navTarget == stringNavTarget }?.nodeOrNull as Child? + } } @@ -246,6 +254,9 @@ class ChildCreationTest { } } + @Parcelize + data class StringNavTarget(val value: String) : Parcelable + // endregion } diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ChildLifecycleTest.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ChildLifecycleTest.kt index 91599142c..35d8a3fed 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ChildLifecycleTest.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ChildLifecycleTest.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.lifecycle +import android.os.Parcelable import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -7,6 +8,7 @@ import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import com.bumble.appyx.core.children.nodeOrNull +import com.bumble.appyx.core.lifecycle.ChildLifecycleTest.TestNavModel.OnScreenState import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.NavElement @@ -18,6 +20,7 @@ import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode import com.bumble.appyx.core.node.build import com.bumble.appyx.testing.junit4.util.MainDispatcherRule +import kotlinx.parcelize.Parcelize import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test @@ -153,38 +156,44 @@ class ChildLifecycleTest { // region Setup - private class TestNavModel : BaseNavModel( - screenResolver = object : OnScreenStateResolver { - override fun isOnScreen(state: Boolean): Boolean = state + private class TestNavModel : BaseNavModel( + screenResolver = object : OnScreenStateResolver { + override fun isOnScreen(state: OnScreenState): Boolean = state.value }, finalState = null, savedStateMap = null, ) { - override val initialElements: NavElements = emptyList() + @Parcelize + data class OnScreenState(val value: Boolean) : Parcelable + + override val initialElements: NavElements = emptyList() fun add(key: String, onScreen: Boolean) { updateState { list -> list + NavElement( - key = NavKey(key), - targetState = onScreen, - fromState = onScreen, + key = NavKey(StringNavTarget(key)), + targetState = OnScreenState(onScreen), + fromState = OnScreenState(onScreen), operation = Operation.Noop(), ) } } fun remove(key: String) { - updateState { list -> list.filter { it.key.navTarget != key } } + val stringNavTarget = StringNavTarget(key) + updateState { list -> list.filter { it.key.navTarget != stringNavTarget } } } fun changeState(key: String, onScreen: Boolean) { + val stringNavTarget = StringNavTarget(key) + val onScreenState = OnScreenState(onScreen) updateState { list -> list .map { - if (it.key.navTarget == key) { + if (it.key.navTarget == stringNavTarget) { it .transitionTo( - newTargetState = onScreen, + newTargetState = onScreenState, operation = Operation.Noop() ) .onTransitionFinished() @@ -199,11 +208,11 @@ class ChildLifecycleTest { private class Parent( buildContext: BuildContext, val testNavModel: TestNavModel = TestNavModel(), - ) : ParentNode( + ) : ParentNode( buildContext = buildContext, navModel = testNavModel, ) { - override fun resolve(navTarget: String, buildContext: BuildContext): Node = + override fun resolve(navTarget: StringNavTarget, buildContext: BuildContext): Node = Child(buildContext) @Composable @@ -232,6 +241,9 @@ class ChildLifecycleTest { } } + @Parcelize + data class StringNavTarget(val value: String) : Parcelable + // endregion } diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ParentLifecycleTest.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ParentLifecycleTest.kt index 1e3d3cb09..fa303ed39 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ParentLifecycleTest.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/core/lifecycle/ParentLifecycleTest.kt @@ -1,9 +1,11 @@ package com.bumble.appyx.core.lifecycle +import android.os.Parcelable import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.lifecycle.Lifecycle +import com.bumble.appyx.core.lifecycle.ParentLifecycleTest.Parent.StringNavTarget import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.NavElement @@ -15,6 +17,7 @@ import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode import com.bumble.appyx.core.node.build import com.bumble.appyx.testing.junit4.util.MainDispatcherRule +import kotlinx.parcelize.Parcelize import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test @@ -32,7 +35,7 @@ class ParentLifecycleTest { fun `parent node finishes transitions for off screen elements when lifecycle is not stopped`() { val parent = Parent(BuildContext.root(null)).build() val navModel = parent.navModelImpl - val navTarget = "0" + val navTarget = StringNavTarget("0") parent.updateLifecycleState(Lifecycle.State.STARTED) navModel.add(navTarget = navTarget, defaultState = NavModelImpl.State.StateOne) @@ -46,7 +49,7 @@ class ParentLifecycleTest { ) } - private class NavModelImpl : BaseNavModel( + private class NavModelImpl : BaseNavModel( screenResolver = object : OnScreenStateResolver { override fun isOnScreen(state: State): Boolean = when (state) { @@ -60,16 +63,17 @@ class ParentLifecycleTest { savedStateMap = null, ) { - enum class State { + @Parcelize + enum class State: Parcelable { StateOne, StateTwo, StateThree, StateFour, } - override val initialElements: NavElements = emptyList() + override val initialElements: NavElements = emptyList() - fun add(navTarget: String, defaultState: State) { + fun add(navTarget: StringNavTarget, defaultState: State) { updateState { list -> list + NavElement( key = NavKey(navTarget), @@ -80,18 +84,18 @@ class ParentLifecycleTest { } } - fun get(navTarget: String): NavElement { + fun get(navTarget: StringNavTarget): NavElement { return requireNotNull( value = elements.value.find { it.key.navTarget == navTarget }, lazyMessage = { "element with navTarget $navTarget is not found" }, ) } - fun remove(navTarget: String) { + fun remove(navTarget: StringNavTarget) { updateState { list -> list.filter { it.key.navTarget != navTarget } } } - fun changeState(navTarget: String, defaultState: State) { + fun changeState(navTarget: StringNavTarget, defaultState: State) { updateState { list -> list .map { @@ -112,11 +116,14 @@ class ParentLifecycleTest { private class Parent( buildContext: BuildContext, val navModelImpl: NavModelImpl = NavModelImpl(), - ) : ParentNode( + ) : ParentNode( buildContext = buildContext, navModel = navModelImpl, ) { - override fun resolve(navTarget: String, buildContext: BuildContext): Node = + @Parcelize + data class StringNavTarget(val value: String) : Parcelable + + override fun resolve(navTarget: StringNavTarget, buildContext: BuildContext): Node = Child(buildContext) @Composable diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/core/navigation/upnavigation/UpNavigationTest.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/core/navigation/upnavigation/UpNavigationTest.kt index e222555bc..02d25505e 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/core/navigation/upnavigation/UpNavigationTest.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/core/navigation/upnavigation/UpNavigationTest.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.navigation.upnavigation +import android.os.Parcelable import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -15,6 +16,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.bumble.appyx.testing.unit.common.util.TestIntegrationPoint import com.bumble.appyx.testing.unit.common.util.TestUpNavigationHandler +import kotlinx.parcelize.Parcelize import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test @@ -136,7 +138,8 @@ class UpNavigationTest { navModel = backStack, plugins = upNavigationHandler?.let { listOf(it) } ?: emptyList(), ), NodeWithId { - data class Configuration(val id: UUID) + @Parcelize + data class Configuration(val id: UUID): Parcelable init { manageTransitionsInTest() diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/core/node/ParentNodeTest.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/core/node/ParentNodeTest.kt index edd433750..5cf01a7f5 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/core/node/ParentNodeTest.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/core/node/ParentNodeTest.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.core.node +import android.os.Parcelable import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.ParentNodeTest.NodeB.Companion.StatusExecuted @@ -17,6 +18,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest +import kotlinx.parcelize.Parcelize import org.junit.Rule import org.junit.Test @@ -88,8 +90,10 @@ class ParentNodeTest { navModel = backStack ) { - sealed class NavTarget { + sealed class NavTarget: Parcelable { + @Parcelize object ChildA : NavTarget() + @Parcelize object ChildB : NavTarget() } diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/RoutingElementsHelper.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/RoutingElementsHelper.kt index ad51a6818..6696f636d 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/RoutingElementsHelper.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/RoutingElementsHelper.kt @@ -1,10 +1,11 @@ package com.bumble.appyx.navmodel +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import org.junit.Assert.assertEquals -internal fun NavElements.assertNavTargetElementsEqual( +internal fun NavElements.assertNavTargetElementsEqual( elements: NavElements ) { assertEquals(size, elements.size) diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/BackStackTest.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/BackStackTest.kt index ea9825c75..596ab7f5a 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/BackStackTest.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/BackStackTest.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.backstack +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel.Companion.KEY_NAV_MODEL import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavKey @@ -524,7 +525,7 @@ internal class BackStackTest { actual.assertNavTargetElementsEqual(expectedElements) } - private fun push(element: T) = Push( + private fun push(element: T) = Push( element = element ) diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/operation/NavTarget.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/operation/NavTarget.kt index da7164d1a..e0d708e29 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/operation/NavTarget.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/backstack/operation/NavTarget.kt @@ -1,6 +1,10 @@ package com.bumble.appyx.navmodel.backstack.operation -internal sealed class NavTarget { +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +internal sealed class NavTarget: Parcelable { object NavTarget1 : NavTarget() object NavTarget2 : NavTarget() object NavTarget3 : NavTarget() diff --git a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/spotlight/operation/NavTarget.kt b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/spotlight/operation/NavTarget.kt index b1d87f4fe..84de15af4 100644 --- a/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/spotlight/operation/NavTarget.kt +++ b/libraries/core/src/test/kotlin/com/bumble/appyx/navmodel/spotlight/operation/NavTarget.kt @@ -1,7 +1,13 @@ package com.bumble.appyx.navmodel.spotlight.operation -internal sealed class NavTarget { +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +internal sealed class NavTarget: Parcelable { + @Parcelize object NavTarget1 : NavTarget() + @Parcelize object NavTarget2 : NavTarget() + @Parcelize object NavTarget3 : NavTarget() } diff --git a/libraries/testing-ui/build.gradle.kts b/libraries/testing-ui/build.gradle.kts index 351c2b5c7..45de09cc4 100644 --- a/libraries/testing-ui/build.gradle.kts +++ b/libraries/testing-ui/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.android.library") id("kotlin-android") + id("kotlin-parcelize") id("appyx-publish-android") id("appyx-lint") id("appyx-detekt") diff --git a/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/rules/AppyxViewTestRule.kt b/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/rules/AppyxViewTestRule.kt index 5b3db45cd..1048b4e20 100644 --- a/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/rules/AppyxViewTestRule.kt +++ b/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/rules/AppyxViewTestRule.kt @@ -47,7 +47,7 @@ open class AppyxViewTestRule( override fun beforeActivityLaunched() { AppyxTestActivity.composableView = { CompositionLocalProvider( - LocalNode provides DummyParentNode(), + LocalNode provides DummyParentNode(), ) { view.View(modifier = Modifier) } diff --git a/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/utils/DummyParentNode.kt b/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/utils/DummyParentNode.kt index 591b4489b..0ffb78269 100644 --- a/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/utils/DummyParentNode.kt +++ b/libraries/testing-ui/src/main/kotlin/com/bumble/appyx/testing/ui/utils/DummyParentNode.kt @@ -1,12 +1,20 @@ package com.bumble.appyx.testing.ui.utils +import android.os.Parcelable import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.node.ParentNode import com.bumble.appyx.core.node.node +import com.bumble.appyx.testing.ui.utils.DummyParentNode.DummyNavTarget +import kotlinx.parcelize.Parcelize -class DummyParentNode : ParentNode( - navModel = DummyNavModel(), +class DummyParentNode : ParentNode( + navModel = DummyNavModel(), buildContext = BuildContext.root(savedStateMap = null) ) { - override fun resolve(navTarget: NavTarget, buildContext: BuildContext) = node(buildContext) { } + @Suppress("PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY") + @Parcelize + class DummyNavTarget internal constructor() : Parcelable + + override fun resolve(navTarget: DummyNavTarget, buildContext: BuildContext) = node(buildContext) { } } diff --git a/libraries/testing-unit-common/src/main/kotlin/com/bumble/appyx/testing/unit/common/helper/ParentNodeTestHelper.kt b/libraries/testing-unit-common/src/main/kotlin/com/bumble/appyx/testing/unit/common/helper/ParentNodeTestHelper.kt index e9fadb88f..a561290f7 100644 --- a/libraries/testing-unit-common/src/main/kotlin/com/bumble/appyx/testing/unit/common/helper/ParentNodeTestHelper.kt +++ b/libraries/testing-unit-common/src/main/kotlin/com/bumble/appyx/testing/unit/common/helper/ParentNodeTestHelper.kt @@ -1,21 +1,22 @@ package com.bumble.appyx.testing.unit.common.helper +import android.os.Parcelable import androidx.lifecycle.Lifecycle import com.bumble.appyx.core.children.nodeOrNull import com.bumble.appyx.core.node.ParentNode import kotlin.test.assertEquals import kotlin.test.assertNull -fun > N.parentNodeTestHelper() = +fun > N.parentNodeTestHelper() = ParentNodeTestHelper(this) -class ParentNodeTestHelper>( +class ParentNodeTestHelper>( private val node: N ) : NodeTestHelper( node = node ) { - fun assertChildHasLifecycle(navTarget: NavTarget, state: Lifecycle.State) { + fun assertChildHasLifecycle(navTarget: NavTarget, state: Lifecycle.State) { val childMap = node.children.value val key = childMap.keys.find { it.navTarget == navTarget } @@ -35,7 +36,7 @@ class ParentNodeTestHelper>( } } - fun assertHasNoChild(navTarget: NavTarget) { + fun assertHasNoChild(navTarget: NavTarget) { val key = node.children.value.keys.find { it.navTarget == navTarget } assertNull(key) } diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/InsideTheBackStack.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/InsideTheBackStack.kt index 4dd7c01fe..28a89ad15 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/InsideTheBackStack.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/InsideTheBackStack.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.app.node.backstack +import android.os.Parcelable import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -30,6 +31,7 @@ import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode import kotlinx.coroutines.delay import kotlinx.coroutines.isActive +import kotlinx.parcelize.Parcelize class InsideTheBackStack( buildContext: BuildContext, @@ -61,7 +63,8 @@ class InsideTheBackStack( } } - sealed class NavTarget { + sealed class NavTarget : Parcelable { + @Parcelize data class Child(val index: Int) : NavTarget() { override fun toString(): String = index.toString() } diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/composable/PeekInsideBackStack.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/composable/PeekInsideBackStack.kt index dc1e1950b..e500c615f 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/composable/PeekInsideBackStack.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/composable/PeekInsideBackStack.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.app.node.backstack.app.composable +import android.os.Parcelable import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.isSystemInDarkTheme @@ -35,7 +36,7 @@ import com.bumble.appyx.core.navigation.NavElement import java.util.Locale @Composable -fun PeekInsideBackStack( +fun PeekInsideBackStack( backStack: IndexedBackStack, modifier: Modifier = Modifier ) { @@ -63,7 +64,7 @@ fun PeekInsideBackStack( } @Composable -private fun BackStackElement( +private fun BackStackElement( element: NavElement, ) { Column( diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/IndexedBackStack.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/IndexedBackStack.kt index aeb197321..fa7172d19 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/IndexedBackStack.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/IndexedBackStack.kt @@ -1,12 +1,14 @@ package com.bumble.appyx.app.node.backstack.app.indexedbackstack +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.core.state.SavedStateMap +import kotlinx.parcelize.Parcelize -class IndexedBackStack( +class IndexedBackStack( savedState: SavedStateMap?, initialElement: NavTarget ) : BaseNavModel( @@ -15,14 +17,20 @@ class IndexedBackStack( savedStateMap = savedState ) { - sealed interface State { + sealed interface State : Parcelable { + @Parcelize object Created : State + + @Parcelize object Active : State + + @Parcelize class Stashed( val index: Int, val size: Int ) : State + @Parcelize object Destroyed : State } diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/IndexedBackStackOperation.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/IndexedBackStackOperation.kt index 16f8282f5..c0782f9c7 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/IndexedBackStackOperation.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/IndexedBackStackOperation.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.app.node.backstack.app.indexedbackstack.operation +import android.os.Parcelable import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack import com.bumble.appyx.core.navigation.Operation -interface IndexedBackStackOperation : Operation +interface IndexedBackStackOperation : Operation diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Pop.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Pop.kt index 67e9997cd..6b3f18c45 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Pop.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Pop.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.app.node.backstack.app.indexedbackstack.operation +import android.os.Parcelable import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack.State import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack.State.Active @@ -9,7 +10,7 @@ import com.bumble.appyx.core.navigation.NavElements import kotlinx.parcelize.Parcelize @Parcelize -class Pop : IndexedBackStackOperation { +class Pop : IndexedBackStackOperation { override fun isApplicable(elements: NavElements): Boolean = elements.any { it.targetState is Active } && @@ -25,7 +26,7 @@ class Pop : IndexedBackStackOperation { } } -fun IndexedBackStack.pop() { +fun IndexedBackStack.pop() { accept(Pop()) accept(UpdateSize()) } diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Push.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Push.kt index 8c27b7625..8fed54a57 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Push.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/Push.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.app.node.backstack.app.indexedbackstack.operation +import android.os.Parcelable import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack.State.Created import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack.State.Active @@ -11,8 +12,8 @@ import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @Parcelize -class Push( - private val element: @RawValue T +class Push( + private val element: T ) : IndexedBackStackOperation { override fun isApplicable(elements: NavElements): Boolean = @@ -36,7 +37,7 @@ class Push( } } -fun IndexedBackStack.push(element: T) { +fun IndexedBackStack.push(element: T) { accept(Push(element)) accept(UpdateSize()) } diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/UpdateSize.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/UpdateSize.kt index c369e7b12..4ab04d630 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/UpdateSize.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/operation/UpdateSize.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.app.node.backstack.app.indexedbackstack.operation +import android.os.Parcelable import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack.State.Destroyed import com.bumble.appyx.app.node.backstack.app.indexedbackstack.IndexedBackStack.State.Stashed @@ -7,7 +8,7 @@ import com.bumble.appyx.core.navigation.NavElements import kotlinx.parcelize.Parcelize @Parcelize -class UpdateSize : IndexedBackStackOperation { +class UpdateSize : IndexedBackStackOperation { override fun isApplicable(elements: NavElements): Boolean = true diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/transition/RecentsTransitionHandler.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/transition/RecentsTransitionHandler.kt index 9baffbb56..3b83d2850 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/transition/RecentsTransitionHandler.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/backstack/app/indexedbackstack/transition/RecentsTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.app.node.backstack.app.indexedbackstack.transition import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat @@ -28,7 +29,7 @@ import com.bumble.appyx.core.navigation.transition.TransitionDescriptor import com.bumble.appyx.core.navigation.transition.TransitionSpec import kotlin.math.roundToInt -class RecentsTransitionHandler( +class RecentsTransitionHandler( private val specFloat: TransitionSpec = { spring() }, private val specOffset: TransitionSpec = { spring() }, ) : ModifierTransitionHandler() { @@ -170,7 +171,7 @@ class RecentsTransitionHandler( } @Composable -fun rememberRecentsTransitionHandler( +fun rememberRecentsTransitionHandler( specFloat: TransitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) }, specOffset: TransitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) }, ): ModifierTransitionHandler = diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/samples/SamplesSelectorNode.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/samples/SamplesSelectorNode.kt index 1870e1ad3..d7876eb06 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/samples/SamplesSelectorNode.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/samples/SamplesSelectorNode.kt @@ -22,6 +22,7 @@ import com.bumble.appyx.core.composable.ChildRenderer import com.bumble.appyx.core.integrationpoint.LocalIntegrationPoint import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.navigation.EmptyNavModel +import com.bumble.appyx.core.navigation.EmptyState import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode import com.bumble.appyx.core.node.node @@ -32,7 +33,7 @@ class SamplesSelectorNode( buildContext: BuildContext, private val outputFunc: (Output) -> Unit ) : ParentNode( - navModel = EmptyNavModel(), + navModel = EmptyNavModel(), buildContext = buildContext ) { sealed class NavTarget : Parcelable { @@ -53,7 +54,7 @@ class SamplesSelectorNode( object OpenCardsExample : Output() object OpenOnboarding : Output() object OpenComposeNavigation : Output() - object OpenInsideTheBackStack: Output() + object OpenInsideTheBackStack : Output() } @ExperimentalUnitApi diff --git a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/teaser/backstack/transitionhandler/CustomBackStackTransitionHandler.kt b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/teaser/backstack/transitionhandler/CustomBackStackTransitionHandler.kt index 664b382ac..3c40d139d 100644 --- a/samples/app/src/main/kotlin/com/bumble/appyx/app/node/teaser/backstack/transitionhandler/CustomBackStackTransitionHandler.kt +++ b/samples/app/src/main/kotlin/com/bumble/appyx/app/node/teaser/backstack/transitionhandler/CustomBackStackTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.app.node.teaser.backstack.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat @@ -21,7 +22,7 @@ import com.bumble.appyx.navmodel.backstack.BackStack import kotlin.math.roundToInt @Suppress("TransitionPropertiesLabel") -class CustomBackStackTransitionHandler : ModifierTransitionHandler() { +class CustomBackStackTransitionHandler : ModifierTransitionHandler() { @SuppressLint("ModifierFactoryExtensionFunction") override fun createModifier( @@ -75,6 +76,6 @@ class CustomBackStackTransitionHandler : ModifierTransitionHandler rememberCustomHandler(): ModifierTransitionHandler = remember { +fun rememberCustomHandler(): ModifierTransitionHandler = remember { CustomBackStackTransitionHandler() } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/Cards.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/Cards.kt index 4d085875b..cdc30df30 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/Cards.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/Cards.kt @@ -14,7 +14,7 @@ import com.bumble.appyx.navmodel.cards.Cards.State.VoteLike import com.bumble.appyx.navmodel.cards.Cards.State.VotePass import kotlinx.parcelize.Parcelize -class Cards( +class Cards( initialItems: List = listOf(), ) : BaseNavModel( screenResolver = CardsOnScreenResolver, diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/CardsOperation.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/CardsOperation.kt index c2dedd84c..840fc24d2 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/CardsOperation.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/CardsOperation.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.navmodel.cards.Cards -interface CardsOperation : Operation +interface CardsOperation : Operation diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicateLike.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicateLike.kt index b709e6a41..e1aa7f3de 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicateLike.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicateLike.kt @@ -1,15 +1,16 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.cards.Cards import com.bumble.appyx.navmodel.cards.Cards.Companion.TOP_STATES import com.bumble.appyx.navmodel.cards.CardsElements import kotlinx.parcelize.Parcelize @Parcelize -class IndicateLike : TopCardOperation( +class IndicateLike : TopCardOperation( newTargetState = Cards.State.IndicateLike ) -fun Cards.indicateLike() { +fun Cards.indicateLike() { accept(IndicateLike()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicatePass.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicatePass.kt index 569bfd138..11f617f89 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicatePass.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/IndicatePass.kt @@ -1,14 +1,15 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.cards.Cards import com.bumble.appyx.navmodel.cards.Cards.State.IndicatePass import kotlinx.parcelize.Parcelize @Parcelize -class IndicatePass : TopCardOperation( +class IndicatePass : TopCardOperation( newTargetState = IndicatePass ) -fun Cards.indicatePass() { +fun Cards.indicatePass() { accept(IndicatePass()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/PromoteAll.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/PromoteAll.kt index d1a120f73..efd315b65 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/PromoteAll.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/PromoteAll.kt @@ -1,19 +1,20 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.cards.Cards import com.bumble.appyx.navmodel.cards.CardsElements import kotlinx.parcelize.Parcelize @Parcelize -internal class PromoteAll : CardsOperation { +internal class PromoteAll : CardsOperation { override fun isApplicable(elements: CardsElements): Boolean = true - override fun invoke(elements: CardsElements, ): CardsElements = + override fun invoke(elements: CardsElements): CardsElements = elements.transitionTo { it.targetState.next() } } -internal fun Cards.promoteAll() { +internal fun Cards.promoteAll() { accept(PromoteAll()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/TopCardOperation.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/TopCardOperation.kt index eafd7efa0..f26ada74f 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/TopCardOperation.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/TopCardOperation.kt @@ -1,11 +1,12 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.cards.Cards import com.bumble.appyx.navmodel.cards.CardsElements -abstract class TopCardOperation( +abstract class TopCardOperation( private val newTargetState: Cards.State - ) : CardsOperation { +) : CardsOperation { override fun isApplicable(elements: CardsElements): Boolean = elements.any { it.targetState in Cards.TOP_STATES } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VoteLike.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VoteLike.kt index 802447543..8a9c9c3ad 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VoteLike.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VoteLike.kt @@ -1,14 +1,15 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.cards.Cards import kotlinx.parcelize.Parcelize @Parcelize -class VoteLike internal constructor() : TopCardOperation( +class VoteLike internal constructor() : TopCardOperation( newTargetState = Cards.State.VoteLike ) -fun Cards.voteLike() { +fun Cards.voteLike() { accept(VoteLike()) promoteAll() } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VotePass.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VotePass.kt index d793fb0d7..708a6cc4d 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VotePass.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/operation/VotePass.kt @@ -1,16 +1,17 @@ package com.bumble.appyx.navmodel.cards.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.cards.Cards import com.bumble.appyx.navmodel.cards.Cards.Companion.FINAL_STATES import com.bumble.appyx.navmodel.cards.CardsElements import kotlinx.parcelize.Parcelize @Parcelize -class VotePass internal constructor() : TopCardOperation( +class VotePass internal constructor() : TopCardOperation( newTargetState = Cards.State.VotePass ) -fun Cards.votePass() { +fun Cards.votePass() { accept(VotePass()) promoteAll() } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/transitionhandler/CardsTransitionHandler.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/transitionhandler/CardsTransitionHandler.kt index 6dfc283f6..70b725554 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/transitionhandler/CardsTransitionHandler.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/cards/transitionhandler/CardsTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.cards.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat @@ -35,7 +36,7 @@ import kotlin.math.roundToInt import kotlin.math.sin @Suppress("TransitionPropertiesLabel", "MagicNumber") -class CardsTransitionHandler( +class CardsTransitionHandler( private val transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) } ) : ModifierTransitionHandler(clipToBounds = true) { @@ -154,7 +155,7 @@ class CardsTransitionHandler( } @Composable -fun rememberCardsTransitionHandler( +fun rememberCardsTransitionHandler( transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) } ): ModifierTransitionHandler = remember { CardsTransitionHandler(transitionSpec) diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/Modal.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/Modal.kt index b8641aed9..a6f9a28bb 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/Modal.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/Modal.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavElements @@ -13,8 +14,9 @@ import com.bumble.appyx.navmodel.modal.Modal.State import com.bumble.appyx.navmodel.modal.Modal.State.CREATED import com.bumble.appyx.navmodel.modal.Modal.State.DESTROYED import com.bumble.appyx.navmodel.modal.backpresshandler.RevertBackPressHandler +import kotlinx.parcelize.Parcelize -class Modal( +class Modal( initialElement: NavTarget, savedStateMap: SavedStateMap?, key: String = KEY_NAV_MODEL, @@ -30,7 +32,8 @@ class Modal( finalState = DESTROYED ) { - enum class State { + @Parcelize + enum class State : Parcelable { CREATED, MODAL, FULL_SCREEN, DESTROYED } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/ModalTransitionHandler.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/ModalTransitionHandler.kt index 4a555f791..a795ba5b0 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/ModalTransitionHandler.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/ModalTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.modal import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.tween @@ -21,7 +22,7 @@ import com.bumble.appyx.core.navigation.transition.TransitionSpec import com.bumble.appyx.navmodel.modal.Modal.State @Suppress("TransitionPropertiesLabel") -class ModalTransitionHandler( +class ModalTransitionHandler( private val transitionSpec: TransitionSpec = { tween(500) } ) : ModifierTransitionHandler() { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/backpresshandler/RevertBackPressHandler.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/backpresshandler/RevertBackPressHandler.kt index a21261308..b985e2114 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/backpresshandler/RevertBackPressHandler.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/backpresshandler/RevertBackPressHandler.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.modal.Modal.State import com.bumble.appyx.navmodel.modal.Modal.State.FULL_SCREEN @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.modal.operation.Revert import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class RevertBackPressHandler : +class RevertBackPressHandler : BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow by lazy { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Add.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Add.kt index 6e1870a80..b6d5c730e 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Add.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Add.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal import com.bumble.appyx.navmodel.modal.Modal.State.CREATED import com.bumble.appyx.navmodel.modal.ModalElement @@ -9,8 +10,8 @@ import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @Parcelize -data class Add( - private val element: @RawValue T +data class Add( + private val element: T ) : ModalOperation { override fun isApplicable(elements: ModalElements) = true @@ -25,6 +26,6 @@ data class Add( } } -fun Modal.add(element: T) { +fun Modal.add(element: T) { accept(Add(element)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Destroy.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Destroy.kt index e6d2d62c3..39a6d6818 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Destroy.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Destroy.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal import com.bumble.appyx.navmodel.modal.Modal.State.DESTROYED import com.bumble.appyx.navmodel.modal.ModalElements @@ -7,7 +8,7 @@ import com.bumble.appyx.core.navigation.NavKey import kotlinx.parcelize.Parcelize @Parcelize -data class Destroy( +data class Destroy( private val key: NavKey ) : ModalOperation { @@ -27,6 +28,6 @@ data class Destroy( } } -fun Modal.destroy(key: NavKey) { +fun Modal.destroy(key: NavKey) { accept(Destroy(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Dismiss.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Dismiss.kt index a627a178b..faa90d2dc 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Dismiss.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Dismiss.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal import com.bumble.appyx.navmodel.modal.Modal.State.CREATED import com.bumble.appyx.navmodel.modal.ModalElements @@ -7,7 +8,7 @@ import com.bumble.appyx.core.navigation.NavKey import kotlinx.parcelize.Parcelize @Parcelize -data class Dismiss( +data class Dismiss( private val key: NavKey ) : ModalOperation { @@ -27,6 +28,6 @@ data class Dismiss( } } -fun Modal.dismiss(key: NavKey) { +fun Modal.dismiss(key: NavKey) { accept(Dismiss(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/FullScreen.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/FullScreen.kt index 1eeecc013..f12d0dbff 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/FullScreen.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/FullScreen.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal import com.bumble.appyx.navmodel.modal.Modal.State.FULL_SCREEN import com.bumble.appyx.navmodel.modal.ModalElements @@ -7,7 +8,7 @@ import com.bumble.appyx.core.navigation.NavKey import kotlinx.parcelize.Parcelize @Parcelize -data class FullScreen( +data class FullScreen( private val key: NavKey ) : ModalOperation { @@ -27,6 +28,6 @@ data class FullScreen( } } -fun Modal.fullScreen(key: NavKey) { +fun Modal.fullScreen(key: NavKey) { accept(FullScreen(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/ModalOperation.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/ModalOperation.kt index 789bd03ca..352a51c47 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/ModalOperation.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/ModalOperation.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal.State import com.bumble.appyx.core.navigation.Operation -interface ModalOperation : Operation +interface ModalOperation : Operation diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Revert.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Revert.kt index 678d078c1..80b1aac4a 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Revert.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Revert.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal import com.bumble.appyx.navmodel.modal.Modal.State.FULL_SCREEN import com.bumble.appyx.navmodel.modal.Modal.State.MODAL @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.modal.ModalElements import kotlinx.parcelize.Parcelize @Parcelize -class Revert : ModalOperation { +class Revert : ModalOperation { override fun isApplicable(elements: ModalElements): Boolean = true @@ -35,6 +36,6 @@ class Revert : ModalOperation { } } -fun Modal.revert() { +fun Modal.revert() { accept(Revert()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Show.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Show.kt index e3c9c3f84..2e4ae82b4 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Show.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/modal/operation/Show.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.modal.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.modal.Modal import com.bumble.appyx.navmodel.modal.Modal.State.MODAL import com.bumble.appyx.navmodel.modal.ModalElements @@ -7,7 +8,7 @@ import com.bumble.appyx.core.navigation.NavKey import kotlinx.parcelize.Parcelize @Parcelize -data class Show( +data class Show( private val key: NavKey ) : ModalOperation { @@ -27,6 +28,6 @@ data class Show( } } -fun Modal.show(key: NavKey) { +fun Modal.show(key: NavKey) { accept(Show(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/Promoter.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/Promoter.kt index 9ac073ea7..ab42ba475 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/Promoter.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/Promoter.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.promoter.navmodel +import android.os.Parcelable import com.bumble.appyx.navmodel.promoter.navmodel.Promoter.State import com.bumble.appyx.navmodel.promoter.navmodel.Promoter.State.CREATED import com.bumble.appyx.navmodel.promoter.navmodel.Promoter.State.DESTROYED @@ -7,8 +8,9 @@ import com.bumble.appyx.navmodel.promoter.navmodel.Promoter.State.STAGE1 import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavKey +import kotlinx.parcelize.Parcelize -class Promoter( +class Promoter( initialItems: List = listOf(), ) : BaseNavModel( screenResolver = PromoterOnScreenResolver, @@ -16,7 +18,8 @@ class Promoter( savedStateMap = null ) { - enum class State { + @Parcelize + enum class State : Parcelable { CREATED, STAGE1, STAGE2, STAGE3, STAGE4, SELECTED, DESTROYED; fun next(): State = diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/AddFirst.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/AddFirst.kt index 21480ed43..2db948d37 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/AddFirst.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/AddFirst.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.promoter.navmodel.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.promoter.navmodel.Promoter import com.bumble.appyx.navmodel.promoter.navmodel.Promoter.State.CREATED import com.bumble.appyx.navmodel.promoter.navmodel.PromoterElement @@ -10,8 +11,8 @@ import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @Parcelize -data class AddFirst( - private val element: @RawValue T +data class AddFirst( + private val element: T ) : PromoterOperation { override fun isApplicable(elements: PromoterElements): Boolean = @@ -31,6 +32,6 @@ data class AddFirst( } } -fun Promoter.addFirst(element: T) { +fun Promoter.addFirst(element: T) { accept(AddFirst(element)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt index ae0cddf4e..4c1c38081 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt @@ -1,12 +1,13 @@ package com.bumble.appyx.navmodel.promoter.navmodel.operation +import android.os.Parcelable import com.bumble.appyx.navmodel.promoter.navmodel.Promoter import com.bumble.appyx.navmodel.promoter.navmodel.PromoterElements import com.bumble.appyx.core.navigation.NavElements import kotlinx.parcelize.Parcelize @Parcelize -class PromoteAll : PromoterOperation { +class PromoteAll : PromoterOperation { override fun isApplicable(elements: PromoterElements): Boolean = true @@ -17,6 +18,6 @@ class PromoteAll : PromoterOperation { elements.transitionTo { it.targetState.next() } } -fun Promoter.promoteAll() { +fun Promoter.promoteAll() { accept(PromoteAll()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoterOperation.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoterOperation.kt index f21c368b2..85682e651 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoterOperation.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoterOperation.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.promoter.navmodel.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.navmodel.promoter.navmodel.Promoter -interface PromoterOperation : Operation +interface PromoterOperation : Operation diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/transitionhandler/PromoterTransitionHandler.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/transitionhandler/PromoterTransitionHandler.kt index 3952de651..4b841c027 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/transitionhandler/PromoterTransitionHandler.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/promoter/transitionhandler/PromoterTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.promoter.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.tween @@ -28,7 +29,7 @@ import kotlin.math.roundToInt import kotlin.math.sin @Suppress("TransitionPropertiesLabel") -class PromoterTransitionHandler( +class PromoterTransitionHandler( private val childSize: Dp, private val transitionSpec: TransitionSpec = { tween(500) } ) : ModifierTransitionHandler() { @@ -160,7 +161,7 @@ class PromoterTransitionHandler( } @Composable -fun rememberPromoterTransitionHandler( +fun rememberPromoterTransitionHandler( childSize: Dp, transitionSpec: TransitionSpec = { tween(500) } ): ModifierTransitionHandler = remember { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvanced.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvanced.kt index c55caf23b..a44bd2289 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvanced.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvanced.kt @@ -12,7 +12,7 @@ import com.bumble.appyx.navmodel.spotlightadvanced.backpresshandler.GoToDefault import com.bumble.appyx.navmodel.spotlightadvanced.operation.toSpotlightAdvancedElements import kotlinx.parcelize.Parcelize -class SpotlightAdvanced( +class SpotlightAdvanced( items: List, initialActiveIndex: Int = 0, savedStateMap: SavedStateMap?, diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedElementExt.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedElementExt.kt index 33883ca10..80103c2ec 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedElementExt.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedElementExt.kt @@ -1,9 +1,10 @@ package com.bumble.appyx.navmodel.spotlightadvanced +import android.os.Parcelable import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State.Active -val SpotlightAdvancedElements.current: SpotlightAdvancedElement? +val SpotlightAdvancedElements.current: SpotlightAdvancedElement? get() = this.lastOrNull { it.targetState == Active } -val SpotlightAdvancedElements.currentIndex: Int +val SpotlightAdvancedElements.currentIndex: Int get() = this.indexOfLast { it.targetState == Active } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedExt.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedExt.kt index 3615a7e69..0c6e33ad1 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedExt.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/SpotlightAdvancedExt.kt @@ -1,19 +1,20 @@ package com.bumble.appyx.navmodel.spotlightadvanced +import android.os.Parcelable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -fun SpotlightAdvanced.hasNext() = +fun SpotlightAdvanced.hasNext() = elements.map { value -> value.lastIndex != elements.value.currentIndex } -fun SpotlightAdvanced.hasPrevious() = +fun SpotlightAdvanced.hasPrevious() = elements.map { value -> value.currentIndex != 0 } -fun SpotlightAdvanced.activeIndex() = +fun SpotlightAdvanced.activeIndex() = elements.map { value -> value.currentIndex } -fun SpotlightAdvanced.elementsCount() = +fun SpotlightAdvanced.elementsCount() = elements.value.size -fun SpotlightAdvanced.isCarousel(): Flow = +fun SpotlightAdvanced.isCarousel(): Flow = elements.map { it.any { it.targetState is SpotlightAdvanced.State.Carousel } } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToDefault.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToDefault.kt index d8a74db8c..9acb4a0ff 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToDefault.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToDefault.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State.Active @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.spotlightadvanced.operation.Activate import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class GoToDefault( +class GoToDefault( private val defaultElementIndex: Int = 0 ) : BaseBackPressHandlerStrategy() { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToPrevious.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToPrevious.kt index 5c1f56875..e58deb1e7 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToPrevious.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/GoToPrevious.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvancedElements @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.spotlightadvanced.operation.Previous import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class GoToPrevious : +class GoToPrevious : BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow by lazy { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/UndoHistory.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/UndoHistory.kt index a6445a3ef..68235075c 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/UndoHistory.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/backpresshandler/UndoHistory.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.backpresshandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State.Active @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.spotlightadvanced.operation.Activate import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class UndoHistory( +class UndoHistory( private val historyLimit: Int = 10 ) : BaseBackPressHandlerStrategy() { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Activate.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Activate.kt index e092449dd..2b9b9223c 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Activate.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Activate.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.spotlightadvanced.currentIndex import kotlinx.parcelize.Parcelize @Parcelize -class Activate( +class Activate( private val index: Int ) : SpotlightAdvancedOperation { @@ -42,6 +43,6 @@ class Activate( } } -fun SpotlightAdvanced.activate(index: Int) { +fun SpotlightAdvanced.activate(index: Int) { accept(Activate(index)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Next.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Next.kt index ec00d1341..93f45c182 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Next.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Next.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State @@ -10,7 +11,7 @@ import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State.Inact import kotlinx.parcelize.Parcelize @Parcelize -class Next : SpotlightAdvancedOperation { +class Next : SpotlightAdvancedOperation { override fun isApplicable(elements: NavElements) = elements.any { (it.fromState == InactiveAfter && it.targetState == InactiveAfter) || it.fromState is Carousel } @@ -61,7 +62,7 @@ class Next : SpotlightAdvancedOperation { } } -fun SpotlightAdvanced.next() { +fun SpotlightAdvanced.next() { accept(Next()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Previous.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Previous.kt index b6c73aacc..7396af311 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Previous.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/Previous.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State @@ -11,7 +12,7 @@ import kotlinx.parcelize.Parcelize @Parcelize -class Previous : SpotlightAdvancedOperation { +class Previous : SpotlightAdvancedOperation { override fun isApplicable(elements: NavElements) = elements.any { @@ -72,6 +73,6 @@ class Previous : SpotlightAdvancedOperation { } } -fun SpotlightAdvanced.previous() { +fun SpotlightAdvanced.previous() { accept(Previous()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToCarousel.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToCarousel.kt index b506f63f9..0e5cc8006 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToCarousel.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToCarousel.kt @@ -1,12 +1,13 @@ package com.bumble.appyx.navmodel.spotlightadvanced.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State import kotlinx.parcelize.Parcelize @Parcelize -class SwitchToCarousel: SpotlightAdvancedOperation { +class SwitchToCarousel : SpotlightAdvancedOperation { override fun isApplicable(elements: NavElements) = elements.all { it.fromState !is State.Carousel } @@ -26,6 +27,6 @@ class SwitchToCarousel: SpotlightAdvancedOperation { } } -fun SpotlightAdvanced.switchToCarousel() { +fun SpotlightAdvanced.switchToCarousel() { accept(SwitchToCarousel()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToPager.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToPager.kt index 68483d164..bc6bb41ae 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToPager.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/SwitchToPager.kt @@ -1,12 +1,13 @@ package com.bumble.appyx.navmodel.spotlightadvanced.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced import com.bumble.appyx.navmodel.spotlightadvanced.SpotlightAdvanced.State import kotlinx.parcelize.Parcelize @Parcelize -class SwitchToPager : SpotlightAdvancedOperation { +class SwitchToPager : SpotlightAdvancedOperation { override fun isApplicable(elements: NavElements) = elements.all { it.fromState is State.Carousel } @@ -36,6 +37,6 @@ class SwitchToPager : SpotlightAdvancedOperation { } -fun SpotlightAdvanced.switchToPager() { +fun SpotlightAdvanced.switchToPager() { accept(SwitchToPager()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/UpdateElements.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/UpdateElements.kt index cf56430b9..1acb56643 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/UpdateElements.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/operation/UpdateElements.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.core.navigation.Operation @@ -14,8 +15,8 @@ import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @Parcelize -class UpdateElements( - private val elements: @RawValue List, +class UpdateElements( + private val elements: List, private val initialActiveIndex: Int? = null, ) : SpotlightAdvancedOperation { @@ -46,14 +47,14 @@ class UpdateElements( } } -fun SpotlightAdvanced.updateElements( +fun SpotlightAdvanced.updateElements( items: List, initialActiveItem: Int? = null ) { accept(UpdateElements(items, initialActiveItem)) } -internal fun List.toSpotlightAdvancedElements(activeIndex: Int): SpotlightAdvancedElements = +internal fun List.toSpotlightAdvancedElements(activeIndex: Int): SpotlightAdvancedElements = mapIndexed { index, item -> val state = when { index < activeIndex -> InactiveBefore diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/transitionhandler/SpotlightAdvancedSlider.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/transitionhandler/SpotlightAdvancedSlider.kt index 11d6c76cc..6f4e58572 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/transitionhandler/SpotlightAdvancedSlider.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/spotlightadvanced/transitionhandler/SpotlightAdvancedSlider.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.spotlightadvanced.transitionhandler +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat @@ -33,7 +34,7 @@ import kotlin.math.roundToInt import kotlin.math.sin @Suppress("TransitionPropertiesLabel") -class SpotlightAdvancedSlider( +class SpotlightAdvancedSlider( private val transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessLow) } @@ -140,7 +141,7 @@ class SpotlightAdvancedSlider( } @Composable -fun rememberSpotlightAdvancedSlider( +fun rememberSpotlightAdvancedSlider( transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessLow) } ): ModifierTransitionHandler = remember { SpotlightAdvancedSlider( diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt index ea3943579..ffa6e829f 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles +import android.os.Parcelable import com.bumble.appyx.core.navigation.BaseNavModel import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavKey @@ -8,8 +9,9 @@ import com.bumble.appyx.navmodel.tiles.backPressHandler.DeselectAllTiles import com.bumble.appyx.navmodel.tiles.Tiles.State import com.bumble.appyx.navmodel.tiles.Tiles.State.CREATED import com.bumble.appyx.navmodel.tiles.Tiles.State.STANDARD +import kotlinx.parcelize.Parcelize -class Tiles( +class Tiles( initialItems: List, backPressHandler: BackPressHandlerStrategy = DeselectAllTiles() ) : BaseNavModel( @@ -19,7 +21,8 @@ class Tiles( savedStateMap = null, ) { - enum class State { + @Parcelize + enum class State : Parcelable { CREATED, STANDARD, SELECTED, DESTROYED } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt index 7c75b7d55..4d9092c05 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.backPressHandler +import android.os.Parcelable import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy import com.bumble.appyx.navmodel.tiles.Tiles import com.bumble.appyx.navmodel.tiles.TilesElements @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.tiles.operation.DeselectAll import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class DeselectAllTiles : +class DeselectAllTiles : BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow by lazy { diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt index b541df28a..f1618066b 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles @@ -11,8 +12,8 @@ import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @Parcelize -data class Add( - private val element: @RawValue T +data class Add( + private val element: T ) : TilesOperation { override fun isApplicable(elements: TilesElements): Boolean = true @@ -28,6 +29,6 @@ data class Add( ) } -fun Tiles.add(element: T) { +fun Tiles.add(element: T) { accept(Add(element)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt index 5da20d196..17f95b929 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles @@ -9,7 +10,7 @@ import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @Parcelize -data class Deselect( +data class Deselect( private val key: NavKey ) : TilesOperation { @@ -23,6 +24,6 @@ data class Deselect( } } -fun Tiles.deselect(key: NavKey) { +fun Tiles.deselect(key: NavKey) { accept(Deselect(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt index d1ff4b7a1..24a471351 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.tiles.Tiles import com.bumble.appyx.navmodel.tiles.Tiles.State.SELECTED @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @Parcelize -class DeselectAll : TilesOperation { +class DeselectAll : TilesOperation { override fun isApplicable(elements: TilesElements): Boolean = true @@ -24,6 +25,6 @@ class DeselectAll : TilesOperation { override fun hashCode(): Int = this.javaClass.hashCode() } -fun Tiles.deselectAll() { +fun Tiles.deselectAll() { accept(DeselectAll()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt index 0af151f9b..73a4d7416 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @Parcelize -data class Destroy( +data class Destroy( private val key: NavKey ) : TilesOperation { @@ -22,6 +23,6 @@ data class Destroy( } } -fun Tiles.destroy(key: NavKey) { +fun Tiles.destroy(key: NavKey) { accept(Destroy(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt index 42fae5d2b..5b4f30125 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.tiles.Tiles import com.bumble.appyx.navmodel.tiles.Tiles.State.DESTROYED @@ -8,7 +9,7 @@ import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @Parcelize -class RemoveSelected : TilesOperation { +class RemoveSelected : TilesOperation { override fun isApplicable(elements: TilesElements): Boolean = true @@ -24,6 +25,6 @@ class RemoveSelected : TilesOperation { override fun hashCode(): Int = this.javaClass.hashCode() } -fun Tiles.removeSelected() { +fun Tiles.removeSelected() { accept(RemoveSelected()) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt index d64c069a3..605fe66b1 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles @@ -9,7 +10,7 @@ import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @Parcelize -data class Select( +data class Select( private val key: NavKey ) : TilesOperation { @@ -23,6 +24,6 @@ data class Select( } } -fun Tiles.select(key: NavKey) { +fun Tiles.select(key: NavKey) { accept(Select(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt index 8c691dea4..fadf5d35b 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.navmodel.tiles.Tiles -interface TilesOperation : Operation +interface TilesOperation : Operation diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt index 006754052..deeff4b43 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.navmodel.tiles.operation +import android.os.Parcelable import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles @@ -7,7 +8,7 @@ import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @Parcelize -data class ToggleSelection( +data class ToggleSelection( private val key: NavKey ) : TilesOperation { @@ -35,6 +36,6 @@ data class ToggleSelection( } } -fun Tiles.toggleSelection(key: NavKey) { +fun Tiles.toggleSelection(key: NavKey) { accept(ToggleSelection(key)) } diff --git a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt index 0a601648a..82b14f28a 100644 --- a/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt +++ b/samples/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.navmodel.tiles.transitionhandler import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat @@ -20,7 +21,7 @@ import com.bumble.appyx.navmodel.tiles.Tiles import kotlin.math.roundToInt @Suppress("TransitionPropertiesLabel") -class TilesTransitionHandler( +class TilesTransitionHandler( private val transitionSpec: TransitionSpec = { spring() } ) : ModifierTransitionHandler() { @@ -62,7 +63,7 @@ class TilesTransitionHandler( } @Composable -fun rememberTilesTransitionHandler( +fun rememberTilesTransitionHandler( transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) } ): ModifierTransitionHandler = remember { TilesTransitionHandler(transitionSpec) diff --git a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/backstack/BackStackExampleTransitionHandler.kt b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/backstack/BackStackExampleTransitionHandler.kt index df1526dec..0d30b3e85 100644 --- a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/backstack/BackStackExampleTransitionHandler.kt +++ b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/backstack/BackStackExampleTransitionHandler.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.sandbox.client.backstack import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.Transition import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -12,7 +13,7 @@ import com.bumble.appyx.navmodel.backstack.operation.Replace import com.bumble.appyx.navmodel.backstack.transitionhandler.BackStackFader import com.bumble.appyx.navmodel.backstack.transitionhandler.BackStackSlider -class BackStackExampleTransitionHandler : +class BackStackExampleTransitionHandler : ModifierTransitionHandler(clipToBounds = true) { private val slider = BackStackSlider(clipToBounds = clipToBounds) @@ -31,7 +32,7 @@ class BackStackExampleTransitionHandler : } @Composable -fun rememberBackStackExampleTransitionHandler( +fun rememberBackStackExampleTransitionHandler( ): ModifierTransitionHandler = remember { BackStackExampleTransitionHandler() } diff --git a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/list/LazyListContainerNode.kt b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/list/LazyListContainerNode.kt index 1eb67a0b8..d542a8c1c 100644 --- a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/list/LazyListContainerNode.kt +++ b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/list/LazyListContainerNode.kt @@ -85,7 +85,7 @@ class LazyListContainerNode constructor( } @Composable - private fun ColumnExample(elements: ImmutableList>) { + private fun ColumnExample(elements: ImmutableList>) { LazyColumn( modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(horizontal = 16.dp), @@ -99,7 +99,7 @@ class LazyListContainerNode constructor( } @Composable - private fun RowExample(elements: ImmutableList>) { + private fun RowExample(elements: ImmutableList>) { LazyRow( modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(vertical = 16.dp), @@ -112,7 +112,7 @@ class LazyListContainerNode constructor( } @Composable - private fun GridExample(elements: ImmutableList>) { + private fun GridExample(elements: ImmutableList>) { LazyVerticalGrid( columns = Fixed(2), modifier = Modifier.fillMaxSize(), diff --git a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/spotlight/SpotlightFaderThrough.kt b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/spotlight/SpotlightFaderThrough.kt index 9a9168ea2..9a5d2e81a 100644 --- a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/spotlight/SpotlightFaderThrough.kt +++ b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/spotlight/SpotlightFaderThrough.kt @@ -1,6 +1,7 @@ package com.bumble.appyx.sandbox.client.spotlight import android.annotation.SuppressLint +import android.os.Parcelable import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat @@ -19,7 +20,7 @@ import com.bumble.appyx.navmodel.spotlight.Spotlight * Fade through transition from material design * [Specification](https://m2.material.io/design/motion/the-motion-system.html#fade-through) */ -class SpotlightFaderThrough : ModifierTransitionHandler() { +class SpotlightFaderThrough : ModifierTransitionHandler() { @SuppressLint("ModifierFactoryExtensionFunction") override fun createModifier( @@ -91,5 +92,5 @@ class SpotlightFaderThrough : ModifierTransitionHandler() } @Composable -fun rememberSpotlightFaderThrough(): ModifierTransitionHandler = +fun rememberSpotlightFaderThrough(): ModifierTransitionHandler = remember { SpotlightFaderThrough() } diff --git a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/tiles/TilesExampleNode.kt b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/tiles/TilesExampleNode.kt index 9dae32953..600818c94 100644 --- a/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/tiles/TilesExampleNode.kt +++ b/samples/sandbox/src/main/kotlin/com/bumble/appyx/sandbox/client/tiles/TilesExampleNode.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.sandbox.client.tiles +import android.os.Parcelable import android.util.Log import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -36,6 +37,7 @@ import com.bumble.appyx.sandbox.client.tiles.TilesExampleNode.NavTarget.Child1 import com.bumble.appyx.sandbox.client.tiles.TilesExampleNode.NavTarget.Child2 import com.bumble.appyx.sandbox.client.tiles.TilesExampleNode.NavTarget.Child3 import com.bumble.appyx.sandbox.client.tiles.TilesExampleNode.NavTarget.Child4 +import kotlinx.parcelize.Parcelize class TilesExampleNode( buildContext: BuildContext, @@ -49,7 +51,8 @@ class TilesExampleNode( buildContext = buildContext, ) { - enum class NavTarget { + @Parcelize + enum class NavTarget : Parcelable { Child1, Child2, Child3, Child4, } diff --git a/samples/sandbox/src/test/kotlin/com/bumble/appyx/sandbox/stub/NodeViewStub.kt b/samples/sandbox/src/test/kotlin/com/bumble/appyx/sandbox/stub/NodeViewStub.kt index 4a43ce57a..16d6b8843 100644 --- a/samples/sandbox/src/test/kotlin/com/bumble/appyx/sandbox/stub/NodeViewStub.kt +++ b/samples/sandbox/src/test/kotlin/com/bumble/appyx/sandbox/stub/NodeViewStub.kt @@ -1,5 +1,6 @@ package com.bumble.appyx.sandbox.stub +import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.bumble.appyx.core.node.ParentNode @@ -10,7 +11,7 @@ import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposables import io.reactivex.functions.Consumer -open class NodeViewStub( +open class NodeViewStub( val eventsRelay: PublishRelay = PublishRelay.create(), val viewModelRelay: PublishRelay = PublishRelay.create(), private val disposable: Disposable = Disposables.empty()