Skip to content

Instantly share code, notes, and snippets.

@hikaMaeng
Created June 22, 2024 08:41
Show Gist options
  • Save hikaMaeng/5e3555e821ee4cd45cbb5a9d1e15e4ef to your computer and use it in GitHub Desktop.
Save hikaMaeng/5e3555e821ee4cd45cbb5a9d1e15e4ef to your computer and use it in GitHub Desktop.
@file:Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
package kore.vo
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.mapSaver
import androidx.compose.runtime.saveable.rememberSaveable
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
abstract class StateVO<T:StateVO<T>>:VO(){
companion object{
@Composable
inline operator fun <reified T:StateVO<T>> invoke(block:T.()->Unit):T{
val toggle = rememberSaveable{mutableStateOf(true)}
val modelState = rememberSaveable(stateSaver = saver(T::class)){mutableStateOf(null)}
val model = modelState.value ?: T::class.java.getDeclaredConstructor().newInstance().init(modelState as MutableState<T?>, block)
model.stateToggle = toggle
toggle.value
return model as T
}
@PublishedApi internal val savers = hashMapOf<KClass<out StateVO<*>>, Saver<StateVO<*>?, Any>>()
@PublishedApi internal inline fun saver(type:KClass<out StateVO<*>>):Saver<StateVO<*>?, Any> = savers.getOrPut(type) {
mapSaver({it?.props ?: emptyMap()}){
type.java.getDeclaredConstructor().newInstance().apply{
(props as HashMap<String, Any?>).putAll(it)
stateToggle?.value = stateToggle?.value != true
}
}
}
}
@PublishedApi internal var stateToggle:MutableState<Boolean>? = null
inline fun init(model:MutableState<T?>, block:T.()->Unit = {}):T
= (this as T).also{
block()
model.value = it
}
final override fun afterSet(key:String, value:Any){
stateToggle?.value = stateToggle?.value != true
}
class StateValue<V>(private val vo:StateVO<*>, private val prop:String){
operator fun invoke(value:V){
vo[prop] = value as Any
}
operator fun invoke():V = vo[prop] as V
@get:Composable
val state:State<V> get() = rememberUpdatedState(vo[prop] as V)
}
inline fun <V> value(prop:KProperty1<T, V>):StateValue<V>
= StateValue(this, prop.name)
@Composable
inline fun <V> state(prop:KProperty1<T, V>):State<V>
= rememberUpdatedState(this[prop.name] as V)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment