From af84841a50366205099f0b6833ad7dd8099beead Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Wed, 21 Sep 2022 12:05:18 +0100 Subject: [PATCH 1/8] Add operation helpers --- .../bumble/appyx/core/navigation/Operation.kt | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt b/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt index b9f0cab15..1857997fd 100644 --- a/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt +++ b/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt @@ -8,6 +8,57 @@ interface Operation : fun isApplicable(elements: NavElements): Boolean + /** + * Transitions all elements to a new state + */ + fun NavElements.transitionTo( + newTargetState: State + ) = transitionTo(newTargetState) { _, _ -> true } + + /** + * Transitions all elements to a new state based on the individual elements + */ + fun NavElements.transitionTo( + newTargetState: (NavElement) -> State + ) = map { element -> + element.transitionTo( + newTargetState = newTargetState.invoke(element), + operation = this@Operation + ) + } + + /** + * Transitions elements to a new state if they pass a condition based on the element + */ + fun NavElements.transitionTo( + newTargetState: State, condition: (element: NavElement) -> Boolean + ) = map { element -> + if (condition.invoke(element)) { + element.transitionTo( + newTargetState = newTargetState, + operation = this@Operation + ) + } else { + element + } + } + + /** + * Transitions elements to a new state if they pass a condition based on the element and its position + */ + fun NavElements.transitionTo( + newTargetState: State, condition: (index: Int, element: NavElement) -> Boolean + ) = mapIndexed { index, element -> + if (condition.invoke(index, element)) { + element.transitionTo( + newTargetState = newTargetState, + operation = this@Operation + ) + } else { + element + } + } + @Parcelize class Noop : Operation { @@ -21,4 +72,4 @@ interface Operation : override fun hashCode(): Int = this.javaClass.hashCode() } -} +} \ No newline at end of file From fb1b16089d49b83ff3df898595d19745e9046105 Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Wed, 21 Sep 2022 12:06:22 +0100 Subject: [PATCH 2/8] Use helpers in existing navmodels --- .../navmodel/backstack/operation/Push.kt | 18 ++++----------- .../navmodel/backstack/operation/Replace.kt | 14 +++-------- .../navmodel/backstack/operation/SingleTop.kt | 14 ++++------- .../promoter/navmodel/operation/PromoteAll.kt | 7 +----- .../com/bumble/appyx/navmodel/tiles/Tiles.kt | 12 +++++----- .../appyx/navmodel/tiles/TilesElement.kt | 4 ++-- .../appyx/navmodel/tiles/TilesElements.kt | 4 ++-- .../navmodel/tiles/TilesOnScreenResolver.kt | 14 +++++------ .../backPressHandler/DeselectAllTiles.kt | 4 ++-- .../appyx/navmodel/tiles/operation/Add.kt | 6 ++--- .../navmodel/tiles/operation/Deselect.kt | 15 ++++-------- .../navmodel/tiles/operation/DeselectAll.kt | 19 ++++----------- .../appyx/navmodel/tiles/operation/Destroy.kt | 14 ++++------- .../tiles/operation/RemoveSelected.kt | 15 ++++-------- .../appyx/navmodel/tiles/operation/Select.kt | 15 ++++-------- .../tiles/operation/TilesOperation.kt | 2 +- .../tiles/operation/ToggleSelection.kt | 10 ++++---- .../TilesTransitionHandler.kt | 23 ++++++++++--------- 18 files changed, 77 insertions(+), 133 deletions(-) diff --git a/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt b/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt index 5f17e66b3..892ac0409 100644 --- a/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt +++ b/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Push.kt @@ -2,10 +2,10 @@ package com.bumble.appyx.navmodel.backstack.operation import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState +import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState.* import com.bumble.appyx.navmodel.backstack.BackStackElement import com.bumble.appyx.navmodel.backstack.BackStackElements -import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState.ACTIVE -import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState.CREATED import com.bumble.appyx.navmodel.backstack.activeElement import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @@ -23,23 +23,15 @@ data class Push( override fun isApplicable(elements: BackStackElements): Boolean = element != elements.activeElement - override fun invoke(elements: BackStackElements): BackStackElements { - return elements.map { - if (it.targetState == BackStack.TransitionState.ACTIVE) { - it.transitionTo( - newTargetState = BackStack.TransitionState.STASHED_IN_BACK_STACK, - operation = this - ) - } else { - it - } + override fun invoke(elements: BackStackElements): BackStackElements = + elements.transitionTo(STASHED_IN_BACK_STACK) { element -> + element.targetState == ACTIVE } + BackStackElement( key = NavKey(element), fromState = CREATED, targetState = ACTIVE, operation = this ) - } } fun BackStack.push(element: T) { diff --git a/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt b/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt index ba8d73e75..51a70ea6f 100644 --- a/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt +++ b/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/Replace.kt @@ -2,11 +2,10 @@ package com.bumble.appyx.navmodel.backstack.operation import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState.* import com.bumble.appyx.navmodel.backstack.BackStackElement import com.bumble.appyx.navmodel.backstack.BackStackElements import com.bumble.appyx.navmodel.backstack.activeIndex -import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState.ACTIVE -import com.bumble.appyx.navmodel.backstack.BackStack.TransitionState.CREATED import com.bumble.appyx.navmodel.backstack.activeElement import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @@ -29,15 +28,8 @@ data class Replace( ): BackStackElements { require(elements.any { it.targetState == ACTIVE }) { "No element to be replaced, state=$elements" } - return elements.mapIndexed { index, element -> - if (index == elements.activeIndex) { - element.transitionTo( - newTargetState = BackStack.TransitionState.DESTROYED, - operation = this - ) - } else { - element - } + return elements.transitionTo(DESTROYED) { index, _ -> + index == elements.activeIndex } + BackStackElement( key = NavKey(element), fromState = CREATED, diff --git a/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt b/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt index 09c91ebb7..5ff2657d5 100644 --- a/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt +++ b/core/src/main/kotlin/com/bumble/appyx/navmodel/backstack/operation/SingleTop.kt @@ -35,17 +35,11 @@ sealed class SingleTop : BackStackOperation { val current = elements.active requireNotNull(current) - val newElements = elements.dropLast(elements.size - position - 1) + val newElements = elements + .dropLast(elements.size - position - 1) - return newElements.mapIndexed { index, element -> - if (index == newElements.lastIndex) { - element.transitionTo( - newTargetState = BackStack.TransitionState.ACTIVE, - operation = this - ) - } else { - element - } + return newElements.transitionTo(ACTIVE) { index, _ -> + index == newElements.lastIndex } + current.transitionTo( newTargetState = BackStack.TransitionState.DESTROYED, operation = this diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt index deff67d70..8a08a0fee 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/promoter/navmodel/operation/PromoteAll.kt @@ -14,12 +14,7 @@ class PromoteAll : PromoterOperation { override fun invoke( elements: PromoterElements, ): NavElements = - elements.map { - it.transitionTo( - newTargetState = it.targetState.next(), - operation = this - ) - } + elements.transitionTo { it.targetState.next() } } fun Promoter.promoteAll() { diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt index 8140894c0..ea3943579 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/Tiles.kt @@ -5,21 +5,21 @@ import com.bumble.appyx.core.navigation.Operation.Noop import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BackPressHandlerStrategy import com.bumble.appyx.navmodel.tiles.backPressHandler.DeselectAllTiles -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState.CREATED -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState.STANDARD +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 class Tiles( initialItems: List, - backPressHandler: BackPressHandlerStrategy = DeselectAllTiles() -) : BaseNavModel( + backPressHandler: BackPressHandlerStrategy = DeselectAllTiles() +) : BaseNavModel( backPressHandler = backPressHandler, screenResolver = TilesOnScreenResolver, finalState = null, savedStateMap = null, ) { - enum class TransitionState { + enum class State { CREATED, STANDARD, SELECTED, DESTROYED } diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElement.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElement.kt index 8f3228e8d..5818e05ed 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElement.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElement.kt @@ -1,6 +1,6 @@ package com.bumble.appyx.navmodel.tiles import com.bumble.appyx.core.navigation.NavElement -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState +import com.bumble.appyx.navmodel.tiles.Tiles.State -typealias TilesElement = NavElement +typealias TilesElement = NavElement diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElements.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElements.kt index bda407926..30d56e106 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElements.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesElements.kt @@ -1,6 +1,6 @@ package com.bumble.appyx.navmodel.tiles import com.bumble.appyx.core.navigation.NavElements -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState +import com.bumble.appyx.navmodel.tiles.Tiles.State -typealias TilesElements = NavElements +typealias TilesElements = NavElements diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesOnScreenResolver.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesOnScreenResolver.kt index ec8c1c6ab..612de907f 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesOnScreenResolver.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/TilesOnScreenResolver.kt @@ -1,14 +1,14 @@ package com.bumble.appyx.navmodel.tiles import com.bumble.appyx.core.navigation.onscreen.OnScreenStateResolver -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState +import com.bumble.appyx.navmodel.tiles.Tiles.State -internal object TilesOnScreenResolver : OnScreenStateResolver { - override fun isOnScreen(state: TransitionState): Boolean = +internal object TilesOnScreenResolver : OnScreenStateResolver { + override fun isOnScreen(state: State): Boolean = when (state) { - TransitionState.CREATED, - TransitionState.STANDARD, - TransitionState.SELECTED -> true - TransitionState.DESTROYED -> false + State.CREATED, + State.STANDARD, + State.SELECTED -> true + State.DESTROYED -> false } } diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt index 4f6350e40..7c75b7d55 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/backPressHandler/DeselectAllTiles.kt @@ -8,14 +8,14 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map class DeselectAllTiles : - BaseBackPressHandlerStrategy() { + BaseBackPressHandlerStrategy() { override val canHandleBackPressFlow: Flow by lazy { navModel.elements.map(::areThereSelectedTiles) } private fun areThereSelectedTiles(elements: TilesElements) = - elements.any { it.targetState == Tiles.TransitionState.SELECTED } + elements.any { it.targetState == Tiles.State.SELECTED } override fun onBackPressed() { navModel.accept(DeselectAll()) diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt index 93b6fd3f4..b541df28a 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Add.kt @@ -5,8 +5,8 @@ import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles import com.bumble.appyx.navmodel.tiles.TilesElement import com.bumble.appyx.navmodel.tiles.TilesElements -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState.CREATED -import com.bumble.appyx.navmodel.tiles.Tiles.TransitionState.STANDARD +import com.bumble.appyx.navmodel.tiles.Tiles.State.CREATED +import com.bumble.appyx.navmodel.tiles.Tiles.State.STANDARD import kotlinx.parcelize.Parcelize import kotlinx.parcelize.RawValue @@ -19,7 +19,7 @@ data class Add( override fun invoke( elements: TilesElements, - ): NavElements = + ): NavElements = elements + TilesElement( key = NavKey(element), fromState = CREATED, diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt index f9889df7f..5da20d196 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt @@ -3,6 +3,8 @@ package com.bumble.appyx.navmodel.tiles.operation import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles +import com.bumble.appyx.navmodel.tiles.Tiles.State.SELECTED +import com.bumble.appyx.navmodel.tiles.Tiles.State.STANDARD import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @@ -15,16 +17,9 @@ data class Deselect( override fun invoke( elements: TilesElements - ): NavElements = - elements.map { - if (it.key == key && it.targetState == Tiles.TransitionState.SELECTED) { - it.transitionTo( - newTargetState = Tiles.TransitionState.STANDARD, - operation = this - ) - } else { - it - } + ): NavElements = + elements.transitionTo(STANDARD) { + it.key == key && it.targetState == SELECTED } } diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt index 1944c57b4..288944278 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt @@ -2,6 +2,8 @@ package com.bumble.appyx.navmodel.tiles.operation import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.tiles.Tiles +import com.bumble.appyx.navmodel.tiles.Tiles.State.SELECTED +import com.bumble.appyx.navmodel.tiles.Tiles.State.STANDARD import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @@ -12,21 +14,10 @@ class DeselectAll : TilesOperation { override fun invoke( elements: TilesElements - ): NavElements = - elements.map { - if (it.targetState == Tiles.TransitionState.SELECTED) { - it.transitionTo( - newTargetState = Tiles.TransitionState.STANDARD, - operation = this - ) - } else { - it - } + ): NavElements = + elements.transitionTo(STANDARD) { + it.targetState == SELECTED } - - override fun equals(other: Any?): Boolean = this.javaClass == other?.javaClass - - override fun hashCode(): Int = this.javaClass.hashCode() } fun Tiles.deselectAll() { diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt index 709c7e27e..0af151f9b 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Destroy.kt @@ -3,6 +3,7 @@ package com.bumble.appyx.navmodel.tiles.operation import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles +import com.bumble.appyx.navmodel.tiles.Tiles.State.DESTROYED import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @@ -15,16 +16,9 @@ data class Destroy( override fun invoke( elements: TilesElements - ): NavElements = - elements.map { - if (it.key == key) { - it.transitionTo( - newTargetState = Tiles.TransitionState.DESTROYED, - operation = this - ) - } else { - it - } + ): NavElements = + elements.transitionTo(DESTROYED) { + it.key == key } } diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt index 8f1a76e6a..42fae5d2b 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/RemoveSelected.kt @@ -2,6 +2,8 @@ package com.bumble.appyx.navmodel.tiles.operation import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.navmodel.tiles.Tiles +import com.bumble.appyx.navmodel.tiles.Tiles.State.DESTROYED +import com.bumble.appyx.navmodel.tiles.Tiles.State.SELECTED import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @@ -12,16 +14,9 @@ class RemoveSelected : TilesOperation { override fun invoke( elements: TilesElements - ): NavElements = - elements.map { - if (it.targetState == Tiles.TransitionState.SELECTED) { - it.transitionTo( - newTargetState = Tiles.TransitionState.DESTROYED, - operation = this - ) - } else { - it - } + ): NavElements = + elements.transitionTo(DESTROYED) { + it.targetState == SELECTED } override fun equals(other: Any?): Boolean = this.javaClass == other?.javaClass diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt index c7308757f..d64c069a3 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Select.kt @@ -3,6 +3,8 @@ package com.bumble.appyx.navmodel.tiles.operation import com.bumble.appyx.core.navigation.NavElements import com.bumble.appyx.core.navigation.NavKey import com.bumble.appyx.navmodel.tiles.Tiles +import com.bumble.appyx.navmodel.tiles.Tiles.State.SELECTED +import com.bumble.appyx.navmodel.tiles.Tiles.State.STANDARD import com.bumble.appyx.navmodel.tiles.TilesElements import kotlinx.parcelize.Parcelize @@ -15,16 +17,9 @@ data class Select( override fun invoke( elements: TilesElements - ): NavElements = - elements.map { - if (it.key == key && it.targetState == Tiles.TransitionState.STANDARD) { - it.transitionTo( - newTargetState = Tiles.TransitionState.SELECTED, - operation = this - ) - } else { - it - } + ): NavElements = + elements.transitionTo(SELECTED) { + it.key == key && it.targetState == STANDARD } } diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt index 6799a3362..8c691dea4 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/TilesOperation.kt @@ -3,4 +3,4 @@ package com.bumble.appyx.navmodel.tiles.operation import com.bumble.appyx.core.navigation.Operation import com.bumble.appyx.navmodel.tiles.Tiles -interface TilesOperation : Operation +interface TilesOperation : Operation diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt index 301c3c056..006754052 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt +++ b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/ToggleSelection.kt @@ -15,16 +15,16 @@ data class ToggleSelection( override fun invoke( elements: TilesElements - ): NavElements = + ): NavElements = elements.map { if (it.key == key) { when (it.targetState) { - Tiles.TransitionState.SELECTED -> it.transitionTo( - newTargetState = Tiles.TransitionState.STANDARD, + Tiles.State.SELECTED -> it.transitionTo( + newTargetState = Tiles.State.STANDARD, operation = this ) - Tiles.TransitionState.STANDARD -> it.transitionTo( - newTargetState = Tiles.TransitionState.SELECTED, + Tiles.State.STANDARD -> it.transitionTo( + newTargetState = Tiles.State.SELECTED, operation = this ) else -> it diff --git a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt b/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt index a9cac58c9..0a601648a 100644 --- a/navmodel-addons/src/main/kotlin/com/bumble/appyx/navmodel/tiles/transitionhandler/TilesTransitionHandler.kt +++ b/navmodel-addons/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 androidx.compose.animation.core.Spring import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.spring @@ -20,23 +21,23 @@ import kotlin.math.roundToInt @Suppress("TransitionPropertiesLabel") class TilesTransitionHandler( - private val transitionSpec: TransitionSpec = { spring() } -) : ModifierTransitionHandler() { + private val transitionSpec: TransitionSpec = { spring() } +) : ModifierTransitionHandler() { @SuppressLint("ModifierFactoryExtensionFunction") override fun createModifier( modifier: Modifier, - transition: Transition, - descriptor: TransitionDescriptor + transition: Transition, + descriptor: TransitionDescriptor ): Modifier = modifier.composed { val scale = transition.animateFloat( transitionSpec = transitionSpec, targetValueByState = { when (it) { - Tiles.TransitionState.CREATED -> 0f - Tiles.TransitionState.STANDARD -> 0.75f - Tiles.TransitionState.SELECTED -> 1.0f - Tiles.TransitionState.DESTROYED -> 0f + Tiles.State.CREATED -> 0f + Tiles.State.STANDARD -> 0.75f + Tiles.State.SELECTED -> 1.0f + Tiles.State.DESTROYED -> 0f } }) @@ -44,7 +45,7 @@ class TilesTransitionHandler( transitionSpec = transitionSpec, targetValueByState = { when (it) { - Tiles.TransitionState.DESTROYED -> 1f + Tiles.State.DESTROYED -> 1f else -> 0f } }) @@ -62,7 +63,7 @@ class TilesTransitionHandler( @Composable fun rememberTilesTransitionHandler( - transitionSpec: TransitionSpec = { spring() } -): ModifierTransitionHandler = remember { + transitionSpec: TransitionSpec = { spring(stiffness = Spring.StiffnessVeryLow) } +): ModifierTransitionHandler = remember { TilesTransitionHandler(transitionSpec) } From 157e626061b11f612b016ff096d451ad569b86fa Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Wed, 21 Sep 2022 21:36:10 +0100 Subject: [PATCH 3/8] Restore accidental removal of equals override --- .../com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt b/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt index 288944278..d1ff4b7a1 100644 --- a/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt +++ b/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/DeselectAll.kt @@ -18,6 +18,10 @@ class DeselectAll : TilesOperation { elements.transitionTo(STANDARD) { it.targetState == SELECTED } + + override fun equals(other: Any?): Boolean = this.javaClass == other?.javaClass + + override fun hashCode(): Int = this.javaClass.hashCode() } fun Tiles.deselectAll() { From 290582664a922a08b1f9626772aef5f747c040d9 Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Wed, 21 Sep 2022 21:36:22 +0100 Subject: [PATCH 4/8] Fix code style missing EOL --- .../main/kotlin/com/bumble/appyx/core/navigation/Operation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt b/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt index b594e36a2..38327834f 100644 --- a/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt +++ b/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt @@ -72,4 +72,4 @@ interface Operation : override fun hashCode(): Int = this.javaClass.hashCode() } -} \ No newline at end of file +} From 464aa96ddaef7cf8f2f24ce54f4160f62a79e487 Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Thu, 22 Sep 2022 00:32:45 +0100 Subject: [PATCH 5/8] Fix rename --- .../com/bumble/appyx/navmodel/tiles/operation/Deselect.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt b/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt index 84e3de1f0..5da20d196 100644 --- a/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt +++ b/navmodel-samples/src/main/kotlin/com/bumble/appyx/navmodel/tiles/operation/Deselect.kt @@ -18,7 +18,7 @@ data class Deselect( override fun invoke( elements: TilesElements ): NavElements = - elements.transitionToIndexed(STANDARD) { + elements.transitionTo(STANDARD) { it.key == key && it.targetState == SELECTED } } From 338630be7c7e5c72bbd58e9c6bae08ab59649975 Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Thu, 22 Sep 2022 00:41:26 +0100 Subject: [PATCH 6/8] Update CHANGELOG.md --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31d50eb06..a5716bd31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,14 @@ ## Pending changes - [#151](https://github.com/bumble-tech/appyx/issues/151) - **Breaking change**: Renamed `Routing` to `NavTarget`. All related namings are affected (`RoutingElement`, `RoutingKey`, etc.) -- [#151](https://github.com/bumble-tech/appyx/issues/158) - **Breaking change**: Renamed `TransitionState` to `State` in all NavModel impls. Renamed `STASHED_IN_BACK_STACK` to `STASHED`. +- [#158](https://github.com/bumble-tech/appyx/issues/158) - **Breaking change**: Renamed `TransitionState` to `State` in all NavModel impls. Renamed `STASHED_IN_BACK_STACK` to `STASHED`. - [#146](https://github.com/bumble-tech/appyx/issues/146) - **Breaking change**: Removed `FragmentIntegrationPoint`. Clients should use `ActivityIntegrationPoint.getIntegrationPoint(context: Context)` to get integration point from Fragment -- [#146](https://github.com/bumble-tech/appyx/issues/160) - **Breaking change**: Renamed `navmodel-addons` to `navmodel-samples` and stopped publishing the binary. If you feel we should add any of the samples to the main codebase, please let us know! +- [#168](https://github.com/bumble-tech/appyx/issues/160) - **Breaking change**: Renamed `navmodel-addons` to `navmodel-samples` and stopped publishing the binary. If you feel we should add any of the samples to the main codebase, please let us know! - [#138](https://github.com/bumble-tech/appyx/pull/138) - **Fixed**: `androidx.appcompat:appcompat` from is exposed via `api` within `com.bumble.appyx:core`. This prevents potential compilation bugs. - [#143](https://github.com/bumble-tech/appyx/issues/143) - **Fixed**: Correctly exposed transitive dependencies that are part of the libraries ABI - [#145](https://github.com/bumble-tech/appyx/issues/145) - **Updated**: `SpotlightSlider` now uses offset modifier with lambda - [#159](https://github.com/bumble-tech/appyx/pull/159) - **Added**: `NodeHost` now takes modifier parameter to decorate the view of a root node +- [#161](https://github.com/bumble-tech/appyx/pull/151) - **Added**: Operations helpers --- From 843aed8389c9780c45f2e1e89793f8bcc7fdc16d Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Thu, 22 Sep 2022 00:44:33 +0100 Subject: [PATCH 7/8] Mention helpers in documentation --- documentation/navmodel/custom.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/navmodel/custom.md b/documentation/navmodel/custom.md index 03e10e0a5..40be939ae 100644 --- a/documentation/navmodel/custom.md +++ b/documentation/navmodel/custom.md @@ -64,6 +64,7 @@ class SomeOperation : FooOperation { ): NavElements = // TODO: Mutate elements however you please. Add, remove, change. // In this example we're changing all elements to transition to BAR. + // You can also use helper methods elements.transitionTo & elements.transitionToIndexed elements.map { it.transitionTo( newTargetState = BAR, From 4f15f184dd870194092fd50ff75952e23352d846 Mon Sep 17 00:00:00 2001 From: Zsolt Kocsi Date: Thu, 22 Sep 2022 13:41:06 +0100 Subject: [PATCH 8/8] Fix code formatting --- .../com/bumble/appyx/core/navigation/Operation.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt b/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt index 38327834f..53f42e32e 100644 --- a/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt +++ b/core/src/main/kotlin/com/bumble/appyx/core/navigation/Operation.kt @@ -13,7 +13,12 @@ interface Operation : */ fun NavElements.transitionTo( newTargetState: State - ) = transitionToIndexed(newTargetState) { _, _ -> true } + ) = map { element -> + element.transitionTo( + newTargetState = newTargetState, + operation = this@Operation + ) + } /** * Transitions all elements to a new state based on the individual elements @@ -31,7 +36,8 @@ interface Operation : * Transitions elements to a new state if they pass a condition based on the element */ fun NavElements.transitionTo( - newTargetState: State, condition: (element: NavElement) -> Boolean + newTargetState: State, + condition: (NavElement) -> Boolean ) = map { element -> if (condition.invoke(element)) { element.transitionTo( @@ -47,7 +53,8 @@ interface Operation : * Transitions elements to a new state if they pass a condition based on the element and its position */ fun NavElements.transitionToIndexed( - newTargetState: State, condition: (index: Int, element: NavElement) -> Boolean + newTargetState: State, + condition: (Int, NavElement) -> Boolean ) = mapIndexed { index, element -> if (condition.invoke(index, element)) { element.transitionTo(