Skip to content

Commit

Permalink
Migrate to xterm
Browse files Browse the repository at this point in the history
  • Loading branch information
Felix committed Dec 26, 2016
1 parent 7c22827 commit 542dd40
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 181 deletions.
18 changes: 0 additions & 18 deletions chromeapp/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,11 @@ div {
-webkit-user-select: auto;
}



.terminal {
float: left;
border: #000 solid 5px;
font-family: "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
color: #f0f0f0;
background: #000;
}

.reverse-video {
color: #000;
background: #f0f0f0;
}

.terminal-col-fixed{
width:1030px;
//background:red;
//position:fixed;
height:100%;
}

.modal-backdrop {
z-index:100; /* default makes modal be hidden behind the modal-backdrop div.*/
}
Expand Down
29 changes: 6 additions & 23 deletions chromeapp/src/main/scala/util/ChromePlatformService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Promise}
import scala.scalajs.js
import scala.scalajs.js.Function1
import scala.scalajs.js.typedarray.ArrayBuffer

object ChromePlatformService extends PlatformService {
override def appVersion: String = chrome.runtime.getManifest().version
Expand Down Expand Up @@ -208,32 +209,14 @@ class ChromeDockerConnection(val connection: Connection) extends DockerConnectio
// Bridge between common class and Chrome WebSocket
class WebSocketAdapter(socket: WebSocket) extends BasicWebSocket {

override def send(data: String): Unit = socket.send(data)
override def send(data: js.Any): Unit = socket.send(data.asInstanceOf[ArrayBuffer])

override def close(code: Int, reason: String): Unit = socket.close(code, reason)

socket.onopen = { event: Event => this.onopen() }
socket.onmessage = { event: MessageEvent =>
this.onmessage(new {
def data = event.data.asInstanceOf[js.Any]
})
}
socket.onclose = { event: CloseEvent =>
this.onclose(new {
def code = event.code
})
}

socket.onerror = { event: ErrorEvent =>
this.onerror(new {
def message = event.message
})
}

override var onopen: Function1[Unit, _] = { x: Unit => () }
override var onmessage: js.Function1[ {def data: js.Any}, _] = { x: {def data: js.Any} => () }
override var onclose: js.Function1[ {def code: Int}, _] = { x: {def code: Int} => () }
override var onerror: js.Function1[ {def message: String}, _] = { x: {def message: String} => () }
def addEventListener(`type`: String, listener: js.Function1[Any, _]): Unit =
socket.addEventListener(`type`,listener)

def removeEventListener(`type`: String, listener: js.Function1[Any, _]): Unit =
socket.addEventListener(`type`,listener)

}
2 changes: 1 addition & 1 deletion electron/bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
"bootstrap": "~3.3.4",
"bootcards": "~1.1.0",
"font-awesome": "~4.3.0",
"term.js": "~0.0.3"
"xterm.js": "2.2.3"
}
}
16 changes: 0 additions & 16 deletions electron/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,11 @@ div {
}



.terminal {
float: left;
border: #000 solid 5px;
font-family: "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
color: #f0f0f0;
background: #000;
}

.reverse-video {
color: #000;
background: #f0f0f0;
}

.terminal-col-fixed{
width:1030px;
//background:red;
//position:fixed;
height:100%;
}

