Cleanup and added some methods to actionObservable
This commit is contained in:
parent
f95f50574e
commit
857fd03bf1
@ -12,8 +12,8 @@ import com.softwaremill.macwire._
|
||||
import io.odin._
|
||||
import io.odin.syntax._
|
||||
import nova.monadic_sfx.executors._
|
||||
import nova.monadic_sfx.util.IOUtils._
|
||||
import sttp.client.httpclient.monix.HttpClientMonixBackend
|
||||
// import nova.monadic_sfx.util.IOUtils._
|
||||
// import sttp.client.httpclient.monix.HttpClientMonixBackend
|
||||
object Main extends MainModule with BIOApp {
|
||||
|
||||
def appResource(startTime: Long) =
|
||||
|
@ -7,6 +7,7 @@ import nova.monadic_sfx.executors.Schedulers
|
||||
import nova.monadic_sfx.implicits.JFXButton
|
||||
import nova.monadic_sfx.implicits.JavaFXMonixObservables._
|
||||
import nova.monadic_sfx.ui.MyFxApp
|
||||
import nova.monadic_sfx.ui.components.todo.TodoListStore
|
||||
import nova.monadic_sfx.ui.components.todo.TodoListView
|
||||
import org.gerweck.scalafx.util._
|
||||
import scalafx.Includes._
|
||||
@ -21,7 +22,6 @@ import scalafx.scene.control.TableView
|
||||
import scalafx.scene.layout.HBox
|
||||
import scalafx.scene.paint.Color
|
||||
import scalafx.scene.shape.Rectangle
|
||||
import nova.monadic_sfx.ui.components.todo.TodoListStore
|
||||
|
||||
class MainApp(
|
||||
// spawnProtocol: ActorSystem[SpawnProtocol.Command],
|
||||
@ -131,8 +131,8 @@ class MainApp(
|
||||
def createTodoComponent: Task[Unit] =
|
||||
for {
|
||||
store <- TodoListStore(logger)
|
||||
lv <- TodoListView(store)
|
||||
_ <- Task(_scene.getChildren += lv)
|
||||
rootNode <- TodoListView(store)
|
||||
_ <- Task(_scene.getChildren += rootNode)
|
||||
} yield ()
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
package nova.monadic_sfx.implicits
|
||||
|
||||
import monix.execution.Scheduler
|
||||
import monix.reactive.Observable
|
||||
import monix.reactive.Observer
|
||||
import monix.{eval => me}
|
||||
import monix.execution.Scheduler
|
||||
|
||||
class ActionObservableExecuter[T](
|
||||
delegate: Observable[T]
|
||||
) {
|
||||
class ActionObservableExecutor[T](
|
||||
private val delegate: Observable[T]
|
||||
) extends AnyVal {
|
||||
def -->(sub: Observer[T])(implicit s: Scheduler) =
|
||||
delegate
|
||||
.doOnNext(el => me.Task(sub.onNext(el)))
|
||||
@ -15,23 +15,69 @@ class ActionObservableExecuter[T](
|
||||
|
||||
}
|
||||
class ActionObservableBuilder[A](
|
||||
observableAction: Observable[A]
|
||||
) {
|
||||
def useLazy[T](v: => T) =
|
||||
new ActionObservableExecuter[T](observableAction.mapEval(_ => me.Task(v)))
|
||||
private val observableAction: Observable[A]
|
||||
) extends AnyVal {
|
||||
def useLazyEval[T](v: => me.Task[T]) =
|
||||
new ActionObservableExecutor[T](observableAction.mapEval(_ => v))
|
||||
|
||||
def use[T](cb: A => T) =
|
||||
new ActionObservableExecuter[T](
|
||||
observableAction.mapEval(ae => me.Task(cb(ae)))
|
||||
def useEval[T](cb: A => me.Task[T]) =
|
||||
new ActionObservableExecutor[T](
|
||||
observableAction.mapEval(cb)
|
||||
)
|
||||
|
||||
def useIterable[T](cb: A => collection.immutable.Iterable[T]) =
|
||||
new ActionObservableExecuter[T](
|
||||
def useIterableEval[T](cb: A => collection.immutable.Iterable[T]) =
|
||||
new ActionObservableExecutor[T](
|
||||
observableAction.flatMap(a =>
|
||||
Observable.suspend(Observable.fromIterable(cb(a)))
|
||||
)
|
||||
)
|
||||
|
||||
def map[B](cb: A => B) =
|
||||
new ActionObservableBuilder(observableAction.mapEval(v => me.Task(cb(v))))
|
||||
def doOnNext(cb: A => me.Task[Unit]): ActionObservableBuilder[A] =
|
||||
new ActionObservableBuilder(observableAction.doOnNext(cb))
|
||||
|
||||
def mapEval[B](cb: A => me.Task[B]) =
|
||||
new ActionObservableBuilder(observableAction.mapEval(cb))
|
||||
|
||||
def underlying = observableAction
|
||||
|
||||
// def publish[B](f: Observable[A] => Observable[B]) =
|
||||
// new ActionObservableBuilder(observableAction.publishSelector(f))
|
||||
|
||||
def useEval2[B, C](f: A => me.Task[B], g: A => me.Task[C]) =
|
||||
new ActionObservableExecutor[(B, C)](
|
||||
observableAction.publishSelector(conn =>
|
||||
conn
|
||||
.mapEval(f)
|
||||
.switchMap(b =>
|
||||
conn.mapEval(a =>
|
||||
for {
|
||||
c <- g(a)
|
||||
} yield (b, c)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def bifurcate[B, C](
|
||||
f: ActionObservableBuilder[A] => B,
|
||||
g: ActionObservableBuilder[A] => C
|
||||
)(implicit s: Scheduler) =
|
||||
observableAction
|
||||
.publishSelector(conn =>
|
||||
Observable(
|
||||
Observable.unit.doOnNext(_ =>
|
||||
me.Task(f(new ActionObservableBuilder[A](conn))) >> me.Task.unit
|
||||
),
|
||||
Observable.unit.doOnNext(_ =>
|
||||
me.Task(g(new ActionObservableBuilder[A](conn))) >> me.Task.unit
|
||||
)
|
||||
).merge
|
||||
)
|
||||
.subscribe()
|
||||
|
||||
// def useEval2[B,C](a1: ActionObservableBuilder[A] => B, a2: ActionObservableBuilder[A] => C) = observableAction.publishSelector(conn =>
|
||||
// new ActionObservableBuilder[]
|
||||
// )
|
||||
}
|
||||
|
||||
// class MappedActionExecutor(actionMap: Map[])
|
||||
|
@ -14,9 +14,6 @@ object JFXButton {
|
||||
if (v != null) v.delegate else null
|
||||
}
|
||||
|
||||
// extends ButtonBase(delegate)
|
||||
// with SFXDelegate[jfoenixc.JFXButton]
|
||||
|
||||
class JFXButton(
|
||||
override val delegate: jfoenixc.JFXButton = new jfoenixc.JFXButton
|
||||
) extends Button(delegate) {
|
||||
|
@ -2,6 +2,8 @@ package nova.monadic_sfx.implicits
|
||||
|
||||
import javafx.beans.property.ObjectProperty
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.event.ActionEvent
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.{input => jfxsi}
|
||||
import javafx.{event => jfxe}
|
||||
import monix.bio.Task
|
||||
@ -13,18 +15,15 @@ import monix.reactive.Observer
|
||||
import monix.reactive.OverflowStrategy
|
||||
import monix.tail.Iterant
|
||||
import monix.{eval => me}
|
||||
import org.gerweck.scalafx.util._
|
||||
import scalafx.Includes._
|
||||
import scalafx.beans.property.Property
|
||||
import scalafx.beans.property.ReadOnlyProperty
|
||||
import scalafx.beans.value.ObservableValue
|
||||
import scalafx.collections.ObservableBuffer
|
||||
import scalafx.scene.Scene
|
||||
import scalafx.scene.control.ButtonBase
|
||||
import scalafx.beans.property.ReadOnlyProperty
|
||||
import javafx.event.ActionEvent
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.{control => jfxsc}
|
||||
import scalafx.scene.control.MenuItem
|
||||
import org.gerweck.scalafx.util._
|
||||
|
||||
object JavaFXMonixObservables {
|
||||
|
||||
@ -80,8 +79,8 @@ object JavaFXMonixObservables {
|
||||
op.onNext(prop.value)
|
||||
}
|
||||
|
||||
def -->(op: Property[T, J]) = {
|
||||
op() = prop.value
|
||||
def ==>(op: Property[T, J]) = {
|
||||
op <== prop
|
||||
}
|
||||
|
||||
def <--(obs: Observable[T])(implicit s: Scheduler) = {
|
||||
@ -90,13 +89,12 @@ object JavaFXMonixObservables {
|
||||
|
||||
def asOption = prop.map(Option(_))
|
||||
|
||||
def observableChange[J1 >: J]()
|
||||
: Observable[(ObservableValue[T, J], J1, J1)] = {
|
||||
def observableChange[J1 >: J](): Observable[J1] = {
|
||||
import monix.execution.cancelables.SingleAssignCancelable
|
||||
Observable.create(OverflowStrategy.Unbounded) { sub =>
|
||||
val c = SingleAssignCancelable()
|
||||
|
||||
val canc = prop.onChange((a, b, c) => sub.onNext((a, b, c)))
|
||||
val canc = prop.onChange((a, b, c) => sub.onNext(c))
|
||||
|
||||
c := Cancelable(() => canc.cancel())
|
||||
c
|
||||
@ -107,18 +105,9 @@ object JavaFXMonixObservables {
|
||||
implicit final class BindObs2[A](private val prop: ObjectProperty[A])
|
||||
extends AnyVal {
|
||||
|
||||
// def -->(sub: Var[A]) =
|
||||
// prop.onChange((a, b, c) => sub := c)
|
||||
|
||||
def -->(sub: Observer[A]) =
|
||||
prop.onChange((a, b, c) => if (c != null) sub.onNext(c))
|
||||
|
||||
// def -->[J1 >: A, T](
|
||||
// op: Observable[J1] => me.Task[T]
|
||||
// )(implicit s: Scheduler) = {
|
||||
// op(prop.observableChange().map(_._3)).runToFuture
|
||||
// }
|
||||
|
||||
def -->(op: Property[A, A]) = {
|
||||
prop.onChange((a, b, c) => if (c != null) op() = c)
|
||||
}
|
||||
@ -147,21 +136,16 @@ object JavaFXMonixObservables {
|
||||
op.onNext(prop.value)
|
||||
}
|
||||
|
||||
def -->(op: Property[T, J]) = {
|
||||
def ==>(op: Property[T, J]) = {
|
||||
op <== prop
|
||||
}
|
||||
|
||||
// def <--(obs: Observable[T])(implicit s: Scheduler) = {
|
||||
// obs.doOnNext(v => me.Task(prop.value = v)).subscribe()
|
||||
// }
|
||||
|
||||
def observableChange[J1 >: J]()
|
||||
: Observable[(ObservableValue[T, J], J1, J1)] = {
|
||||
def observableChange[J1 >: J](): Observable[J1] = {
|
||||
import monix.execution.cancelables.SingleAssignCancelable
|
||||
Observable.create(OverflowStrategy.Unbounded) { sub =>
|
||||
val c = SingleAssignCancelable()
|
||||
|
||||
val canc = prop.onChange((a, b, c) => sub.onNext((a, b, c)))
|
||||
val canc = prop.onChange((a, b, c) => sub.onNext(c))
|
||||
|
||||
c := Cancelable(() => canc.cancel())
|
||||
c
|
||||
@ -227,17 +211,6 @@ object JavaFXMonixObservables {
|
||||
implicit final class OnActionObservable(
|
||||
private val button: ButtonBase
|
||||
) extends AnyVal {
|
||||
// def -->[T](
|
||||
// op: Observable[jfxe.ActionEvent] => me.Task[T]
|
||||
// )(implicit s: Scheduler) = {
|
||||
// op(button.observableAction()).runToFuture
|
||||
// }
|
||||
|
||||
// def -->(
|
||||
// sub: ConcurrentSubject[jfxe.ActionEvent, jfxe.ActionEvent]
|
||||
// ) = {
|
||||
// button.onAction = value => sub.onNext(value)
|
||||
// }
|
||||
|
||||
def observableAction(): Observable[jfxe.ActionEvent] = {
|
||||
import monix.execution.cancelables.SingleAssignCancelable
|
||||
@ -262,19 +235,8 @@ object JavaFXMonixObservables {
|
||||
}
|
||||
|
||||
implicit final class MenuItemActionObservable(
|
||||
private val et: MenuItem
|
||||
private val item: MenuItem
|
||||
) extends AnyVal {
|
||||
// def -->[T](
|
||||
// op: Observable[jfxe.ActionEvent] => me.Task[T]
|
||||
// )(implicit s: Scheduler) = {
|
||||
// op(button.observableAction()).runToFuture
|
||||
// }
|
||||
|
||||
// def -->(
|
||||
// sub: ConcurrentSubject[jfxe.ActionEvent, jfxe.ActionEvent]
|
||||
// ) = {
|
||||
// button.onAction = value => sub.onNext(value)
|
||||
// }
|
||||
|
||||
def observableAction(): Observable[jfxe.ActionEvent] = {
|
||||
import monix.execution.cancelables.SingleAssignCancelable
|
||||
@ -286,9 +248,9 @@ object JavaFXMonixObservables {
|
||||
}
|
||||
}
|
||||
|
||||
et.onAction = l
|
||||
item.onAction = l
|
||||
c := Cancelable(() =>
|
||||
et.removeEventHandler(
|
||||
item.removeEventHandler(
|
||||
jfxe.ActionEvent.ACTION,
|
||||
l
|
||||
)
|
||||
|
@ -1,8 +1,9 @@
|
||||
package nova.monadic_sfx.implicits
|
||||
|
||||
import JavaFXMonixObservables._
|
||||
import scalafx.scene.{control => sfxc}
|
||||
|
||||
import JavaFXMonixObservables._
|
||||
|
||||
class MenuItem extends sfxc.MenuItem {
|
||||
def obsAction =
|
||||
new ActionObservableBuilder(this.observableAction())
|
||||
|
@ -14,6 +14,7 @@ import nova.monadic_sfx.implicits.FontIcon
|
||||
import nova.monadic_sfx.implicits.IconLiteral
|
||||
import nova.monadic_sfx.implicits.JFXListView
|
||||
import nova.monadic_sfx.implicits.JavaFXMonixObservables._
|
||||
import nova.monadic_sfx.util.reactive._
|
||||
import scalafx.Includes._
|
||||
import scalafx.beans.property.StringProperty
|
||||
import scalafx.collections.ObservableBuffer
|
||||
@ -23,7 +24,6 @@ import scalafx.scene.control.MenuItem
|
||||
import scalafx.scene.control.SelectionMode
|
||||
import scalafx.scene.layout.HBox
|
||||
import scalafx.scene.text.Text
|
||||
import nova.monadic_sfx.util.reactive._
|
||||
|
||||
class TodoListViewOld(
|
||||
val listView: JFXListView[Todo] = TodoListViewOld.defaultListView,
|
||||
|
@ -1,14 +1,12 @@
|
||||
package nova.monadic_sfx.ui.components.todo
|
||||
|
||||
import nova.monadic_sfx.util.reactive.Store
|
||||
import nova.monadic_sfx.util.reactive.Reducer
|
||||
import nova.monadic_sfx.util.reactive.Middlewares.actionLoggerMiddleware
|
||||
import com.softwaremill.quicklens._
|
||||
import io.circe.generic.JsonCodec
|
||||
import io.odin.Logger
|
||||
import monix.bio.Task
|
||||
import io.odin._
|
||||
import io.odin.syntax._
|
||||
import io.circe.generic.JsonCodec
|
||||
import com.softwaremill.quicklens._
|
||||
import nova.monadic_sfx.util.reactive.Middlewares.actionLoggerMiddleware
|
||||
import nova.monadic_sfx.util.reactive.Reducer
|
||||
import nova.monadic_sfx.util.reactive.Store
|
||||
|
||||
case class Todo(id: Int, content: String)
|
||||
|
||||
@ -34,28 +32,15 @@ object TodoListStore {
|
||||
todos = state.todos :+ Todo(state.counter, content),
|
||||
counter = state.counter + 1
|
||||
)
|
||||
case Edit(id, content) =>
|
||||
case Edit(_id, content) =>
|
||||
val condition: Todo => Boolean = _.id == _id
|
||||
state
|
||||
.modify(_.todos.eachWhere(_.id == id))
|
||||
.modify(_.todos.eachWhere(condition))
|
||||
.using(_.copy(content = content))
|
||||
case Delete(id) =>
|
||||
state.copy(state.todos.filterNot(_.id == id))
|
||||
}
|
||||
|
||||
def updateTodo(id: Int, content: String, todos: Vector[Todo]) =
|
||||
todos.view.zipWithIndex
|
||||
.find {
|
||||
case (todo, index) => todo.id == id
|
||||
}
|
||||
.map {
|
||||
case (todo, index) => todo.copy(content = content) -> index
|
||||
}
|
||||
.map {
|
||||
case (todo, index) => todos.updated(index, todo)
|
||||
}
|
||||
|
||||
val middlewareLogger = consoleLogger[Task]().withAsync()
|
||||
|
||||
def apply(logger: Logger[Task]) =
|
||||
Store
|
||||
.createL[Command, State](
|
||||
|
@ -12,11 +12,11 @@ import nova.monadic_sfx.implicits.JFXButton
|
||||
import nova.monadic_sfx.implicits.JFXListView
|
||||
import nova.monadic_sfx.implicits.JFXTextArea
|
||||
import nova.monadic_sfx.implicits.JFXTextField
|
||||
import nova.monadic_sfx.ui.components.todo.TodoListComponentOld
|
||||
import scalafx.collections.ObservableBuffer
|
||||
import scalafx.scene.control.Label
|
||||
import scalafx.scene.layout.HBox
|
||||
import scalafx.scene.paint.Color
|
||||
import nova.monadic_sfx.ui.components.todo.TodoListComponentOld
|
||||
|
||||
class TodoController(todoListComponent: TodoListComponentOld) {
|
||||
import AnimFX._
|
||||
|
@ -1,8 +1,8 @@
|
||||
package nova.monadic_sfx.util.reactive
|
||||
|
||||
import io.odin.Logger
|
||||
import monix.reactive.Observable
|
||||
import monix.bio.Task
|
||||
import monix.reactive.Observable
|
||||
import nova.monadic_sfx.util.IOUtils._
|
||||
|
||||
// object Middleware {
|
||||
|
@ -1,11 +1,12 @@
|
||||
package nova.monadic_sfx.util.reactive
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
import monix.execution.Ack
|
||||
import monix.execution.Cancelable
|
||||
import monix.reactive.Observable
|
||||
import monix.reactive.Observer
|
||||
import scala.concurrent.Future
|
||||
import monix.reactive.observers.Subscriber
|
||||
import monix.execution.Ack
|
||||
|
||||
object MonixProSubject {
|
||||
def from[I, O](
|
||||
|
@ -1,8 +1,8 @@
|
||||
package nova.monadic_sfx.util.reactive
|
||||
|
||||
import monix.reactive.ObservableLike
|
||||
import cats.implicits._
|
||||
import monix.reactive.Observable
|
||||
import monix.reactive.ObservableLike
|
||||
|
||||
object Reducer {
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
package nova.monadic_sfx.util.reactive
|
||||
|
||||
import cats.effect.Sync
|
||||
import monix.bio.Task
|
||||
import monix.execution.Scheduler
|
||||
import monix.reactive.Observable
|
||||
import monix.reactive.OverflowStrategy
|
||||
import monix.reactive.subjects.ConcurrentSubject
|
||||
import monix.reactive.Observable
|
||||
import monix.bio.Task
|
||||
import cats.effect.Sync
|
||||
import monix.execution.Scheduler
|
||||
|
||||
object Store {
|
||||
def createL[A, M](
|
||||
|
Loading…
Reference in New Issue
Block a user