Skip to content

Commit

Permalink
#198 : Update launch method name and signature. Add TyrianApp compani…
Browse files Browse the repository at this point in the history
…on objects.
  • Loading branch information
stevechy committed May 16, 2023
1 parent 3c06daf commit a00cbfc
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 17 deletions.
1 change: 0 additions & 1 deletion examples/main-launcher/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
<body>
<h1>Main launcher example</h1>
<div data-tyrian-app="CounterApp" data-tyrian-app-flag-initial-counter="42"></div>

<div data-tyrian-app="ChatApp" data-tyrian-app-flag-initial-message="Hello"></div>
</body>

Expand Down
5 changes: 5 additions & 0 deletions examples/main-launcher/src/main/scala/example/ChatApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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

Expand All @@ -39,4 +43,4 @@ object Model:
def -(other: Int): Model = i - other

enum Msg:
case Increment, Decrement
case Increment, Decrement, RouteMsg
9 changes: 4 additions & 5 deletions examples/main-launcher/src/main/scala/example/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
}
8 changes: 8 additions & 0 deletions tyrian-io/src/main/scala/tyrian/TyrianApp.scala
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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: _*)
8 changes: 8 additions & 0 deletions tyrian-zio/src/main/scala/tyrian/TyrianApp.scala
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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: _*)
19 changes: 9 additions & 10 deletions tyrian/js/src/main/scala/tyrian/TyrianAppF.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand All @@ -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 {
Expand Down

0 comments on commit a00cbfc

Please sign in to comment.