oolong
oolong copied to clipboard
Subscription support
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:
- Get an event every X seconds
- Subscribe to events from a websocket
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.
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
)
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!