const m = require('mithril') var io = require('./socket') var socket = io() let onevent = socket.onevent socket.onevent = function(packet) { onevent.call(this, packet) // original call m.redraw() } class Client { constructor(socket) { this.socket = socket this.isConnected = false this.status = {} this.socket.on('status', status => { if (this.status.version && status?.version && this.status.version !== status.version) { window.location.reload(true) } this.status = status }) this.socket.on('disconnect', this.disconnected.bind(this)) this.socket.on('connect', this.connected.bind(this)) this.components = new Map() } registerComponent(component) { this.components.set(component, []) if (component.ioInit) { component.ioInit() } if (this.isConnected && component.ioConnected) { component.ioConnected() } } safeGetComponent(component) { if (typeof(component) === 'string') { throw new Error('io.on was called without specifying active component') } let arr = this.components.get(component) if (!arr) { throw new Error('Registered component was missing but was attempting to add socket listener') } return arr } on(component, name, fn) { let arr = this.safeGetComponent(component) arr.push([name, fn]) this.socket.on(name, (data) => { Promise.resolve().then(() => { return fn(data) }) .catch(err => { console.error('Error running io handler for ' + name, err) }) }) } emit(name, data) { this.socket.emit(name, data) } unregisterComponent(component) { let arr = this.safeGetComponent(component) for (let item of arr) { this.socket.off(item[0], item[1]) } this.components.delete(component) } disconnected() { this.isConnected = false this.status = { } this.notifyConnectionChanged() m.redraw() } connected() { this.isConnected = true this.socket.emit('status', {}) this.notifyConnectionChanged() m.redraw() } notifyConnectionChanged() { for (let component of this.components) { if (component[0].ioConnectionChanged) { component[0].ioConnectionChanged(this.isConnected) } } } } module.exports = new Client(socket)