You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
6.7 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package nova.monadic_sfx
  2. import scalafx.application.JFXApp
  3. import scalafx.application.JFXApp.PrimaryStage
  4. import monix.eval.Task
  5. import monix.execution.Scheduler
  6. // import sttp.client.asynchttpclient.monix.AsyncHttpClientMonixBackend
  7. // import sttp.client._
  8. // import sttp.client.circe._
  9. // import io.circe.generic.auto._
  10. import scala.util.Failure
  11. import scala.util.Success
  12. import akka.{actor => classic}
  13. import nova.monadic_sfx.executors._
  14. import cats.effect.Resource
  15. import nova.monadic_sfx.models._
  16. import nova.monadic_sfx.ui.DefaultUI
  17. import nova.monadic_sfx.http.Backend
  18. import nova.monadic_sfx.modules.MainModule
  19. import scalafx.stage.Stage
  20. import scalafx.scene.layout.FlowPane
  21. import nova.monadic_sfx.pages.LoginPage
  22. import scala.concurrent.duration._
  23. import sttp.client.asynchttpclient.monix.AsyncHttpClientMonixBackend
  24. import scalafx.Includes._
  25. import scala.concurrent.Await
  26. import akka.actor.typed.scaladsl.adapter._
  27. import scalafx.application.Platform
  28. import io.odin.syntax._
  29. // import io.odin._
  30. import io.odin.monix._
  31. import nova.monadic_sfx.pages.HomePage
  32. import monix.execution.Callback
  33. object Main extends JFXApp with MainModule {
  34. val logger = consoleLogger().withAsyncUnsafe()
  35. lazy val schedulers: Schedulers = new Schedulers()
  36. implicit lazy val defaultScheduler: Scheduler = schedulers.fx
  37. lazy val backendTask = AsyncHttpClientMonixBackend()
  38. lazy val actorSystemTask = Task {
  39. classic.ActorSystem(
  40. name = "FXActorSystem"
  41. )
  42. }
  43. lazy val application = for {
  44. _ <- logger.info("Starting application..")
  45. backend <- backendTask
  46. actorSystem <- actorSystemTask
  47. // to spawn child actors
  48. // _ <- Task { actorSystem.spawn() }
  49. appStage <- Task { makePrimaryStage(backend, actorSystem) }
  50. // splash screen
  51. _ <- Task {
  52. // this stage refers to implicit jfx stage
  53. // makes this impure, but I can't think of a better way right now
  54. stage = appStage
  55. }
  56. // wait 2 seconds before showing home screen
  57. // d <- deps
  58. // fib1 <- d.send().start
  59. _ <- Task.sleep(2.seconds)
  60. loginScene <- LoginPage(appStage, backend, actorSystem)
  61. _ <- Task {
  62. // appStage.maximized = true
  63. appStage.height = 800
  64. appStage.width = 800
  65. appStage
  66. .scene()
  67. .setRoot(
  68. loginScene
  69. )
  70. }
  71. // _ <- fib1.join
  72. } yield ()
  73. application.timed.runAsync(
  74. new Callback[Throwable, (FiniteDuration, Unit)] {
  75. override def onSuccess(value: (FiniteDuration, Unit)): Unit = {
  76. val (duration, _) = value
  77. println(
  78. s"Application started successfully in ${duration.toSeconds} seconds"
  79. )
  80. }
  81. override def onError(e: Throwable): Unit = {
  82. println("Application start failed. Reason -")
  83. e.printStackTrace()
  84. }
  85. }
  86. )
  87. // Task
  88. // .suspend {
  89. // val program = Task {
  90. // stage = new PrimaryStage {
  91. // // initStyle(StageStyle.Unified)
  92. // title = "ScalaFX Hello World"
  93. // scene = defaultUI.scene
  94. // }
  95. // }
  96. // val backendResource = AsyncHttpClientMonixBackend
  97. // .resource()
  98. // .use { implicit backend =>
  99. // Task
  100. // .suspend(
  101. // (for {
  102. // req <-
  103. // basicRequest
  104. // .get(uri"https://httpbin.org/get")
  105. // .response(asJson[HttpBinResponse])
  106. // .send()
  107. // } yield println(req)) >>
  108. // Task(println(Thread.currentThread().getName()))
  109. // )
  110. // // .delayExecution(1.second)
  111. // }
  112. // .executeOn(Scheduler.global)
  113. // val akkaResource = Resource
  114. // .make(Task {
  115. // classic.ActorSystem(
  116. // name = "FXActorSystem"
  117. // )
  118. // })(sys => Task(println("Shutting down actor system")) >> Task(sys.terminate()))
  119. // .use { implicit system =>
  120. // // system.spa
  121. // // system.typed
  122. // // val javaFxActor = system.actorOf(
  123. // // Props[JavaFxActor]().withDispatcher("javafx-dispatcher"),
  124. // // "javaFxActor"
  125. // // )
  126. // // val swingActor = system.actorOf(
  127. // // Props[SwingActor]().withDispatcher("swing-dispatcher"),
  128. // // "swingActor"
  129. // // )
  130. // Task.unit
  131. // }
  132. // .delayExecution(1.second)
  133. // backendResource.start >> akkaResource.start >>
  134. // program.to[Task].asyncBoundary >>
  135. // Task(println(Thread.currentThread().getName()))
  136. // .executeOn(Scheduler.global)
  137. // Task.parZip3(
  138. // program.to[Task].executeOn(defaultScheduler),
  139. // // backendResource,
  140. // // dummyRequester.send(),
  141. // // akkaResource,
  142. // Task(println(Thread.currentThread().getName()))
  143. // .executeOn(schedulers.cpu)
  144. // )
  145. // }
  146. // .runToFuture
  147. // .onComplete(res =>
  148. // res match {
  149. // case Failure(exception) => {
  150. // println("Application start failed. Reason -")
  151. // exception.printStackTrace()
  152. // }
  153. // case Success(value) => println("Application started Successfully")
  154. // }
  155. // )
  156. // new TaskApp {
  157. // override protected def scheduler: Scheduler =
  158. // JFXExecutionContexts.javaFxScheduler
  159. // override def run(args: List[String]): Task[ExitCode] =
  160. // Task.suspend {
  161. // Task {
  162. // AsyncHttpClientMonixBackend().flatMap(implicit backend => {
  163. // val req = RequestPayload("").asJson
  164. // basicRequest.get(uri"").body(req).send()
  165. // })
  166. // } >>
  167. // program.to[Task].executeOn(JFXExecutionContexts.javaFxScheduler) >>
  168. // Task(println(Thread.currentThread().getName()))
  169. // .executeOn(Scheduler.global) >>
  170. // // Task.unit.asyncBoundary >>
  171. // Task.pure(ExitCode.Success)
  172. // }
  173. // }
  174. // }
  175. // Task.sleep(3.seconds).flatMap { _ =>
  176. //
  177. // (for {
  178. // req <-
  179. // basicRequest
  180. // .get(uri"https://httpbin.org/get")
  181. // .response(asJson[HttpBinResponse])
  182. // .send()
  183. // } yield println(req)) >> Task(
  184. // println(Thread.currentThread().getName())
  185. // ) >>
  186. // backend.close()
  187. // }
  188. //
  189. def test(stage: Stage) = {
  190. stage.scene().setRoot(new FlowPane())
  191. }
  192. def makePrimaryStage(
  193. backend: AppTypes.HttpBackend,
  194. actorSystem: classic.ActorSystem
  195. ) = {
  196. new PrimaryStage {
  197. scene = new DefaultUI().scene
  198. onCloseRequest = () => {
  199. val f2 = actorSystem.terminate()
  200. val f1 = backend.close().runToFuture
  201. println("Closing backend")
  202. Await.result(f1, 3.seconds)
  203. println("Closing actor system")
  204. println(Thread.currentThread().getName())
  205. Await.result(f2, 3.seconds)
  206. println("Actor system closed")
  207. Platform.exit()
  208. System.exit(0)
  209. }
  210. }
  211. }
  212. }