Browse Source

TodoApp. Get rid of Dependencies interfaces. (#480)

pull/500/head
Arkadii Ivanov 4 years ago committed by GitHub
parent
commit
8d6be48499
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      examples/todoapp/android/src/main/java/example/todo/android/MainActivity.kt
  2. 17
      examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/TodoEdit.kt
  3. 15
      examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditComponent.kt
  4. 16
      examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/TodoMain.kt
  5. 14
      examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainComponent.kt
  6. 13
      examples/todoapp/common/main/src/commonTest/kotlin/example/todo/common/main/integration/TodoMainTest.kt
  7. 34
      examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt
  8. 31
      examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootComponent.kt
  9. 2
      examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt
  10. 9
      examples/todoapp/desktop/src/jvmMain/kotlin/example/todo/desktop/Main.kt
  11. 11
      examples/todoapp/ios/ios/ContentView.swift

11
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 androidx.compose.material.Surface
import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.jetbrains.rememberRootComponent 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.logging.store.LoggingStoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.arkivanov.mvikotlin.timetravel.store.TimeTravelStoreFactory import com.arkivanov.mvikotlin.timetravel.store.TimeTravelStoreFactory
import example.todo.common.database.TodoDatabaseDriver import example.todo.common.database.TodoDatabaseDriver
import example.todo.common.root.TodoRoot import example.todo.common.root.TodoRoot
import example.todo.common.root.integration.TodoRootComponent
import example.todo.common.ui.TodoRootContent import example.todo.common.ui.TodoRootContent
import example.todo.database.TodoDatabase import example.todo.database.TodoDatabase
@ -30,12 +30,9 @@ class MainActivity : AppCompatActivity() {
} }
private fun todoRoot(componentContext: ComponentContext): TodoRoot = private fun todoRoot(componentContext: ComponentContext): TodoRoot =
TodoRoot( TodoRootComponent(
componentContext = componentContext, componentContext = componentContext,
dependencies = object : TodoRoot.Dependencies { storeFactory = LoggingStoreFactory(TimeTravelStoreFactory(DefaultStoreFactory)),
// You can play with time travel using IDEA plugin: https://arkivanov.github.io/MVIKotlin/time_travel.html database = TodoDatabase(TodoDatabaseDriver(context = this))
override val storeFactory: StoreFactory = LoggingStoreFactory(TimeTravelStoreFactory(DefaultStoreFactory))
override val database: TodoDatabase = TodoDatabase(TodoDatabaseDriver(this@MainActivity))
}
) )
} }

17
examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/TodoEdit.kt

@ -1,12 +1,6 @@
package example.todo.common.edit package example.todo.common.edit
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.value.Value 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 { interface TodoEdit {
@ -23,18 +17,7 @@ interface TodoEdit {
val isDone: Boolean val isDone: Boolean
) )
interface Dependencies {
val storeFactory: StoreFactory
val database: TodoDatabase
val itemId: Long
val editOutput: Consumer<Output>
}
sealed class Output { sealed class Output {
object Finished : Output() object Finished : Output()
} }
} }
@Suppress("FunctionName") // Factory function
fun TodoEdit(componentContext: ComponentContext, dependencies: Dependencies): TodoEdit =
TodoEditImpl(componentContext, dependencies)

15
examples/todoapp/common/edit/src/commonMain/kotlin/example/todo/common/edit/integration/TodoEditImpl.kt → 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.ComponentContext
import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.Value
import com.arkivanov.decompose.value.operator.map 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 com.badoo.reaktive.base.invoke
import example.todo.common.edit.TodoEdit 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.Model
import example.todo.common.edit.TodoEdit.Output import example.todo.common.edit.TodoEdit.Output
import example.todo.common.edit.store.TodoEditStore.Intent import example.todo.common.edit.store.TodoEditStore.Intent
import example.todo.common.edit.store.TodoEditStoreProvider import example.todo.common.edit.store.TodoEditStoreProvider
import example.todo.common.utils.asValue import example.todo.common.utils.asValue
import example.todo.common.utils.getStore import example.todo.common.utils.getStore
import example.todo.database.TodoDatabase
internal class TodoEditImpl( class TodoEditComponent(
componentContext: ComponentContext, componentContext: ComponentContext,
dependencies: Dependencies storeFactory: StoreFactory,
) : TodoEdit, ComponentContext by componentContext, Dependencies by dependencies { database: TodoDatabase,
itemId: Long,
private val output: Consumer<Output>
) : TodoEdit, ComponentContext by componentContext {
private val store = private val store =
instanceKeeper.getStore { instanceKeeper.getStore {
@ -38,6 +43,6 @@ internal class TodoEditImpl(
} }
override fun onCloseClicked() { override fun onCloseClicked() {
editOutput(Output.Finished) output(Output.Finished)
} }
} }

16
examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/TodoMain.kt

@ -1,12 +1,6 @@
package example.todo.common.main package example.todo.common.main
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.value.Value 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 { interface TodoMain {
@ -27,17 +21,7 @@ interface TodoMain {
val text: String val text: String
) )
interface Dependencies {
val storeFactory: StoreFactory
val database: TodoDatabase
val mainOutput: Consumer<Output>
}
sealed class Output { sealed class Output {
data class Selected(val id: Long) : Output() data class Selected(val id: Long) : Output()
} }
} }
@Suppress("FunctionName") // Factory function
fun TodoMain(componentContext: ComponentContext, dependencies: Dependencies): TodoMain =
TodoMainImpl(componentContext, dependencies)

