Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Routing source #186

Merged
merged 72 commits into from
Jun 1, 2020
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
d82abf9
WIP
zsoltk May 21, 2020
b5d90b0
Fit tutorials
zsoltk May 21, 2020
ce66c1e
Update templates
zsoltk May 21, 2020
69d3539
Fix test compilation errors
zsoltk May 21, 2020
6ae2ef5
Fix detekt
zsoltk May 21, 2020
50a4867
Fix unit tests
zsoltk May 21, 2020
3d4f730
Change overlays List<C> -> List<Routing<C>>
zsoltk May 22, 2020
444293f
Implement Remove back stack operation
zsoltk May 22, 2020
76e9799
WIP
zsoltk May 22, 2020
b12c892
Implement basic id maintenance for back stack
zsoltk May 22, 2020
940bb14
Extract methods
zsoltk May 23, 2020
da0c4ba
Implement id in Permanent source
zsoltk May 23, 2020
688806f
Add static helper method to create Permanent
zsoltk May 23, 2020
d554546
Add operator plus to merge RoutingSources
zsoltk May 23, 2020
e22fdb6
Remove field for permanentParts in favour of merged RoutingSource
zsoltk May 23, 2020
48810ea
Use Routing<C> directly as key in pool
zsoltk May 23, 2020
d62f618
Fix combined RoutingSource
zsoltk May 23, 2020
f0a9858
Implement proper id in BackStackFeature
zsoltk May 23, 2020
97e04bf
Use new differ
zsoltk May 23, 2020
44d0c36
Cleanup
zsoltk May 23, 2020
7021637
Fix forwarding back press to combined sources
zsoltk May 23, 2020
6902e6a
Create named data classes for proper equals checks for transition rev…
zsoltk May 23, 2020
c8b7cfe
Extract class
zsoltk May 23, 2020
5060fca
Extract methods
zsoltk May 23, 2020
32019ba
WIP RecyclerView
zsoltk May 26, 2020
7cd1145
WIP RecyclerView
zsoltk May 26, 2020
7353ad3
Fix resolution cache lookup order to avoid calling resolve twice
zsoltk May 27, 2020
f0895d7
Communicate with RecyclerViewHost via Connectable
zsoltk May 27, 2020
4a9f4f3
Make underlying datastructure immutable
zsoltk May 27, 2020
a462222
Fix RecyclerViewHost
zsoltk May 27, 2020
92d72f7
Refactor child activation
zsoltk May 28, 2020
f171ec6
Change meta to Parcelable
zsoltk May 28, 2020
1dfd311
Remove unused imports
zsoltk May 28, 2020
4688600
Remove Scope annotation
zsoltk May 28, 2020
3e83058
Remove one-liner
zsoltk May 28, 2020
edd3ac9
Log error if holder is not bound on recycle
zsoltk May 28, 2020
063ab5a
Fix formatting
zsoltk May 28, 2020
167ab30
Fix type inference issue
zsoltk May 28, 2020
7b985c3
Quick fix unit test compilation errors
zsoltk May 28, 2020
aeef6b4
Fix SingleTop comparison
zsoltk May 29, 2020
1af0018
Add integration test for BackStackFeature + RoutingHistoryDiffer
zsoltk May 29, 2020
6c06b6d
Remove legacy ConfigurationCommandCreator
zsoltk May 29, 2020
a142a53
Add reminder for more tests
zsoltk May 29, 2020
50022ba
Cleanup leftover
zsoltk May 29, 2020
0b82d0a
Update comments
zsoltk May 29, 2020
529b29f
Remove legacy ConfigurationKey
zsoltk May 29, 2020
162d0d2
Remove unused import
zsoltk May 29, 2020
2be78ea
Make field private
zsoltk May 29, 2020
1445f05
Revert accidental change
zsoltk May 29, 2020
7db13ad
Fix dialog nodes to be built with correct AttachMode
zsoltk May 29, 2020
0dc825b
Support allowRepeatingConfigurations in default id
zsoltk May 29, 2020
39a3d27
Create Observable only once
zsoltk May 29, 2020
cfc43bf
Remove leftovers
zsoltk May 29, 2020
56c9e30
Rename BackStackChangesToCommands to RoutingHistoryToCommands
zsoltk May 29, 2020
2e3d348
Fix array index typo
zsoltk May 29, 2020
776c1ee
Fix issue when buffer contains only 1 element
zsoltk May 29, 2020
47bc8ee
Ignore test for now (functionality is covered by integration test)
zsoltk May 29, 2020
2df0c13
Create back stack on main thread in tests
zsoltk May 30, 2020
d7afde6
Fix rendering condition
zsoltk May 30, 2020
66bf995
Add RoutingSource.baseLineState
zsoltk May 30, 2020
bc96677
Remove implementing BackPressHandler (covered correctly through imple…
zsoltk May 30, 2020
4b2b1b8
Implement correct baseLineState restoration
zsoltk May 30, 2020
c29529b
Rename
zsoltk May 30, 2020
b88fdfa
Create permanents w/o buildParams
zsoltk May 30, 2020
7b6dc6c
Restore BackStackFeature constructor with timecapsule as internal
zsoltk May 31, 2020
cb88b1c
Rework BackStackFeatureTest
zsoltk May 31, 2020
a2ea8f6
Move add/demove execution to RoutingActivator
zsoltk May 31, 2020
635f61c
Remove duplicate
zsoltk May 31, 2020
61ec322
Ensure saveViewState
zsoltk May 31, 2020
81cff05
Remove unused parm
zsoltk May 31, 2020
9ba7aa2
Move pending state flag maintenance to RoutingActivator
zsoltk May 31, 2020
9ada51b
Adapt tests
zsoltk May 31, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/app-example/src/main/res/layout/activity_root.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
23 changes: 23 additions & 0 deletions android/app-example/src/main/res/layout/debug_switcher.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/debug_switcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp"
android:orientation="horizontal"
android:layout_gravity="center"
android:gravity="center">

<Button
android:id="@+id/workflow_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Workflow 1" />

<Button
android:id="@+id/workflow_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Workflow 2"/>

</LinearLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import com.badoo.ribs.core.Interactor
import com.badoo.ribs.core.Node
import com.badoo.ribs.core.Router
import com.badoo.ribs.core.builder.BuildParams
import com.badoo.ribs.core.routing.RoutingSource
import com.badoo.ribs.core.routing.action.RoutingAction
import com.badoo.ribs.core.routing.history.Routing
import com.badoo.ribs.core.view.RibView
import com.jakewharton.rxrelay2.Relay
import io.reactivex.ObservableSource
Expand All @@ -21,17 +23,14 @@ private val buildParams = BuildParams.Empty()

class InteractorTestHelper<View : RibView>(
val interactor: Interactor<*, View>,
val viewFactory: ((ViewGroup) -> View?)? = null,
router: Router<*, *, *, *, View>? = null
zsoltk marked this conversation as resolved.
Show resolved Hide resolved
val viewFactory: ((ViewGroup) -> View?)? = null
) {

val router: Router<*, *, *, *, View> = router ?: TestRouter.createTestRouter()

var nodeCreator: () -> Node<View> = {
Node(
buildParams = buildParams,
viewFactory = viewFactory,
plugins = listOf(this.router, interactor)
plugins = listOf(interactor)
)
}

Expand Down Expand Up @@ -73,11 +72,10 @@ class InteractorTestHelper<View : RibView>(
companion object {
inline fun <reified View, ViewEvent> create(
interactor: Interactor<*, View>,
viewEventRelay: Relay<ViewEvent>,
router: Router<*, *, *, *, View>? = null
viewEventRelay: Relay<ViewEvent>
): InteractorTestHelper<View> where View : RibView, View : ObservableSource<ViewEvent> {
val view: View = viewEventRelay.subscribedView()
return InteractorTestHelper(interactor, { view }, router)
return InteractorTestHelper(interactor, { view })
}
}
}
Expand All @@ -91,22 +89,20 @@ inline fun <reified RView, ViewEvent> Relay<ViewEvent>.subscribedView(): RView w
}
}

