mirror of
https://github.com/phfroidmont/scalive.git
synced 2025-12-25 21:46:59 +01:00
Fix splitById
This commit is contained in:
parent
21309629bc
commit
1da129f855
6 changed files with 247 additions and 40 deletions
|
|
@ -10,10 +10,10 @@ enum Diff:
|
|||
dynamic: Seq[Diff.Dynamic] = Seq.empty)
|
||||
case Comprehension(
|
||||
static: Seq[String] = Seq.empty,
|
||||
entries: Seq[Diff.Dynamic] = Seq.empty,
|
||||
entries: Seq[Diff.Dynamic | Diff.IndexChange] = Seq.empty,
|
||||
count: Int = 0)
|
||||
case Value(value: String)
|
||||
case Dynamic(key: String, diff: Diff)
|
||||
case Dynamic(index: Int, diff: Diff)
|
||||
case Deleted
|
||||
|
||||
extension (diff: Diff)
|
||||
|
|
@ -27,6 +27,8 @@ extension (diff: Diff)
|
|||
object Diff:
|
||||
given JsonEncoder[Diff] = JsonEncoder[Json].contramap(toJson(_))
|
||||
|
||||
final case class IndexChange(index: Int, previousIndex: Int)
|
||||
|
||||
private def toJson(diff: Diff): Json =
|
||||
diff match
|
||||
case Diff.Tag(static, dynamic) =>
|
||||
|
|
@ -35,7 +37,7 @@ object Diff:
|
|||
.when(static.nonEmpty)("s" -> Json.Arr(static.map(Json.Str(_))*))
|
||||
.to(Chunk)
|
||||
.appendedAll(
|
||||
dynamic.map(d => d.key -> toJson(d.diff))
|
||||
dynamic.map(d => d.index.toString -> toJson(d.diff))
|
||||
)
|
||||
)
|
||||
case Diff.Comprehension(static, entries, count) =>
|
||||
|
|
@ -47,7 +49,12 @@ object Diff:
|
|||
"k" ->
|
||||
Json
|
||||
.Obj(
|
||||
entries.map(d => d.key -> toJson(d.diff))*
|
||||
entries.map {
|
||||
case Diff.Dynamic(index, diff) =>
|
||||
index.toString -> toJson(diff)
|
||||
case Diff.IndexChange(index, previousIndex) =>
|
||||
index.toString -> Json.Num(previousIndex)
|
||||
}*
|
||||
).add("kc", Json.Num(count))
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ object DiffBuilder:
|
|||
static = static,
|
||||
dynamic =
|
||||
buildDynamic(dynamicMods, trackUpdates).zipWithIndex.collect { case (Some(diff), index) =>
|
||||
Diff.Dynamic(index.toString, diff)
|
||||
Diff.Dynamic(index, diff)
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -47,15 +47,24 @@ object DiffBuilder:
|
|||
case Some((entries, keysCount, includeStatics)) =>
|
||||
val static =
|
||||
if !trackUpdates || includeStatics then
|
||||
entries.collectFirst { case (_, el) => el.static }.getOrElse(List.empty)
|
||||
entries.collectFirst { case (_, _, el) => el.static }.getOrElse(List.empty)
|
||||
else List.empty
|
||||
List(
|
||||
Some(
|
||||
Diff.Comprehension(
|
||||
static = static,
|
||||
entries = entries.map((key, el) =>
|
||||
Diff.Dynamic(key.toString, build(Seq.empty, el.dynamicMods, trackUpdates))
|
||||
),
|
||||
entries = entries.map {
|
||||
case entry @ (previousIndex = None) =>
|
||||
Diff.Dynamic(
|
||||
entry.index,
|
||||
build(Seq.empty, entry.value.dynamicMods, trackUpdates)
|
||||
)
|
||||
case (index, Some(previousIndex), _) =>
|
||||
Diff.IndexChange(
|
||||
index,
|
||||
previousIndex
|
||||
)
|
||||
},
|
||||
count = keysCount
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -99,11 +99,14 @@ private class SplitVar[I, O, Key](
|
|||
private val memoized: mutable.Map[Key, (Var[I], O)] =
|
||||
mutable.Map.empty
|
||||
|
||||
private var previousKeysToIndex: Map[Key, Int] = Map.empty
|
||||
|
||||
private var nonEmptySyncCount = 0
|
||||
|
||||
private[scalive] def sync(): Unit =
|
||||
parent.sync()
|
||||
if parent.changed then
|
||||
previousKeysToIndex = memoized.keys.zipWithIndex.toMap
|
||||
// We keep track of the keys to remove deleted ones afterwards
|
||||
val nextKeys = mutable.HashSet.empty[Key]
|
||||
parent.currentValue.foreach(input =>
|
||||
|
|
@ -126,15 +129,25 @@ private class SplitVar[I, O, Key](
|
|||
)
|
||||
if memoized.nonEmpty then nonEmptySyncCount += 1
|
||||
|
||||
private[scalive] def render(trackUpdates: Boolean)
|
||||
: Option[(changeList: List[(Int, O)], keysCount: Int, includeStatics: Boolean)] =
|
||||
private[scalive] def render(trackUpdates: Boolean): Option[
|
||||
(
|
||||
changeList: List[(index: Int, previousIndex: Option[Int], value: O)],
|
||||
keysCount: Int,
|
||||
includeStatics: Boolean
|
||||
)
|
||||
] =
|
||||
if parent.changed || !trackUpdates then
|
||||
Some(
|
||||
(
|
||||
changeList = memoized.values.zipWithIndex.collect {
|
||||
case ((entryVar, output), index) if !trackUpdates || entryVar.changed =>
|
||||
(index, output)
|
||||
}.toList,
|
||||
changeList = memoized.zipWithIndex
|
||||
.map { case ((key, (entryVar, output)), index) =>
|
||||
(index, previousKeysToIndex.get(key).filterNot(_ == index), entryVar, output)
|
||||
}
|
||||
.collect {
|
||||
case (index, previousIndex, entryVar, output)
|
||||
if !trackUpdates || entryVar.changed || previousIndex.isDefined =>
|
||||
(index, previousIndex, output)
|
||||
}.toList,
|
||||
keysCount = memoized.size,
|
||||
includeStatics = nonEmptySyncCount == 1
|
||||
)
|
||||
|
|
|
|||
|
|
@ -36,10 +36,8 @@ object HtmlBuilder:
|
|||
case Content.DynElementColl(dyn) => ???
|
||||
case Content.DynSplit(splitVar) =>
|
||||
val (entries, _, _) = splitVar.render(false).getOrElse((List.empty, 0, true))
|
||||
val staticOpt = entries.collectFirst { case (_, el) => el.static }
|
||||
entries.foreach((_, entryEl) =>
|
||||
build(staticOpt.getOrElse(Nil), entryEl.dynamicMods, strw)
|
||||
)
|
||||
val staticOpt = entries.collectFirst { case (value = el) => el.static }
|
||||
entries.foreach(entry => build(staticOpt.getOrElse(Nil), entry.value.dynamicMods, strw))
|
||||
strw.write(static.last)
|
||||
|
||||
end HtmlBuilder
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue