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.timed.runToFuture .onComplete(res => res match { case Failure(exception) => { println("Application start failed. Reason -") exception.printStackTrace() } case Success((duration, _)) => println( s"Application started successfully in ${duration.toSeconds} seconds" ) } ) // 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) } } } }