Compare commits
No commits in common. "77b34a2ca7fac8ece7c07ce7ce6b6afa54e741f3" and "5ac864f15ef28dd809b50b83d8ccfd6c3df091c8" have entirely different histories.
77b34a2ca7
...
5ac864f15e
|
@ -26,7 +26,7 @@ object MyHttpService {
|
||||||
val send: Stream[IO, WebSocketFrame] =
|
val send: Stream[IO, WebSocketFrame] =
|
||||||
Stream
|
Stream
|
||||||
.emits(TestModels.testChangesList)
|
.emits(TestModels.testChangesList)
|
||||||
.covary[IO].metered(2.second).map(state => WebSocketFrame.Text(state.asJson.noSpaces))
|
.covary[IO].metered(5.second).map(state => WebSocketFrame.Text(state.asJson.noSpaces))
|
||||||
|
|
||||||
val receive: Pipe[IO, WebSocketFrame, Unit] = _.evalMap {
|
val receive: Pipe[IO, WebSocketFrame, Unit] = _.evalMap {
|
||||||
case WebSocketFrame.Text(text, _) => Sync[IO].delay(println(text))
|
case WebSocketFrame.Text(text, _) => Sync[IO].delay(println(text))
|
||||||
|
|
|
@ -22,6 +22,10 @@ object Models {
|
||||||
}
|
}
|
||||||
|
|
||||||
object RoomStateView {
|
object RoomStateView {
|
||||||
|
given Encoder[Map[PlayerID, String]] = Encoder.encodeMap[PlayerID, String]
|
||||||
|
given Decoder[Map[PlayerID, String]] = Decoder.decodeMap[PlayerID, String]
|
||||||
|
given Codec[Map[PlayerID, String]] = Codec.from(summon[Decoder[Map[PlayerID, String]]], summon[Encoder[Map[PlayerID, String]]])
|
||||||
|
|
||||||
val empty = RoomStateView(
|
val empty = RoomStateView(
|
||||||
List.empty, PlayerID(0), List.empty, RoundState.Voting(None, List.empty), false
|
List.empty, PlayerID(0), List.empty, RoundState.Voting(None, List.empty), false
|
||||||
)
|
)
|
||||||
|
@ -41,9 +45,16 @@ object Models {
|
||||||
/** view state for round after opening the votes
|
/** view state for round after opening the votes
|
||||||
*/
|
*/
|
||||||
case Viewing(
|
case Viewing(
|
||||||
votes: List[(PlayerID, String)]
|
votes: Map[PlayerID, String]
|
||||||
)
|
)
|
||||||
|
|
||||||
final case class PlayerID(id: Long) derives Codec.AsObject
|
final case class PlayerID(id: Long) derives Codec.AsObject
|
||||||
|
object PlayerID {
|
||||||
|
given KeyEncoder[PlayerID] with
|
||||||
|
def apply(key: PlayerID): String = key.toString
|
||||||
|
given KeyDecoder[PlayerID] with
|
||||||
|
def apply(key: String): Option[PlayerID] = key.toLongOption.map(PlayerID.apply(_))
|
||||||
|
}
|
||||||
|
|
||||||
final case class Player(name: String, id: PlayerID) derives Codec.AsObject
|
final case class Player(name: String, id: PlayerID) derives Codec.AsObject
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ object TestModels {
|
||||||
me = me.id,
|
me = me.id,
|
||||||
allowedCards = List("xs", "s", "m", "l", "xl"),
|
allowedCards = List("xs", "s", "m", "l", "xl"),
|
||||||
round = RoundState.Viewing(
|
round = RoundState.Viewing(
|
||||||
List(me.id -> "xs", pony.id -> "l", birdy.id -> "s", horsey.id -> "m")
|
Map(me.id -> "xs", pony.id -> "l", birdy.id -> "s", horsey.id -> "m")
|
||||||
),
|
),
|
||||||
canCloseRound = true
|
canCloseRound = true
|
||||||
)
|
)
|
||||||
|
@ -98,7 +98,7 @@ object TestModels {
|
||||||
me = me.id,
|
me = me.id,
|
||||||
allowedCards = List("xs", "s", "m", "l", "xl"),
|
allowedCards = List("xs", "s", "m", "l", "xl"),
|
||||||
round = RoundState.Viewing(
|
round = RoundState.Viewing(
|
||||||
List(me.id -> "m", pony.id -> "l", birdy.id -> "s", horsey.id -> "m")
|
Map(me.id -> "m", pony.id -> "l", birdy.id -> "s", horsey.id -> "m")
|
||||||
),
|
),
|
||||||
canCloseRound = true
|
canCloseRound = true
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,7 +30,9 @@ object Main {
|
||||||
import io.laminext.websocket.circe.WebSocket._
|
import io.laminext.websocket.circe.WebSocket._
|
||||||
import io.laminext.websocket.circe.webSocketReceiveBuilderSyntax
|
import io.laminext.websocket.circe.webSocketReceiveBuilderSyntax
|
||||||
|
|
||||||
val roomStateWSStream = io.laminext.websocket.WebSocket.path("/api/subscribe").json[RoomStateView, Unit]
|
val roomStateWSStream = io.laminext.websocket.circe.WebSocket
|
||||||
|
.url("ws://0.0.0.0:5153/api/subscribe")
|
||||||
|
.json[RoomStateView, Unit]
|
||||||
.build(
|
.build(
|
||||||
managed = true,
|
managed = true,
|
||||||
autoReconnect = false,
|
autoReconnect = false,
|
||||||
|
@ -42,7 +44,7 @@ object Main {
|
||||||
val stateStream = roomStateWSStream.received
|
val stateStream = roomStateWSStream.received
|
||||||
// and what's the difference between EventStream and Signal???
|
// and what's the difference between EventStream and Signal???
|
||||||
val stateSignal =
|
val stateSignal =
|
||||||
stateStream.startWith(RoomStateView.empty)
|
stateStream.startWith(TestModels.testRoom, cacheInitialValue = true)
|
||||||
|
|
||||||
// NOTE let's try with fetch \ rest
|
// NOTE let's try with fetch \ rest
|
||||||
// import io.laminext.fetch.Fetch
|
// import io.laminext.fetch.Fetch
|
||||||
|
@ -54,11 +56,23 @@ object Main {
|
||||||
def appElement(): Element = {
|
def appElement(): Element = {
|
||||||
div(
|
div(
|
||||||
className := "w-screen h-screen flex flex-col justify-center items-center",
|
className := "w-screen h-screen flex flex-col justify-center items-center",
|
||||||
|
div(
|
||||||
|
className := "bg-yellow-400",
|
||||||
|
child.text <-- roomStateWSStream.events
|
||||||
|
.map { ev =>
|
||||||
|
{
|
||||||
|
val a = ev.toString()
|
||||||
|
g.console.warn(s"got state $a")
|
||||||
|
a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.startWith("BEFORE WS")
|
||||||
|
),
|
||||||
div(
|
div(
|
||||||
className := "h-24 w-full flex flex-for justify-center items-center bg-green-200",
|
className := "h-24 w-full flex flex-for justify-center items-center bg-green-200",
|
||||||
p(className := "text-2xl", "Here be header")
|
p(className := "text-2xl", "Here be header")
|
||||||
),
|
),
|
||||||
RoomView.renderRoom(stateSignal),
|
RoomView.renderRoom(staticStateSignal),
|
||||||
roomStateWSStream.connect
|
roomStateWSStream.connect
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,11 @@ object TableView {
|
||||||
} else isOpen.alreadyVoted.find(_.id == id).fold(NoCard(name))(_ => CardBack)
|
} else isOpen.alreadyVoted.find(_.id == id).fold(NoCard(name))(_ => CardBack)
|
||||||
case isClosed: RoundState.Viewing =>
|
case isClosed: RoundState.Viewing =>
|
||||||
isClosed.votes
|
isClosed.votes
|
||||||
.find(_._1 == id)
|
.get(id)
|
||||||
.fold {
|
.fold {
|
||||||
g.console.error(s"missing vote for player $name")
|
g.console.error(s"missing vote for player $name")
|
||||||
Open("error")
|
Open("error")
|
||||||
} { case (_, vote) => Open(vote) }
|
} { vote => Open(vote) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue