From a00cbfc7afbf6bd0532a3daa94c24a45deda8aa8 Mon Sep 17 00:00:00 2001 From: stevechy Date: Tue, 16 May 2023 09:18:49 -0600 Subject: [PATCH] #198 : Update launch method name and signature. Add TyrianApp companion objects. --- examples/main-launcher/index.html | 1 - .../src/main/scala/example/ChatApp.scala | 5 +++++ .../src/main/scala/example/CounterApp.scala | 6 +++++- .../src/main/scala/example/Main.scala | 9 ++++----- .../src/main/scala/tyrian/TyrianApp.scala | 8 ++++++++ .../src/main/scala/tyrian/TyrianApp.scala | 8 ++++++++ .../js/src/main/scala/tyrian/TyrianAppF.scala | 19 +++++++++---------- 7 files changed, 39 insertions(+), 17 deletions(-) diff --git a/examples/main-launcher/index.html b/examples/main-launcher/index.html index 0d93745b..c4d9bfaa 100644 --- a/examples/main-launcher/index.html +++ b/examples/main-launcher/index.html @@ -10,7 +10,6 @@

Main launcher example

-
diff --git a/examples/main-launcher/src/main/scala/example/ChatApp.scala b/examples/main-launcher/src/main/scala/example/ChatApp.scala index 2f0ff9f1..5b24a7b9 100644 --- a/examples/main-launcher/src/main/scala/example/ChatApp.scala +++ b/examples/main-launcher/src/main/scala/example/ChatApp.scala @@ -16,6 +16,7 @@ object ChatApp extends TyrianApp[ChatAppMsg, ChatAppModel]: def update(model: ChatAppModel): ChatAppMsg => (ChatAppModel, Cmd[IO, ChatAppMsg]) = case ChatInput(input) => (model.copy(chatInput = input), Cmd.None) case SendChat() => (model.copy(chatInput = "", messages = model.messages :+ model.chatInput), Cmd.None) + case RouteMsg() => (model, Cmd.None) def view(model: ChatAppModel): Html[ChatAppMsg] = div( @@ -27,12 +28,16 @@ object ChatApp extends TyrianApp[ChatAppMsg, ChatAppModel]: button(onClick(SendChat()))("Send Chat") ) + def router: Location => ChatAppMsg = + _ => RouteMsg() + def subscriptions(model: ChatAppModel): Sub[IO, ChatAppMsg] = Sub.None case class ChatAppModel(chatInput: String, messages: Seq[String]) sealed abstract class ChatAppMsg +case class RouteMsg() extends ChatAppMsg case class ChatInput(input: String) extends ChatAppMsg case class SendChat() extends ChatAppMsg diff --git a/examples/main-launcher/src/main/scala/example/CounterApp.scala b/examples/main-launcher/src/main/scala/example/CounterApp.scala index 9169c248..955c9bc3 100644 --- a/examples/main-launcher/src/main/scala/example/CounterApp.scala +++ b/examples/main-launcher/src/main/scala/example/CounterApp.scala @@ -19,6 +19,7 @@ object CounterApp extends TyrianApp[Msg, Model]: def update(model: Model): Msg => (Model, Cmd[IO, Msg]) = case Msg.Increment => (model + 1, Cmd.None) case Msg.Decrement => (model - 1, Cmd.None) + case Msg.RouteMsg => (model, Cmd.None) def view(model: Model): Html[Msg] = div( @@ -27,6 +28,9 @@ object CounterApp extends TyrianApp[Msg, Model]: button(onClick(Msg.Increment))("+") ) + def router: Location => Msg = + _ => Msg.RouteMsg + def subscriptions(model: Model): Sub[IO, Msg] = Sub.None @@ -39,4 +43,4 @@ object Model: def -(other: Int): Model = i - other enum Msg: - case Increment, Decrement + case Increment, Decrement, RouteMsg diff --git a/examples/main-launcher/src/main/scala/example/Main.scala b/examples/main-launcher/src/main/scala/example/Main.scala index 9ee01de2..a726eb14 100644 --- a/examples/main-launcher/src/main/scala/example/Main.scala +++ b/examples/main-launcher/src/main/scala/example/Main.scala @@ -6,9 +6,8 @@ import tyrian.* object Main { def main(args: Array[String]): Unit = - TyrianAppF.launchOnContentLoaded(Map( - "CounterApp" -> (() => CounterApp), - "ChatApp" -> (() => ChatApp) - )) - println("") + TyrianApp.onLoad( + "CounterApp" -> CounterApp, + "ChatApp" -> ChatApp + ) } \ No newline at end of file diff --git a/tyrian-io/src/main/scala/tyrian/TyrianApp.scala b/tyrian-io/src/main/scala/tyrian/TyrianApp.scala index 89d7501f..696d339a 100644 --- a/tyrian-io/src/main/scala/tyrian/TyrianApp.scala +++ b/tyrian-io/src/main/scala/tyrian/TyrianApp.scala @@ -1,6 +1,7 @@ package tyrian import cats.effect.IO +import cats.effect.kernel.Async import cats.effect.kernel.Resource import cats.effect.unsafe.implicits.global import tyrian.TyrianAppF @@ -13,3 +14,10 @@ trait TyrianApp[Msg, Model] extends TyrianAppF[IO, Msg, Model]: val run: Resource[IO, TyrianRuntime[IO, Model, Msg]] => Unit = _.map(_.start()).useForever.unsafeRunAndForget() + +object TyrianApp: + def onLoad[F[_] : Async](appDirectory: (String, TyrianAppF[F, _, _])*): Unit = + TyrianAppF.onLoad(appDirectory: _*) + + def launch[F[_] : Async](appDirectory: (String, TyrianAppF[F, _, _])*): Unit = + TyrianAppF.launch(appDirectory: _*) diff --git a/tyrian-zio/src/main/scala/tyrian/TyrianApp.scala b/tyrian-zio/src/main/scala/tyrian/TyrianApp.scala index 591bda77..be2042be 100644 --- a/tyrian-zio/src/main/scala/tyrian/TyrianApp.scala +++ b/tyrian-zio/src/main/scala/tyrian/TyrianApp.scala @@ -1,6 +1,7 @@ package tyrian import cats.effect.Async +import cats.effect.kernel.Async import cats.effect.kernel.Resource import tyrian.TyrianAppF import tyrian.runtime.TyrianRuntime @@ -20,3 +21,10 @@ trait TyrianApp[Msg, Model](using Async[Task]) extends TyrianAppF[Task, Msg, Mod Unsafe.unsafe { implicit unsafe => runtime.unsafe.run(runnable).getOrThrowFiberFailure() } + +object TyrianApp: + def onLoad[F[_] : Async](appDirectory: (String, TyrianAppF[F, _, _])*): Unit = + TyrianAppF.onLoad(appDirectory: _*) + + def launch[F[_] : Async](appDirectory: (String, TyrianAppF[F, _, _])*): Unit = + TyrianAppF.launch(appDirectory: _*) diff --git a/tyrian/js/src/main/scala/tyrian/TyrianAppF.scala b/tyrian/js/src/main/scala/tyrian/TyrianAppF.scala index aa4324ec..e5e66c68 100644 --- a/tyrian/js/src/main/scala/tyrian/TyrianAppF.scala +++ b/tyrian/js/src/main/scala/tyrian/TyrianAppF.scala @@ -134,7 +134,7 @@ trait TyrianAppF[F[_]: Async, Msg, Model]: object TyrianAppF: /** Launch app instances after DOMContentLoaded. */ - def launchOnContentLoaded[F[_] : Async](appDirectory: Map[String, () => TyrianAppF[F, _, _]]): Unit = { + def onLoad[F[_] : Async](appDirectory: (String, TyrianAppF[F, _, _])*): Unit = val documentReady = new Promise((resolve, _reject) => { document.addEventListener("DOMContentLoaded", _ => { resolve(()) @@ -144,29 +144,28 @@ object TyrianAppF: } }) documentReady.`then`(_ => { - launch[F](appDirectory) + launch[F](appDirectory: _*) }) - } /** Find data-tyrian-app HTMLElements and launch corresponding TyrianAppF instances */ - def launch[F[_] : Async](appDirectory: Map[String, () => TyrianAppF[F, _, _]]): Unit = { + def launch[F[_] : Async](appDirectory: (String, TyrianAppF[F, _, _])*): Unit = + val appMap = appDirectory.toMap for { element <- document.querySelectorAll("[data-tyrian-app]") } yield { val tyrianAppElement = element.asInstanceOf[HTMLElement] + val tyrianAppName = tyrianAppElement.dataset.get("tyrianApp") val appSupplierOption = for { - appName <- tyrianAppElement.dataset.get("tyrianApp") - appSupplier <- appDirectory.get(appName) + appName <- tyrianAppName + appSupplier <- appMap.get(appName) } yield appSupplier appSupplierOption match case Some(appSupplier) => - appSupplier().launch(tyrianAppElement, appElementFlags(tyrianAppElement)) + appSupplier.launch(tyrianAppElement, appElementFlags(tyrianAppElement)) case _ => - // Log a warning message? - () + println(s"Could not find an app entry for ${tyrianAppName.getOrElse("")}") } - } private def appElementFlags(tyrianAppElement: HTMLElement): Map[String,String] = val appFlags = for {