14
examples/todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainImpl.kt → 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.ComponentContext
import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.Value
import com.arkivanov.decompose.value.operator.map 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 com.badoo.reaktive.base.invoke
import example.todo.common.main.TodoMain 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.Model
import example.todo.common.main.TodoMain.Output import example.todo.common.main.TodoMain.Output
import example.todo.common.main.store.TodoMainStore.Intent import example.todo.common.main.store.TodoMainStore.Intent
import example.todo.common.main.store.TodoMainStoreProvider import example.todo.common.main.store.TodoMainStoreProvider
import example.todo.common.utils.asValue import example.todo.common.utils.asValue
import example.todo.common.utils.getStore import example.todo.common.utils.getStore
import example.todo.database.TodoDatabase
internal class TodoMainImpl( class TodoMainComponent(
componentContext: ComponentContext, componentContext: ComponentContext,
dependencies: Dependencies storeFactory: StoreFactory,
) : TodoMain, ComponentContext by componentContext, Dependencies by dependencies { database: TodoDatabase,
private val output: Consumer<Output>
) : TodoMain, ComponentContext by componentContext {
private val store = private val store =
instanceKeeper.getStore { instanceKeeper.getStore {
@ -29,7 +33,7 @@ internal class TodoMainImpl(
override val models: Value<Model> = store.asValue().map(stateToModel) override val models: Value<Model> = store.asValue().map(stateToModel)
override fun onItemClicked(id: Long) { override fun onItemClicked(id: Long) {
mainOutput(Output.Selected(id = id)) output(Output.Selected(id = id))
} }
override fun onItemDoneChanged(id: Long, isDone: Boolean) { override fun onItemDoneChanged(id: Long, isDone: Boolean) {

13
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.DefaultComponentContext
import com.arkivanov.decompose.lifecycle.LifecycleRegistry import com.arkivanov.decompose.lifecycle.LifecycleRegistry
import com.arkivanov.mvikotlin.core.store.StoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.badoo.reaktive.base.Consumer
import com.badoo.reaktive.scheduler.overrideSchedulers import com.badoo.reaktive.scheduler.overrideSchedulers
import com.badoo.reaktive.subject.publish.PublishSubject import com.badoo.reaktive.subject.publish.PublishSubject
import com.badoo.reaktive.test.observable.assertValue 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.TestDatabaseDriver
import example.todo.common.database.TodoItemEntity import example.todo.common.database.TodoItemEntity
import example.todo.common.main.TodoItem 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.Model
import example.todo.common.main.TodoMain.Output import example.todo.common.main.TodoMain.Output
import example.todo.database.TodoDatabase import example.todo.database.TodoDatabase
@ -35,13 +32,11 @@ class TodoMainTest {
private val queries = database.todoDatabaseQueries private val queries = database.todoDatabaseQueries
private val impl by lazy { private val impl by lazy {
TodoMainImpl( TodoMainComponent(
componentContext = DefaultComponentContext(lifecycle = lifecycle), componentContext = DefaultComponentContext(lifecycle = lifecycle),
dependencies = object : Dependencies { storeFactory = DefaultStoreFactory,
override val storeFactory: StoreFactory = DefaultStoreFactory database = database,
override val database: TodoDatabase = this@TodoMainTest.database output = outputSubject
override val mainOutput: Consumer<Output> = outputSubject
}
) )
} }

34
examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt

@ -1,15 +1,9 @@
package example.todo.common.root package example.todo.common.root
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.RouterState import com.arkivanov.decompose.RouterState
import com.arkivanov.decompose.value.Value 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.TodoEdit
import example.todo.common.main.TodoMain 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 { interface TodoRoot {
@ -19,32 +13,4 @@ interface TodoRoot {
data class Main(val component: TodoMain) : Child() data class Main(val component: TodoMain) : Child()
data class Edit(val component: TodoEdit) : 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<TodoMain.Output> = output
}
)
},
todoEdit = { childContext, itemId, output ->
TodoEdit(
componentContext = childContext,
dependencies = object : TodoEdit.Dependencies, Dependencies by dependencies {
override val itemId: Long = itemId
override val editOutput: Consumer<TodoEdit.Output> = output
}
)
}
)

31
examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt → 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.Parcelable
import com.arkivanov.decompose.statekeeper.Parcelize import com.arkivanov.decompose.statekeeper.Parcelize
import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.Value
import com.arkivanov.mvikotlin.core.store.StoreFactory
import com.badoo.reaktive.base.Consumer import com.badoo.reaktive.base.Consumer
import example.todo.common.edit.TodoEdit import example.todo.common.edit.TodoEdit
import example.todo.common.edit.integration.TodoEditComponent
import example.todo.common.main.TodoMain 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
import example.todo.common.root.TodoRoot.Child import example.todo.common.root.TodoRoot.Child
import example.todo.common.utils.Consumer import example.todo.common.utils.Consumer
import example.todo.database.TodoDatabase
internal class TodoRootImpl( class TodoRootComponent internal constructor(
componentContext: ComponentContext, componentContext: ComponentContext,
private val todoMain: (ComponentContext, Consumer<TodoMain.Output>) -> TodoMain, private val todoMain: (ComponentContext, Consumer<TodoMain.Output>) -> TodoMain,
private val todoEdit: (ComponentContext, itemId: Long, Consumer<TodoEdit.Output>) -> TodoEdit private val todoEdit: (ComponentContext, itemId: Long, Consumer<TodoEdit.Output>) -> TodoEdit
) : TodoRoot, ComponentContext by componentContext { ) : 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 = private val router =
router<Configuration, Child>( router<Configuration, Child>(
initialConfiguration = Configuration.Main, initialConfiguration = Configuration.Main,

2
examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt

@ -45,7 +45,7 @@ class TodoRootTest {
} }
private fun root(): TodoRoot = private fun root(): TodoRoot =
TodoRootImpl( TodoRootComponent(
componentContext = DefaultComponentContext(lifecycle = lifecycle), componentContext = DefaultComponentContext(lifecycle = lifecycle),
todoMain = { _, output -> TodoMainFake(output) }, todoMain = { _, output -> TodoMainFake(output) },
todoEdit = { _, itemId, output -> TodoEditFake(itemId, output) } todoEdit = { _, itemId, output -> TodoEditFake(itemId, output) }

9
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 com.badoo.reaktive.scheduler.overrideSchedulers
import example.todo.common.database.TodoDatabaseDriver import example.todo.common.database.TodoDatabaseDriver
import example.todo.common.root.TodoRoot import example.todo.common.root.TodoRoot
import example.todo.common.root.integration.TodoRootComponent
import example.todo.common.ui.TodoRootContent import example.todo.common.ui.TodoRootContent
import example.todo.database.TodoDatabase import example.todo.database.TodoDatabase
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -32,10 +33,8 @@ fun main() {
} }
private fun todoRoot(componentContext: ComponentContext): TodoRoot = private fun todoRoot(componentContext: ComponentContext): TodoRoot =
TodoRoot( TodoRootComponent(
componentContext = componentContext, componentContext = componentContext,
dependencies = object : TodoRoot.Dependencies { storeFactory = DefaultStoreFactory,
override val storeFactory = DefaultStoreFactory database = TodoDatabase(TodoDatabaseDriver())
override val database = TodoDatabase(TodoDatabaseDriver())
}
) )

11
examples/todoapp/ios/ios/ContentView.swift

@ -5,9 +5,10 @@ struct ContentView: View {
@State @State
private var componentHolder = private var componentHolder =
ComponentHolder { ComponentHolder {
TodoRootKt.TodoRoot( TodoRootComponent(
componentContext: $0, 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 { struct ContentView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
ContentView() ContentView()

Loading…
Cancel
Save