Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Chrome System Monitor
=========
Simple example of chrome application.

## For developers
To create unpacked application:

```
sbt
chromeUnpackedFast
````
You can find result in `./target/chrome/unpacked-fast` folder.

After you install unpacked extension to Chrome, it can be found on `chrome://apps` page.
98 changes: 48 additions & 50 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,56 +1,54 @@
import chrome.Impl._
import chrome.permissions.APIPermission._
import Dependencies.{addLibraries, addJsLibraries}
import chrome.permissions.Permission
import chrome.permissions.Permission.API
import chrome.{App, AppManifest, Background}
import net.lullabyte.{Chrome, ChromeSbtPlugin}

lazy val root = project.in(file("."))
.enablePlugins(ChromeSbtPlugin)
.settings(
name := "System Monitor",
version := "0.1.0",
scalaVersion := "2.11.8",
scalacOptions ++= Seq(
"-language:implicitConversions",
"-language:existentials",
"-Xlint",
"-deprecation",
"-Xfatal-warnings",
"-feature"
),
persistLauncher := true,
persistLauncher in Test := false,
relativeSourceMaps := true,
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-dom" % "0.9.0" withSources() withJavadoc(),
"com.github.japgolly.scalajs-react" %%% "core" % "0.9.1" withSources() withJavadoc(),
"com.github.japgolly.scalajs-react" %%% "extra" % "0.9.1" withSources() withJavadoc(),
"com.github.japgolly.scalacss" %%% "core" % "0.3.0" withSources() withJavadoc(),
"com.github.japgolly.scalacss" %%% "ext-react" % "0.3.0" withSources() withJavadoc(),
"net.lullabyte" %%% "scala-js-chrome" % "0.2.0" withSources() withJavadoc()
),
jsDependencies += "org.webjars" % "react" % "0.13.3" / "react-with-addons.min.js" commonJSName "React",
skip in packageJSDependencies := false,
chromeManifest := AppManifest(
name = name.value,
version = version.value,
app = App(
background = Background(
scripts = List("deps.js", "main.js", "launcher.js")
)
),
defaultLocale = Some("en"),
icons = Chrome.icons(
"assets/icons",
"app.png",
Set(16, 32, 48, 64, 96, 128, 256, 512)
),
permissions = Set(
System.CPU,
System.Display,
System.Memory,
System.Network,
Storage
)
enablePlugins(ChromeSbtPlugin)

name := "System Monitor"
version := "0.2.1"
scalaVersion := "2.12.4"


addLibraries()
addJsLibraries()


scalaJSUseMainModuleInitializer := true
scalaJSUseMainModuleInitializer in Test := false
relativeSourceMaps := true
skip in packageJSDependencies := false


scalacOptions ++= MyBuildConfig.scalacOptions


chromeManifest := new AppManifest {
val name = Keys.name.value
val version = Keys.version.value
val app = App(
background = Background(
scripts = List("dependencies.js", "main.js")
)
)

override val defaultLocale = Some("en")

override val icons = Chrome.icons(
"assets/icons",
"app.png",
Set(16, 32, 48, 64, 96, 128, 256, 512)
)

override val permissions: Set[Permission] = Set(
API.System.CPU,
API.System.Display,
API.System.Memory,
API.System.Network,
API.Storage
)
}



52 changes: 52 additions & 0 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
import sbt.Keys.libraryDependencies
import sbt._

object Dependencies {

object versions {
val scalacss = "0.5.6"
val scalaReact = "1.4.2"

val react = "16.7.0"
}

def addLibraries() = {
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-dom" % "0.9.2" withSources() withJavadoc(),
"com.github.japgolly.scalajs-react" %%% "core" % versions.scalaReact withSources() withJavadoc(),
"com.github.japgolly.scalajs-react" %%% "extra" % versions.scalaReact withSources() withJavadoc(),
"com.github.japgolly.scalacss" %%% "core" % versions.scalacss withSources() withJavadoc(),
"com.github.japgolly.scalacss" %%% "ext-react" % versions.scalacss withSources() withJavadoc(),
"net.lullabyte" %%% "scala-js-chrome" % "0.5.0" withSources() withJavadoc()
)
}

def addJsLibraries() = {
jsDependencies ++= Seq(
"org.webjars.npm" % "react" % versions.react
/ "umd/react.development.js"
minified "umd/react.production.min.js"
commonJSName "React",

"org.webjars.npm" % "react-dom" % versions.react
/ "umd/react-dom.development.js"
minified "umd/react-dom.production.min.js"
dependsOn "umd/react.development.js"
commonJSName "ReactDOM"
)
}
}

