Use Dyn as key for LiveState

This commit is contained in:
Paul-Henri Froidmont 2025-08-18 04:52:07 +02:00
parent 57f43a0780
commit 8f19ccfbb4
Signed by: phfroidmont
GPG key ID: BE948AFD7E7873BE
6 changed files with 19 additions and 19 deletions

View file

@ -6,9 +6,9 @@ final case class Elem(name: String, age: Int)
class TestView extends LiveView[TestView.Cmd]: class TestView extends LiveView[TestView.Cmd]:
import TestView.Cmd.* import TestView.Cmd.*
private val textCls = LiveState.Key[String] private val textCls = Dyn[String]
private val someBool = LiveState.Key[Boolean] private val someBool = Dyn[Boolean]
private val elems = LiveState.Key[List[Elem]] private val elems = Dyn[List[Elem]]
def mount(state: LiveState): LiveState = def mount(state: LiveState): LiveState =
state state

View file

@ -40,7 +40,7 @@ object Fingerprint:
case Mod.DynAttrValueAsPresence(_, _) => md.update(Fingerprint.dynAttrValueAsPresence) case Mod.DynAttrValueAsPresence(_, _) => md.update(Fingerprint.dynAttrValueAsPresence)
case Mod.DynText(_) => md.update(Fingerprint.dynText) case Mod.DynText(_) => md.update(Fingerprint.dynText)
case Mod.When(_, _) => md.update(Fingerprint.dynWhen) case Mod.When(_, _) => md.update(Fingerprint.dynWhen)
case Mod.Split(_, project) => md.update(digest(project(Dyn.dummy))) case Mod.Split(_, project) => md.update(digest(project(Dyn.apply)))
case Mod.Tag(el) => Right(digest(el)) case Mod.Tag(el) => Right(digest(el))
} }
md.digest() md.digest()

View file

@ -41,7 +41,7 @@ enum Mod:
dynList: Dyn[List[T]], dynList: Dyn[List[T]],
project: Dyn[T] => HtmlElement) project: Dyn[T] => HtmlElement)
final case class Dyn[T](key: LiveState.Key, f: key.Type => T): final case class Dyn[T] private[scalive] (key: LiveState.Key, f: key.Type => T):
def render(state: LiveState, trackUpdates: Boolean): Option[T] = def render(state: LiveState, trackUpdates: Boolean): Option[T] =
val entry = state(key) val entry = state(key)
if !trackUpdates | entry.changed then Some(f(entry.value)) if !trackUpdates | entry.changed then Some(f(entry.value))
@ -61,4 +61,4 @@ extension [T](dyn: Dyn[List[T]])
Mod.Split(dyn, project) Mod.Split(dyn, project)
object Dyn: object Dyn:
def dummy[T] = Dyn(LiveState.Key[T], identity) def apply[T]: Dyn[T] = Dyn(LiveState.Key[T], identity)

View file

@ -3,9 +3,10 @@ package scalive
final case class LiveState private (val data: Map[LiveState.Key, LiveState.Entry[Any]]): final case class LiveState private (val data: Map[LiveState.Key, LiveState.Entry[Any]]):
def get(k: LiveState.Key): Option[LiveState.Entry[k.Type]] = def get(k: LiveState.Key): Option[LiveState.Entry[k.Type]] =
data.get(k).asInstanceOf[Option[LiveState.Entry[k.Type]]] data.get(k).asInstanceOf[Option[LiveState.Entry[k.Type]]]
def set(k: LiveState.Key, v: k.Type): LiveState = def set[T](k: Dyn[T], v: T): LiveState =
copy(data = data.updated(k, LiveState.Entry(true, v))) copy(data = data.updated(k.key, LiveState.Entry(true, v)))
def apply(k: LiveState.Key): LiveState.Entry[k.Type] = get(k).get def apply(k: LiveState.Key): LiveState.Entry[k.Type] =
get(k).getOrElse(throw new IllegalArgumentException("An assign of type"))
def update(k: LiveState.Key, update: k.Type => k.Type): LiveState = def update(k: LiveState.Key, update: k.Type => k.Type): LiveState =
copy(data = copy(data =
data.updatedWith(k)( data.updatedWith(k)(
@ -24,8 +25,8 @@ object LiveState:
class Key: class Key:
type Type type Type
def id: Dyn[Type] = Dyn(this, identity) def toDyn: Dyn[Type] = Dyn(this, identity)
def apply[T](f: Type => T): Dyn[T] = Dyn(this, f) def toDyn[T](f: Type => T): Dyn[T] = Dyn(this, f)
object Key: object Key:
def apply[T] = new Key: def apply[T] = new Key:
type Type = T type Type = T

View file

@ -41,14 +41,14 @@ object Rendered:
.render(state, trackUpdates) .render(state, trackUpdates)
.collect { .collect {
case items if items.nonEmpty => case items if items.nonEmpty =>
val el = mod.project(Dyn.dummy) val el = mod.project(Dyn.apply)
Comprehension( Comprehension(
Fingerprint.apply(el), Fingerprint.apply(el),
el.static, el.static,
items.map(item => items.map(item =>
val localKey = LiveState.Key[Any] val localDyn = Dyn[Any]
val localState = LiveState.empty.set(localKey, item) val localState = LiveState.empty.set(localDyn, item)
val localElem = mod.project(localKey.id) val localElem = mod.project(localDyn)
trackElemUpdates => trackElemUpdates =>
buildDynamicRendered(localElem, localState).map(_(trackElemUpdates)) buildDynamicRendered(localElem, localState).map(_(trackElemUpdates))
) )

View file

@ -6,4 +6,3 @@ package object scalive extends HtmlTags with HtmlAttrs with ComplexHtmlKeys:
implicit def stringToMod(v: String): Mod = Mod.Text(v) implicit def stringToMod(v: String): Mod = Mod.Text(v)
implicit def htmlElementToMod(el: HtmlElement): Mod = Mod.Tag(el) implicit def htmlElementToMod(el: HtmlElement): Mod = Mod.Tag(el)
implicit def dynStringToMod(d: Dyn[String]): Mod = Mod.DynText(d) implicit def dynStringToMod(d: Dyn[String]): Mod = Mod.DynText(d)
implicit def keyToDyn(k: LiveState.Key): Dyn[k.Type] = k.id