forked from kscience/visionforge
Allow custom events
This commit is contained in:
parent
f40bed7bb9
commit
9c2db6d321
@ -8,11 +8,11 @@ kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
// wasm()
|
||||
useCoroutines()
|
||||
dependencies {
|
||||
commonMain {
|
||||
api("space.kscience:dataforge-context:$dataforgeVersion")
|
||||
api(spclibs.kotlinx.html)
|
||||
// api("org.jetbrains.kotlin-wrappers:kotlin-css")
|
||||
}
|
||||
jsMain {
|
||||
api("org.jetbrains.kotlin-wrappers:kotlin-extensions")
|
||||
|
@ -12,12 +12,12 @@ import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.parseAsName
|
||||
|
||||
@Serializable
|
||||
@SerialName("control")
|
||||
public sealed class VisionControlEvent : VisionEvent, MetaRepr {
|
||||
public abstract class VisionControlEvent : VisionEvent, MetaRepr {
|
||||
public abstract val meta: Meta
|
||||
|
||||
override fun toMeta(): Meta = meta
|
||||
|
||||
override fun toString(): String = toMeta().toString()
|
||||
}
|
||||
|
||||
public interface ControlVision : Vision {
|
||||
@ -42,7 +42,7 @@ public class VisionClickEvent(override val meta: Meta) : VisionControlEvent() {
|
||||
public val payload: Meta? by meta.node()
|
||||
public val name: Name? get() = meta["name"].string?.parseAsName()
|
||||
|
||||
override fun toString(): String = meta.toString()
|
||||
override fun toString(): String = meta.toString()
|
||||
}
|
||||
|
||||
public fun VisionClickEvent(payload: Meta = Meta.EMPTY, name: Name? = null): VisionClickEvent = VisionClickEvent(
|
||||
|
@ -3,13 +3,13 @@ package space.kscience.visionforge
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MetaRepr
|
||||
import space.kscience.dataforge.names.Name
|
||||
|
||||
/**
|
||||
* An event propagated from client to a server
|
||||
*/
|
||||
@Serializable
|
||||
public sealed interface VisionEvent {
|
||||
public interface VisionEvent {
|
||||
public companion object {
|
||||
public val CLICK_EVENT_KEY: Name get() = Name.of("events", "click", "payload")
|
||||
}
|
||||
@ -20,4 +20,9 @@ public sealed interface VisionEvent {
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("meta")
|
||||
public class VisionMetaEvent(public val meta: Meta) : VisionEvent
|
||||
public class VisionMetaEvent(public val meta: Meta) : VisionEvent, MetaRepr {
|
||||
override fun toMeta(): Meta = meta
|
||||
|
||||
override fun toString(): String = toMeta().toString()
|
||||
|
||||
}
|
@ -30,10 +30,11 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta), MutableVisionCont
|
||||
}
|
||||
}
|
||||
|
||||
public val jsonFormat: Json
|
||||
get() = Json(defaultJson) {
|
||||
public val jsonFormat: Json by lazy {
|
||||
Json(defaultJson) {
|
||||
serializersModule = this@VisionManager.serializersModule
|
||||
}
|
||||
}
|
||||
|
||||
public fun decodeFromString(string: String): Vision = jsonFormat.decodeFromString(visionSerializer, string)
|
||||
|
||||
@ -78,6 +79,13 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta), MutableVisionCont
|
||||
subclass(VisionOfHtmlForm.serializer())
|
||||
subclass(VisionOfHtmlButton.serializer())
|
||||
}
|
||||
|
||||
polymorphic(VisionEvent::class) {
|
||||
subclass(VisionChange.serializer())
|
||||
subclass(VisionMetaEvent.serializer())
|
||||
subclass(VisionClickEvent.serializer())
|
||||
subclass(VisionValueChangeEvent.serializer())
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@ -107,7 +115,7 @@ public abstract class VisionPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(met
|
||||
/**
|
||||
* Fetch a [VisionManager] from this plugin or create a child plugin with a [VisionManager]
|
||||
*/
|
||||
public val Context.visionManager: VisionManager get() = request(VisionManager )
|
||||
public val Context.visionManager: VisionManager get() = request(VisionManager)
|
||||
|
||||
public fun Vision.encodeToString(): String =
|
||||
manager?.encodeToString(this) ?: error("Orphan vision could not be encoded")
|
||||
|
@ -12,6 +12,7 @@ import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.serialization.encodeToString
|
||||
import org.w3c.dom.*
|
||||
import org.w3c.dom.url.URL
|
||||
import space.kscience.dataforge.context.*
|
||||
@ -81,9 +82,7 @@ public class JsVisionClient : AbstractPlugin(), VisionClient {
|
||||
}
|
||||
}
|
||||
|
||||
private val eventCollector by lazy {
|
||||
MutableSharedFlow<Pair<Name, VisionEvent>>(meta["feedback.eventCache"].int ?: 100)
|
||||
}
|
||||
private val eventCollector = MutableSharedFlow<Pair<Name, VisionEvent>>(meta["feedback.eventCache"].int ?: 100)
|
||||
|
||||
/**
|
||||
* Send a custom feedback event
|
||||
@ -122,10 +121,7 @@ public class JsVisionClient : AbstractPlugin(), VisionClient {
|
||||
onmessage = { messageEvent ->
|
||||
val stringData: String? = messageEvent.data as? String
|
||||
if (stringData != null) {
|
||||
val event: VisionEvent = visionManager.jsonFormat.decodeFromString(
|
||||
VisionEvent.serializer(),
|
||||
stringData
|
||||
)
|
||||
val event: VisionEvent = visionManager.jsonFormat.decodeFromString(stringData)
|
||||
|
||||
// If change contains root vision replacement, do it
|
||||
if (event is VisionChange) {
|
||||
@ -154,7 +150,7 @@ public class JsVisionClient : AbstractPlugin(), VisionClient {
|
||||
feedbackJob = visionManager.context.launch {
|
||||
//launch a separate coroutine to send events to the backend
|
||||
eventCollector.filter { it.first == visionName }.onEach {
|
||||
send(visionManager.jsonFormat.encodeToString(VisionEvent.serializer(), it.second))
|
||||
send(visionManager.jsonFormat.encodeToString(it.second))
|
||||
}.launchIn(this)
|
||||
|
||||
//aggregate atomic changes
|
||||
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.html.*
|
||||
import kotlinx.serialization.encodeToString
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.ContextAware
|
||||
import space.kscience.dataforge.meta.*
|
||||
@ -97,9 +98,7 @@ public fun Application.serveVisionData(
|
||||
for (frame in incoming) {
|
||||
val data = frame.data.decodeToString()
|
||||
application.log.debug("Received event for $name: \n$data")
|
||||
val event = configuration.visionManager.jsonFormat.decodeFromString(
|
||||
VisionEvent.serializer(), data
|
||||
)
|
||||
val event: VisionEvent = configuration.visionManager.jsonFormat.decodeFromString(data)
|
||||
|
||||
vision.receiveEvent(event)
|
||||
}
|
||||
@ -108,10 +107,7 @@ public fun Application.serveVisionData(
|
||||
try {
|
||||
withContext(configuration.context.coroutineContext) {
|
||||
vision.flowChanges(configuration.updateInterval.milliseconds).onEach { event ->
|
||||
val json = configuration.visionManager.jsonFormat.encodeToString(
|
||||
VisionEvent.serializer(),
|
||||
event
|
||||
)
|
||||
val json = configuration.visionManager.jsonFormat.encodeToString<VisionEvent>(event)
|
||||
application.log.debug("Sending update for $name: \n$json")
|
||||
outgoing.send(Frame.Text(json))
|
||||
}.collect()
|
||||
@ -155,7 +151,7 @@ public fun Application.visionPage(
|
||||
headers: Collection<HtmlFragment>,
|
||||
connector: EngineConnectorConfig? = null,
|
||||
visionFragment: HtmlVisionFragment,
|
||||
){
|
||||
) {
|
||||
require(WebSockets)
|
||||
|
||||
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
||||
|
Loading…
Reference in New Issue
Block a user