First commit
This commit is contained in:
parent
56dac9a58a
commit
e3abe03456
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
*.class
|
||||
*.log
|
||||
|
||||
# sbt specific
|
||||
.cache/
|
||||
.history/
|
||||
.lib/
|
||||
dist/*
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
project/plugins/project/
|
||||
metals.sbt
|
||||
.metals
|
||||
.bloop
|
||||
|
||||
# Scala-IDE specific
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
.idea/
|
||||
.vscode
|
||||
/project/project
|
1
.scalafmt.conf
Normal file
1
.scalafmt.conf
Normal file
@ -0,0 +1 @@
|
||||
version = "2.6.4"
|
24
UNLICENSE
Normal file
24
UNLICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
61
build.sbt
Normal file
61
build.sbt
Normal file
@ -0,0 +1,61 @@
|
||||
// Name of the project
|
||||
name := "ScalaFX Hello World"
|
||||
|
||||
// Project version
|
||||
version := "14-R19"
|
||||
|
||||
// Version of Scala used by the project
|
||||
scalaVersion := "2.13.3"
|
||||
|
||||
// Add dependency on ScalaFX library
|
||||
libraryDependencies += "org.scalafx" %% "scalafx" % "14-R19"
|
||||
resolvers += Resolver.sonatypeRepo("snapshots")
|
||||
|
||||
enablePlugins(JavaFxPlugin)
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"org.typelevel" %% "cats-core" % "2.1.1",
|
||||
"org.typelevel" %% "cats-effect" % "2.1.4",
|
||||
"io.monix" %% "monix" % "3.2.2",
|
||||
"io.monix" %% "monix-bio" % "1.0.0",
|
||||
"io.circe" %% "circe-core" % "0.13.0",
|
||||
"io.circe" %% "circe-generic" % "0.13.0",
|
||||
"com.softwaremill.sttp.client" %% "core" % "2.2.5",
|
||||
"com.softwaremill.sttp.client" %% "monix" % "2.2.5",
|
||||
"com.softwaremill.sttp.client" %% "circe" % "2.2.5",
|
||||
"com.softwaremill.sttp.client" %% "async-http-client-backend-monix" % "2.2.5",
|
||||
"com.github.valskalla" %% "odin-monix" % "0.8.1",
|
||||
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.8",
|
||||
"com.softwaremill.macwire" %% "util" % "2.3.7",
|
||||
"com.softwaremill.macwire" %% "macros" % "2.3.6" % "provided",
|
||||
"com.softwaremill.macwire" %% "macrosakka" % "2.3.6" % "provided",
|
||||
"com.github.valskalla" %% "odin-slf4j" % "0.8.1"
|
||||
)
|
||||
|
||||
scalacOptions ++= Seq(
|
||||
"-unchecked",
|
||||
"-deprecation",
|
||||
"-Xcheckinit",
|
||||
"-encoding",
|
||||
"utf8",
|
||||
"-feature",
|
||||
"-Ywarn-unused:imports"
|
||||
)
|
||||
|
||||
// Fork a new JVM for 'run' and 'test:run', to avoid JavaFX double initialization problems
|
||||
fork := true
|
||||
|
||||
// Determine OS version of JavaFX binaries
|
||||
lazy val osName = System.getProperty("os.name") match {
|
||||
case n if n.startsWith("Linux") => "linux"
|
||||
case n if n.startsWith("Mac") => "mac"
|
||||
case n if n.startsWith("Windows") => "win"
|
||||
case _ => throw new Exception("Unknown platform!")
|
||||
}
|
||||
|
||||
// Add JavaFX dependencies
|
||||
lazy val javaFXModules =
|
||||
Seq("base", "controls", "fxml", "graphics", "media", "swing", "web")
|
||||
libraryDependencies ++= javaFXModules.map(m =>
|
||||
"org.openjfx" % s"javafx-$m" % "14.0.1" classifier osName
|
||||
)
|
2
project/build.properties
Normal file
2
project/build.properties
Normal file
@ -0,0 +1,2 @@
|
||||
sbt.version=1.3.10
|
||||
|
6
project/plugin.sbt
Normal file
6
project/plugin.sbt
Normal file
@ -0,0 +1,6 @@
|
||||
scalacOptions ++= Seq("-unchecked", "-deprecation")
|
||||
|
||||
// [https://github.com/sbt/sbteclipse]
|
||||
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
|
||||
// addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")
|
||||
addSbtPlugin("com.quadstingray" % "sbt-javafx" % "1.5.2")
|
5
src/main/resources/application.conf
Normal file
5
src/main/resources/application.conf
Normal file
@ -0,0 +1,5 @@
|
||||
javafx-dispatcher {
|
||||
type = "Dispatcher"
|
||||
executor = "akka.dispatch.gui.JavaFXEventThreadExecutorServiceConfigurator"
|
||||
throughput = 1
|
||||
}
|
219
src/main/scala/nova/monadic_sfx/SFXActors.scala
Normal file
219
src/main/scala/nova/monadic_sfx/SFXActors.scala
Normal file
@ -0,0 +1,219 @@
|
||||
package nova.monadic_sfx
|
||||
|
||||
import scalafx.application.JFXApp
|
||||
import scalafx.application.JFXApp.PrimaryStage
|
||||
import monix.eval.Task
|
||||
import monix.execution.Scheduler
|
||||
// import sttp.client.asynchttpclient.monix.AsyncHttpClientMonixBackend
|
||||
// import sttp.client._
|
||||
// import sttp.client.circe._
|
||||
// import io.circe.generic.auto._
|
||||
import scala.util.Failure
|
||||
import scala.util.Success
|
||||
import akka.{actor => classic}
|
||||
import nova.monadic_sfx.executors._
|
||||
import cats.effect.Resource
|
||||
import nova.monadic_sfx.models._
|
||||
import nova.monadic_sfx.ui.DefaultUI
|
||||
import nova.monadic_sfx.http.Backend
|
||||
import nova.monadic_sfx.modules.MainModule
|
||||
import scalafx.stage.Stage
|
||||
import scalafx.scene.layout.FlowPane
|
||||
import nova.monadic_sfx.pages.LoginPage
|
||||
import scala.concurrent.duration._
|
||||
import sttp.client.asynchttpclient.monix.AsyncHttpClientMonixBackend
|
||||
import scalafx.Includes._
|
||||
import scala.concurrent.Await
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import scalafx.application.Platform
|
||||
import io.odin.syntax._
|
||||
// import io.odin._
|
||||
import io.odin.monix._
|
||||
import nova.monadic_sfx.pages.HomePage
|
||||
|
||||
object ScalaFXHelloWorld extends JFXApp with MainModule {
|
||||
|
||||
val logger = consoleLogger().withAsyncUnsafe()
|
||||
|
||||
lazy val schedulers: Schedulers = new Schedulers()
|
||||
|
||||
implicit lazy val defaultScheduler: Scheduler = schedulers.fx
|
||||
|
||||
lazy val backendTask = AsyncHttpClientMonixBackend()
|
||||
lazy val actorSystemTask = Task {
|
||||
classic.ActorSystem(
|
||||
name = "FXActorSystem"
|
||||
)
|
||||
}
|
||||
|
||||
lazy val application = for {
|
||||
_ <- logger.info("Starting application..")
|
||||
backend <- backendTask
|
||||
actorSystem <- actorSystemTask
|
||||
// to spawn child actors
|
||||
// _ <- Task { actorSystem.spawn() }
|
||||
appStage <- Task { makePrimaryStage(backend, actorSystem) }
|
||||
// splash screen
|
||||
_ <- Task {
|
||||
// this stage refers to implicit jfx stage
|
||||
// makes this impure, but I can't think of a better way right now
|
||||
stage = appStage
|
||||
}
|
||||
// wait 2 seconds before showing home screen
|
||||
d <- deps
|
||||
fib1 <- d.send().start
|
||||
_ <- Task.sleep(2.seconds)
|
||||
_ <- Task {
|
||||
// appStage.maximized = true
|
||||
appStage.height = 800
|
||||
appStage.width = 800
|
||||
appStage
|
||||
.scene()
|
||||
.setRoot(
|
||||
LoginPage(appStage, backend, actorSystem)
|
||||
)
|
||||
}
|
||||
// _ <- fib1.join
|
||||
} yield ()
|
||||
application.runToFuture
|
||||
.onComplete(res =>
|
||||
res match {
|
||||
case Failure(exception) => {
|
||||
println("Application start failed. Reason -")
|
||||
exception.printStackTrace()
|
||||
}
|
||||
case Success(value) => println("Application started Successfully")
|
||||
}
|
||||
)
|
||||
|
||||
// Task
|
||||
// .suspend {
|
||||
// val program = Task {
|
||||
// stage = new PrimaryStage {
|
||||
// // initStyle(StageStyle.Unified)
|
||||
// title = "ScalaFX Hello World"
|
||||
// scene = defaultUI.scene
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// val backendResource = AsyncHttpClientMonixBackend
|
||||
// .resource()
|
||||
// .use { implicit backend =>
|
||||
// Task
|
||||
// .suspend(
|
||||
// (for {
|
||||
// req <-
|
||||
// basicRequest
|
||||
// .get(uri"https://httpbin.org/get")
|
||||
// .response(asJson[HttpBinResponse])
|
||||
// .send()
|
||||
// } yield println(req)) >>
|
||||
// Task(println(Thread.currentThread().getName()))
|
||||
// )
|
||||
// // .delayExecution(1.second)
|
||||
// }
|
||||
// .executeOn(Scheduler.global)
|
||||
// val akkaResource = Resource
|
||||
// .make(Task {
|
||||
// classic.ActorSystem(
|
||||
// name = "FXActorSystem"
|
||||
// )
|
||||
// })(sys => Task(println("Shutting down actor system")) >> Task(sys.terminate()))
|
||||
// .use { implicit system =>
|
||||
// // system.spa
|
||||
// // system.typed
|
||||
// // val javaFxActor = system.actorOf(
|
||||
// // Props[JavaFxActor]().withDispatcher("javafx-dispatcher"),
|
||||
// // "javaFxActor"
|
||||
// // )
|
||||
// // val swingActor = system.actorOf(
|
||||
// // Props[SwingActor]().withDispatcher("swing-dispatcher"),
|
||||
// // "swingActor"
|
||||
// // )
|
||||
// Task.unit
|
||||
// }
|
||||
// .delayExecution(1.second)
|
||||
// backendResource.start >> akkaResource.start >>
|
||||
// program.to[Task].asyncBoundary >>
|
||||
// Task(println(Thread.currentThread().getName()))
|
||||
// .executeOn(Scheduler.global)
|
||||
// Task.parZip3(
|
||||
// program.to[Task].executeOn(defaultScheduler),
|
||||
// // backendResource,
|
||||
// // dummyRequester.send(),
|
||||
// // akkaResource,
|
||||
// Task(println(Thread.currentThread().getName()))
|
||||
// .executeOn(schedulers.cpu)
|
||||
// )
|
||||
// }
|
||||
// .runToFuture
|
||||
// .onComplete(res =>
|
||||
// res match {
|
||||
// case Failure(exception) => {
|
||||
// println("Application start failed. Reason -")
|
||||
// exception.printStackTrace()
|
||||
// }
|
||||
// case Success(value) => println("Application started Successfully")
|
||||
// }
|
||||
// )
|
||||
|
||||
// new TaskApp {
|
||||
// override protected def scheduler: Scheduler =
|
||||
// JFXExecutionContexts.javaFxScheduler
|
||||
// override def run(args: List[String]): Task[ExitCode] =
|
||||
// Task.suspend {
|
||||
// Task {
|
||||
// AsyncHttpClientMonixBackend().flatMap(implicit backend => {
|
||||
// val req = RequestPayload("").asJson
|
||||
// basicRequest.get(uri"").body(req).send()
|
||||
// })
|
||||
// } >>
|
||||
// program.to[Task].executeOn(JFXExecutionContexts.javaFxScheduler) >>
|
||||
// Task(println(Thread.currentThread().getName()))
|
||||
// .executeOn(Scheduler.global) >>
|
||||
// // Task.unit.asyncBoundary >>
|
||||
// Task.pure(ExitCode.Success)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Task.sleep(3.seconds).flatMap { _ =>
|
||||
//
|
||||
// (for {
|
||||
// req <-
|
||||
// basicRequest
|
||||
// .get(uri"https://httpbin.org/get")
|
||||
// .response(asJson[HttpBinResponse])
|
||||
// .send()
|
||||
// } yield println(req)) >> Task(
|
||||
// println(Thread.currentThread().getName())
|
||||
// ) >>
|
||||
// backend.close()
|
||||
// }
|
||||
//
|
||||
def test(stage: Stage) = {
|
||||
stage.scene().setRoot(new FlowPane())
|
||||
}
|
||||
def makePrimaryStage(
|
||||
backend: AppTypes.HttpBackend,
|
||||
actorSystem: classic.ActorSystem
|
||||
) = {
|
||||
new PrimaryStage {
|
||||
scene = new DefaultUI().scene
|
||||
onCloseRequest = () => {
|
||||
val f2 = actorSystem.terminate()
|
||||
val f1 = backend.close().runToFuture
|
||||
|
||||
println("Closing backend")
|
||||
Await.result(f1, 3.seconds)
|
||||
println("Closing actor system")
|
||||
println(Thread.currentThread().getName())
|
||||
Await.result(f2, 3.seconds)
|
||||
println("Actor system closed")
|
||||
Platform.exit()
|
||||
System.exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
src/main/scala/nova/monadic_sfx/Types.scala
Normal file
13
src/main/scala/nova/monadic_sfx/Types.scala
Normal file
@ -0,0 +1,13 @@
|
||||
package nova.monadic_sfx
|
||||
|
||||
import monix.eval.Task
|
||||
import sttp.client.SttpBackend
|
||||
import monix.reactive.Observable
|
||||
import sttp.client.asynchttpclient.WebSocketHandler
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
trait AppTypes {}
|
||||
object AppTypes {
|
||||
type HttpBackend =
|
||||
SttpBackend[Task, Observable[ByteBuffer], WebSocketHandler]
|
||||
}
|
84
src/main/scala/nova/monadic_sfx/executors/GUIExecutor.scala
Normal file
84
src/main/scala/nova/monadic_sfx/executors/GUIExecutor.scala
Normal file
@ -0,0 +1,84 @@
|
||||
package nova.monadic_sfx.executors
|
||||
|
||||
import akka.dispatch.{
|
||||
DispatcherPrerequisites,
|
||||
ExecutorServiceFactory,
|
||||
ExecutorServiceConfigurator
|
||||
}
|
||||
import com.typesafe.config.Config
|
||||
import java.util.concurrent.{
|
||||
ExecutorService,
|
||||
AbstractExecutorService,
|
||||
ThreadFactory,
|
||||
TimeUnit
|
||||
}
|
||||
import java.util.Collections
|
||||
import javax.swing.SwingUtilities
|
||||
import javafx.application.Platform
|
||||
import monix.execution.Scheduler
|
||||
import scala.concurrent.ExecutionContext
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
// First we wrap invokeLater/runLater as an ExecutorService
|
||||
abstract class GUIExecutorService extends AbstractExecutorService {
|
||||
def execute(command: Runnable): Unit
|
||||
|
||||
def shutdown(): Unit = ()
|
||||
|
||||
def shutdownNow() = Collections.emptyList[Runnable]
|
||||
|
||||
def isShutdown = false
|
||||
|
||||
def isTerminated = false
|
||||
|
||||
def awaitTermination(l: Long, timeUnit: TimeUnit) = true
|
||||
}
|
||||
|
||||
object JavaFXExecutorService extends GUIExecutorService {
|
||||
override def execute(command: Runnable) = Platform.runLater(command)
|
||||
}
|
||||
|
||||
object SwingExecutorService extends GUIExecutorService {
|
||||
override def execute(command: Runnable) = SwingUtilities.invokeLater(command)
|
||||
}
|
||||
|
||||
class JavaFXEventThreadExecutorServiceConfigurator(
|
||||
config: Config,
|
||||
prerequisites: DispatcherPrerequisites
|
||||
) extends ExecutorServiceConfigurator(config, prerequisites) {
|
||||
private val f = new ExecutorServiceFactory {
|
||||
def createExecutorService: ExecutorService = JavaFXExecutorService
|
||||
}
|
||||
|
||||
def createExecutorServiceFactory(
|
||||
id: String,
|
||||
threadFactory: ThreadFactory
|
||||
): ExecutorServiceFactory = f
|
||||
}
|
||||
|
||||
// Then we create an ExecutorServiceConfigurator so that Akka can use our SwingExecutorService for the dispatchers
|
||||
class SwingEventThreadExecutorServiceConfigurator(
|
||||
config: Config,
|
||||
prerequisites: DispatcherPrerequisites
|
||||
) extends ExecutorServiceConfigurator(config, prerequisites) {
|
||||
private val f = new ExecutorServiceFactory {
|
||||
def createExecutorService: ExecutorService = SwingExecutorService
|
||||
}
|
||||
|
||||
def createExecutorServiceFactory(
|
||||
id: String,
|
||||
threadFactory: ThreadFactory
|
||||
): ExecutorServiceFactory = f
|
||||
}
|
||||
|
||||
object JFXExecutionContexts {
|
||||
val javaFxExecutionContext: ExecutionContext =
|
||||
ExecutionContext.fromExecutor(new Executor {
|
||||
def execute(command: Runnable): Unit = {
|
||||
Platform.runLater(command)
|
||||
}
|
||||
})
|
||||
val fxScheduler =
|
||||
Scheduler(javaFxExecutionContext)
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package nova.monadic_sfx.executors
|
||||
|
||||
import monix.execution.Scheduler
|
||||
|
||||
class Schedulers(
|
||||
val blockingIO: Scheduler = Scheduler.io(),
|
||||
val cpu: Scheduler = Scheduler.global,
|
||||
val fx: Scheduler = JFXExecutionContexts.fxScheduler
|
||||
)
|
10
src/main/scala/nova/monadic_sfx/http/Backend.scala
Normal file
10
src/main/scala/nova/monadic_sfx/http/Backend.scala
Normal file
@ -0,0 +1,10 @@
|
||||
package nova.monadic_sfx.http
|
||||
|
||||
import sttp.client.asynchttpclient.monix.AsyncHttpClientMonixBackend
|
||||
import nova.monadic_sfx.AppTypes
|
||||
|
||||
object Backend {
|
||||
val backend = AsyncHttpClientMonixBackend
|
||||
.resource()
|
||||
def apply() = { backend }
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package nova.monadic_sfx.http.requests
|
||||
|
||||
import nova.monadic_sfx.AppTypes
|
||||
|
||||
import nova.monadic_sfx.AppTypes.HttpBackend
|
||||
import monix.eval.Task
|
||||
import sttp.client._
|
||||
import sttp.client.circe._
|
||||
import io.circe.generic.auto._
|
||||
import nova.monadic_sfx.models._
|
||||
|
||||
class DummyRequest(backend: HttpBackend) extends AppTypes {
|
||||
private implicit val _backend = backend
|
||||
def send() = {
|
||||
Task
|
||||
.suspend(
|
||||
(for {
|
||||
req <-
|
||||
basicRequest
|
||||
.get(uri"https://httpbin.org/get")
|
||||
.response(asJson[HttpBinResponse])
|
||||
.send()
|
||||
} yield println(req)) >>
|
||||
Task(println(Thread.currentThread().getName()))
|
||||
)
|
||||
}
|
||||
}
|
8
src/main/scala/nova/monadic_sfx/models/DummyModels.scala
Normal file
8
src/main/scala/nova/monadic_sfx/models/DummyModels.scala
Normal file
@ -0,0 +1,8 @@
|
||||
package nova.monadic_sfx.models
|
||||
|
||||
case class RequestPayload(data: String)
|
||||
final case class HttpBinResponse(
|
||||
url: String,
|
||||
origin: String,
|
||||
headers: Map[String, String]
|
||||
)
|
79
src/main/scala/nova/monadic_sfx/modules/MainModule.scala
Normal file
79
src/main/scala/nova/monadic_sfx/modules/MainModule.scala
Normal file
@ -0,0 +1,79 @@
|
||||
package nova.monadic_sfx.modules
|
||||
|
||||
import nova.monadic_sfx.executors.Schedulers
|
||||
import monix.execution.Scheduler
|
||||
import nova.monadic_sfx.http.requests.DummyRequest
|
||||
import monix.eval.Task
|
||||
import akka.{actor => classic}
|
||||
import cats.effect.Resource
|
||||
import nova.monadic_sfx.AppTypes
|
||||
|
||||
trait MainModule {
|
||||
import com.softwaremill.macwire._
|
||||
// val schedulers: Schedulers = new Schedulers()
|
||||
|
||||
// implicit val defaultScheduler: Scheduler = schedulers.fx
|
||||
|
||||
// val program =
|
||||
// for {
|
||||
// backend <- Backend()
|
||||
// fxActorSystem <-
|
||||
// Resource
|
||||
// .make(Task {
|
||||
// classic.ActorSystem(
|
||||
// name = "FXActorSystem"
|
||||
// )
|
||||
// })(sys => Task(sys.terminate()))
|
||||
|
||||
// } yield {
|
||||
// val dummyRequester = wire[DummyRequest]
|
||||
// dummyRequester.send()
|
||||
// }
|
||||
|
||||
// val program = Backend().use(backend =>
|
||||
// Resource
|
||||
// .make(Task {
|
||||
// classic.ActorSystem(
|
||||
// name = "FXActorSystem"
|
||||
// )
|
||||
// })(sys => Task(sys.terminate()))
|
||||
// .use { implicit system =>
|
||||
// // system.spa
|
||||
// // system.typed
|
||||
// // val javaFxActor = system.actorOf(
|
||||
// // Props[JavaFxActor]().withDispatcher("javafx-dispatcher"),
|
||||
// // "javaFxActor"
|
||||
// // )
|
||||
// // val swingActor = system.actorOf(
|
||||
// // Props[SwingActor]().withDispatcher("swing-dispatcher"),
|
||||
// // "swingActor"
|
||||
// // )
|
||||
// Task(new DummyRequest(backend)) >>
|
||||
// Task.unit
|
||||
// }
|
||||
// )
|
||||
def schedulers: Schedulers
|
||||
|
||||
def defaultScheduler: Scheduler
|
||||
|
||||
def backendTask: Task[AppTypes.HttpBackend]
|
||||
def actorSystemTask: Task[classic.ActorSystem]
|
||||
|
||||
def deps =
|
||||
for {
|
||||
backend <- backendTask
|
||||
actorSystem <- actorSystemTask
|
||||
dummyRequesterTask <- Task {
|
||||
wireDeps(backend, actorSystem)
|
||||
}
|
||||
} yield dummyRequesterTask
|
||||
|
||||
def wireDeps(
|
||||
backend: AppTypes.HttpBackend,
|
||||
system: classic.ActorSystem
|
||||
): DummyRequest = {
|
||||
wire[DummyRequest]
|
||||
// new DummyRequest(backend)
|
||||
}
|
||||
|
||||
}
|
39
src/main/scala/nova/monadic_sfx/pages/HomePage.scala
Normal file
39
src/main/scala/nova/monadic_sfx/pages/HomePage.scala
Normal file
@ -0,0 +1,39 @@
|
||||
package nova.monadic_sfx.pages
|
||||
import nova.monadic_sfx.AppTypes
|
||||
import scalafx.scene.control.TextField
|
||||
import scalafx.scene.control._
|
||||
import scalafx.scene.layout.VBox
|
||||
import scalafx.scene.Node
|
||||
import scalafx.Includes._
|
||||
import scalafx.scene.layout.HBox
|
||||
import scalafx.scene.text.Text
|
||||
import scalafx.scene.Parent
|
||||
import scalafx.application.JFXApp.PrimaryStage
|
||||
|
||||
class HomePage(
|
||||
backend: AppTypes.HttpBackend,
|
||||
system: akka.actor.ActorSystem,
|
||||
onLogout: () => Unit
|
||||
) {
|
||||
private lazy val root = new HBox {
|
||||
children = List(
|
||||
new Text {
|
||||
text = "hello"
|
||||
},
|
||||
new Button {
|
||||
text = "logout"
|
||||
onAction = () => onLogout()
|
||||
}
|
||||
)
|
||||
}
|
||||
def render = root
|
||||
}
|
||||
|
||||
object HomePage {
|
||||
def apply(
|
||||
backend: AppTypes.HttpBackend,
|
||||
system: akka.actor.ActorSystem,
|
||||
onLogout: () => Unit
|
||||
): Parent =
|
||||
new HomePage(backend, system, onLogout).render
|
||||
}
|
57
src/main/scala/nova/monadic_sfx/pages/LoginPage.scala
Normal file
57
src/main/scala/nova/monadic_sfx/pages/LoginPage.scala
Normal file
@ -0,0 +1,57 @@
|
||||
package nova.monadic_sfx.pages
|
||||
import nova.monadic_sfx.AppTypes
|
||||
import scalafx.scene.control.TextField
|
||||
import scalafx.scene.control._
|
||||
import scalafx.scene.layout.VBox
|
||||
import scalafx.scene.Node
|
||||
import scalafx.Includes._
|
||||
import scalafx.scene.Parent
|
||||
import scalafx.application.JFXApp.PrimaryStage
|
||||
// import io.odin.syntax._
|
||||
// import _root_.monix.eval.Task
|
||||
// import io.odin.monix._
|
||||
// import javafx.beans.property.ObjectProperty
|
||||
// import javafx.event.{ActionEvent, EventHandler}
|
||||
class LoginPage(
|
||||
appStage: PrimaryStage,
|
||||
backend: AppTypes.HttpBackend,
|
||||
system: akka.actor.ActorSystem
|
||||
) {
|
||||
|
||||
//pure function callbacks, but with side effects still
|
||||
private def onLogout(stage: PrimaryStage) = {
|
||||
println("logging out")
|
||||
stage.scene().setRoot(render)
|
||||
}
|
||||
private def onLogin(stage: PrimaryStage) = {
|
||||
println("logging in")
|
||||
stage
|
||||
.scene()
|
||||
.setRoot(HomePage(backend, system, () => onLogout(appStage)))
|
||||
}
|
||||
private lazy val root = new VBox {
|
||||
children = Seq(
|
||||
new TextField {
|
||||
text = "username"
|
||||
editable = true
|
||||
},
|
||||
new TextField {
|
||||
text = "password"
|
||||
},
|
||||
new Button {
|
||||
text = "Login"
|
||||
onAction = () => onLogin(appStage)
|
||||
}
|
||||
)
|
||||
}
|
||||
def render: Parent = root
|
||||
|
||||
}
|
||||
|
||||
object LoginPage {
|
||||
def apply(
|
||||
appStage: PrimaryStage,
|
||||
backend: AppTypes.HttpBackend,
|
||||
system: akka.actor.ActorSystem
|
||||
) = new LoginPage(appStage, backend, system).render
|
||||
}
|
55
src/main/scala/nova/monadic_sfx/ui/DefaultUI.scala
Normal file
55
src/main/scala/nova/monadic_sfx/ui/DefaultUI.scala
Normal file
@ -0,0 +1,55 @@
|
||||
package nova.monadic_sfx.ui
|
||||
|
||||
import scalafx.geometry.Insets
|
||||
import scalafx.scene.Scene
|
||||
import scalafx.scene.effect.DropShadow
|
||||
import scalafx.scene.layout.HBox
|
||||
import scalafx.scene.paint.Color._
|
||||
import scalafx.scene.paint._
|
||||
import scalafx.scene.text.Text
|
||||
import monix.eval.Coeval
|
||||
|
||||
class DefaultUI {
|
||||
val scene =
|
||||
new Scene {
|
||||
fill = Color.rgb(38, 38, 38)
|
||||
content = new HBox {
|
||||
padding = Insets(50, 80, 50, 80)
|
||||
children = Seq(
|
||||
new Text {
|
||||
text = "Scala"
|
||||
style = "-fx-font: normal bold 100pt sans-serif"
|
||||
fill = new LinearGradient(endX = 0, stops = Stops(Red, DarkRed))
|
||||
},
|
||||
new Text {
|
||||
text = "FX"
|
||||
style = "-fx-font: italic bold 100pt sans-serif"
|
||||
fill = new LinearGradient(
|
||||
endX = 0,
|
||||
stops = Stops(White, DarkGray)
|
||||
)
|
||||
effect = new DropShadow {
|
||||
color = DarkGray
|
||||
radius = 15
|
||||
spread = 0.25
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// val program = Coeval
|
||||
// .suspend {
|
||||
// Coeval(println("hello")) >>
|
||||
// Coeval(println(Thread.currentThread().getName())) >>
|
||||
// Coeval {
|
||||
// stage = new PrimaryStage {
|
||||
// // initStyle(StageStyle.Unified)
|
||||
// title = "ScalaFX Hello World"
|
||||
// scene = scn
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
36
src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
Normal file
36
src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
Normal file
@ -0,0 +1,36 @@
|
||||
package org.slf4j.impl
|
||||
|
||||
import cats.effect.{ContextShift, Clock, Effect, IO, Timer}
|
||||
import io.odin._
|
||||
import io.odin.slf4j.OdinLoggerBinder
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
import _root_.monix.execution.Scheduler
|
||||
|
||||
//effect type should be specified inbefore
|
||||
//log line will be recorded right after the call with no suspension
|
||||
class StaticLoggerBinder extends OdinLoggerBinder[IO] {
|
||||
|
||||
val ec: ExecutionContext = Scheduler.global
|
||||
implicit val timer: Timer[IO] = IO.timer(ec)
|
||||
implicit val clock: Clock[IO] = timer.clock
|
||||
implicit val cs: ContextShift[IO] = IO.contextShift(ec)
|
||||
implicit val F: Effect[IO] = IO.ioEffect
|
||||
|
||||
val loggers: PartialFunction[String, Logger[IO]] = {
|
||||
case "some.external.package.SpecificClass" =>
|
||||
consoleLogger[IO](minLevel = Level.Warn) //disable noisy external logs
|
||||
case "org.asynchttpclient.netty.channel.DefaultChannelPool" =>
|
||||
consoleLogger[IO](minLevel = Level.Warn)
|
||||
case _ => //if wildcard case isn't provided, default logger is no-op
|
||||
consoleLogger[IO]()
|
||||
}
|
||||
}
|
||||
|
||||
object StaticLoggerBinder extends StaticLoggerBinder {
|
||||
|
||||
var REQUESTED_API_VERSION: String = "1.7"
|
||||
|
||||
def getSingleton: StaticLoggerBinder = this
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user