.modal-backdrop {
z-index:100; /* default makes modal be hidden behind the modal-backdrop div.*/
Expand Down
15 changes: 14 additions & 1 deletion electron/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,23 @@
<script src="./bower_components/chrome-platform-analytics/google-analytics-bundle.js"></script>

<script type="text/javascript"
src="./bower_components/term.js/src/term.js"></script>
src="./bower_components/xterm.js/dist/xterm.js"></script>

<script type="text/javascript"
src="./bower_components/xterm.js/dist/addons/attach/attach.js"></script>

<script type="text/javascript"
src="./bower_components/xterm.js/dist/addons/terminado/terminado.js"></script>


<script type="text/javascript"
src="./bower_components/xterm.js/dist/addons/fit/fit.js"></script>


<link rel="stylesheet" href="./bower_components/font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="./bower_components/xterm.js/dist/xterm.css" />

</head>
<body>
<div class="main-container">
Expand Down
4 changes: 4 additions & 0 deletions electron/src/main/scala/util/ElectronPlatformService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,15 @@ class ElectronDockerConnection(val connection: Connection) extends DockerConnect
if (msg == null) {
if (dialOptions.hijack) {
processHijackResponse(onWebSocketCreated, response)

} else if (dialOptions.isStream) {
def onComplete { p.success(Response("", 200)) }
processStreamingResponse(onStreamingData, shouldAbort, onComplete, response)

} else {
val responseText = js.Dynamic.global.JSON.stringify(response).asInstanceOf[String]
p.success(Response(responseText, 200))

}
} else {
log.debug(s"dial fail: $msg")
Expand Down Expand Up @@ -197,6 +200,7 @@ class ElectronDockerConnection(val connection: Connection) extends DockerConnect
hijack = true,
openStdin = true
)

dial(options, onWebSocketCreated = onWebSocketCreated)
.onFailure { case ex: Exception =>
log.debug(s"Unable to connect WS - ${ex.toString}")
Expand Down
65 changes: 37 additions & 28 deletions electron/src/main/scala/util/HijackSocket.scala
Original file line number Diff line number Diff line change
@@ -1,59 +1,68 @@
package util

import model.BasicWebSocket
import org.scalajs.dom.raw.Event
import util.logger.log

import scala.language.reflectiveCalls
import scala.scalajs.js
import scala.scalajs.js.Function1
import scala.scalajs.js.annotation.{JSExport, JSExportAll}

import js.Dynamic.{ global => g, newInstance => jsnew }

@js.native
trait HijackSocket extends js.Object {
def addListener(eventName: String, listener: js.Function1[js.Dynamic, _]): this.type = js.native
def write(data: String): Unit = js.native
def addListener(eventName: String, listener: js.Function1[_, _]): this.type = js.native

def removeListener(eventName: String, listener: js.Function1[_, _]): this.type = js.native
def write(data: js.Any): Unit = js.native
def destroy(): Unit = js.native
}

@JSExportAll
case class CustomTextEvent(data: String)

@JSExportAll
class HijackWebSocket(socket: HijackSocket) extends BasicWebSocket {

socket.addListener("data", { socketData: js.Any =>
log.debug(s"HijackWebSocket data: $socketData")
onmessage(new {
def data = socketData
})
})

socket.addListener("connect", { socketData: js.Any =>
log.debug(s"HijackWebSocket connect: $socketData")
onopen()
})

socket.addListener("close", { socketData: js.Any =>
log.debug(s"HijackWebSocket close: $socketData")
onclose(new {
def code = 1
})
})

socket.addListener("error", { socketData: js.Dynamic =>
log.debug(s"HijackWebSocket error: $socketData")
onerror(new {
def message = socketData.message.toString
})
})

override def send(data: String): Unit = {
@JSExport
override def send(data: js.Any): Unit = {
socket.write(data)
}

@JSExport
override def close(code: Int, reason: String): Unit = {
socket.destroy()
}

// Default impl, will be replaced by the attached Terminal
override var onopen: Function1[Unit, _] = { x: Unit => () }
override var onmessage: js.Function1[ {def data: js.Any}, _] = { x: {def data: js.Any} => () }
override var onclose: js.Function1[ {def code: Int}, _] = { x: {def code: Int} => () }
override var onerror: js.Function1[ {def message: String}, _] = { x: {def message: String} => () }
@JSExport
def addEventListener(`type`: String, listener: js.Function1[Any, _]): Unit = {
if (`type` == "message") {
socket.addListener("data", { socketData: js.Any =>
log.debug(s"HijackWebSocket data: $socketData")
val decoder = jsnew(g.TextDecoder)("utf-8")
val data = decoder.decode(socketData).replace("\r$/g", "\r\n")
listener(new CustomTextEvent(data.toString.replace("\n", "\r\n")))
()
})
} else {
socket.addListener(`type`, listener)
}

}

@JSExport
def removeEventListener(`type`: String, listener: js.Function1[Any, _]): Unit = {
if (`type` == "message") {
socket.removeListener("data", listener)
}
socket.removeListener(`type`, listener)
}
}
18 changes: 12 additions & 6 deletions src/main/scala/api/DockerClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ case class DockerClient(con: DockerConnection) {
}

private def removeImage(imageId: String): Future[Unit] = {
val id = imageId.replace("sha256:","")
val id = imageId.replace("sha256:", "")
con.delete(path = s"/images/$id").map { xhr =>
log.info("[dockerClient.removeImage] return: " + xhr.statusCode)
}.transform(identity, ex => ex match {
Expand Down Expand Up @@ -204,10 +204,11 @@ case class DockerClient(con: DockerConnection) {
}

val tasksFut = orderedImages.map { imagesToGC =>
val tasks = imagesToGC.map { image => () => {
status(s"Removing ${image.id}/ ${image.RepoTags.mkString(" ")}")
removeImage(image)
}
val tasks = imagesToGC.map { image =>
() => {
status(s"Removing ${image.id}/ ${image.RepoTags.mkString(" ")}")
removeImage(image)
}

}
FutureUtils.sequenceWithDelay(tasks, FutureUtils.LongDelay, ignoreErrors = true)
Expand Down Expand Up @@ -240,6 +241,7 @@ case class DockerClient(con: DockerConnection) {
case head :: tail => removeContainer(head.Id).andThen { case _ => delete(tail) }
case Nil => Future.successful(())
}

delete(all.drop(KeepInGarbageCollection).toList)
}
}
Expand Down Expand Up @@ -338,7 +340,11 @@ case class DockerClient(con: DockerConnection) {

// https://docs.docker.com/engine/reference/api/docker_remote_api_v1.19/#get-container-stats-based-on-resource-usage
def containerStats(containerId: String)(updateUI: (Option[ContainerStats], ConnectedStream) => Unit): Unit =
con.containerStats(containerId)(updateUI)
con.containerStats(containerId)(updateUI)

def resizeTTY(containerId: String, h: Int, w: Int) = {
con.post(path = s"/containers/$containerId/resize?h=$h&w=$w")
}
}

trait ConnectedStream {
Expand Down
13 changes: 4 additions & 9 deletions src/main/scala/model/WebSocket.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ import scala.scalajs.js
// Shared code between Chrome app WebSocket and Node.js Socket
trait BasicWebSocket {

var onmessage: js.Function1[ {def data: js.Any}, _]

var onopen: js.Function1[ Unit, _]

var onclose: js.Function1[ {def code: Int}, _]

var onerror: js.Function1[ {def message: String}, _]

def send(data: String): Unit
def send(data: js.Any): Unit

def close(code: Int, reason: String): Unit

def addEventListener(`type`: String, listener: js.Function1[Any, _]): Unit
def removeEventListener(`type`: String, listener: js.Function1[Any, _]): Unit
}
Loading

0 comments on commit 542dd40

Please sign in to comment.