oolong-kt / oolong

MVU for Kotlin Multiplatform
http://oolong-kt.org
Apache License 2.0
300 stars 14 forks source link

Subscription support #104

Open jcornaz opened 4 years ago

jcornaz commented 4 years ago

Is your feature request related to a problem? Please describe.

I want to subscribe to some events, that might be external to my system. Example:

Describe the solution you'd like

Since the present library is inspired from elm, I'd find natural to imitate elm's subscription system (in Browser.element).

That could be translated in Kotlin like this:

data class Model(val ticks: Int = 0)
sealed class Msg {
  object Tick : Msg()
}

val subscribe = Subscribe<Model, Msg> { model ->
  every(10.seconds).map { Msg.Tick }
}

// ...

val dispose = Oolong.runtime(
    init,
    update,
    suscribe,
    view,
    render
)

Of course this is only a draft example, and any variation of the API would do.

Describe alternatives you've considered

I think I could start a coroutine from a disposable effect that will call dispatch to fire the messages.

That would however require me to keep an instance of the dispose in my model, so that I can cancel it later.

jcornaz commented 4 years ago

Actually, after playing a little bit, I think using disposableEffect to start a long running job that fire messages is not so bad.

Maybe all we need is only documentation on how to create/cancel a subscriptions using disposableEffect.

P.S: Here is an adaptation of the code I wrote above, using effects:

data class Model(val ticks: Int = 0)

sealed class Msg {
  object Tick : Msg()
}

fun every(duration: Duration): Effect<Int> = { dispatch ->
  var count = 0
  while (isActive) {
    dispatch(count++)
    delay(duration)
  }
}

val tick = every(10.seconds).map {  Msg.Tick }

val init = { Model() to tick }

// ...

val dispose = Oolong.runtime(
    init,
    update,
    view,
    render
)
pardom commented 4 years ago

Yes, I agree that we need better documentation, recipes, and examples. You're right on track with using disposableEffect for subscriptions that you want to cancel, though. For reference, here's an example of a tick subscription which is very similar to what you already have:

https://github.com/oolong-kt/samples/blob/master/samples/time/core/src/commonMain/kotlin/time/Time.kt#L25

I'll add this to the documentation project. Thanks for the contribution!