@seamly/web-ui 19.1.4 → 19.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -79,7 +79,7 @@ eval("/**\n * marked - a markdown parser\n * Copyright (c) 2011-2021, Christophe
79
79
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
80
80
 
81
81
  "use strict";
82
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Channel\": () => (/* binding */ Channel),\n/* harmony export */ \"LongPoll\": () => (/* binding */ LongPoll),\n/* harmony export */ \"Presence\": () => (/* binding */ Presence),\n/* harmony export */ \"Serializer\": () => (/* binding */ serializer_default),\n/* harmony export */ \"Socket\": () => (/* binding */ Socket)\n/* harmony export */ });\n// js/phoenix/utils.js\nvar closure = value => {\n if (typeof value === \"function\") {\n return value;\n } else {\n let closure2 = function () {\n return value;\n };\n\n return closure2;\n }\n}; // js/phoenix/constants.js\n\n\nvar globalSelf = typeof self !== \"undefined\" ? self : null;\nvar phxWindow = typeof window !== \"undefined\" ? window : null;\nvar global = globalSelf || phxWindow || void 0;\nvar DEFAULT_VSN = \"2.0.0\";\nvar SOCKET_STATES = {\n connecting: 0,\n open: 1,\n closing: 2,\n closed: 3\n};\nvar DEFAULT_TIMEOUT = 1e4;\nvar WS_CLOSE_NORMAL = 1e3;\nvar CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\"\n};\nvar CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n};\nvar TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n};\nvar XHR_STATES = {\n complete: 4\n}; // js/phoenix/push.js\n\nvar Push = class {\n constructor(channel, event, payload, timeout) {\n this.channel = channel;\n this.event = event;\n\n this.payload = payload || function () {\n return {};\n };\n\n this.receivedResp = null;\n this.timeout = timeout;\n this.timeoutTimer = null;\n this.recHooks = [];\n this.sent = false;\n }\n\n resend(timeout) {\n this.timeout = timeout;\n this.reset();\n this.send();\n }\n\n send() {\n if (this.hasReceived(\"timeout\")) {\n return;\n }\n\n this.startTimeout();\n this.sent = true;\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n });\n }\n\n receive(status, callback) {\n if (this.hasReceived(status)) {\n callback(this.receivedResp.response);\n }\n\n this.recHooks.push({\n status,\n callback\n });\n return this;\n }\n\n reset() {\n this.cancelRefEvent();\n this.ref = null;\n this.refEvent = null;\n this.receivedResp = null;\n this.sent = false;\n }\n\n matchReceive({\n status,\n response,\n _ref\n }) {\n this.recHooks.filter(h => h.status === status).forEach(h => h.callback(response));\n }\n\n cancelRefEvent() {\n if (!this.refEvent) {\n return;\n }\n\n this.channel.off(this.refEvent);\n }\n\n cancelTimeout() {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = null;\n }\n\n startTimeout() {\n if (this.timeoutTimer) {\n this.cancelTimeout();\n }\n\n this.ref = this.channel.socket.makeRef();\n this.refEvent = this.channel.replyEventName(this.ref);\n this.channel.on(this.refEvent, payload => {\n this.cancelRefEvent();\n this.cancelTimeout();\n this.receivedResp = payload;\n this.matchReceive(payload);\n });\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {});\n }, this.timeout);\n }\n\n hasReceived(status) {\n return this.receivedResp && this.receivedResp.status === status;\n }\n\n trigger(status, response) {\n this.channel.trigger(this.refEvent, {\n status,\n response\n });\n }\n\n}; // js/phoenix/timer.js\n\nvar Timer = class {\n constructor(callback, timerCalc) {\n this.callback = callback;\n this.timerCalc = timerCalc;\n this.timer = null;\n this.tries = 0;\n }\n\n reset() {\n this.tries = 0;\n clearTimeout(this.timer);\n }\n\n scheduleTimeout() {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1;\n this.callback();\n }, this.timerCalc(this.tries + 1));\n }\n\n}; // js/phoenix/channel.js\n\nvar Channel = class {\n constructor(topic, params, socket) {\n this.state = CHANNEL_STATES.closed;\n this.topic = topic;\n this.params = closure(params || {});\n this.socket = socket;\n this.bindings = [];\n this.bindingRef = 0;\n this.timeout = this.socket.timeout;\n this.joinedOnce = false;\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout);\n this.pushBuffer = [];\n this.stateChangeRefs = [];\n this.rejoinTimer = new Timer(() => {\n if (this.socket.isConnected()) {\n this.rejoin();\n }\n }, this.socket.rejoinAfterMs);\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()));\n this.stateChangeRefs.push(this.socket.onOpen(() => {\n this.rejoinTimer.reset();\n\n if (this.isErrored()) {\n this.rejoin();\n }\n }));\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined;\n this.rejoinTimer.reset();\n this.pushBuffer.forEach(pushEvent => pushEvent.send());\n this.pushBuffer = [];\n });\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored;\n\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.onClose(() => {\n this.rejoinTimer.reset();\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`);\n this.state = CHANNEL_STATES.closed;\n this.socket.remove(this);\n });\n this.onError(reason => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason);\n\n if (this.isJoining()) {\n this.joinPush.reset();\n }\n\n this.state = CHANNEL_STATES.errored;\n\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.joinPush.receive(\"timeout\", () => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout);\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout);\n leavePush.send();\n this.state = CHANNEL_STATES.errored;\n this.joinPush.reset();\n\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload);\n });\n }\n\n join(timeout = this.timeout) {\n if (this.joinedOnce) {\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\");\n } else {\n this.timeout = timeout;\n this.joinedOnce = true;\n this.rejoin();\n return this.joinPush;\n }\n }\n\n onClose(callback) {\n this.on(CHANNEL_EVENTS.close, callback);\n }\n\n onError(callback) {\n return this.on(CHANNEL_EVENTS.error, reason => callback(reason));\n }\n\n on(event, callback) {\n let ref = this.bindingRef++;\n this.bindings.push({\n event,\n ref,\n callback\n });\n return ref;\n }\n\n off(event, ref) {\n this.bindings = this.bindings.filter(bind => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref));\n });\n }\n\n canPush() {\n return this.socket.isConnected() && this.isJoined();\n }\n\n push(event, payload, timeout = this.timeout) {\n payload = payload || {};\n\n if (!this.joinedOnce) {\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`);\n }\n\n let pushEvent = new Push(this, event, function () {\n return payload;\n }, timeout);\n\n if (this.canPush()) {\n pushEvent.send();\n } else {\n pushEvent.startTimeout();\n this.pushBuffer.push(pushEvent);\n }\n\n return pushEvent;\n }\n\n leave(timeout = this.timeout) {\n this.rejoinTimer.reset();\n this.joinPush.cancelTimeout();\n this.state = CHANNEL_STATES.leaving;\n\n let onClose = () => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`);\n this.trigger(CHANNEL_EVENTS.close, \"leave\");\n };\n\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout);\n leavePush.receive(\"ok\", () => onClose()).receive(\"timeout\", () => onClose());\n leavePush.send();\n\n if (!this.canPush()) {\n leavePush.trigger(\"ok\", {});\n }\n\n return leavePush;\n }\n\n onMessage(_event, payload, _ref) {\n return payload;\n }\n\n isMember(topic, event, payload, joinRef) {\n if (this.topic !== topic) {\n return false;\n }\n\n if (joinRef && joinRef !== this.joinRef()) {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {\n topic,\n event,\n payload,\n joinRef\n });\n return false;\n } else {\n return true;\n }\n }\n\n joinRef() {\n return this.joinPush.ref;\n }\n\n rejoin(timeout = this.timeout) {\n if (this.isLeaving()) {\n return;\n }\n\n this.socket.leaveOpenTopic(this.topic);\n this.state = CHANNEL_STATES.joining;\n this.joinPush.resend(timeout);\n }\n\n trigger(event, payload, ref, joinRef) {\n let handledPayload = this.onMessage(event, payload, ref, joinRef);\n\n if (payload && !handledPayload) {\n throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\");\n }\n\n let eventBindings = this.bindings.filter(bind => bind.event === event);\n\n for (let i = 0; i < eventBindings.length; i++) {\n let bind = eventBindings[i];\n bind.callback(handledPayload, ref, joinRef || this.joinRef());\n }\n }\n\n replyEventName(ref) {\n return `chan_reply_${ref}`;\n }\n\n isClosed() {\n return this.state === CHANNEL_STATES.closed;\n }\n\n isErrored() {\n return this.state === CHANNEL_STATES.errored;\n }\n\n isJoined() {\n return this.state === CHANNEL_STATES.joined;\n }\n\n isJoining() {\n return this.state === CHANNEL_STATES.joining;\n }\n\n isLeaving() {\n return this.state === CHANNEL_STATES.leaving;\n }\n\n}; // js/phoenix/ajax.js\n\nvar Ajax = class {\n static request(method, endPoint, accept, body, timeout, ontimeout, callback) {\n if (global.XDomainRequest) {\n let req = new global.XDomainRequest();\n this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback);\n } else {\n let req = new global.XMLHttpRequest();\n this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback);\n }\n }\n\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback) {\n req.timeout = timeout;\n req.open(method, endPoint);\n\n req.onload = () => {\n let response = this.parseJSON(req.responseText);\n callback && callback(response);\n };\n\n if (ontimeout) {\n req.ontimeout = ontimeout;\n }\n\n req.onprogress = () => {};\n\n req.send(body);\n }\n\n static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback) {\n req.open(method, endPoint, true);\n req.timeout = timeout;\n req.setRequestHeader(\"Content-Type\", accept);\n\n req.onerror = () => {\n callback && callback(null);\n };\n\n req.onreadystatechange = () => {\n if (req.readyState === XHR_STATES.complete && callback) {\n let response = this.parseJSON(req.responseText);\n callback(response);\n }\n };\n\n if (ontimeout) {\n req.ontimeout = ontimeout;\n }\n\n req.send(body);\n }\n\n static parseJSON(resp) {\n if (!resp || resp === \"\") {\n return null;\n }\n\n try {\n return JSON.parse(resp);\n } catch (e) {\n console && console.log(\"failed to parse JSON response\", resp);\n return null;\n }\n }\n\n static serialize(obj, parentKey) {\n let queryStr = [];\n\n for (var key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) {\n continue;\n }\n\n let paramKey = parentKey ? `${parentKey}[${key}]` : key;\n let paramVal = obj[key];\n\n if (typeof paramVal === \"object\") {\n queryStr.push(this.serialize(paramVal, paramKey));\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal));\n }\n }\n\n return queryStr.join(\"&\");\n }\n\n static appendParams(url, params) {\n if (Object.keys(params).length === 0) {\n return url;\n }\n\n let prefix = url.match(/\\?/) ? \"&\" : \"?\";\n return `${url}${prefix}${this.serialize(params)}`;\n }\n\n}; // js/phoenix/longpoll.js\n\nvar LongPoll = class {\n constructor(endPoint) {\n this.endPoint = null;\n this.token = null;\n this.skipHeartbeat = true;\n\n this.onopen = function () {};\n\n this.onerror = function () {};\n\n this.onmessage = function () {};\n\n this.onclose = function () {};\n\n this.pollEndpoint = this.normalizeEndpoint(endPoint);\n this.readyState = SOCKET_STATES.connecting;\n this.poll();\n }\n\n normalizeEndpoint(endPoint) {\n return endPoint.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\").replace(new RegExp(\"(.*)/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll);\n }\n\n endpointURL() {\n return Ajax.appendParams(this.pollEndpoint, {\n token: this.token\n });\n }\n\n closeAndRetry() {\n this.close();\n this.readyState = SOCKET_STATES.connecting;\n }\n\n ontimeout() {\n this.onerror(\"timeout\");\n this.closeAndRetry();\n }\n\n poll() {\n if (!(this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting)) {\n return;\n }\n\n Ajax.request(\"GET\", this.endpointURL(), \"application/json\", null, this.timeout, this.ontimeout.bind(this), resp => {\n if (resp) {\n var {\n status,\n token,\n messages\n } = resp;\n this.token = token;\n } else {\n status = 0;\n }\n\n switch (status) {\n case 200:\n messages.forEach(msg => {\n setTimeout(() => {\n this.onmessage({\n data: msg\n });\n }, 0);\n });\n this.poll();\n break;\n\n case 204:\n this.poll();\n break;\n\n case 410:\n this.readyState = SOCKET_STATES.open;\n this.onopen();\n this.poll();\n break;\n\n case 403:\n this.onerror();\n this.close();\n break;\n\n case 0:\n case 500:\n this.onerror();\n this.closeAndRetry();\n break;\n\n default:\n throw new Error(`unhandled poll status ${status}`);\n }\n });\n }\n\n send(body) {\n Ajax.request(\"POST\", this.endpointURL(), \"application/json\", body, this.timeout, this.onerror.bind(this, \"timeout\"), resp => {\n if (!resp || resp.status !== 200) {\n this.onerror(resp && resp.status);\n this.closeAndRetry();\n }\n });\n }\n\n close(_code, _reason) {\n this.readyState = SOCKET_STATES.closed;\n this.onclose();\n }\n\n}; // js/phoenix/presence.js\n\nvar Presence = class {\n constructor(channel, opts = {}) {\n let events = opts.events || {\n state: \"presence_state\",\n diff: \"presence_diff\"\n };\n this.state = {};\n this.pendingDiffs = [];\n this.channel = channel;\n this.joinRef = null;\n this.caller = {\n onJoin: function () {},\n onLeave: function () {},\n onSync: function () {}\n };\n this.channel.on(events.state, newState => {\n let {\n onJoin,\n onLeave,\n onSync\n } = this.caller;\n this.joinRef = this.channel.joinRef();\n this.state = Presence.syncState(this.state, newState, onJoin, onLeave);\n this.pendingDiffs.forEach(diff => {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave);\n });\n this.pendingDiffs = [];\n onSync();\n });\n this.channel.on(events.diff, diff => {\n let {\n onJoin,\n onLeave,\n onSync\n } = this.caller;\n\n if (this.inPendingSyncState()) {\n this.pendingDiffs.push(diff);\n } else {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave);\n onSync();\n }\n });\n }\n\n onJoin(callback) {\n this.caller.onJoin = callback;\n }\n\n onLeave(callback) {\n this.caller.onLeave = callback;\n }\n\n onSync(callback) {\n this.caller.onSync = callback;\n }\n\n list(by) {\n return Presence.list(this.state, by);\n }\n\n inPendingSyncState() {\n return !this.joinRef || this.joinRef !== this.channel.joinRef();\n }\n\n static syncState(currentState, newState, onJoin, onLeave) {\n let state = this.clone(currentState);\n let joins = {};\n let leaves = {};\n this.map(state, (key, presence) => {\n if (!newState[key]) {\n leaves[key] = presence;\n }\n });\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key];\n\n if (currentPresence) {\n let newRefs = newPresence.metas.map(m => m.phx_ref);\n let curRefs = currentPresence.metas.map(m => m.phx_ref);\n let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0);\n let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0);\n\n if (joinedMetas.length > 0) {\n joins[key] = newPresence;\n joins[key].metas = joinedMetas;\n }\n\n if (leftMetas.length > 0) {\n leaves[key] = this.clone(currentPresence);\n leaves[key].metas = leftMetas;\n }\n } else {\n joins[key] = newPresence;\n }\n });\n return this.syncDiff(state, {\n joins,\n leaves\n }, onJoin, onLeave);\n }\n\n static syncDiff(state, diff, onJoin, onLeave) {\n let {\n joins,\n leaves\n } = this.clone(diff);\n\n if (!onJoin) {\n onJoin = function () {};\n }\n\n if (!onLeave) {\n onLeave = function () {};\n }\n\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key];\n state[key] = this.clone(newPresence);\n\n if (currentPresence) {\n let joinedRefs = state[key].metas.map(m => m.phx_ref);\n let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0);\n state[key].metas.unshift(...curMetas);\n }\n\n onJoin(key, currentPresence, newPresence);\n });\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key];\n\n if (!currentPresence) {\n return;\n }\n\n let refsToRemove = leftPresence.metas.map(m => m.phx_ref);\n currentPresence.metas = currentPresence.metas.filter(p => {\n return refsToRemove.indexOf(p.phx_ref) < 0;\n });\n onLeave(key, currentPresence, leftPresence);\n\n if (currentPresence.metas.length === 0) {\n delete state[key];\n }\n });\n return state;\n }\n\n static list(presences, chooser) {\n if (!chooser) {\n chooser = function (key, pres) {\n return pres;\n };\n }\n\n return this.map(presences, (key, presence) => {\n return chooser(key, presence);\n });\n }\n\n static map(obj, func) {\n return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]));\n }\n\n static clone(obj) {\n return JSON.parse(JSON.stringify(obj));\n }\n\n}; // js/phoenix/serializer.js\n\nvar serializer_default = {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: {\n push: 0,\n reply: 1,\n broadcast: 2\n },\n\n encode(msg, callback) {\n if (msg.payload.constructor === ArrayBuffer) {\n return callback(this.binaryEncode(msg));\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload];\n return callback(JSON.stringify(payload));\n }\n },\n\n decode(rawPayload, callback) {\n if (rawPayload.constructor === ArrayBuffer) {\n return callback(this.binaryDecode(rawPayload));\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload);\n return callback({\n join_ref,\n ref,\n topic,\n event,\n payload\n });\n }\n },\n\n binaryEncode(message) {\n let {\n join_ref,\n ref,\n event,\n topic,\n payload\n } = message;\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length;\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength);\n let view = new DataView(header);\n let offset = 0;\n view.setUint8(offset++, this.KINDS.push);\n view.setUint8(offset++, join_ref.length);\n view.setUint8(offset++, ref.length);\n view.setUint8(offset++, topic.length);\n view.setUint8(offset++, event.length);\n Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)));\n var combined = new Uint8Array(header.byteLength + payload.byteLength);\n combined.set(new Uint8Array(header), 0);\n combined.set(new Uint8Array(payload), header.byteLength);\n return combined.buffer;\n },\n\n binaryDecode(buffer) {\n let view = new DataView(buffer);\n let kind = view.getUint8(0);\n let decoder = new TextDecoder();\n\n switch (kind) {\n case this.KINDS.push:\n return this.decodePush(buffer, view, decoder);\n\n case this.KINDS.reply:\n return this.decodeReply(buffer, view, decoder);\n\n case this.KINDS.broadcast:\n return this.decodeBroadcast(buffer, view, decoder);\n }\n },\n\n decodePush(buffer, view, decoder) {\n let joinRefSize = view.getUint8(1);\n let topicSize = view.getUint8(2);\n let eventSize = view.getUint8(3);\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1;\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));\n offset = offset + joinRefSize;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n return {\n join_ref: joinRef,\n ref: null,\n topic,\n event,\n payload: data\n };\n },\n\n decodeReply(buffer, view, decoder) {\n let joinRefSize = view.getUint8(1);\n let refSize = view.getUint8(2);\n let topicSize = view.getUint8(3);\n let eventSize = view.getUint8(4);\n let offset = this.HEADER_LENGTH + this.META_LENGTH;\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));\n offset = offset + joinRefSize;\n let ref = decoder.decode(buffer.slice(offset, offset + refSize));\n offset = offset + refSize;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n let payload = {\n status: event,\n response: data\n };\n return {\n join_ref: joinRef,\n ref,\n topic,\n event: CHANNEL_EVENTS.reply,\n payload\n };\n },\n\n decodeBroadcast(buffer, view, decoder) {\n let topicSize = view.getUint8(1);\n let eventSize = view.getUint8(2);\n let offset = this.HEADER_LENGTH + 2;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n return {\n join_ref: null,\n ref: null,\n topic,\n event,\n payload: data\n };\n }\n\n}; // js/phoenix/socket.js\n\nvar Socket = class {\n constructor(endPoint, opts = {}) {\n this.stateChangeCallbacks = {\n open: [],\n close: [],\n error: [],\n message: []\n };\n this.channels = [];\n this.sendBuffer = [];\n this.ref = 0;\n this.timeout = opts.timeout || DEFAULT_TIMEOUT;\n this.transport = opts.transport || global.WebSocket || LongPoll;\n this.establishedConnections = 0;\n this.defaultEncoder = serializer_default.encode.bind(serializer_default);\n this.defaultDecoder = serializer_default.decode.bind(serializer_default);\n this.closeWasClean = false;\n this.binaryType = opts.binaryType || \"arraybuffer\";\n this.connectClock = 1;\n\n if (this.transport !== LongPoll) {\n this.encode = opts.encode || this.defaultEncoder;\n this.decode = opts.decode || this.defaultDecoder;\n } else {\n this.encode = this.defaultEncoder;\n this.decode = this.defaultDecoder;\n }\n\n let awaitingConnectionOnPageShow = null;\n\n if (phxWindow && phxWindow.addEventListener) {\n phxWindow.addEventListener(\"pagehide\", _e => {\n if (this.conn) {\n this.disconnect();\n awaitingConnectionOnPageShow = this.connectClock;\n }\n });\n phxWindow.addEventListener(\"pageshow\", _e => {\n if (awaitingConnectionOnPageShow === this.connectClock) {\n awaitingConnectionOnPageShow = null;\n this.connect();\n }\n });\n }\n\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 3e4;\n\n this.rejoinAfterMs = tries => {\n if (opts.rejoinAfterMs) {\n return opts.rejoinAfterMs(tries);\n } else {\n return [1e3, 2e3, 5e3][tries - 1] || 1e4;\n }\n };\n\n this.reconnectAfterMs = tries => {\n if (opts.reconnectAfterMs) {\n return opts.reconnectAfterMs(tries);\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1e3, 2e3][tries - 1] || 5e3;\n }\n };\n\n this.logger = opts.logger || null;\n this.longpollerTimeout = opts.longpollerTimeout || 2e4;\n this.params = closure(opts.params || {});\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`;\n this.vsn = opts.vsn || DEFAULT_VSN;\n this.heartbeatTimer = null;\n this.pendingHeartbeatRef = null;\n this.reconnectTimer = new Timer(() => {\n this.teardown(() => this.connect());\n }, this.reconnectAfterMs);\n }\n\n replaceTransport(newTransport) {\n this.disconnect();\n this.transport = newTransport;\n }\n\n protocol() {\n return location.protocol.match(/^https/) ? \"wss\" : \"ws\";\n }\n\n endPointURL() {\n let uri = Ajax.appendParams(Ajax.appendParams(this.endPoint, this.params()), {\n vsn: this.vsn\n });\n\n if (uri.charAt(0) !== \"/\") {\n return uri;\n }\n\n if (uri.charAt(1) === \"/\") {\n return `${this.protocol()}:${uri}`;\n }\n\n return `${this.protocol()}://${location.host}${uri}`;\n }\n\n disconnect(callback, code, reason) {\n this.connectClock++;\n this.closeWasClean = true;\n this.reconnectTimer.reset();\n this.teardown(callback, code, reason);\n }\n\n connect(params) {\n this.connectClock++;\n\n if (params) {\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\");\n this.params = closure(params);\n }\n\n if (this.conn) {\n return;\n }\n\n this.closeWasClean = false;\n this.conn = new this.transport(this.endPointURL());\n this.conn.binaryType = this.binaryType;\n this.conn.timeout = this.longpollerTimeout;\n\n this.conn.onopen = () => this.onConnOpen();\n\n this.conn.onerror = error => this.onConnError(error);\n\n this.conn.onmessage = event => this.onConnMessage(event);\n\n this.conn.onclose = event => this.onConnClose(event);\n }\n\n log(kind, msg, data) {\n this.logger(kind, msg, data);\n }\n\n hasLogger() {\n return this.logger !== null;\n }\n\n onOpen(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.open.push([ref, callback]);\n return ref;\n }\n\n onClose(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.close.push([ref, callback]);\n return ref;\n }\n\n onError(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.error.push([ref, callback]);\n return ref;\n }\n\n onMessage(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.message.push([ref, callback]);\n return ref;\n }\n\n onConnOpen() {\n if (this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`);\n this.closeWasClean = false;\n this.establishedConnections++;\n this.flushSendBuffer();\n this.reconnectTimer.reset();\n this.resetHeartbeat();\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback());\n }\n\n heartbeatTimeout() {\n if (this.pendingHeartbeatRef) {\n this.pendingHeartbeatRef = null;\n\n if (this.hasLogger()) {\n this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\");\n }\n\n this.abnormalClose(\"heartbeat timeout\");\n }\n }\n\n resetHeartbeat() {\n if (this.conn && this.conn.skipHeartbeat) {\n return;\n }\n\n this.pendingHeartbeatRef = null;\n clearTimeout(this.heartbeatTimer);\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);\n }\n\n teardown(callback, code, reason) {\n if (!this.conn) {\n return callback && callback();\n }\n\n this.waitForBufferDone(() => {\n if (this.conn) {\n if (code) {\n this.conn.close(code, reason || \"\");\n } else {\n this.conn.close();\n }\n }\n\n this.waitForSocketClosed(() => {\n if (this.conn) {\n this.conn.onclose = function () {};\n\n this.conn = null;\n }\n\n callback && callback();\n });\n });\n }\n\n waitForBufferDone(callback, tries = 1) {\n if (tries === 5 || !this.conn || !this.conn.bufferedAmount) {\n callback();\n return;\n }\n\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1);\n }, 150 * tries);\n }\n\n waitForSocketClosed(callback, tries = 1) {\n if (tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed) {\n callback();\n return;\n }\n\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1);\n }, 150 * tries);\n }\n\n onConnClose(event) {\n let closeCode = event && event.code;\n if (this.hasLogger()) this.log(\"transport\", \"close\", event);\n this.triggerChanError();\n clearTimeout(this.heartbeatTimer);\n\n if (!this.closeWasClean && closeCode !== 1e3) {\n this.reconnectTimer.scheduleTimeout();\n }\n\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event));\n }\n\n onConnError(error) {\n if (this.hasLogger()) this.log(\"transport\", error);\n let transportBefore = this.transport;\n let establishedBefore = this.establishedConnections;\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore);\n });\n\n if (transportBefore === this.transport || establishedBefore > 0) {\n this.triggerChanError();\n }\n }\n\n triggerChanError() {\n this.channels.forEach(channel => {\n if (!(channel.isErrored() || channel.isLeaving() || channel.isClosed())) {\n channel.trigger(CHANNEL_EVENTS.error);\n }\n });\n }\n\n connectionState() {\n switch (this.conn && this.conn.readyState) {\n case SOCKET_STATES.connecting:\n return \"connecting\";\n\n case SOCKET_STATES.open:\n return \"open\";\n\n case SOCKET_STATES.closing:\n return \"closing\";\n\n default:\n return \"closed\";\n }\n }\n\n isConnected() {\n return this.connectionState() === \"open\";\n }\n\n remove(channel) {\n this.off(channel.stateChangeRefs);\n this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef());\n }\n\n off(refs) {\n for (let key in this.stateChangeCallbacks) {\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1;\n });\n }\n }\n\n channel(topic, chanParams = {}) {\n let chan = new Channel(topic, chanParams, this);\n this.channels.push(chan);\n return chan;\n }\n\n push(data) {\n if (this.hasLogger()) {\n let {\n topic,\n event,\n payload,\n ref,\n join_ref\n } = data;\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload);\n }\n\n if (this.isConnected()) {\n this.encode(data, result => this.conn.send(result));\n } else {\n this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)));\n }\n }\n\n makeRef() {\n let newRef = this.ref + 1;\n\n if (newRef === this.ref) {\n this.ref = 0;\n } else {\n this.ref = newRef;\n }\n\n return this.ref.toString();\n }\n\n sendHeartbeat() {\n if (this.pendingHeartbeatRef && !this.isConnected()) {\n return;\n }\n\n this.pendingHeartbeatRef = this.makeRef();\n this.push({\n topic: \"phoenix\",\n event: \"heartbeat\",\n payload: {},\n ref: this.pendingHeartbeatRef\n });\n this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs);\n }\n\n abnormalClose(reason) {\n this.closeWasClean = false;\n\n if (this.isConnected()) {\n this.conn.close(WS_CLOSE_NORMAL, reason);\n }\n }\n\n flushSendBuffer() {\n if (this.isConnected() && this.sendBuffer.length > 0) {\n this.sendBuffer.forEach(callback => callback());\n this.sendBuffer = [];\n }\n }\n\n onConnMessage(rawMessage) {\n this.decode(rawMessage.data, msg => {\n let {\n topic,\n event,\n payload,\n ref,\n join_ref\n } = msg;\n\n if (ref && ref === this.pendingHeartbeatRef) {\n clearTimeout(this.heartbeatTimer);\n this.pendingHeartbeatRef = null;\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);\n }\n\n if (this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload);\n\n for (let i = 0; i < this.channels.length; i++) {\n const channel = this.channels[i];\n\n if (!channel.isMember(topic, event, payload, join_ref)) {\n continue;\n }\n\n channel.trigger(event, payload, ref, join_ref);\n }\n\n for (let i = 0; i < this.stateChangeCallbacks.message.length; i++) {\n let [, callback] = this.stateChangeCallbacks.message[i];\n callback(msg);\n }\n });\n }\n\n leaveOpenTopic(topic) {\n let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()));\n\n if (dupChannel) {\n if (this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`);\n dupChannel.leave();\n }\n }\n\n};\n\n\n//# sourceURL=webpack://@seamly/web-ui/./node_modules/phoenix/priv/static/phoenix.esm.js?");
82
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Channel\": () => (/* binding */ Channel),\n/* harmony export */ \"LongPoll\": () => (/* binding */ LongPoll),\n/* harmony export */ \"Presence\": () => (/* binding */ Presence),\n/* harmony export */ \"Serializer\": () => (/* binding */ serializer_default),\n/* harmony export */ \"Socket\": () => (/* binding */ Socket)\n/* harmony export */ });\n// js/phoenix/utils.js\nvar closure = value => {\n if (typeof value === \"function\") {\n return value;\n } else {\n let closure2 = function () {\n return value;\n };\n\n return closure2;\n }\n}; // js/phoenix/constants.js\n\n\nvar globalSelf = typeof self !== \"undefined\" ? self : null;\nvar phxWindow = typeof window !== \"undefined\" ? window : null;\nvar global = globalSelf || phxWindow || void 0;\nvar DEFAULT_VSN = \"2.0.0\";\nvar SOCKET_STATES = {\n connecting: 0,\n open: 1,\n closing: 2,\n closed: 3\n};\nvar DEFAULT_TIMEOUT = 1e4;\nvar WS_CLOSE_NORMAL = 1e3;\nvar CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\"\n};\nvar CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n};\nvar TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n};\nvar XHR_STATES = {\n complete: 4\n}; // js/phoenix/push.js\n\nvar Push = class {\n constructor(channel, event, payload, timeout) {\n this.channel = channel;\n this.event = event;\n\n this.payload = payload || function () {\n return {};\n };\n\n this.receivedResp = null;\n this.timeout = timeout;\n this.timeoutTimer = null;\n this.recHooks = [];\n this.sent = false;\n }\n\n resend(timeout) {\n this.timeout = timeout;\n this.reset();\n this.send();\n }\n\n send() {\n if (this.hasReceived(\"timeout\")) {\n return;\n }\n\n this.startTimeout();\n this.sent = true;\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n });\n }\n\n receive(status, callback) {\n if (this.hasReceived(status)) {\n callback(this.receivedResp.response);\n }\n\n this.recHooks.push({\n status,\n callback\n });\n return this;\n }\n\n reset() {\n this.cancelRefEvent();\n this.ref = null;\n this.refEvent = null;\n this.receivedResp = null;\n this.sent = false;\n }\n\n matchReceive({\n status,\n response,\n _ref\n }) {\n this.recHooks.filter(h => h.status === status).forEach(h => h.callback(response));\n }\n\n cancelRefEvent() {\n if (!this.refEvent) {\n return;\n }\n\n this.channel.off(this.refEvent);\n }\n\n cancelTimeout() {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = null;\n }\n\n startTimeout() {\n if (this.timeoutTimer) {\n this.cancelTimeout();\n }\n\n this.ref = this.channel.socket.makeRef();\n this.refEvent = this.channel.replyEventName(this.ref);\n this.channel.on(this.refEvent, payload => {\n this.cancelRefEvent();\n this.cancelTimeout();\n this.receivedResp = payload;\n this.matchReceive(payload);\n });\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {});\n }, this.timeout);\n }\n\n hasReceived(status) {\n return this.receivedResp && this.receivedResp.status === status;\n }\n\n trigger(status, response) {\n this.channel.trigger(this.refEvent, {\n status,\n response\n });\n }\n\n}; // js/phoenix/timer.js\n\nvar Timer = class {\n constructor(callback, timerCalc) {\n this.callback = callback;\n this.timerCalc = timerCalc;\n this.timer = null;\n this.tries = 0;\n }\n\n reset() {\n this.tries = 0;\n clearTimeout(this.timer);\n }\n\n scheduleTimeout() {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1;\n this.callback();\n }, this.timerCalc(this.tries + 1));\n }\n\n}; // js/phoenix/channel.js\n\nvar Channel = class {\n constructor(topic, params, socket) {\n this.state = CHANNEL_STATES.closed;\n this.topic = topic;\n this.params = closure(params || {});\n this.socket = socket;\n this.bindings = [];\n this.bindingRef = 0;\n this.timeout = this.socket.timeout;\n this.joinedOnce = false;\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout);\n this.pushBuffer = [];\n this.stateChangeRefs = [];\n this.rejoinTimer = new Timer(() => {\n if (this.socket.isConnected()) {\n this.rejoin();\n }\n }, this.socket.rejoinAfterMs);\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()));\n this.stateChangeRefs.push(this.socket.onOpen(() => {\n this.rejoinTimer.reset();\n\n if (this.isErrored()) {\n this.rejoin();\n }\n }));\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined;\n this.rejoinTimer.reset();\n this.pushBuffer.forEach(pushEvent => pushEvent.send());\n this.pushBuffer = [];\n });\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored;\n\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.onClose(() => {\n this.rejoinTimer.reset();\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`);\n this.state = CHANNEL_STATES.closed;\n this.socket.remove(this);\n });\n this.onError(reason => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason);\n\n if (this.isJoining()) {\n this.joinPush.reset();\n }\n\n this.state = CHANNEL_STATES.errored;\n\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.joinPush.receive(\"timeout\", () => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout);\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout);\n leavePush.send();\n this.state = CHANNEL_STATES.errored;\n this.joinPush.reset();\n\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload);\n });\n }\n\n join(timeout = this.timeout) {\n if (this.joinedOnce) {\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\");\n } else {\n this.timeout = timeout;\n this.joinedOnce = true;\n this.rejoin();\n return this.joinPush;\n }\n }\n\n onClose(callback) {\n this.on(CHANNEL_EVENTS.close, callback);\n }\n\n onError(callback) {\n return this.on(CHANNEL_EVENTS.error, reason => callback(reason));\n }\n\n on(event, callback) {\n let ref = this.bindingRef++;\n this.bindings.push({\n event,\n ref,\n callback\n });\n return ref;\n }\n\n off(event, ref) {\n this.bindings = this.bindings.filter(bind => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref));\n });\n }\n\n canPush() {\n return this.socket.isConnected() && this.isJoined();\n }\n\n push(event, payload, timeout = this.timeout) {\n payload = payload || {};\n\n if (!this.joinedOnce) {\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`);\n }\n\n let pushEvent = new Push(this, event, function () {\n return payload;\n }, timeout);\n\n if (this.canPush()) {\n pushEvent.send();\n } else {\n pushEvent.startTimeout();\n this.pushBuffer.push(pushEvent);\n }\n\n return pushEvent;\n }\n\n leave(timeout = this.timeout) {\n this.rejoinTimer.reset();\n this.joinPush.cancelTimeout();\n this.state = CHANNEL_STATES.leaving;\n\n let onClose = () => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`);\n this.trigger(CHANNEL_EVENTS.close, \"leave\");\n };\n\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout);\n leavePush.receive(\"ok\", () => onClose()).receive(\"timeout\", () => onClose());\n leavePush.send();\n\n if (!this.canPush()) {\n leavePush.trigger(\"ok\", {});\n }\n\n return leavePush;\n }\n\n onMessage(_event, payload, _ref) {\n return payload;\n }\n\n isMember(topic, event, payload, joinRef) {\n if (this.topic !== topic) {\n return false;\n }\n\n if (joinRef && joinRef !== this.joinRef()) {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {\n topic,\n event,\n payload,\n joinRef\n });\n return false;\n } else {\n return true;\n }\n }\n\n joinRef() {\n return this.joinPush.ref;\n }\n\n rejoin(timeout = this.timeout) {\n if (this.isLeaving()) {\n return;\n }\n\n this.socket.leaveOpenTopic(this.topic);\n this.state = CHANNEL_STATES.joining;\n this.joinPush.resend(timeout);\n }\n\n trigger(event, payload, ref, joinRef) {\n let handledPayload = this.onMessage(event, payload, ref, joinRef);\n\n if (payload && !handledPayload) {\n throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\");\n }\n\n let eventBindings = this.bindings.filter(bind => bind.event === event);\n\n for (let i = 0; i < eventBindings.length; i++) {\n let bind = eventBindings[i];\n bind.callback(handledPayload, ref, joinRef || this.joinRef());\n }\n }\n\n replyEventName(ref) {\n return `chan_reply_${ref}`;\n }\n\n isClosed() {\n return this.state === CHANNEL_STATES.closed;\n }\n\n isErrored() {\n return this.state === CHANNEL_STATES.errored;\n }\n\n isJoined() {\n return this.state === CHANNEL_STATES.joined;\n }\n\n isJoining() {\n return this.state === CHANNEL_STATES.joining;\n }\n\n isLeaving() {\n return this.state === CHANNEL_STATES.leaving;\n }\n\n}; // js/phoenix/ajax.js\n\nvar Ajax = class {\n static request(method, endPoint, accept, body, timeout, ontimeout, callback) {\n if (global.XDomainRequest) {\n let req = new global.XDomainRequest();\n this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback);\n } else {\n let req = new global.XMLHttpRequest();\n this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback);\n }\n }\n\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback) {\n req.timeout = timeout;\n req.open(method, endPoint);\n\n req.onload = () => {\n let response = this.parseJSON(req.responseText);\n callback && callback(response);\n };\n\n if (ontimeout) {\n req.ontimeout = ontimeout;\n }\n\n req.onprogress = () => {};\n\n req.send(body);\n }\n\n static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback) {\n req.open(method, endPoint, true);\n req.timeout = timeout;\n req.setRequestHeader(\"Content-Type\", accept);\n\n req.onerror = () => {\n callback && callback(null);\n };\n\n req.onreadystatechange = () => {\n if (req.readyState === XHR_STATES.complete && callback) {\n let response = this.parseJSON(req.responseText);\n callback(response);\n }\n };\n\n if (ontimeout) {\n req.ontimeout = ontimeout;\n }\n\n req.send(body);\n }\n\n static parseJSON(resp) {\n if (!resp || resp === \"\") {\n return null;\n }\n\n try {\n return JSON.parse(resp);\n } catch (e) {\n console && console.log(\"failed to parse JSON response\", resp);\n return null;\n }\n }\n\n static serialize(obj, parentKey) {\n let queryStr = [];\n\n for (var key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) {\n continue;\n }\n\n let paramKey = parentKey ? `${parentKey}[${key}]` : key;\n let paramVal = obj[key];\n\n if (typeof paramVal === \"object\") {\n queryStr.push(this.serialize(paramVal, paramKey));\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal));\n }\n }\n\n return queryStr.join(\"&\");\n }\n\n static appendParams(url, params) {\n if (Object.keys(params).length === 0) {\n return url;\n }\n\n let prefix = url.match(/\\?/) ? \"&\" : \"?\";\n return `${url}${prefix}${this.serialize(params)}`;\n }\n\n}; // js/phoenix/longpoll.js\n\nvar LongPoll = class {\n constructor(endPoint) {\n this.endPoint = null;\n this.token = null;\n this.skipHeartbeat = true;\n\n this.onopen = function () {};\n\n this.onerror = function () {};\n\n this.onmessage = function () {};\n\n this.onclose = function () {};\n\n this.pollEndpoint = this.normalizeEndpoint(endPoint);\n this.readyState = SOCKET_STATES.connecting;\n this.poll();\n }\n\n normalizeEndpoint(endPoint) {\n return endPoint.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\").replace(new RegExp(\"(.*)/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll);\n }\n\n endpointURL() {\n return Ajax.appendParams(this.pollEndpoint, {\n token: this.token\n });\n }\n\n closeAndRetry() {\n this.close();\n this.readyState = SOCKET_STATES.connecting;\n }\n\n ontimeout() {\n this.onerror(\"timeout\");\n this.closeAndRetry();\n }\n\n poll() {\n if (!(this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting)) {\n return;\n }\n\n Ajax.request(\"GET\", this.endpointURL(), \"application/json\", null, this.timeout, this.ontimeout.bind(this), resp => {\n if (resp) {\n var {\n status,\n token,\n messages\n } = resp;\n this.token = token;\n } else {\n status = 0;\n }\n\n switch (status) {\n case 200:\n messages.forEach(msg => {\n setTimeout(() => {\n this.onmessage({\n data: msg\n });\n }, 0);\n });\n this.poll();\n break;\n\n case 204:\n this.poll();\n break;\n\n case 410:\n this.readyState = SOCKET_STATES.open;\n this.onopen();\n this.poll();\n break;\n\n case 403:\n this.onerror();\n this.close();\n break;\n\n case 0:\n case 500:\n this.onerror();\n this.closeAndRetry();\n break;\n\n default:\n throw new Error(`unhandled poll status ${status}`);\n }\n });\n }\n\n send(body) {\n Ajax.request(\"POST\", this.endpointURL(), \"application/json\", body, this.timeout, this.onerror.bind(this, \"timeout\"), resp => {\n if (!resp || resp.status !== 200) {\n this.onerror(resp && resp.status);\n this.closeAndRetry();\n }\n });\n }\n\n close(_code, _reason) {\n this.readyState = SOCKET_STATES.closed;\n this.onclose();\n }\n\n}; // js/phoenix/presence.js\n\nvar Presence = class {\n constructor(channel, opts = {}) {\n let events = opts.events || {\n state: \"presence_state\",\n diff: \"presence_diff\"\n };\n this.state = {};\n this.pendingDiffs = [];\n this.channel = channel;\n this.joinRef = null;\n this.caller = {\n onJoin: function () {},\n onLeave: function () {},\n onSync: function () {}\n };\n this.channel.on(events.state, newState => {\n let {\n onJoin,\n onLeave,\n onSync\n } = this.caller;\n this.joinRef = this.channel.joinRef();\n this.state = Presence.syncState(this.state, newState, onJoin, onLeave);\n this.pendingDiffs.forEach(diff => {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave);\n });\n this.pendingDiffs = [];\n onSync();\n });\n this.channel.on(events.diff, diff => {\n let {\n onJoin,\n onLeave,\n onSync\n } = this.caller;\n\n if (this.inPendingSyncState()) {\n this.pendingDiffs.push(diff);\n } else {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave);\n onSync();\n }\n });\n }\n\n onJoin(callback) {\n this.caller.onJoin = callback;\n }\n\n onLeave(callback) {\n this.caller.onLeave = callback;\n }\n\n onSync(callback) {\n this.caller.onSync = callback;\n }\n\n list(by) {\n return Presence.list(this.state, by);\n }\n\n inPendingSyncState() {\n return !this.joinRef || this.joinRef !== this.channel.joinRef();\n }\n\n static syncState(currentState, newState, onJoin, onLeave) {\n let state = this.clone(currentState);\n let joins = {};\n let leaves = {};\n this.map(state, (key, presence) => {\n if (!newState[key]) {\n leaves[key] = presence;\n }\n });\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key];\n\n if (currentPresence) {\n let newRefs = newPresence.metas.map(m => m.phx_ref);\n let curRefs = currentPresence.metas.map(m => m.phx_ref);\n let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0);\n let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0);\n\n if (joinedMetas.length > 0) {\n joins[key] = newPresence;\n joins[key].metas = joinedMetas;\n }\n\n if (leftMetas.length > 0) {\n leaves[key] = this.clone(currentPresence);\n leaves[key].metas = leftMetas;\n }\n } else {\n joins[key] = newPresence;\n }\n });\n return this.syncDiff(state, {\n joins,\n leaves\n }, onJoin, onLeave);\n }\n\n static syncDiff(state, diff, onJoin, onLeave) {\n let {\n joins,\n leaves\n } = this.clone(diff);\n\n if (!onJoin) {\n onJoin = function () {};\n }\n\n if (!onLeave) {\n onLeave = function () {};\n }\n\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key];\n state[key] = this.clone(newPresence);\n\n if (currentPresence) {\n let joinedRefs = state[key].metas.map(m => m.phx_ref);\n let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0);\n state[key].metas.unshift(...curMetas);\n }\n\n onJoin(key, currentPresence, newPresence);\n });\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key];\n\n if (!currentPresence) {\n return;\n }\n\n let refsToRemove = leftPresence.metas.map(m => m.phx_ref);\n currentPresence.metas = currentPresence.metas.filter(p => {\n return refsToRemove.indexOf(p.phx_ref) < 0;\n });\n onLeave(key, currentPresence, leftPresence);\n\n if (currentPresence.metas.length === 0) {\n delete state[key];\n }\n });\n return state;\n }\n\n static list(presences, chooser) {\n if (!chooser) {\n chooser = function (key, pres) {\n return pres;\n };\n }\n\n return this.map(presences, (key, presence) => {\n return chooser(key, presence);\n });\n }\n\n static map(obj, func) {\n return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]));\n }\n\n static clone(obj) {\n return JSON.parse(JSON.stringify(obj));\n }\n\n}; // js/phoenix/serializer.js\n\nvar serializer_default = {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: {\n push: 0,\n reply: 1,\n broadcast: 2\n },\n\n encode(msg, callback) {\n if (msg.payload.constructor === ArrayBuffer) {\n return callback(this.binaryEncode(msg));\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload];\n return callback(JSON.stringify(payload));\n }\n },\n\n decode(rawPayload, callback) {\n if (rawPayload.constructor === ArrayBuffer) {\n return callback(this.binaryDecode(rawPayload));\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload);\n return callback({\n join_ref,\n ref,\n topic,\n event,\n payload\n });\n }\n },\n\n binaryEncode(message) {\n let {\n join_ref,\n ref,\n event,\n topic,\n payload\n } = message;\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length;\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength);\n let view = new DataView(header);\n let offset = 0;\n view.setUint8(offset++, this.KINDS.push);\n view.setUint8(offset++, join_ref.length);\n view.setUint8(offset++, ref.length);\n view.setUint8(offset++, topic.length);\n view.setUint8(offset++, event.length);\n Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)));\n var combined = new Uint8Array(header.byteLength + payload.byteLength);\n combined.set(new Uint8Array(header), 0);\n combined.set(new Uint8Array(payload), header.byteLength);\n return combined.buffer;\n },\n\n binaryDecode(buffer) {\n let view = new DataView(buffer);\n let kind = view.getUint8(0);\n let decoder = new TextDecoder();\n\n switch (kind) {\n case this.KINDS.push:\n return this.decodePush(buffer, view, decoder);\n\n case this.KINDS.reply:\n return this.decodeReply(buffer, view, decoder);\n\n case this.KINDS.broadcast:\n return this.decodeBroadcast(buffer, view, decoder);\n }\n },\n\n decodePush(buffer, view, decoder) {\n let joinRefSize = view.getUint8(1);\n let topicSize = view.getUint8(2);\n let eventSize = view.getUint8(3);\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1;\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));\n offset = offset + joinRefSize;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n return {\n join_ref: joinRef,\n ref: null,\n topic,\n event,\n payload: data\n };\n },\n\n decodeReply(buffer, view, decoder) {\n let joinRefSize = view.getUint8(1);\n let refSize = view.getUint8(2);\n let topicSize = view.getUint8(3);\n let eventSize = view.getUint8(4);\n let offset = this.HEADER_LENGTH + this.META_LENGTH;\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));\n offset = offset + joinRefSize;\n let ref = decoder.decode(buffer.slice(offset, offset + refSize));\n offset = offset + refSize;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n let payload = {\n status: event,\n response: data\n };\n return {\n join_ref: joinRef,\n ref,\n topic,\n event: CHANNEL_EVENTS.reply,\n payload\n };\n },\n\n decodeBroadcast(buffer, view, decoder) {\n let topicSize = view.getUint8(1);\n let eventSize = view.getUint8(2);\n let offset = this.HEADER_LENGTH + 2;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n return {\n join_ref: null,\n ref: null,\n topic,\n event,\n payload: data\n };\n }\n\n}; // js/phoenix/socket.js\n\nvar Socket = class {\n constructor(endPoint, opts = {}) {\n this.stateChangeCallbacks = {\n open: [],\n close: [],\n error: [],\n message: []\n };\n this.channels = [];\n this.sendBuffer = [];\n this.ref = 0;\n this.timeout = opts.timeout || DEFAULT_TIMEOUT;\n this.transport = opts.transport || global.WebSocket || LongPoll;\n this.establishedConnections = 0;\n this.defaultEncoder = serializer_default.encode.bind(serializer_default);\n this.defaultDecoder = serializer_default.decode.bind(serializer_default);\n this.closeWasClean = false;\n this.binaryType = opts.binaryType || \"arraybuffer\";\n this.connectClock = 1;\n\n if (this.transport !== LongPoll) {\n this.encode = opts.encode || this.defaultEncoder;\n this.decode = opts.decode || this.defaultDecoder;\n } else {\n this.encode = this.defaultEncoder;\n this.decode = this.defaultDecoder;\n }\n\n let awaitingConnectionOnPageShow = null;\n\n if (phxWindow && phxWindow.addEventListener) {\n phxWindow.addEventListener(\"pagehide\", _e => {\n if (this.conn) {\n this.disconnect();\n awaitingConnectionOnPageShow = this.connectClock;\n }\n });\n phxWindow.addEventListener(\"pageshow\", _e => {\n if (awaitingConnectionOnPageShow === this.connectClock) {\n awaitingConnectionOnPageShow = null;\n this.connect();\n }\n });\n }\n\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 3e4;\n\n this.rejoinAfterMs = tries => {\n if (opts.rejoinAfterMs) {\n return opts.rejoinAfterMs(tries);\n } else {\n return [1e3, 2e3, 5e3][tries - 1] || 1e4;\n }\n };\n\n this.reconnectAfterMs = tries => {\n if (opts.reconnectAfterMs) {\n return opts.reconnectAfterMs(tries);\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1e3, 2e3][tries - 1] || 5e3;\n }\n };\n\n this.logger = opts.logger || null;\n this.longpollerTimeout = opts.longpollerTimeout || 2e4;\n this.params = closure(opts.params || {});\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`;\n this.vsn = opts.vsn || DEFAULT_VSN;\n this.heartbeatTimer = null;\n this.pendingHeartbeatRef = null;\n this.reconnectTimer = new Timer(() => {\n this.teardown(() => this.connect());\n }, this.reconnectAfterMs);\n }\n\n replaceTransport(newTransport) {\n this.disconnect();\n this.transport = newTransport;\n }\n\n protocol() {\n return location.protocol.match(/^https/) ? \"wss\" : \"ws\";\n }\n\n endPointURL() {\n let uri = Ajax.appendParams(Ajax.appendParams(this.endPoint, this.params()), {\n vsn: this.vsn\n });\n\n if (uri.charAt(0) !== \"/\") {\n return uri;\n }\n\n if (uri.charAt(1) === \"/\") {\n return `${this.protocol()}:${uri}`;\n }\n\n return `${this.protocol()}://${location.host}${uri}`;\n }\n\n disconnect(callback, code, reason) {\n this.connectClock++;\n this.closeWasClean = true;\n this.reconnectTimer.reset();\n this.teardown(callback, code, reason);\n }\n\n connect(params) {\n this.connectClock++;\n\n if (params) {\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\");\n this.params = closure(params);\n }\n\n if (this.conn) {\n return;\n }\n\n this.closeWasClean = false;\n this.conn = new this.transport(this.endPointURL());\n this.conn.binaryType = this.binaryType;\n this.conn.timeout = this.longpollerTimeout;\n\n this.conn.onopen = () => this.onConnOpen();\n\n this.conn.onerror = error => this.onConnError(error);\n\n this.conn.onmessage = event => this.onConnMessage(event);\n\n this.conn.onclose = event => this.onConnClose(event);\n }\n\n log(kind, msg, data) {\n this.logger(kind, msg, data);\n }\n\n hasLogger() {\n return this.logger !== null;\n }\n\n onOpen(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.open.push([ref, callback]);\n return ref;\n }\n\n onClose(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.close.push([ref, callback]);\n return ref;\n }\n\n onError(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.error.push([ref, callback]);\n return ref;\n }\n\n onMessage(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.message.push([ref, callback]);\n return ref;\n }\n\n onConnOpen() {\n if (this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`);\n this.closeWasClean = false;\n this.establishedConnections++;\n this.flushSendBuffer();\n this.reconnectTimer.reset();\n this.resetHeartbeat();\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback());\n }\n\n heartbeatTimeout() {\n if (this.pendingHeartbeatRef) {\n this.pendingHeartbeatRef = null;\n\n if (this.hasLogger()) {\n this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\");\n }\n\n this.abnormalClose(\"heartbeat timeout\");\n }\n }\n\n resetHeartbeat() {\n if (this.conn && this.conn.skipHeartbeat) {\n return;\n }\n\n this.pendingHeartbeatRef = null;\n clearTimeout(this.heartbeatTimer);\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);\n }\n\n teardown(callback, code, reason) {\n if (!this.conn) {\n return callback && callback();\n }\n\n this.waitForBufferDone(() => {\n if (this.conn) {\n if (code) {\n this.conn.close(code, reason || \"\");\n } else {\n this.conn.close();\n }\n }\n\n this.waitForSocketClosed(() => {\n if (this.conn) {\n this.conn.onclose = function () {};\n\n this.conn = null;\n }\n\n callback && callback();\n });\n });\n }\n\n waitForBufferDone(callback, tries = 1) {\n if (tries === 5 || !this.conn || !this.conn.bufferedAmount) {\n callback();\n return;\n }\n\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1);\n }, 150 * tries);\n }\n\n waitForSocketClosed(callback, tries = 1) {\n if (tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed) {\n callback();\n return;\n }\n\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1);\n }, 150 * tries);\n }\n\n onConnClose(event) {\n if (this.hasLogger()) this.log(\"transport\", \"close\", event);\n this.triggerChanError();\n clearTimeout(this.heartbeatTimer);\n\n if (!this.closeWasClean) {\n this.reconnectTimer.scheduleTimeout();\n }\n\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event));\n }\n\n onConnError(error) {\n if (this.hasLogger()) this.log(\"transport\", error);\n let transportBefore = this.transport;\n let establishedBefore = this.establishedConnections;\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore);\n });\n\n if (transportBefore === this.transport || establishedBefore > 0) {\n this.triggerChanError();\n }\n }\n\n triggerChanError() {\n this.channels.forEach(channel => {\n if (!(channel.isErrored() || channel.isLeaving() || channel.isClosed())) {\n channel.trigger(CHANNEL_EVENTS.error);\n }\n });\n }\n\n connectionState() {\n switch (this.conn && this.conn.readyState) {\n case SOCKET_STATES.connecting:\n return \"connecting\";\n\n case SOCKET_STATES.open:\n return \"open\";\n\n case SOCKET_STATES.closing:\n return \"closing\";\n\n default:\n return \"closed\";\n }\n }\n\n isConnected() {\n return this.connectionState() === \"open\";\n }\n\n remove(channel) {\n this.off(channel.stateChangeRefs);\n this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef());\n }\n\n off(refs) {\n for (let key in this.stateChangeCallbacks) {\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1;\n });\n }\n }\n\n channel(topic, chanParams = {}) {\n let chan = new Channel(topic, chanParams, this);\n this.channels.push(chan);\n return chan;\n }\n\n push(data) {\n if (this.hasLogger()) {\n let {\n topic,\n event,\n payload,\n ref,\n join_ref\n } = data;\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload);\n }\n\n if (this.isConnected()) {\n this.encode(data, result => this.conn.send(result));\n } else {\n this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)));\n }\n }\n\n makeRef() {\n let newRef = this.ref + 1;\n\n if (newRef === this.ref) {\n this.ref = 0;\n } else {\n this.ref = newRef;\n }\n\n return this.ref.toString();\n }\n\n sendHeartbeat() {\n if (this.pendingHeartbeatRef && !this.isConnected()) {\n return;\n }\n\n this.pendingHeartbeatRef = this.makeRef();\n this.push({\n topic: \"phoenix\",\n event: \"heartbeat\",\n payload: {},\n ref: this.pendingHeartbeatRef\n });\n this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs);\n }\n\n abnormalClose(reason) {\n this.closeWasClean = false;\n\n if (this.isConnected()) {\n this.conn.close(WS_CLOSE_NORMAL, reason);\n }\n }\n\n flushSendBuffer() {\n if (this.isConnected() && this.sendBuffer.length > 0) {\n this.sendBuffer.forEach(callback => callback());\n this.sendBuffer = [];\n }\n }\n\n onConnMessage(rawMessage) {\n this.decode(rawMessage.data, msg => {\n let {\n topic,\n event,\n payload,\n ref,\n join_ref\n } = msg;\n\n if (ref && ref === this.pendingHeartbeatRef) {\n clearTimeout(this.heartbeatTimer);\n this.pendingHeartbeatRef = null;\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);\n }\n\n if (this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload);\n\n for (let i = 0; i < this.channels.length; i++) {\n const channel = this.channels[i];\n\n if (!channel.isMember(topic, event, payload, join_ref)) {\n continue;\n }\n\n channel.trigger(event, payload, ref, join_ref);\n }\n\n for (let i = 0; i < this.stateChangeCallbacks.message.length; i++) {\n let [, callback] = this.stateChangeCallbacks.message[i];\n callback(msg);\n }\n });\n }\n\n leaveOpenTopic(topic) {\n let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()));\n\n if (dupChannel) {\n if (this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`);\n dupChannel.leave();\n }\n }\n\n};\n\n\n//# sourceURL=webpack://@seamly/web-ui/./node_modules/phoenix/priv/static/phoenix.esm.js?");
83
83
 
