From 8d6be48499cfb0c38e32994788cdc85c62bfe9ae Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Thu, 11 Mar 2021 13:15:47 +0000 Subject: [PATCH] TodoApp. Get rid of Dependencies interfaces. (#480) --- .../java/example/todo/android/MainActivity.kt | 11 +++--- .../example/todo/common/edit/TodoEdit.kt | 17 ---------- .../{TodoEditImpl.kt => TodoEditComponent.kt} | 15 +++++--- .../example/todo/common/main/TodoMain.kt | 16 --------- .../{TodoMainImpl.kt => TodoMainComponent.kt} | 14 +++++--- .../common/main/integration/TodoMainTest.kt | 13 +++---- .../example/todo/common/root/TodoRoot.kt | 34 ------------------- .../{TodoRootImpl.kt => TodoRootComponent.kt} | 31 ++++++++++++++++- .../common/root/integration/TodoRootTest.kt | 2 +- .../kotlin/example/todo/desktop/Main.kt | 9 +++-- examples/todoapp/ios/ios/ContentView.swift | 11 ++---- 11 files changed, 65 insertions(+), 108 deletions(-) rename examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/{TodoEditImpl.kt => TodoEditComponent.kt} (77%) rename examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/{TodoMainImpl.kt => TodoMainComponent.kt} (79%) rename examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/{TodoRootImpl.kt => TodoRootComponent.kt} (67%) diff --git a/examples/todoapp/android/src/main/java/example/todo/android/MainActivity.kt b/examples/todoapp/android/src/main/java/example/todo/android/MainActivity.kt index 1b4a00d86a..7845540d8c 100755 --- a/examples/todoapp/android/src/main/java/example/todo/android/MainActivity.kt +++ b/examples/todoapp/android/src/main/java/example/todo/android/MainActivity.kt @@ -7,12 +7,12 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.extensions.compose.jetbrains.rememberRootComponent -import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.arkivanov.mvikotlin.timetravel.store.TimeTravelStoreFactory import example.todo.common.database.TodoDatabaseDriver import example.todo.common.root.TodoRoot +import example.todo.common.root.integration.TodoRootComponent import example.todo.common.ui.TodoRootContent import example.todo.database.TodoDatabase @@ -30,12 +30,9 @@ class MainActivity : AppCompatActivity() { } private fun todoRoot(componentContext: ComponentContext): TodoRoot = - TodoRoot( + TodoRootComponent( componentContext = componentContext, - dependencies = object : TodoRoot.Dependencies { - // You can play with time travel using IDEA plugin: https://arkivanov.github.io/MVIKotlin/time_travel.html - override val storeFactory: StoreFactory = LoggingStoreFactory(TimeTravelStoreFactory(DefaultStoreFactory)) - override val database: TodoDatabase = TodoDatabase(TodoDatabaseDriver(this@MainActivity)) - } + storeFactory = LoggingStoreFactory(TimeTravelStoreFactory(DefaultStoreFactory)), + database = TodoDatabase(TodoDatabaseDriver(context = this)) ) } diff --git a/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/TodoEdit.kt b/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/TodoEdit.kt index e03378fdbf..8ca3091b6e 100644 --- a/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/TodoEdit.kt +++ b/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/TodoEdit.kt @@ -1,12 +1,6 @@ package example.todo.common.edit -import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.value.Value -import com.arkivanov.mvikotlin.core.store.StoreFactory -import com.badoo.reaktive.base.Consumer -import example.todo.common.edit.TodoEdit.Dependencies -import example.todo.common.edit.integration.TodoEditImpl -import example.todo.database.TodoDatabase interface TodoEdit { @@ -23,18 +17,7 @@ interface TodoEdit { val isDone: Boolean ) - interface Dependencies { - val storeFactory: StoreFactory - val database: TodoDatabase - val itemId: Long - val editOutput: Consumer - } - sealed class Output { object Finished : Output() } } - -@Suppress("FunctionName") // Factory function -fun TodoEdit(componentContext: ComponentContext, dependencies: Dependencies): TodoEdit = - TodoEditImpl(componentContext, dependencies) diff --git a/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditImpl.kt b/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditComponent.kt similarity index 77% rename from examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditImpl.kt rename to examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditComponent.kt index b27501e6bb..287dac75bd 100644 --- a/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditImpl.kt +++ b/examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditComponent.kt @@ -3,20 +3,25 @@ package example.todo.common.edit.integration import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.operator.map +import com.arkivanov.mvikotlin.core.store.StoreFactory +import com.badoo.reaktive.base.Consumer import com.badoo.reaktive.base.invoke import example.todo.common.edit.TodoEdit -import example.todo.common.edit.TodoEdit.Dependencies import example.todo.common.edit.TodoEdit.Model import example.todo.common.edit.TodoEdit.Output import example.todo.common.edit.store.TodoEditStore.Intent import example.todo.common.edit.store.TodoEditStoreProvider import example.todo.common.utils.asValue import example.todo.common.utils.getStore +import example.todo.database.TodoDatabase -internal class TodoEditImpl( +class TodoEditComponent( componentContext: ComponentContext, - dependencies: Dependencies -) : TodoEdit, ComponentContext by componentContext, Dependencies by dependencies { + storeFactory: StoreFactory, + database: TodoDatabase, + itemId: Long, + private val output: Consumer +) : TodoEdit, ComponentContext by componentContext { private val store = instanceKeeper.getStore { @@ -38,6 +43,6 @@ internal class TodoEditImpl( } override fun onCloseClicked() { - editOutput(Output.Finished) + output(Output.Finished) } } diff --git a/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/TodoMain.kt b/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/TodoMain.kt index 0c0d57663c..24d434313c 100644 --- a/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/TodoMain.kt +++ b/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/TodoMain.kt @@ -1,12 +1,6 @@ package example.todo.common.main -import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.value.Value -import com.arkivanov.mvikotlin.core.store.StoreFactory -import com.badoo.reaktive.base.Consumer -import example.todo.common.main.TodoMain.Dependencies -import example.todo.common.main.integration.TodoMainImpl -import example.todo.database.TodoDatabase interface TodoMain { @@ -27,17 +21,7 @@ interface TodoMain { val text: String ) - interface Dependencies { - val storeFactory: StoreFactory - val database: TodoDatabase - val mainOutput: Consumer - } - sealed class Output { data class Selected(val id: Long) : Output() } } - -@Suppress("FunctionName") // Factory function -fun TodoMain(componentContext: ComponentContext, dependencies: Dependencies): TodoMain = - TodoMainImpl(componentContext, dependencies) diff --git a/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainImpl.kt b/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainComponent.kt similarity index 79% rename from examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainImpl.kt rename to examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainComponent.kt index 86d5990d01..ed8efb8cf6 100644 --- a/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainImpl.kt +++ b/examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainComponent.kt @@ -3,20 +3,24 @@ package example.todo.common.main.integration import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.operator.map +import com.arkivanov.mvikotlin.core.store.StoreFactory +import com.badoo.reaktive.base.Consumer import com.badoo.reaktive.base.invoke import example.todo.common.main.TodoMain -import example.todo.common.main.TodoMain.Dependencies import example.todo.common.main.TodoMain.Model import example.todo.common.main.TodoMain.Output import example.todo.common.main.store.TodoMainStore.Intent import example.todo.common.main.store.TodoMainStoreProvider import example.todo.common.utils.asValue import example.todo.common.utils.getStore +import example.todo.database.TodoDatabase -internal class TodoMainImpl( +class TodoMainComponent( componentContext: ComponentContext, - dependencies: Dependencies -) : TodoMain, ComponentContext by componentContext, Dependencies by dependencies { + storeFactory: StoreFactory, + database: TodoDatabase, + private val output: Consumer +) : TodoMain, ComponentContext by componentContext { private val store = instanceKeeper.getStore { @@ -29,7 +33,7 @@ internal class TodoMainImpl( override val models: Value = store.asValue().map(stateToModel) override fun onItemClicked(id: Long) { - mainOutput(Output.Selected(id = id)) + output(Output.Selected(id = id)) } override fun onItemDoneChanged(id: Long, isDone: Boolean) { diff --git a/examples/todoapp/common/main/src/commonTest/kotlin/example/todo/common/main/integration/TodoMainTest.kt b/examples/todoapp/common/main/src/commonTest/kotlin/example/todo/common/main/integration/TodoMainTest.kt index 711be8b5c4..b57f9e1074 100644 --- a/examples/todoapp/common/main/src/commonTest/kotlin/example/todo/common/main/integration/TodoMainTest.kt +++ b/examples/todoapp/common/main/src/commonTest/kotlin/example/todo/common/main/integration/TodoMainTest.kt @@ -2,9 +2,7 @@ package example.todo.common.main.integration import com.arkivanov.decompose.DefaultComponentContext import com.arkivanov.decompose.lifecycle.LifecycleRegistry -import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory -import com.badoo.reaktive.base.Consumer import com.badoo.reaktive.scheduler.overrideSchedulers import com.badoo.reaktive.subject.publish.PublishSubject import com.badoo.reaktive.test.observable.assertValue @@ -13,7 +11,6 @@ import com.badoo.reaktive.test.scheduler.TestScheduler import example.todo.common.database.TestDatabaseDriver import example.todo.common.database.TodoItemEntity import example.todo.common.main.TodoItem -import example.todo.common.main.TodoMain.Dependencies import example.todo.common.main.TodoMain.Model import example.todo.common.main.TodoMain.Output import example.todo.database.TodoDatabase @@ -35,13 +32,11 @@ class TodoMainTest { private val queries = database.todoDatabaseQueries private val impl by lazy { - TodoMainImpl( + TodoMainComponent( componentContext = DefaultComponentContext(lifecycle = lifecycle), - dependencies = object : Dependencies { - override val storeFactory: StoreFactory = DefaultStoreFactory - override val database: TodoDatabase = this@TodoMainTest.database - override val mainOutput: Consumer = outputSubject - } + storeFactory = DefaultStoreFactory, + database = database, + output = outputSubject ) } diff --git a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt index 156280edc6..867ffcca2c 100644 --- a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt +++ b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt @@ -1,15 +1,9 @@ package example.todo.common.root -import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.RouterState import com.arkivanov.decompose.value.Value -import com.arkivanov.mvikotlin.core.store.StoreFactory -import com.badoo.reaktive.base.Consumer import example.todo.common.edit.TodoEdit import example.todo.common.main.TodoMain -import example.todo.common.root.TodoRoot.Dependencies -import example.todo.common.root.integration.TodoRootImpl -import example.todo.database.TodoDatabase interface TodoRoot { @@ -19,32 +13,4 @@ interface TodoRoot { data class Main(val component: TodoMain) : Child() data class Edit(val component: TodoEdit) : Child() } - - interface Dependencies { - val storeFactory: StoreFactory - val database: TodoDatabase - } } - -@Suppress("FunctionName") // Factory function -fun TodoRoot(componentContext: ComponentContext, dependencies: Dependencies): TodoRoot = - TodoRootImpl( - componentContext = componentContext, - todoMain = { childContext, output -> - TodoMain( - componentContext = childContext, - dependencies = object : TodoMain.Dependencies, Dependencies by dependencies { - override val mainOutput: Consumer = output - } - ) - }, - todoEdit = { childContext, itemId, output -> - TodoEdit( - componentContext = childContext, - dependencies = object : TodoEdit.Dependencies, Dependencies by dependencies { - override val itemId: Long = itemId - override val editOutput: Consumer = output - } - ) - } - ) diff --git a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootComponent.kt similarity index 67% rename from examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt rename to examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootComponent.kt index 9d69e8c542..fef255d9c4 100644 --- a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt +++ b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootComponent.kt @@ -8,19 +8,48 @@ import com.arkivanov.decompose.router import com.arkivanov.decompose.statekeeper.Parcelable import com.arkivanov.decompose.statekeeper.Parcelize import com.arkivanov.decompose.value.Value +import com.arkivanov.mvikotlin.core.store.StoreFactory import com.badoo.reaktive.base.Consumer import example.todo.common.edit.TodoEdit +import example.todo.common.edit.integration.TodoEditComponent import example.todo.common.main.TodoMain +import example.todo.common.main.integration.TodoMainComponent import example.todo.common.root.TodoRoot import example.todo.common.root.TodoRoot.Child import example.todo.common.utils.Consumer +import example.todo.database.TodoDatabase -internal class TodoRootImpl( +class TodoRootComponent internal constructor( componentContext: ComponentContext, private val todoMain: (ComponentContext, Consumer) -> TodoMain, private val todoEdit: (ComponentContext, itemId: Long, Consumer) -> TodoEdit ) : TodoRoot, ComponentContext by componentContext { + constructor( + componentContext: ComponentContext, + storeFactory: StoreFactory, + database: TodoDatabase + ) : this( + componentContext = componentContext, + todoMain = { childContext, output -> + TodoMainComponent( + componentContext = childContext, + storeFactory = storeFactory, + database = database, + output = output + ) + }, + todoEdit = { childContext, itemId, output -> + TodoEditComponent( + componentContext = childContext, + storeFactory = storeFactory, + database = database, + itemId = itemId, + output = output + ) + } + ) + private val router = router( initialConfiguration = Configuration.Main, diff --git a/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt index 1fa2122987..f4a75347e0 100644 --- a/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt +++ b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt @@ -45,7 +45,7 @@ class TodoRootTest { } private fun root(): TodoRoot = - TodoRootImpl( + TodoRootComponent( componentContext = DefaultComponentContext(lifecycle = lifecycle), todoMain = { _, output -> TodoMainFake(output) }, todoEdit = { _, itemId, output -> TodoEditFake(itemId, output) } diff --git a/examples/todoapp/desktop/src/jvmMain/kotlin/example/todo/desktop/Main.kt b/examples/todoapp/desktop/src/jvmMain/kotlin/example/todo/desktop/Main.kt index 64cd6e2a01..44d370d468 100644 --- a/examples/todoapp/desktop/src/jvmMain/kotlin/example/todo/desktop/Main.kt +++ b/examples/todoapp/desktop/src/jvmMain/kotlin/example/todo/desktop/Main.kt @@ -13,6 +13,7 @@ import com.badoo.reaktive.coroutinesinterop.asScheduler import com.badoo.reaktive.scheduler.overrideSchedulers import example.todo.common.database.TodoDatabaseDriver import example.todo.common.root.TodoRoot +import example.todo.common.root.integration.TodoRootComponent import example.todo.common.ui.TodoRootContent import example.todo.database.TodoDatabase import kotlinx.coroutines.Dispatchers @@ -32,10 +33,8 @@ fun main() { } private fun todoRoot(componentContext: ComponentContext): TodoRoot = - TodoRoot( + TodoRootComponent( componentContext = componentContext, - dependencies = object : TodoRoot.Dependencies { - override val storeFactory = DefaultStoreFactory - override val database = TodoDatabase(TodoDatabaseDriver()) - } + storeFactory = DefaultStoreFactory, + database = TodoDatabase(TodoDatabaseDriver()) ) diff --git a/examples/todoapp/ios/ios/ContentView.swift b/examples/todoapp/ios/ios/ContentView.swift index 5f891610a5..52bdc98326 100644 --- a/examples/todoapp/ios/ios/ContentView.swift +++ b/examples/todoapp/ios/ios/ContentView.swift @@ -5,9 +5,10 @@ struct ContentView: View { @State private var componentHolder = ComponentHolder { - TodoRootKt.TodoRoot( + TodoRootComponent( componentContext: $0, - dependencies: RootDependencies() + storeFactory: DefaultStoreFactory(), + database: TodoDatabaseCompanion().invoke(driver: TodoDatabaseDriverFactoryKt.TodoDatabaseDriver()) ) } @@ -18,12 +19,6 @@ struct ContentView: View { } } -private class RootDependencies: TodoRootDependencies { - let database: TodoDatabase = TodoDatabaseCompanion().invoke(driver: TodoDatabaseDriverFactoryKt.TodoDatabaseDriver()) - - let storeFactory: MvikotlinStoreFactory = DefaultStoreFactory() -} - struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView()