Skip to content

Commit

Permalink
Use the model Ref to use all updates
Browse files Browse the repository at this point in the history
  • Loading branch information
davesmith00000 committed Mar 31, 2024
1 parent 78532fe commit 543bb01
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 17 deletions.
37 changes: 22 additions & 15 deletions tyrian/js/src/main/scala/tyrian/runtime/Renderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package tyrian.runtime

import cats.effect.kernel.Async
import cats.effect.kernel.Ref
import cats.effect.syntax.all.*
import cats.effect.std.Dispatcher
import cats.syntax.all.*
import org.scalajs.dom
import snabbdom.VNode
import tyrian.Html
Expand All @@ -26,44 +27,50 @@ object Renderer:
var renderer: Renderer = null
val timeout: Long = 1000

def render[Model, Msg](
model: Model,
def render[F[_], Model, Msg](
dispatcher: Dispatcher[F],
model: Ref[F, Model],
view: Model => Html[Msg],
onMsg: Msg => Unit,
router: Location => Msg
)(t: Long): Unit =
)(t: Long)(using Async[F]): Unit =
if t - renderer.lastTriggered >= timeout then
renderer = renderer.copy(
state = RendererState.Idle,
runningTime = t
)
()
else
renderer = renderer.copy(
vnode = Rendering.render(renderer.vnode, model, view, onMsg, router),
state = RendererState.Running,
runningTime = t
)
dom.window.requestAnimationFrame(_ => render(model, view, onMsg, router)(Date.now().toLong))
()
dispatcher.unsafeRunAndForget {
model.get.map { m =>
renderer = renderer.copy(
vnode = Rendering.render(renderer.vnode, m, view, onMsg, router),
state = RendererState.Running,
runningTime = t
)
dom.window.requestAnimationFrame(_ => render(dispatcher, model, view, onMsg, router)(Date.now().toLong))
()
}
}

// This function gets called on every model update
@SuppressWarnings(Array("scalafix:DisableSyntax.null"))
def redraw[Model, Msg](
def redraw[F[_], Model, Msg](
dispatcher: Dispatcher[F],
r: Renderer,
model: Model,
model: Ref[F, Model],
view: Model => Html[Msg],
onMsg: Msg => Unit,
router: Location => Msg
): Renderer =
)(using Async[F]): Renderer =
// Sadly, needs a null check for as long as I'm using a var to hold the state.
if renderer == null then renderer = r

renderer.state match
case RendererState.Idle =>
// If the render state is idle, begin.
renderer = renderer.copy(lastTriggered = Date.now().toLong)
dom.window.requestAnimationFrame(_ => render(model, view, onMsg, router)(Date.now().toLong))
dom.window.requestAnimationFrame(_ => render(dispatcher, model, view, onMsg, router)(Date.now().toLong))
renderer

case RendererState.Running =>
Expand Down
3 changes: 1 addition & 2 deletions tyrian/js/src/main/scala/tyrian/runtime/TyrianRuntime.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ object TyrianRuntime:
}

_ <- runCmd(cmdsAndSubs._1) *> runSub(cmdsAndSubs._2)
m <- model.get
_ <- renderer.update(r => Renderer.redraw(r, m, view, onMsg, router))
_ <- renderer.update(r => Renderer.redraw(dispatcher, r, model, view, onMsg, router))
} yield ()
}.foreverM

Expand Down

0 comments on commit 543bb01

Please sign in to comment.