84
84
  /***/ }),
85
85
 
@@ -750,7 +750,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
750
750
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
751
751
 
752
752
  "use strict";
753
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createStore\": () => (/* binding */ createStore)\n/* harmony export */ });\n/* harmony import */ var redux_thunk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! redux-thunk */ \"./node_modules/redux-thunk/es/index.js\");\n/* harmony import */ var _redux__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../redux */ \"./src/javascripts/domains/redux/index.js\");\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../app */ \"./src/javascripts/domains/app/index.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../config */ \"./src/javascripts/domains/config/index.js\");\n/* harmony import */ var _forms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../forms */ \"./src/javascripts/domains/forms/index.js\");\n/* harmony import */ var _translations__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../translations */ \"./src/javascripts/domains/translations/index.js\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../i18n */ \"./src/javascripts/domains/i18n/index.js\");\n/* harmony import */ var _visibility__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../visibility */ \"./src/javascripts/domains/visibility/index.js\");\n/* harmony import */ var _interrupt__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../interrupt */ \"./src/javascripts/domains/interrupt/index.js\");\n/* harmony import */ var _options__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../options */ \"./src/javascripts/domains/options/index.js\");\n/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../errors */ \"./src/javascripts/domains/errors/index.js\");\n/* harmony import */ var _state_reducer__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./state-reducer */ \"./src/javascripts/domains/store/state-reducer.js\");\n\n\n\n\n\n\n\n\n\n\n\n\nfunction createStore({\n initialState,\n api,\n eventBus\n} = {}) {\n const store = (0,_redux__WEBPACK_IMPORTED_MODULE_1__.createReduxStore)({\n reducers: {\n state: _state_reducer__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n [String(_app__WEBPACK_IMPORTED_MODULE_2__.Reducer)]: _app__WEBPACK_IMPORTED_MODULE_2__.Reducer,\n [String(_config__WEBPACK_IMPORTED_MODULE_3__.Reducer)]: _config__WEBPACK_IMPORTED_MODULE_3__.Reducer,\n [String(_forms__WEBPACK_IMPORTED_MODULE_4__.Reducer)]: _forms__WEBPACK_IMPORTED_MODULE_4__.Reducer,\n [String(_translations__WEBPACK_IMPORTED_MODULE_5__.Reducer)]: _translations__WEBPACK_IMPORTED_MODULE_5__.Reducer,\n [String(_i18n__WEBPACK_IMPORTED_MODULE_6__.Reducer)]: _i18n__WEBPACK_IMPORTED_MODULE_6__.Reducer,\n [String(_interrupt__WEBPACK_IMPORTED_MODULE_8__.Reducer)]: _interrupt__WEBPACK_IMPORTED_MODULE_8__.Reducer,\n [String(_visibility__WEBPACK_IMPORTED_MODULE_7__.Reducer)]: _visibility__WEBPACK_IMPORTED_MODULE_7__.Reducer\n },\n initialState,\n middlewares: [(0,_errors__WEBPACK_IMPORTED_MODULE_10__.createMiddleware)({\n api\n }), redux_thunk__WEBPACK_IMPORTED_MODULE_0__[\"default\"].withExtraArgument({\n api,\n eventBus\n }), (0,_config__WEBPACK_IMPORTED_MODULE_3__.createMiddleware)(), (0,_interrupt__WEBPACK_IMPORTED_MODULE_8__.createMiddleware)({\n api\n }), (0,_options__WEBPACK_IMPORTED_MODULE_9__.createMiddleware)({\n api\n }), (0,_translations__WEBPACK_IMPORTED_MODULE_5__.createMiddleware)()]\n });\n return store;\n}\n\n//# sourceURL=webpack://@seamly/web-ui/./src/javascripts/domains/store/index.js?");
753
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createStore\": () => (/* binding */ createStore)\n/* harmony export */ });\n/* harmony import */ var redux_thunk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! redux-thunk */ \"./node_modules/redux-thunk/es/index.js\");\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../app */ \"./src/javascripts/domains/app/index.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config */ \"./src/javascripts/domains/config/index.js\");\n/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ \"./src/javascripts/domains/errors/index.js\");\n/* harmony import */ var _forms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../forms */ \"./src/javascripts/domains/forms/index.js\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../i18n */ \"./src/javascripts/domains/i18n/index.js\");\n/* harmony import */ var _interrupt__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../interrupt */ \"./src/javascripts/domains/interrupt/index.js\");\n/* harmony import */ var _options__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../options */ \"./src/javascripts/domains/options/index.js\");\n/* harmony import */ var _redux__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../redux */ \"./src/javascripts/domains/redux/index.js\");\n/* harmony import */ var _translations__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../translations */ \"./src/javascripts/domains/translations/index.js\");\n/* harmony import */ var _visibility__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../visibility */ \"./src/javascripts/domains/visibility/index.js\");\n/* harmony import */ var _state_reducer__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./state-reducer */ \"./src/javascripts/domains/store/state-reducer.js\");\n\n\n\n\n\n\n\n\n\n\n\n\nfunction createStore({\n initialState,\n api,\n eventBus\n} = {}) {\n const store = (0,_redux__WEBPACK_IMPORTED_MODULE_8__.createReduxStore)({\n reducers: {\n state: _state_reducer__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n [String(_app__WEBPACK_IMPORTED_MODULE_1__.Reducer)]: _app__WEBPACK_IMPORTED_MODULE_1__.Reducer,\n [String(_config__WEBPACK_IMPORTED_MODULE_2__.Reducer)]: _config__WEBPACK_IMPORTED_MODULE_2__.Reducer,\n [String(_forms__WEBPACK_IMPORTED_MODULE_4__.Reducer)]: _forms__WEBPACK_IMPORTED_MODULE_4__.Reducer,\n [String(_translations__WEBPACK_IMPORTED_MODULE_9__.Reducer)]: _translations__WEBPACK_IMPORTED_MODULE_9__.Reducer,\n [String(_i18n__WEBPACK_IMPORTED_MODULE_5__.Reducer)]: _i18n__WEBPACK_IMPORTED_MODULE_5__.Reducer,\n [String(_interrupt__WEBPACK_IMPORTED_MODULE_6__.Reducer)]: _interrupt__WEBPACK_IMPORTED_MODULE_6__.Reducer,\n [String(_visibility__WEBPACK_IMPORTED_MODULE_10__.Reducer)]: _visibility__WEBPACK_IMPORTED_MODULE_10__.Reducer\n },\n initialState,\n middlewares: [(0,_errors__WEBPACK_IMPORTED_MODULE_3__.createMiddleware)({\n api\n }), redux_thunk__WEBPACK_IMPORTED_MODULE_0__[\"default\"].withExtraArgument({\n api,\n eventBus\n }), (0,_config__WEBPACK_IMPORTED_MODULE_2__.createMiddleware)(), (0,_interrupt__WEBPACK_IMPORTED_MODULE_6__.createMiddleware)({\n api\n }), (0,_options__WEBPACK_IMPORTED_MODULE_7__.createMiddleware)({\n api\n }), _translations__WEBPACK_IMPORTED_MODULE_9__.createMiddleware]\n });\n return store;\n}\n\n//# sourceURL=webpack://@seamly/web-ui/./src/javascripts/domains/store/index.js?");
754
754
 
