snaptobus starts to work...

This commit is contained in:
STEINNI
2025-09-21 20:08:12 +00:00
parent 5292af6933
commit 1641f5b07e
3 changed files with 309 additions and 41 deletions
+111 -17
View File
@@ -5,10 +5,69 @@
*/
class Snaptobus{
constructor(config){
this.config = this.observeObject(config, this.configChange.bind(this))
constructor(options){
this.spriteDefs = options.spriteDefs
this._curBusConfig = []
this._stagedBusConfig = options.busConfig
this.snap = options.snap
this.commitConfig()
}
get busConfig() { return this._stagedBusConfig }
get liveBusConfig() { return this._curBusConfig }
set busConfig(newConfig) { this._stagedBusConfig = newConfig }
async commitConfig(){
const chansToAdd = []
const chansToKeep = []
for(const chanObj of this._stagedBusConfig){
console.log('staged chan:',chanObj.chan,' current ones:', this._curBusConfig.map(item => item.chan))
if(this._curBusConfig.map(item => item.chan).includes(chanObj.chan)) chansToKeep.push(chanObj)
else chansToAdd.push(chanObj)
}
const chansToDel = this._curBusConfig.filter(item => (!chansToKeep.map(c=>c.chan).includes(item.chan) && !chansToAdd.map(c=>c.chan).includes(item.chan)))
await app.MessageBus.subscribe(chansToAdd.map(item => item.chan))
await app.MessageBus.unSubscribe(chansToDel.map(item => item.chan))
// console.log('subscribe:', chansToAdd.map(item => item.chan))
// console.log('unSubscribe:', chansToDel)
const eventsToAdd = chansToAdd.flatMap(item => item.events.map(ev => ({ chan:item.chan, eventName:ev.eventName })))
let eventsToDel = []//= chansToDel.flatMap(item => item.events.map(ev => ({ chan:item.chan, eventName:ev.eventName })))
for(const oldChan of this._curBusConfig){
for(const oldEvent of oldChan.events){
for(const keepChan of chansToKeep){
if(!keepChan.events.map(item=>item.eventName).includes(oldEvent.eventName)) eventsToDel.push({chan: oldChan.chan, eventName: oldEvent.eventName})
}
}
}
// console.log('eventsToAdd:', eventsToAdd)
// console.log('eventsToDel:', eventsToDel)
for(const eventToAdd of eventsToAdd){
app.MessageBus.addBusListener(eventToAdd.eventName, [eventToAdd.chan], this.processBusEvent.bind(this, eventToAdd.eventName,), 'snaptobus')
}
for(const eventToDel of eventsToDel){
app.MessageBus.removeBusListener(eventToDel.eventName, this.processBusEvent.bind(this, eventToDel.eventName), 'snaptobus')
}
this._curBusConfig = this.deepClone(this._stagedBusConfig)
}
deepClone(obj) { // Needed because structuredClone doesn't take functions (and we have transformers)
if (obj === null || typeof obj !== 'object') {
return obj
}
if (Array.isArray(obj)) {
return obj.map((el => this.deepClone(el)))
}
const clone = {}
for (const key in obj) {
clone[key] = this.deepClone(obj[key])
}
return clone
}
observeObject(obj, onChange) {
const wrap = (value) =>
(value && typeof value === 'object')
@@ -37,31 +96,49 @@ class Snaptobus{
return new Proxy(obj, handler)
}
configChange(prop, newval, oldval){
//TODO subscribe new chans
//TODO unsubscribe removed chans
//TODO update event filters
//
console.log(prop, oldval, newval)
processBusEvent(eventType, chan, payload, userId, x){
console.log('processBusEvent====>',eventType, chan, payload, userId)
const chanObj = this._curBusConfig.find(item => item.chan==chan)
if(!chanObj) return
console.log('processBusEvent====>chanObj', chanObj)
const eventObj = chanObj.events.find(item => item.eventName==eventType)
if(!eventObj) return
console.log('processBusEvent====>eventObj', eventObj)
// assign attributes in payload to all snap objects for that eventType
// each snap is an assignation of attributes via a selector
for(const snapDef of eventObj.snaps){
const selector = snapDef.selector.replace(/\$\{(\w+)\}/g, (_, key) => this.getValueByPath(payload, key))
console.log('Will look for snap:', selector)
const snaps = this.snap.selectAll(selector)
console.log(`found ${snaps.length} snaps`)
snaps.forEach(snapEl => {
const newAttr = this.assignFromConfig(payload, snapDef.assign)
console.log('newAttr:',newAttr)
snapEl.attr(newAttr)
})
}
}
getValueByPath(obj, path) {
return(path.split('.').reduce((acc, key) => acc?.[key], obj))
}
assignFromConfig(chan, event) {
assignFromConfig(data, replaceDef) {
console.log('assignFromConfig', data, replaceDef)
const result = {}
for (const [key, rule] of Object.entries(this.config.assign)) {
for (const [key, rule] of Object.entries(replaceDef)) {
if (typeof rule === 'string') { // plain path
result[key] = this.getValueByPath(event, rule)
result[key] = this.getValueByPath(data, rule)
} else if((typeof(rule) == 'object') && (typeof(rule.transformer) == 'function')) { // transformer
const fnargs = (rule.arguments || []).map(arg => this.getValueByPath(event,arg))
const fnargs = (rule.arguments || []).map(arg => this.getValueByPath(data,arg))
result[key] = rule.transformer(...fnargs)
}
}
return result
}
getValueByPath(obj, path) {
return(path.split('.').reduce((acc, key) => acc?.[key], obj))
}
}
/*
const s2bConfig = [
@@ -81,6 +158,17 @@ const s2bConfig = [
}
]
},
{ eventName: 'rotating',
snaps: [
{
selector: '#${aid}',
assign: {
r: 'rotangle'
},
animate: true
}
]
},
]
},
{ chan: 'agent:*', // wildcards allowed
@@ -102,3 +190,9 @@ const s2bConfig = [
},
]
*/
/*
payload =
{}
eventType
*/