object MyBuildConfig {

val scalacOptions = Seq(
"-language:implicitConversions",
"-language:existentials",
"-Xlint",
"-deprecation",
"-Xfatal-warnings",
"-feature"
)

}
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 0.13.8
sbt.version = 1.3.4
6 changes: 4 additions & 2 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
addSbtPlugin("net.lullabyte" % "sbt-chrome-plugin" % "0.2.1")
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.6.0")
resolvers += Resolver.bintrayIvyRepo("veinhorn", "sbt-plugins")

addSbtPlugin("net.lullabyte" % "sbt-chrome-plugin" % "0.5.8")
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
2 changes: 1 addition & 1 deletion scalastyle-config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parameter name="maxFileLength"><![CDATA[800]]></parameter>
</parameters>
</check>
<check level="warning" class="org.scalastyle.file.HeaderMatchesChecker" enabled="true">
<check level="warning" class="org.scalastyle.file.HeaderMatchesChecker" enabled="false">
<parameters>
<parameter name="header"><![CDATA[// Copyright (C) 2011-2012 the original author or authors.
// See the LICENCE.txt file distributed with this work for additional
Expand Down
File renamed without changes.
File renamed without changes.
60 changes: 29 additions & 31 deletions src/main/scala/monitor/App.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package monitor

import styles.Default
import japgolly.scalajs.react.{ReactComponentB, BackendScope}
import japgolly.scalajs.react._
import japgolly.scalajs.react.component.builder.Lifecycle
import japgolly.scalajs.react.vdom.TagMod
import japgolly.scalajs.react.vdom.all._
import monitor.modules._
import monitor.styles.Default
import org.scalajs.dom

import scalacss.ScalaCssReact._

object App {
Expand All @@ -15,12 +18,11 @@ object App {


case class Backend(scope: BackendScope[_, State]) {
def select(module: Module): Unit = {

def select(module: Module): CallbackTo[Unit] =
scope.modState(_.copy(currentView = Some(module)))
}
}

case class Props(views: List[() => ReactTag])
}

def centered(element: TagMod) = div(
display := "flex",
Expand All @@ -34,11 +36,9 @@ object App {
def webgl = {
val canvas = dom.document.createElement("canvas").asInstanceOf[dom.html.Canvas]
val gl = canvas.getContext("webgl").asInstanceOf[dom.webgl.RenderingContext]
div(
for (ext <- gl.getSupportedExtensions()) yield {
div(ext)
}
)
val extensionTags = gl.getSupportedExtensions().map(ext => div(ext))

div(extensionTags:_*)
}

val modules = List(
Expand All @@ -49,27 +49,25 @@ object App {
About
)

val component = ReactComponentB[Unit]("App")
val component = ScalaComponent.builder[Unit]("App")
.initialState(State(Some(CPU)))
.backend(new Backend(_))
.render((p, s, b) => {
div(style.app)(
div(style.sidebar)(
for (module <- modules) yield {
div(
onClick --> {
b.select(module)
},
style.menuItem(s.currentView.map(_ == module).getOrElse(false))
)(
img(style.menuItemIcon)(src := module.iconUrl)
)
}
),
div(style.viewStyle)(
s.currentView.map(_.component).getOrElse(empty)
.backend(Backend.apply)
.render(lifecycle => {
div(style.app)(
div(style.sidebar)(moduleTags(lifecycle): _*),
div(style.viewStyle)(
lifecycle.state.currentView.map(_.component).getOrElse(empty)
)
)
)
}).buildU
}).build


def moduleTags(lifecycle: Lifecycle.RenderScope[Unit, State, Backend]): Seq[TagMod] = modules.map { module =>
div(
onClick --> lifecycle.backend.select(module),
style.menuItem(lifecycle.state.currentView.contains(module))
)(
img(style.menuItemIcon)(src := module.iconUrl)
)
}
}
19 changes: 11 additions & 8 deletions src/main/scala/monitor/SystemMonitor.scala
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
package monitor

import styles.Default
import chrome.app.runtime.bindings.LaunchData
import chrome.app.window.bindings.{BoundsSpecification, CreateWindowOptions}
import chrome.app.window._
import japgolly.scalajs.react.React
import org.scalajs.dom.raw.HTMLStyleElement
import chrome.app.window.bindings.CreateWindowOptions
import chrome.utils.ChromeApp
import monitor.styles.Default
import org.scalajs.dom
import org.scalajs.dom.raw.HTMLStyleElement

import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue
import scalacss.Defaults._
import scalacss.DevDefaults._
import scalacss.ScalaCssReact._

object SystemMonitor extends utils.ChromeApp {
object SystemMonitor extends ChromeApp {

override def onLaunched(launchData: LaunchData): Unit = {
val options = CreateWindowOptions(id = "MainWindow")

Window.create("assets/html/App.html", options).foreach { window =>
window.contentWindow.onload = (e: dom.Event) => {
window.contentWindow.onload = (_: dom.Event) => {
val style = Default.render[HTMLStyleElement]
window.contentWindow.document.head.appendChild(style)
React.render(App.component(), window.contentWindow.document.body)

App.component().renderIntoDOM(window.contentWindow.document.body)
}
}
}
Expand Down
32 changes: 20 additions & 12 deletions src/main/scala/monitor/Timeline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import scala.concurrent.duration.FiniteDuration
import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue
import scala.scalajs.js
import chrome.events.EventSource
import japgolly.scalajs.react.{Callback, CallbackTo}

import scala.collection.mutable
import scala.collection.mutable.ListBuffer

class TickSource[T](val sampleInterval: FiniteDuration, fun: => Future[T]) extends EventSource[T] {

Expand All @@ -22,7 +26,7 @@ class TickSource[T](val sampleInterval: FiniteDuration, fun: => Future[T]) exten
object Timeline {

trait Listener[T] {
def update(value: T): Unit
def update(value: T): CallbackTo[Unit]
}

}
Expand All @@ -31,32 +35,36 @@ class Timeline[T](val sampleCount: Int, val sampleInterval: FiniteDuration)(fun:

import Timeline._

private var _samples: List[T] = List()
private var listeners = collection.mutable.ListBuffer[Listener[Timeline[T]]]()
private var _samples: List[T] = List.empty
private val listeners = mutable.ListBuffer[Listener[Timeline[T]]]()
private var intervalHandler: Option[js.timers.SetIntervalHandle] = None

private def addSample(sample: T): Unit = {
private def addSample(sample: T): ListBuffer[CallbackTo[Unit]] = {
_samples = (sample :: _samples).take(sampleCount)
listeners.map(_.update(this))
}

def samples = _samples

def addListener(listener: Listener[Timeline[T]]) = {
def addListener(listener: Listener[Timeline[T]]) = Callback {
listeners += listener
}

def removeListener(listener: Listener[Timeline[T]]) = {
def removeListener(listener: Listener[Timeline[T]]) = Callback {
listeners -= listener
}

private def tick(): Unit = {
fun.onSuccess { case s => addSample(s) }
}
private def tick(): Future[Unit] = for {
sample <- fun
_ <- Future.traverse(addSample(sample))(_.asAsyncCallback.unsafeToFuture())
} yield ()


def start() = {
if (intervalHandler.isEmpty)
intervalHandler = Some(js.timers.setInterval(sampleInterval)(tick()))

def start() = intervalHandler match {
case None => intervalHandler = Some(js.timers.setInterval(sampleInterval)(tick))
case _ =>
this
}

def stop() = intervalHandler foreach js.timers.clearInterval
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/monitor/modules/About.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package monitor.modules

import japgolly.scalajs.react.vdom.all._
import monitor.ui

object About extends Module {

Expand Down
Loading