private class TestRouter<C : Parcelable, Permanent : C, Content : C, Overlay : C, V : RibView>(
initialConfig: Content
) : Router<C, Permanent, Content, Overlay, V>(
private class TestRouter<C : Parcelable> : Router<C>(
buildParams = buildParams,
transitionHandler = null,
initialConfiguration = initialConfig
routingSource = RoutingSource.Permanent<C>(emptySet()),
transitionHandler = null
) {

var resolveConfiguration: (C) -> RoutingAction = { RoutingAction.noop() }

override fun resolveConfiguration(configuration: C): RoutingAction =
resolveConfiguration.invoke(configuration)
override fun resolve(routing: Routing<C>): RoutingAction =
resolveConfiguration.invoke(routing.configuration)

companion object {
fun <V : RibView> createTestRouter() =
TestRouter<TestConfiguration, TestConfiguration, TestConfiguration, TestConfiguration, V>(TestConfiguration)
fun createTestRouter() =
TestRouter<TestConfiguration>()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import androidx.test.espresso.Espresso
import com.badoo.common.ribs.RibsRule
import com.badoo.ribs.android.lifecycle.helper.ExpectedState
import com.badoo.ribs.android.lifecycle.helper.NodeState
import com.badoo.ribs.core.builder.BuildParams
import com.badoo.ribs.core.routing.configuration.feature.BackStackFeature
import com.badoo.ribs.core.routing.configuration.feature.operation.push
import com.badoo.ribs.core.routing.configuration.feature.operation.pushOverlay
import com.badoo.ribs.test.util.ribs.TestNode
Expand All @@ -24,22 +26,35 @@ abstract class BaseNodesTest {
val pushConfiguration2: TestRootRouter.Configuration? = null
)

protected fun test(setup: When, expectedState: ExpectedState, testBlock: (TestRootRouter, TestNode<*>) -> Unit) {
protected fun test(
setup: When,
expectedState: ExpectedState,
testBlock: (BackStackFeature<TestRootRouter.Configuration>, TestNode<*>) -> Unit
) {
val rootProvider = TestRoot.Provider(
initialConfiguration = setup.initialConfiguration,
permanentParts = setup.permanentParts
)

ribsRule.start { activity, savedInstanceState -> rootProvider.create(activity.dialogLauncher(), savedInstanceState) }
val backStack: BackStackFeature<TestRootRouter.Configuration> = BackStackFeature(
buildParams = BuildParams.Empty(),
initialConfiguration = setup.initialConfiguration
)

val router: TestRootRouter = rootProvider.rootNode?.getRouter() as TestRootRouter
ribsRule.start { activity, savedInstanceState ->
rootProvider.create(
dialogLauncher = activity.dialogLauncher(),
savedInstanceState = savedInstanceState,
routingSource = backStack
)
}

testBlock.invoke(router, rootProvider.rootNode!!)
testBlock.invoke(backStack, rootProvider.rootNode!!)

rootProvider.makeAssertions(expectedState)
}

protected fun TestRootRouter.pushIt(configuration: TestRootRouter.Configuration) {
protected fun BackStackFeature<TestRootRouter.Configuration>.pushIt(configuration: TestRootRouter.Configuration) {
when (configuration) {
is TestRootRouter.Configuration.Content -> push(configuration)
is TestRootRouter.Configuration.Overlay -> pushOverlay(configuration)
Expand All @@ -48,11 +63,23 @@ abstract class BaseNodesTest {

private fun TestRoot.Provider.makeAssertions(expected: ExpectedState) {
Espresso.onIdle()
permanentNode1?.let { assertThat(it.toNodeState()).describedAs("Permanent node 1 state").isEqualTo(expected.permanentNode1) }
permanentNode2?.let { assertThat(it.toNodeState()).describedAs("Permanent node 2 state").isEqualTo(expected.permanentNode2) }
childNode1?.let { assertThat(it.toNodeState()).describedAs("Child node 1 state").isEqualTo(expected.node1) }
childNode2?.let { assertThat(it.toNodeState()).describedAs("Child node 2 state").isEqualTo(expected.node2) }
childNode3?.let { assertThat(it.toNodeState()).describedAs("Child node 3 state").isEqualTo(expected.node3) }
permanentNode1?.let {
assertThat(it.toNodeState()).describedAs("Permanent node 1 state")
.isEqualTo(expected.permanentNode1)
}
permanentNode2?.let {
assertThat(it.toNodeState()).describedAs("Permanent node 2 state")
.isEqualTo(expected.permanentNode2)
}
childNode1?.let {
assertThat(it.toNodeState()).describedAs("Child node 1 state").isEqualTo(expected.node1)
}
childNode2?.let {
assertThat(it.toNodeState()).describedAs("Child node 2 state").isEqualTo(expected.node2)
}
childNode3?.let {
assertThat(it.toNodeState()).describedAs("Child node 3 state").isEqualTo(expected.node3)
}
}

private fun TestNode<*>.toNodeState() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import com.badoo.ribs.test.util.runOnMainSync
class PushTwoPopOneDefaultTest : PushTwoPopOneTest() {

override fun pushTwoConfigurationAndPop(setup: When, expectedState: ExpectedState) {
test(setup, expectedState) { router, _ ->
test(setup, expectedState) { backStack, _ ->
runOnMainSync {
router.pushIt(setup.pushConfiguration1!!)
router.pushIt(setup.pushConfiguration2!!)
router.popBackStack()
backStack.pushIt(setup.pushConfiguration1!!)
backStack.pushIt(setup.pushConfiguration2!!)
backStack.popBackStack()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ class RootNodeLifecycleTest {
val node get() = provider.rootNode!!

@get:Rule
val ribsRule = RibsRule { activity, savedInstanceState -> provider.create(activity.dialogLauncher(), savedInstanceState) }
val ribsRule = RibsRule { activity, savedInstanceState ->
provider.create(
dialogLauncher = activity.dialogLauncher(),
savedInstanceState = savedInstanceState
)
}

@Test
fun whenActivityResumed_nodeIsAttached() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.badoo.ribs.core.view.ViewFactory
class TestNode<V: RibView>(
buildParams: BuildParams<*>,
viewFactory: ViewFactory<Nothing?, V>,
private val router: Router<*, *, *, *, V>,
private val router: Router<*>,
interactor: Interactor<*, V>
): Node<V>(
buildParams = buildParams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@ package com.badoo.ribs.test.util.ribs.child
import android.os.Parcelable
import com.badoo.ribs.core.Router
import com.badoo.ribs.core.builder.BuildParams
import com.badoo.ribs.core.routing.RoutingSource.Permanent
import com.badoo.ribs.core.routing.action.RoutingAction
import com.badoo.ribs.core.routing.history.Routing
import com.badoo.ribs.test.util.ribs.child.TestChildRouter.Configuration
import kotlinx.android.parcel.Parcelize

class TestChildRouter(
buildParams: BuildParams<Nothing?>
): Router<Configuration, Nothing, Configuration, Nothing, TestChildView>(
): Router<Configuration>(
buildParams = buildParams,
initialConfiguration = Configuration.Default
routingSource = Permanent(emptySet())
) {
sealed class Configuration : Parcelable {
@Parcelize object Default : Configuration()
}

override fun resolveConfiguration(configuration: Configuration): RoutingAction =
override fun resolve(routing: Routing<Configuration>): RoutingAction =
RoutingAction.noop()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import android.os.Bundle
import com.badoo.ribs.core.builder.BuildParams
import com.badoo.ribs.core.Rib
import com.badoo.ribs.core.builder.BuildContext
import com.badoo.ribs.core.routing.RoutingSource
import com.badoo.ribs.core.routing.configuration.feature.BackStackFeature
import com.badoo.ribs.dialog.DialogLauncher
import com.badoo.ribs.test.util.LifecycleObserver
import com.badoo.ribs.test.util.ribs.TestNode
Expand Down Expand Up @@ -44,13 +46,18 @@ interface TestRoot : Rib {
var rootNode: TestNode<*>? = null
private set

private fun builder(block: (TestNode<TestChildView>) -> Unit): (BuildContext) -> TestNode<TestChildView> = {
TestChildBuilder().build(it).also {
block.invoke(it)
private fun builder(block: (TestNode<TestChildView>) -> Unit): (BuildContext) -> TestNode<TestChildView> =
{
TestChildBuilder().build(it).also {
block.invoke(it)
}
}
}

fun create(dialogLauncher: DialogLauncher, savedInstanceState: Bundle?): TestNode<TestRootView> {
fun create(
dialogLauncher: DialogLauncher,
savedInstanceState: Bundle?,
routingSource: RoutingSource<Configuration> = RoutingSource.Empty()
): TestNode<TestRootView> {
val router = TestRootRouter(
buildParams = BuildParams(
payload = null,
Expand All @@ -59,12 +66,12 @@ interface TestRoot : Rib {
uuid = UUID.randomUUID()
)
),
routingSource = routingSource,
builderPermanent1 = builder { permanentNode1 = it },
builderPermanent2 = builder { permanentNode2 = it },
builder1 = builder { childNode1 = it },
builder2 = builder { childNode2 = it },
builder3 = builder { childNode3 = it },
initialConfiguration = initialConfiguration,
permanentParts = permanentParts,
dialogLauncher = dialogLauncher
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import android.os.Parcelable
import com.badoo.ribs.core.Router
import com.badoo.ribs.core.builder.BuildParams
import com.badoo.ribs.core.builder.NodeFactory
import com.badoo.ribs.core.routing.RoutingSource
import com.badoo.ribs.core.routing.RoutingSource.Permanent.Companion.permanent
import com.badoo.ribs.core.routing.action.AttachRibRoutingAction.Companion.attach
import com.badoo.ribs.core.routing.action.CompositeRoutingAction.Companion.composite
import com.badoo.ribs.core.routing.action.DialogRoutingAction.Companion.showDialog
import com.badoo.ribs.core.routing.action.RoutingAction
import com.badoo.ribs.core.routing.action.RoutingAction.Companion.noop
import com.badoo.ribs.core.routing.history.Routing
import com.badoo.ribs.dialog.DialogLauncher
import com.badoo.ribs.test.util.ribs.TestRibDialog
import com.badoo.ribs.test.util.ribs.root.TestRootRouter.Configuration
Expand All @@ -19,18 +22,17 @@ import kotlinx.android.parcel.Parcelize

class TestRootRouter(
buildParams: BuildParams<Nothing?>,
routingSource: RoutingSource<Configuration>,
private val builderPermanent1: NodeFactory,
private val builderPermanent2: NodeFactory,
private val builder3: NodeFactory,
private val builder1: NodeFactory,
private val builder2: NodeFactory,
private val dialogLauncher: DialogLauncher,
permanentParts: List<Permanent>,
initialConfiguration: Content
) : Router<Configuration, Permanent, Content, Overlay, TestRootView>(
permanentParts: List<Permanent>
) : Router<Configuration>(
buildParams = buildParams,
initialConfiguration = initialConfiguration,
permanentParts = permanentParts
routingSource = routingSource + permanent(permanentParts)
) {

sealed class Configuration : Parcelable {
Expand All @@ -54,8 +56,8 @@ class TestRootRouter(
}
}

override fun resolveConfiguration(configuration: Configuration): RoutingAction =
when (configuration) {
override fun resolve(routing: Routing<Configuration>): RoutingAction =
when (routing.configuration) {
Permanent.Permanent1 -> attach(builderPermanent1)
Permanent.Permanent2 -> attach(builderPermanent2)
Content.NoOp -> noop()
Expand All @@ -66,8 +68,8 @@ class TestRootRouter(
attach(builder1),
attach(builder2)
)
Overlay.AttachNode1AsOverlay -> showDialog(this, dialogLauncher, TestRibDialog(builder1))
Overlay.AttachNode2AsOverlay -> showDialog(this, dialogLauncher, TestRibDialog(builder2))
Overlay.AttachNode3AsOverlay -> showDialog(this, dialogLauncher, TestRibDialog(builder3))
Overlay.AttachNode1AsOverlay -> showDialog(routingSource, routing.identifier, dialogLauncher, TestRibDialog(builder1))
Overlay.AttachNode2AsOverlay -> showDialog(routingSource, routing.identifier, dialogLauncher, TestRibDialog(builder2))
Overlay.AttachNode3AsOverlay -> showDialog(routingSource, routing.identifier, dialogLauncher, TestRibDialog(builder3))
}
}
Loading