755
755
  /***/ }),
756
756
 
@@ -849,7 +849,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
849
849
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
850
850
 
851
851
  "use strict";
852
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ createMiddleware)\n/* harmony export */ });\n/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./actions */ \"./src/javascripts/domains/translations/actions.js\");\n/* harmony import */ var _ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../ui/utils/seamly-utils */ \"./src/javascripts/ui/utils/seamly-utils.js\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../i18n */ \"./src/javascripts/domains/i18n/index.js\");\n\n\n\nfunction createMiddleware() {\n return ({\n dispatch,\n getState\n }) => next => action => {\n var _action$history, _action$history$trans, _action$initialState, _action$initialState$, _action$event, _action$event$payload, _action$event$payload2;\n\n const result = next(action);\n\n switch (action.type) {\n case String(_ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_1__.seamlyActions.SET_HISTORY):\n if ((_action$history = action.history) !== null && _action$history !== void 0 && (_action$history$trans = _action$history.translation) !== null && _action$history$trans !== void 0 && _action$history$trans.enabled) {\n dispatch(_actions__WEBPACK_IMPORTED_MODULE_0__.enable(action.history.translation.locale));\n }\n\n break;\n\n case String(_ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_1__.seamlyActions.SET_INITIAL_STATE):\n if ((_action$initialState = action.initialState) !== null && _action$initialState !== void 0 && (_action$initialState$ = _action$initialState.translation) !== null && _action$initialState$ !== void 0 && _action$initialState$.enabled) {\n dispatch(_actions__WEBPACK_IMPORTED_MODULE_0__.enable(action.initialState.translation.locale));\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_2__.Actions.setLocale(action.locale));\n }\n\n break;\n\n case String(_ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_1__.seamlyActions.ADD_EVENT):\n if (action.event.type === 'info' && ((_action$event = action.event) === null || _action$event === void 0 ? void 0 : (_action$event$payload = _action$event.payload) === null || _action$event$payload === void 0 ? void 0 : (_action$event$payload2 = _action$event$payload.body) === null || _action$event$payload2 === void 0 ? void 0 : _action$event$payload2.subtype) === 'new_translation' && action.event.payload.body.translationEnabled) {\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_2__.Actions.setLocale(action.event.payload.body.translationLocale));\n }\n\n break;\n\n case String(_actions__WEBPACK_IMPORTED_MODULE_0__.disable):\n const initialLocale = _i18n__WEBPACK_IMPORTED_MODULE_2__.Selectors.selectInitialLocale(getState());\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_2__.Actions.setLocale(initialLocale));\n break;\n }\n\n return result;\n };\n}\n\n//# sourceURL=webpack://@seamly/web-ui/./src/javascripts/domains/translations/middleware.js?");
852
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ createMiddleware)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../ui/utils/seamly-utils */ \"./src/javascripts/ui/utils/seamly-utils.js\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../i18n */ \"./src/javascripts/domains/i18n/index.js\");\n/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./actions */ \"./src/javascripts/domains/translations/actions.js\");\n\n\n\nfunction createMiddleware({\n dispatch,\n getState\n}) {\n return next => {\n return action => {\n var _action$history, _action$history$trans, _action$initialState, _action$initialState$, _action$event, _action$event$payload, _action$event$payload2;\n\n const result = next(action);\n\n switch (action.type) {\n case String(_ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_0__.seamlyActions.SET_HISTORY):\n if ((_action$history = action.history) !== null && _action$history !== void 0 && (_action$history$trans = _action$history.translation) !== null && _action$history$trans !== void 0 && _action$history$trans.enabled) {\n dispatch(_actions__WEBPACK_IMPORTED_MODULE_2__.enable(action.history.translation.locale));\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_1__.Actions.setLocale(action.history.translation.locale));\n }\n\n break;\n\n case String(_ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_0__.seamlyActions.SET_INITIAL_STATE):\n if ((_action$initialState = action.initialState) !== null && _action$initialState !== void 0 && (_action$initialState$ = _action$initialState.translation) !== null && _action$initialState$ !== void 0 && _action$initialState$.enabled) {\n dispatch(_actions__WEBPACK_IMPORTED_MODULE_2__.enable(action.initialState.translation.locale));\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_1__.Actions.setLocale(action.locale));\n }\n\n break;\n\n case String(_ui_utils_seamly_utils__WEBPACK_IMPORTED_MODULE_0__.seamlyActions.ADD_EVENT):\n if (action.event.type === 'info' && ((_action$event = action.event) === null || _action$event === void 0 ? void 0 : (_action$event$payload = _action$event.payload) === null || _action$event$payload === void 0 ? void 0 : (_action$event$payload2 = _action$event$payload.body) === null || _action$event$payload2 === void 0 ? void 0 : _action$event$payload2.subtype) === 'new_translation' && action.event.payload.body.translationEnabled) {\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_1__.Actions.setLocale(action.event.payload.body.translationLocale));\n }\n\n break;\n\n case String(_actions__WEBPACK_IMPORTED_MODULE_2__.disable):\n const initialLocale = _i18n__WEBPACK_IMPORTED_MODULE_1__.Selectors.selectInitialLocale(getState());\n dispatch(_i18n__WEBPACK_IMPORTED_MODULE_1__.Actions.setLocale(initialLocale));\n break;\n }\n\n return result;\n };\n };\n}\n\n//# sourceURL=webpack://@seamly/web-ui/./src/javascripts/domains/translations/middleware.js?");
853
853
 
854
854
  /***/ }),
855
855