
commonMain.ru.alexey.event.threads.navgraph.Screen.kt Maven / Gradle / Ivy
package ru.alexey.event.threads.navgraph
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import kotlinx.coroutines.flow.StateFlow
import ru.alexey.event.threads.LocalScope
import ru.alexey.event.threads.datacontainer.Datacontainer
import ru.alexey.event.threads.utils.ListBuilder
import ru.alexey.event.threads.resources.Parameters
import ru.alexey.event.threads.scope
import ru.alexey.event.threads.widget.Widget
import ru.alexey.event.threads.widget.widget
import kotlin.properties.ReadOnlyProperty
import kotlin.random.Random
import kotlin.reflect.KClass
class ScreenBuilder {
private val widgets: MutableMap = mutableMapOf()
private var content: @Composable Parameters.(Map) -> Unit = {}
private var key: String = Random.nextBytes(32).decodeToString()
private val required: MutableList> = mutableListOf()
fun registerWidget(name: String, block: () -> Widget) {
widgets[name] = block()
}
fun registerWidget(name: String, widget: Widget) {
widgets[name] = widget
}
inline fun registerWidget(
name: String,
crossinline content: @Composable (modifier: Modifier) -> Unit
) {
registerWidget(name, block = {
object : Widget {
override val name: String = name
@Composable
override fun Content(modifier: Modifier) {
scope(name) {
content(modifier)
}
}
}
})
}
inline fun registerWidget(
name: String,
crossinline content: @Composable (T, Modifier) -> Unit
) {
registerWidget(name, block = {
object : Widget {
override val name: String = name
@Composable
override fun Content(modifier: Modifier) {
scope(name) {
widget(T::class) {
content(it, modifier)
}
}
}
}
})
}
inline fun registerWidget(noinline block: () -> Widget) {
val widget = block()
registerWidget(widget.name, widget)
}
fun content(content: @Composable Parameters.(Map) -> Unit) {
this.content = content
}
fun key(key: String) {
this.key = key
}
fun key(block: () -> String) {
this.key = block()
}
fun require(required: KClass) {
this.required.add(required)
}
fun require(required: List>) {
this.required.addAll(required)
}
fun require(block: ListBuilder>.() -> Unit) {
this.required.addAll(
ListBuilder>().apply(block).invoke()
)
}
operator fun invoke() = Screen(required, widgets, content, key)
}
class Screen(
private val required: List>,
private val widgets: Map,
private val content: @Composable Parameters.(Map) -> Unit,
val key: String
) : Comparable {
override fun compareTo(other: Screen): Int {
return key.compareTo(other.key)
}
fun checkParams(params: Parameters) {
require(params.size == this.required.size) { "Incorrect number of params" }
params.keys.forEach {
require(it in this.required) { "Incorrect param type! Expect: ${it.simpleName}" }
}
}
@Composable
operator fun invoke(parameters: () -> Parameters) {
with(parameters()) {
content(widgets)
}
}
@Composable
infix fun renderWith(parameters: () -> Parameters) {
with(parameters()) {
content(widgets)
}
}
}
inline fun widget(
name: String? = null,
crossinline content: @Composable (T, Modifier) -> Unit
): ReadOnlyProperty {
return ReadOnlyProperty { thiRef: Any?, property ->
object : Widget {
override val name: String = name ?: property.name
@Composable
override fun Content(modifier: Modifier) {
scope(name ?: property.name) {
val dc: StateFlow by LocalScope.current
val state by dc.collectAsState()
content(state, modifier)
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy