Skip to content

Commit

Permalink
Merge branch '2.x' of github.com:bumble-tech/appyx into 2.x-remove-ut…
Browse files Browse the repository at this point in the history
…ils-classes-from-publication
  • Loading branch information
KovalevAndrey committed Feb 12, 2024
2 parents e226cf0 + bf13c67 commit 59de12d
Show file tree
Hide file tree
Showing 70 changed files with 595 additions and 437 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@

## Pending changes

### API breaking changes

- [#677](https://github.com/bumble-tech/appyx/pull/677) – Moved Builder, SimpleBuilder, Interactor to separate module

### Fixed

- [#670](https://github.com/bumble-tech/appyx/pull/670) - Fixes ios lifecycle
- [#673](https://github.com/bumble-tech/appyx/pull/673) – Fix canHandeBackPress typo

### Enhancement

- [#679](https://github.com/bumble-tech/appyx/pull/679) – Simple api for backStackNode and spotlightNode

---

## 2.0.0-alpha10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ import com.bumble.appyx.interactions.core.AppyxInteractionsContainer
import com.bumble.appyx.interactions.core.model.transition.Operation.Mode.IMMEDIATE
import com.bumble.appyx.interactions.core.model.transition.Operation.Mode.KEYFRAME
import com.bumble.appyx.interactions.core.ui.helper.AppyxComponentSetup
import com.bumble.appyx.interactions.utils.ui.InteractionTarget
import com.bumble.appyx.interactions.utils.ui.InteractionTarget.Child1
import com.bumble.appyx.interactions.utils.ui.InteractionTarget.Child2
import com.bumble.appyx.interactions.utils.ui.InteractionTarget.Child3
import com.bumble.appyx.interactions.utils.ui.InteractionTarget.Child4
import com.bumble.appyx.interactions.utils.ui.Element
import com.bumble.appyx.interactions.utils.testing.TestTarget
import com.bumble.appyx.interactions.utils.testing.TestTarget.Child1
import com.bumble.appyx.interactions.utils.testing.TestTarget.Child2
import com.bumble.appyx.interactions.utils.testing.TestTarget.Child3
import com.bumble.appyx.interactions.utils.testing.TestTarget.Child4
import kotlin.math.roundToInt


Expand All @@ -47,7 +47,7 @@ fun PromoterExperiment(modifier: Modifier = Modifier) {
val promoter = remember {
Promoter(
scope = coroutineScope,
model = PromoterModel<InteractionTarget>(savedStateMap = null),
model = PromoterModel<TestTarget>(savedStateMap = null),
visualisation = {
PromoterVisualisation(
uiContext = it
Expand Down Expand Up @@ -100,13 +100,13 @@ fun PromoterExperiment(modifier: Modifier = Modifier) {
horizontalArrangement = Arrangement.Center
) {
Button(
onClick = { promoter.addFirst(InteractionTarget.values().random(), KEYFRAME) }
onClick = { promoter.addFirst(TestTarget.entries.random(), KEYFRAME) }
) {
Text("KEYFRAME")
}
Spacer(Modifier.size(24.dp))
Button(
onClick = { promoter.addFirst(InteractionTarget.values().random(), IMMEDIATE) }
onClick = { promoter.addFirst(TestTarget.entries.random(), IMMEDIATE) }
) {
Text("IMMEDIATE")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import com.bumble.appyx.components.internal.testdrive.TestDriveUi
import com.bumble.appyx.components.internal.testdrive.ui.simple.TestDriveSimpleVisualisation
import com.bumble.appyx.interactions.core.gesture.GestureValidator.Companion.permissiveValidator
import com.bumble.appyx.interactions.core.ui.helper.AppyxComponentSetup
import com.bumble.appyx.interactions.utils.ui.InteractionTarget
import com.bumble.appyx.interactions.utils.testing.TestTarget
import com.bumble.appyx.interactions.utils.ui.theme.appyx_dark
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -30,9 +30,9 @@ fun ComposeContentTestRule.createTestDrive(
easing = LinearEasing
),
uiAnimationSpec: SpringSpec<Float> = spring()
): TestDrive<InteractionTarget> {
): TestDrive<TestTarget> {
val model = TestDriveModel(
element = InteractionTarget.Child1,
element = TestTarget.Child1,
savedStateMap = null
)
return TestDrive(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import com.bumble.appyx.components.internal.testdrive.TestDriveExperiment
import com.bumble.appyx.interactions.utils.ui.InteractionTarget
import com.bumble.appyx.interactions.utils.testing.TestTarget
import com.bumble.appyx.interactions.utils.ui.theme.appyx_dark
import kotlin.math.roundToInt

Expand All @@ -16,7 +16,7 @@ fun TestDriveExperiment(modifier: Modifier = Modifier) {
TestDriveExperiment(
screenWidthPx = (LocalConfiguration.current.screenWidthDp * LocalDensity.current.density).roundToInt(),
screenHeightPx = (LocalConfiguration.current.screenHeightDp * LocalDensity.current.density).roundToInt(),
element = InteractionTarget.Child1,
element = TestTarget.Child1,
modifier = modifier.fillMaxSize().background(appyx_dark),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import com.bumble.appyx.interactions.core.ui.context.UiContext
import com.bumble.appyx.interactions.utils.testing.setupAppyxComponent
import com.bumble.appyx.interactions.utils.testing.waitUntilAnimationEnded
import com.bumble.appyx.interactions.utils.testing.waitUntilAnimationStarted
import com.bumble.appyx.interactions.utils.ui.InteractionTarget
import com.bumble.appyx.interactions.utils.testing.TestTarget
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import org.junit.Assert
Expand All @@ -32,11 +32,11 @@ class BackStackTest(private val testParam: TestParam) {
@get:Rule
val composeTestRule = createComposeRule()

private lateinit var backStack: BackStack<InteractionTarget>
private lateinit var backStack: BackStack<TestTarget>

companion object {
data class TestParam(
val visualisation: (UiContext) -> Visualisation<InteractionTarget, BackStackModel.State<InteractionTarget>>
val visualisation: (UiContext) -> Visualisation<TestTarget, BackStackModel.State<TestTarget>>
)

@JvmStatic
Expand All @@ -55,9 +55,9 @@ class BackStackTest(private val testParam: TestParam) {
composeTestRule.setupAppyxComponent(backStack)

val tweenTwoSec = tween<Float>(durationMillis = 2000)
backStack.push(interactionTarget = InteractionTarget.Child2)
backStack.push(interactionTarget = InteractionTarget.Child3)
backStack.push(interactionTarget = InteractionTarget.Child4)
backStack.push(navTarget = TestTarget.Child2)
backStack.push(navTarget = TestTarget.Child3)
backStack.push(navTarget = TestTarget.Child4)
backStack.pop(animationSpec = tweenTwoSec)

// all operations finished
Expand All @@ -73,9 +73,9 @@ class BackStackTest(private val testParam: TestParam) {
composeTestRule.setupAppyxComponent(backStack)

val tweenTwoSec = tween<Float>(durationMillis = 2000)
backStack.push(interactionTarget = InteractionTarget.Child2)
backStack.push(interactionTarget = InteractionTarget.Child3)
backStack.push(interactionTarget = InteractionTarget.Child4)
backStack.push(navTarget = TestTarget.Child2)
backStack.push(navTarget = TestTarget.Child3)
backStack.push(navTarget = TestTarget.Child4)
backStack.pop(animationSpec = tweenTwoSec)

// last operation is not finished. advanced time < 2000 (last operation animation spec)
Expand All @@ -89,9 +89,9 @@ class BackStackTest(private val testParam: TestParam) {
createBackStack(disableAnimations = true, testParam.visualisation)
composeTestRule.setupAppyxComponent(backStack)

backStack.push(interactionTarget = InteractionTarget.Child2)
backStack.push(interactionTarget = InteractionTarget.Child3)
backStack.push(interactionTarget = InteractionTarget.Child4)
backStack.push(navTarget = TestTarget.Child2)
backStack.push(navTarget = TestTarget.Child3)
backStack.push(navTarget = TestTarget.Child4)
backStack.pop()

Assert.assertEquals(3, backStack.elements.value.all.size)
Expand All @@ -106,17 +106,17 @@ class BackStackTest(private val testParam: TestParam) {
val popSpringSpec = spring<Float>(stiffness = 10f)

backStack.push(
interactionTarget = InteractionTarget.Child2,
navTarget = TestTarget.Child2,
mode = Operation.Mode.IMMEDIATE,
animationSpec = pushSpringSpec
)
// all subsequent operations will be in IMMEDIATE mode until settled
backStack.push(
interactionTarget = InteractionTarget.Child3,
navTarget = TestTarget.Child3,
animationSpec = pushSpringSpec
)
backStack.push(
interactionTarget = InteractionTarget.Child4,
navTarget = TestTarget.Child4,
animationSpec = pushSpringSpec
)
backStack.pop(animationSpec = popSpringSpec)
Expand All @@ -133,11 +133,11 @@ class BackStackTest(private val testParam: TestParam) {

private fun createBackStack(
disableAnimations: Boolean,
visualisation: (UiContext) -> Visualisation<InteractionTarget, BackStackModel.State<InteractionTarget>>
visualisation: (UiContext) -> Visualisation<TestTarget, BackStackModel.State<TestTarget>>
) {
backStack = BackStack(
model = BackStackModel(
initialTargets = listOf(InteractionTarget.Child1),
initialTargets = listOf(TestTarget.Child1),
savedStateMap = null
),
visualisation = visualisation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.bumble.appyx.components.backstack.BackStackModel
import com.bumble.appyx.components.backstack.operation.push
import com.bumble.appyx.interactions.core.model.transition.Update
import com.bumble.appyx.interactions.utils.testing.setupAppyxComponent
import com.bumble.appyx.interactions.utils.ui.InteractionTarget
import com.bumble.appyx.interactions.utils.testing.TestTarget
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import org.junit.Assert
Expand All @@ -18,22 +18,22 @@ class BackStackParallaxTest {
@get:Rule
val composeTestRule = createComposeRule()

private lateinit var backStack: BackStack<InteractionTarget>
private lateinit var backStackModel: BackStackModel<InteractionTarget>
private lateinit var visualisation: BackStackParallax<InteractionTarget>
private lateinit var backStack: BackStack<TestTarget>
private lateinit var backStackModel: BackStackModel<TestTarget>
private lateinit var visualisation: BackStackParallax<TestTarget>

@Test
fun backStackParallax_resolves_visibility_to_false_when_element_is_not_top_most_stashed_one() {
createBackStack()
composeTestRule.setupAppyxComponent(backStack)

backStack.push(interactionTarget = InteractionTarget.Child2)
backStack.push(interactionTarget = InteractionTarget.Child3)
backStack.push(interactionTarget = InteractionTarget.Child4)
backStack.push(navTarget = TestTarget.Child2)
backStack.push(navTarget = TestTarget.Child3)
backStack.push(navTarget = TestTarget.Child4)

composeTestRule.waitForIdle()

with(visualisation.mapUpdate(backStackModel.output.value as Update<BackStackModel.State<InteractionTarget>>)) {
with(visualisation.mapUpdate(backStackModel.output.value as Update<BackStackModel.State<TestTarget>>)) {
Assert.assertFalse(get(0).visibleState.value) // Child #1 should be false
Assert.assertFalse(get(1).visibleState.value) // Child #2 should be false
Assert.assertFalse(get(2).visibleState.value) // Child #3 should be false
Expand All @@ -43,13 +43,13 @@ class BackStackParallaxTest {

private fun createBackStack() {
backStackModel = BackStackModel(
initialTargets = listOf(InteractionTarget.Child1),
initialTargets = listOf(TestTarget.Child1),
savedStateMap = null
)
backStack = BackStack(
model = backStackModel,
visualisation = { uiContext ->
BackStackParallax<InteractionTarget>(uiContext).also {
BackStackParallax<TestTarget>(uiContext).also {
visualisation = it
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":appyx-interactions:appyx-interactions"))
implementation(project(":appyx-navigation:appyx-navigation"))
api(compose.runtime)
api(compose.foundation)
api(compose.material)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob

class BackStack<InteractionTarget : Any>(
class BackStack<NavTarget : Any>(
scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main),
val model: BackStackModel<InteractionTarget>,
visualisation: (UiContext) -> Visualisation<InteractionTarget, BackStackModel.State<InteractionTarget>>,
val model: BackStackModel<NavTarget>,
visualisation: (UiContext) -> Visualisation<NavTarget, BackStackModel.State<NavTarget>>,
animationSpec: AnimationSpec<Float> = spring(),
gestureFactory: (TransitionBounds) -> GestureFactory<InteractionTarget, BackStackModel.State<InteractionTarget>> = {
gestureFactory: (TransitionBounds) -> GestureFactory<NavTarget, BackStackModel.State<NavTarget>> = {
GestureFactory.Noop()
},
gestureSettleConfig: GestureSettleConfig = GestureSettleConfig(),
backPressStrategy: BackPressHandlerStrategy<InteractionTarget, BackStackModel.State<InteractionTarget>> =
backPressStrategy: BackPressHandlerStrategy<NavTarget, BackStackModel.State<NavTarget>> =
PopBackstackStrategy(scope),
disableAnimations: Boolean = false,
) : BaseAppyxComponent<InteractionTarget, BackStackModel.State<InteractionTarget>>(
) : BaseAppyxComponent<NavTarget, BackStackModel.State<NavTarget>>(
scope = scope,
model = model,
visualisation = visualisation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,56 +9,56 @@ import com.bumble.appyx.utils.multiplatform.Parcelable
import com.bumble.appyx.utils.multiplatform.Parcelize
import com.bumble.appyx.utils.multiplatform.SavedStateMap

class BackStackModel<InteractionTarget : Any>(
initialTargets: List<InteractionTarget>,
class BackStackModel<NavTarget : Any>(
initialTargets: List<NavTarget>,
savedStateMap: SavedStateMap?,
) : BaseTransitionModel<InteractionTarget, State<InteractionTarget>>(
) : BaseTransitionModel<NavTarget, State<NavTarget>>(
savedStateMap = savedStateMap,
) {
@Parcelize
data class State<InteractionTarget>(
data class State<NavTarget>(
/**
* Elements that have been created, but not yet moved to an active state
*/
val created: Elements<InteractionTarget> = listOf(),
val created: Elements<NavTarget> = listOf(),

/**
* The currently active element.
* There should be only one such element in the stack.
*/
val active: Element<InteractionTarget>,
val active: Element<NavTarget>,

/**
* Elements stashed in the back stack (history).
*/
val stashed: Elements<InteractionTarget> = listOf(),
val stashed: Elements<NavTarget> = listOf(),

/**
* Elements that will be destroyed after reaching this state.
*/
val destroyed: Elements<InteractionTarget> = listOf(),
val destroyed: Elements<NavTarget> = listOf(),
) : Parcelable

constructor(
initialTarget: InteractionTarget,
initialTarget: NavTarget,
savedStateMap: SavedStateMap?,
) : this(
initialTargets = listOf(initialTarget),
savedStateMap = savedStateMap
)

override fun State<InteractionTarget>.availableElements(): Set<Element<InteractionTarget>> =
override fun State<NavTarget>.availableElements(): Set<Element<NavTarget>> =
(created + active + stashed + destroyed).toSet()

override fun State<InteractionTarget>.destroyedElements(): Set<Element<InteractionTarget>> =
override fun State<NavTarget>.destroyedElements(): Set<Element<NavTarget>> =
destroyed.toSet()

override fun State<InteractionTarget>.removeDestroyedElement(
element: Element<InteractionTarget>
): State<InteractionTarget> =
override fun State<NavTarget>.removeDestroyedElement(
element: Element<NavTarget>
): State<NavTarget> =
copy(destroyed = destroyed.filterNot { it == element })

override fun State<InteractionTarget>.removeDestroyedElements(): State<InteractionTarget> =
override fun State<NavTarget>.removeDestroyedElements(): State<NavTarget> =
copy(destroyed = emptyList())

override val initialState = State(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import com.bumble.appyx.interactions.core.Element
val <T : Any> BackStackModel<T>.activeElement: Element<T>
get() = output.value.currentTargetState.active

val <T : Any> BackStackModel<T>.activeInteractionTarget: T
val <T : Any> BackStackModel<T>.activeTarget: T
get() = activeElement.interactionTarget
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import com.bumble.appyx.mapState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow

class PopBackstackStrategy<InteractionTarget : Any>(
class PopBackstackStrategy<NavTarget : Any>(
val scope: CoroutineScope,
val animationSpec: AnimationSpec<Float>? = null
) :
BaseBackPressHandlerStrategy<InteractionTarget, BackStackModel.State<InteractionTarget>>() {
BaseBackPressHandlerStrategy<NavTarget, BackStackModel.State<NavTarget>>() {

override val canHandleBackPress: StateFlow<Boolean> by lazy {
transitionModel.output.mapState(scope) { output ->
Expand All @@ -21,7 +21,7 @@ class PopBackstackStrategy<InteractionTarget : Any>(
}

override fun handleBackPress(): Boolean {
val pop = Pop<InteractionTarget>()
val pop = Pop<NavTarget>()
//todo find a better way to check if operation is applicable
return if (pop.isApplicable(transitionModel.output.value.currentTargetState)) {
appyxComponent.operation(operation = Pop(), animationSpec)
Expand Down
Loading

0 comments on commit 59de12d

Please sign in to comment.