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.

222 lines
6.5 KiB

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