summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-08-10 16:40:20 -0700
committerLi Haoyi <haoyi@dropbox.com>2014-08-10 16:40:20 -0700
commit7c3bf500f086bd741703f3c5c87d7a74dd01703c (patch)
treea502661ad19b824e4e2f02590a017cc24797f5a4
parent2c178fdd460a460586e8dd8986772f5d6fe681d0 (diff)
downloadworkbench-7c3bf500f086bd741703f3c5c87d7a74dd01703c.tar.gz
workbench-7c3bf500f086bd741703f3c5c87d7a74dd01703c.tar.bz2
workbench-7c3bf500f086bd741703f3c5c87d7a74dd01703c.zip
Moved all the server stuff into a separate file distinct from all the SBT madness
-rw-r--r--Plugin.scala86
-rw-r--r--Server.scala77
-rw-r--r--example/src/main/scala/example/ScalaJSExample.scala2
3 files changed, 99 insertions, 66 deletions
diff --git a/Plugin.scala b/Plugin.scala
index dab630e..512e195 100644
--- a/Plugin.scala
+++ b/Plugin.scala
@@ -13,52 +13,20 @@ import spray.http.{AllOrigins, HttpResponse}
import spray.routing.SimpleRoutingApp
import spray.http.HttpHeaders.`Access-Control-Allow-Origin`
-object Plugin extends sbt.Plugin with SimpleRoutingApp{
- implicit val system = ActorSystem(
- "SystemLol",
- config = ConfigFactory.load(ActorSystem.getClass.getClassLoader),
- classLoader = ActorSystem.getClass.getClassLoader
- )
+object Plugin extends sbt.Plugin {
+
+
val refreshBrowsers = taskKey[Unit]("Sends a message to all connected web pages asking them to refresh the page")
val updateBrowsers = taskKey[Unit]("partially resets some of the stuff in the browser")
val localUrl = settingKey[(String, Int)]("localUrl")
- private[this] val routes = settingKey[Unit]("local websocket server")
+ private[this] val server = settingKey[Server]("local websocket server")
+
+
val bootSnippet = settingKey[String]("piece of javascript to make things happen")
val updatedJS = taskKey[List[String]]("Provides the addresses of the JS files that have changed")
- val pubSub = actor(new Actor{
- var waitingActor: Option[ActorRef] = None
- var queuedMessages = List[Js.Value]()
- case object Clear
- import system.dispatcher
- system.scheduler.schedule(0 seconds, 10 seconds, self, Clear)
- def respond(a: ActorRef, s: String) = {
- a ! HttpResponse(
- entity = s,
- headers = List(`Access-Control-Allow-Origin`(AllOrigins))
- )
- }
- def receive = (x: Any) => (x, waitingActor, queuedMessages) match {
- case (a: ActorRef, _, Nil) =>
- // Even if there's someone already waiting,
- // a new actor waiting replaces the old one
- waitingActor = Some(a)
- case (a: ActorRef, None, msgs) =>
-
- respond(a, Json.write(Js.Array(msgs)))
- queuedMessages = Nil
- case (msg: Js.Array, None, msgs) =>
- queuedMessages = msg :: msgs
- case (msg: Js.Array, Some(a), Nil) =>
- respond(a, Json.write(Js.Array(Seq(msg))))
- waitingActor = None
- case (Clear, Some(a), Nil) =>
- respond(a, Json.write(Js.Array(Nil)))
- waitingActor = None
- }
- })
val workbenchSettings = Seq(
localUrl := ("localhost", 12345),
@@ -85,9 +53,9 @@ object Plugin extends sbt.Plugin with SimpleRoutingApp{
val clientLogger = FullLogger{
new Logger {
def log(level: Level.Value, message: => String) =
- if(level >= Level.Info) pubSub ! upickle.writeJs(Seq("print", level.toString(), message))
- def success(message: => String) = pubSub ! upickle.writeJs(Seq("print", "info", message))
- def trace(t: => Throwable) = pubSub ! upickle.writeJs(Seq("print", "error", t.toString))
+ if(level >= Level.Info) server.value msg Seq("print", level.toString, message)
+ def success(message: => String) = server.value msg Seq("print", "info", message)
+ def trace(t: => Throwable) = server.value msg Seq("print", "error", t.toString)
}
}
clientLogger.setSuccessEnabled(true)
@@ -96,45 +64,33 @@ object Plugin extends sbt.Plugin with SimpleRoutingApp{
},
refreshBrowsers := {
streams.value.log.info("workbench: Reloading Pages...")
- pubSub ! upickle.writeJs(Seq("reload"))
+ server.value msg Seq("reload")
},
updateBrowsers := {
val changed = updatedJS.value
// There is no point in clearing the browser if no js files have changed.
if (changed.length > 0) {
- pubSub ! upickle.writeJs(Seq("clear"))
+ server.value msg Seq("clear")
changed.foreach {
path =>
streams.value.log.info("workbench: Refreshing " + path)
- pubSub ! upickle.writeJs(Seq(
+ server.value msg Seq(
"run",
path,
bootSnippet.value
- ))
+ )
}
}
},
- routes := startServer(localUrl.value._1, localUrl.value._2){
- get{
- path("workbench.js"){
- complete{
- IO.readStream(
- getClass.getClassLoader
- .getResourceAsStream("workbench_template.js")
- ).replace("<host>", localUrl.value._1)
- .replace("<port>", localUrl.value._2.toString)
- .replace("<bootSnippet>", bootSnippet.value)
- }
- } ~
- getFromDirectory(".")
- } ~
- post{
- path("notifications"){ ctx =>
- pubSub ! ctx.responder
- }
- }
-
+ server := {
+ new Server(localUrl.value._1, localUrl.value._2, bootSnippet.value)
+ },
+ onLoad := { state =>
+ state
+ },
+ onUnload := { state =>
+ state
}
)
}
diff --git a/Server.scala b/Server.scala
new file mode 100644
index 0000000..af4b6b6
--- /dev/null
+++ b/Server.scala
@@ -0,0 +1,77 @@
+package com.lihaoyi.workbench
+
+import akka.actor.{ActorRef, Actor, ActorSystem}
+import com.typesafe.config.ConfigFactory
+import sbt.IO
+import spray.routing.SimpleRoutingApp
+import akka.actor.ActorDSL._
+import scala.Some
+import upickle.{Writer, Json, Js}
+import spray.http.{AllOrigins, HttpResponse}
+import spray.http.HttpHeaders.`Access-Control-Allow-Origin`
+import concurrent.duration._
+class Server(url: String, port: Int, bootSnippet: String) extends SimpleRoutingApp{
+ implicit val system = ActorSystem(
+ "SystemLol",
+ config = ConfigFactory.load(ActorSystem.getClass.getClassLoader),
+ classLoader = ActorSystem.getClass.getClassLoader
+ )
+
+ val pubSub = actor(new Actor{
+ var waitingActor: Option[ActorRef] = None
+ var queuedMessages = List[Js.Value]()
+ case object Clear
+ import system.dispatcher
+
+ system.scheduler.schedule(0 seconds, 10 seconds, self, Clear)
+ def respond(a: ActorRef, s: String) = {
+ a ! HttpResponse(
+ entity = s,
+ headers = List(`Access-Control-Allow-Origin`(AllOrigins))
+ )
+ }
+ def receive = (x: Any) => (x, waitingActor, queuedMessages) match {
+ case (a: ActorRef, _, Nil) =>
+ // Even if there's someone already waiting,
+ // a new actor waiting replaces the old one
+ waitingActor = Some(a)
+ case (a: ActorRef, None, msgs) =>
+
+ respond(a, Json.write(Js.Array(msgs)))
+ queuedMessages = Nil
+ case (msg: Js.Array, None, msgs) =>
+ queuedMessages = msg :: msgs
+ case (msg: Js.Array, Some(a), Nil) =>
+ respond(a, Json.write(Js.Array(Seq(msg))))
+ waitingActor = None
+ case (Clear, Some(a), Nil) =>
+ respond(a, Json.write(Js.Array(Nil)))
+ waitingActor = None
+ }
+ })
+
+ startServer(url, port) {
+ get {
+ path("workbench.js") {
+ complete {
+ IO.readStream(
+ getClass.getClassLoader
+ .getResourceAsStream("workbench_template.js")
+ ).replace("<host>", url)
+ .replace("<port>", port.toString)
+ .replace("<bootSnippet>", bootSnippet)
+ }
+ } ~
+ getFromDirectory(".")
+ } ~
+ post {
+ path("notifications") { ctx =>
+ pubSub ! ctx.responder
+ }
+ }
+ }
+
+ def msg[T: Writer](t: T) = {
+ pubSub ! upickle.writeJs(t)
+ }
+} \ No newline at end of file
diff --git a/example/src/main/scala/example/ScalaJSExample.scala b/example/src/main/scala/example/ScalaJSExample.scala
index 7222143..8509a0e 100644
--- a/example/src/main/scala/example/ScalaJSExample.scala
+++ b/example/src/main/scala/example/ScalaJSExample.scala
@@ -21,7 +21,7 @@ object ScalaJSExample {
val corners = Seq(Point(255, 255), Point(0, 255), Point(128, 0))
def clear() = {
- ctx.fillStyle = "black"
+ ctx.fillStyle = "white"
ctx.fillRect(0, 0, 255, 255)
}