Skip to content

Commit

Permalink
Switch to fs2-dom for BroadcastChannel
Browse files Browse the repository at this point in the history
  • Loading branch information
toddburnside committed Oct 3, 2023
1 parent a2fa07c commit b32bfa0
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 32 deletions.
9 changes: 5 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ lazy val catsVersion = "2.10.0"
lazy val catsRetryVersion = "3.1.0"
lazy val circeVersion = "0.14.6"
lazy val crystalVersion = "0.34.4"
lazy val fs2DomVersion = "0.3.0-M1"
lazy val kittensVersion = "3.0.0"
lazy val http4sVersion = "0.23.23"
lazy val http4sDomVersion = "0.2.9"
lazy val lucumaBCVersion = "0.4.0"
lazy val lucumaCoreVersion = "0.85.1"
lazy val lucumaCoreVersion = "0.86.1"
lazy val lucumaPrimeStylesVersion = "0.2.9"
lazy val lucumaReactVersion = "0.44.1"
lazy val lucumaRefinedVersion = "0.1.2"
Expand Down Expand Up @@ -94,14 +94,15 @@ lazy val ui =
"dev.optics" %%% "monocle-macro" % monocleVersion,
"edu.gemini" %%% "crystal" % crystalVersion,
"com.lihaoyi" %%% "pprint" % pprintVersion,
"com.armanbilge" %%% "fs2-dom" % fs2DomVersion,
"org.http4s" %%% "http4s-core" % http4sVersion,
"org.http4s" %%% "http4s-circe" % http4sVersion,
"org.http4s" %%% "http4s-dom" % http4sDomVersion,
"com.github.cb372" %%% "cats-retry" % catsRetryVersion,
"io.circe" %%% "circe-core" % circeVersion,
"io.circe" %%% "circe-parser" % circeVersion,
"edu.gemini" %%% "lucuma-sso-frontend-client" % lucumaSsoVersion,
"edu.gemini" %%% "lucuma-broadcast-channel" % lucumaBCVersion
"edu.gemini" %%% "lucuma-sso-frontend-client" % lucumaSsoVersion
// "edu.gemini" %%% "lucuma-broadcast-channel" % lucumaBCVersion
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import cats.syntax.all.*
import crystal.react.View
import crystal.react.syntax.view.*
import eu.timepit.refined.types.string.NonEmptyString
import fs2.dom.Serializer
import io.circe.Json
import japgolly.scalajs.react.*
import japgolly.scalajs.react.util.DefaultEffects.{Async => DefaultA}
Expand Down Expand Up @@ -34,7 +35,8 @@ case class IfLogged[E](
)(
val render: DefaultA[Unit] => VdomNode
)(using
val logger: Logger[DefaultA]
val logger: Logger[DefaultA],
val serializerE: Serializer[E]
) extends ReactFnProps(IfLogged.component)

object IfLogged:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
package lucuma.ui.components.state

import cats.Applicative
import cats.effect.Sync
import cats.syntax.all.*
import crystal.react.hooks.*
import eu.timepit.refined.types.string.NonEmptyString
import fs2.dom.BroadcastChannel
import fs2.dom.Serializer
import japgolly.scalajs.react.*
import japgolly.scalajs.react.util.DefaultEffects.{Async => DefaultA}
import japgolly.scalajs.react.vdom.html_<^.*
import lucuma.broadcastchannel.*
import lucuma.react.common.ReactFnProps
import lucuma.refined.*
import lucuma.ui.sso.UserVault
Expand All @@ -22,8 +23,8 @@ case class LogoutTracker[E](
isLogoutEvent: E => Boolean,
getEventNonce: E => String,
createEventWithNonce: String => E
)(val render: DefaultA[Unit] => VdomNode)
extends ReactFnProps(LogoutTracker.component)
)(val render: DefaultA[Unit] => VdomNode)(using val serializerE: Serializer[E])
extends ReactFnProps(LogoutTracker.component) {}

object LogoutTracker:
private type Props[E] = LogoutTracker[E]
Expand All @@ -33,34 +34,27 @@ object LogoutTracker:
.withHooks[Props[E]]
// Create a nonce
.useMemo(())(_ => System.currentTimeMillis)
// Hold the broadcast channel
.useState(none[BroadcastChannel[E]])
.useEffectOnMountBy { (props, nonce, state) =>
val bc = new BroadcastChannel[E](props.channelName.value)

bc.onmessage = (
(e: E) =>
if (props.isLogoutEvent(e))
.useResourceOnMountBy { (props, _) =>
import props.given
BroadcastChannel[DefaultA, E](props.channelName.value)
}
.useStreamBy((_, _, bc) => bc.isReady)((props, nonce, bc) =>
_ =>
bc.toOption.map(_.messages).orEmpty.evalTap { e =>
if (props.isLogoutEvent(e.data))
(props.setVault(none) >> props.setMessage(
"You logged out in another instance".refined
)).whenA(props.getEventNonce(e) =!= nonce.value.toString)
)).whenA(props.getEventNonce(e.data) =!= nonce.value.toString)
else
Applicative[DefaultA].unit
): (E => DefaultA[Unit]) // Scala 3 infers the return type as Any if we don't ascribe

state
.setState(bc.some) *> CallbackTo(Callback(bc.close()).attempt)
}
.render { (props, nonce, bc) =>
bc.value.fold[VdomNode](React.Fragment())(bc =>
}
)
.render { (props, nonce, bc, _) =>
bc.toOption.fold[VdomNode](React.Fragment())(bc =>
props.render(
Sync[DefaultA]
.delay(
bc.postMessage(
props.createEventWithNonce(nonce.value.toString)
)
)
.attempt
bc.postMessage(
props.createEventWithNonce(nonce.value.toString)
).attempt
.void
)
)
Expand Down

0 comments on commit b32bfa0

Please sign in to comment.