aboutsummaryrefslogtreecommitdiff
path: root/client/src/main/scala/chat/Main.scala
blob: 964486e11da3e26879d4922d47871e4ec5ae27ef (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package chat

import org.scalajs.dom.raw.KeyboardEvent
import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue
import scala.scalajs.js

import org.scalajs.dom
import org.scalajs.dom.html
import org.scalajs.dom.raw.MessageEvent
import scala.scalajs.js.annotation.JSExport
import upickle.default._
import scalatags.JsDom.all._


@JSExport
object Main {

  // these need to be rendered as they will be updated by external events
  val history = div(`height`:="300px").render
  val compose = input(`class`:="form-control", placeholder:="say something").render

  // main ui element, uses bootstrap for styling
  val chatUi = div(`class`:="container")(
    div(`class`:="row")(
      div(`class`:="panel panel-default")(
        div(`class`:="panel-heading")(
          h1("Chatterbox")
        ),
        div(`class`:="panel-body")(
          history,
          div(`class`:="input-group", width:= "100%")(
            span(`class`:="input-group-addon")(">"),
            compose
          )
        )
      )
    )
  )

  // display a line in the chat box
  def display(element: Frag) = {
    val line = div(width:="100%")(element)
    history.appendChild(line.render)
  }

  @JSExport
  def main(uid: String): Unit = {
    // root element that will contain this single page app
    val root = dom.document.getElementById("root")
    while (root.firstChild != null) {
      root.removeChild(root.firstChild);
    }
    root.appendChild(chatUi.render)

    // react to messages over web socket
    val sock = new dom.WebSocket("ws://localhost:9000/socket/" + uid)
    sock.onmessage = (msg: MessageEvent) => {
      val event = read[Event](msg.data.asInstanceOf[String])
      event match {
        case Joined(uid) =>
          display(span(s"**Welcome, $uid!**\n"))
        case Message(uid, content) =>
          display(span(s"$uid: $content\n"))
        case _ =>
          dom.console.log(s"unhandled event: $event")
      }
    }

    // react to ui events
    compose.onkeypress = (ev: KeyboardEvent) => {
      if (ev.key == "Enter") {
        val msg = Broadcast(compose.value)
        dom.console.log(s"Sending $msg")
        sock.send(write(msg))
        compose.value = ""
      }
    }
  }

}