package outwatchapp import scala.concurrent.duration._ import colibri.ext.monix._ import com.softwaremill.macwire._ import io.odin.consoleLogger import monix.bio.Task import monix.eval.Coeval import monix.reactive.Observable import monix.{eval => me} import org.scalajs.dom.raw.Element import outwatch._ import outwatch.dsl._ import outwatch.router._ import outwatchapp.components.ChartjsDemo import outwatchapp.components.CounterDemo import outwatchapp.components.DatatablesDemo import outwatchapp.components.FusejsDemo import outwatchapp.components.RequestDemo import outwatchapp.pages.HomePage import outwatchapp.ui.components.todo.TodoListStore import outwatchapp.util.IOUtils import outwatchapp.util.reactive.WebSocket import outwatchapp.util.reactive.WebWorker import outwatchapp.util.reactive.WebsocketData import outwatchapp.util.reactive.WorkerData import outwatchapp.util.reactive.ReconnectingWebSocket import cats.syntax.eq._ import monix.execution.Ack import monix.reactive.Observer class MainApp(el: Element)(implicit backend: AppTypes.Backend, store: RouterStore[Page] ) { import MainApp._ def run: Task[Unit] = for { resolver <- resolver _ <- OutWatch.renderInto[Task](el, Router(resolver)) } yield () def producer(data: Long, ws: Observer[WebsocketData]): me.Task[Unit] = me.Task.deferFuture(ws.onNext(WebsocketData(data))).flatMap { case Ack.Continue => producer(data + 1, ws) // .delayExecution(3.seconds) case Ack.Stop => me.Task.unit } def resolver: Task[PartialFunction[Page, VDomModifier]] = Task.deferAction(implicit s => for { counterDemo <- CounterDemo() chartDemo <- ChartjsDemo() todoStore <- TodoListStore(consoleLogger[Task]()) requestDemo <- RequestDemo(todoStore) demoWorker <- WebWorker[WorkerData]("/worker.js") dtDemo <- DatatablesDemo() _ <- IOUtils .toIO( Observable .interval(1.second) .take(2) .doOnNextF(i => Coeval(println(s"Producer emitted $i"))) .doOnNextF(i => me.Task.deferFuture(demoWorker.onNext(WorkerData(i))).void ) .completedL >> me.Task.deferFuture(demoWorker.onNext(WorkerData(999))) // .delayExecution(6.seconds) ) .startAndForget _ <- ReconnectingWebSocket[WebsocketData]("ws://localhost:6789").flatMap { case (source, sink) => IOUtils .toIO( me.Task.parZip2( // Observable // .interval(3.seconds) // .doOnNext(_ => me.Task(println("Sending websocket data"))) // .doOnNext(i => // me.Task.deferFuture( // ws.onNext(WebsocketData(i)) // ) >> me.Task.unit // ) // .completedL, producer(0, sink.value), source.value .doOnNext(data => me.Task(println(s"Received : $data"))) .completedL ) ) } // .onErrorRestartIf { // case e: Exception => // e.getMessage() === "Websocket closed" // case _ => false // } // .onErrorRestartLoop(Backoff(3, 1.second)) { (err, state, retry) => // val Backoff(maxRetries, delay) = state // if (maxRetries > 0) // retry(Backoff(maxRetries - 1, delay * 2)).delayExecution(delay) // else // // No retries left, rethrow the error // Task.raiseError(err) // } .startAndForget // .start // .startAndForget // _ <- SweetAlertDemo.dumbNotif // _ <- Task(println(s"Notif result: $notifRes")) } yield { case Page.Home => wire[HomePage].render case Page.SomePage => div( div(cls := "title", "SomePage"), // RequestDemo(todoStore), // Observable // .interval(1.second) // .doOnNextF(i => Coeval(println(s"Producer emitted $i"))) // .doOnNextF(i => // Coeval(demoWorker.onNext(WorkerData(i))) >> Coeval.unit // ) // .take(2) // .map(_ => div()), demoWorker.map(_.toString).map(v => p(cls := "text-white", v)), requestDemo, div(cls := "slider") ) case Page.UserHome(id) => div( // cls := "text-white", div(cls := "title", "UserHome"), s"User id: $id", div(FusejsDemo.y.map(_.item.toString).mkString(" ")), // ExampleDataTable.value( // onDomMount.asHtml.foreachSync(el => // Coeval(DatatablesDemo.init(el)) >> Coeval.unit // ) // ) dtDemo ) case Page.NotFound => Task( div( cls := "page-header error-page header-filter", div( cls := "page-header-image" // style := js.Dictionary( // "background-image" -> "url('../assets/img/braden-collum.jpg')" // ) ), div( cls := "container", cls := "text-center", div( cls := "row", div( cls := "col-md-12", h1( fontSize := "12em", color := "#fff", letterSpacing := "14px", fontWeight := 700, cls := "title", "404" ), h2(cls := "description", "Page not found :("), h4( cls := "description", "Ooooups! Looks like you got lost." ) ) ) ) ) ) } ) } object MainApp { final case class Backoff(maxRetries: Long, delay: FiniteDuration) }