| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 | 
							- // eslint-disable-next-line import/no-cycle
 
- import store from "./store";
 
- const onConnect = {
 
- 	temp: [],
 
- 	persist: []
 
- };
 
- let pendingDispatches = [];
 
- const onDisconnect = {
 
- 	temp: [],
 
- 	persist: []
 
- };
 
- // references for when a dispatch event is ready to callback from server to client
 
- const CB_REFS = {};
 
- let CB_REF = 0;
 
- export default {
 
- 	socket: null,
 
- 	dispatcher: null,
 
- 	onConnect(...args) {
 
- 		if (args[0] === true) onConnect.persist.push(args[1]);
 
- 		else onConnect.temp.push(args[0]);
 
- 	},
 
- 	onDisconnect(...args) {
 
- 		if (args[0] === true) onDisconnect.persist.push(args[1]);
 
- 		else onDisconnect.temp.push(args[0]);
 
- 	},
 
- 	clear: () => {
 
- 		onConnect.temp = [];
 
- 		onDisconnect.temp = [];
 
- 	},
 
- 	removeAllListeners: () =>
 
- 		Object.keys(CB_REFS).forEach(id => {
 
- 			if (
 
- 				id.indexOf("$event:") !== -1 &&
 
- 				id.indexOf("$event:keep.") === -1
 
- 			)
 
- 				delete CB_REFS[id];
 
- 		}),
 
- 	init(url) {
 
- 		// ensures correct context of socket object when dispatching (because socket object is recreated on reconnection)
 
- 		const waitForConnectionToDispatch = (...args) =>
 
- 			this.socket.dispatch(...args);
 
- 		class ListenerHandler extends EventTarget {
 
- 			constructor() {
 
- 				super();
 
- 				this.listeners = {};
 
- 			}
 
- 			addEventListener(type, cb) {
 
- 				if (!(type in this.listeners)) this.listeners[type] = []; // add the listener type to listeners object
 
- 				this.listeners[type].push(cb); // push the callback
 
- 			}
 
- 			// eslint-disable-next-line consistent-return
 
- 			removeEventListener(type, cb) {
 
- 				if (!(type in this.listeners)) return true; // event type doesn't exist
 
- 				const stack = this.listeners[type];
 
- 				stack.forEach((element, index) => {
 
- 					if (element === cb) stack.splice(index, 1);
 
- 				});
 
- 			}
 
- 			dispatchEvent(event) {
 
- 				if (!(event.type in this.listeners)) return true; // event type doesn't exist
 
- 				const stack = this.listeners[event.type].slice();
 
- 				stack.forEach(element => element.call(this, event));
 
- 				return !event.defaultPrevented;
 
- 			}
 
- 		}
 
- 		class CustomWebSocket extends WebSocket {
 
- 			constructor() {
 
- 				super(url);
 
- 				this.dispatcher = new ListenerHandler();
 
- 			}
 
- 			on(target, cb) {
 
- 				this.dispatcher.addEventListener(target, event =>
 
- 					cb(...event.detail)
 
- 				);
 
- 			}
 
- 			dispatch(...args) {
 
- 				CB_REF += 1;
 
- 				if (this.readyState !== 1)
 
- 					return pendingDispatches.push(() =>
 
- 						waitForConnectionToDispatch(...args)
 
- 					);
 
- 				const cb = args[args.length - 1];
 
- 				if (typeof cb === "function") {
 
- 					CB_REFS[CB_REF] = cb;
 
- 					return this.send(
 
- 						JSON.stringify([...args.slice(0, -1), { CB_REF }])
 
- 					);
 
- 				}
 
- 				return this.send(JSON.stringify([...args]));
 
- 			}
 
- 		}
 
- 		this.socket = new CustomWebSocket();
 
- 		store.dispatch("websockets/createSocket", this.socket);
 
- 		this.socket.onopen = () => {
 
- 			console.log("WS: SOCKET CONNECTED");
 
- 			setTimeout(() => {
 
- 				onConnect.temp.forEach(cb => cb());
 
- 				// dispatches that were attempted while the server was offline
 
- 				pendingDispatches.forEach(cb => cb());
 
- 				pendingDispatches = [];
 
- 				onConnect.persist.forEach(cb => cb());
 
- 			}, 50); // small delay between readyState being 1 and the server actually receiving dispatches
 
- 		};
 
- 		this.socket.onmessage = message => {
 
- 			const data = JSON.parse(message.data);
 
- 			const name = data.shift(0);
 
- 			if (name === "CB_REF") {
 
- 				const CB_REF = data.shift(0);
 
- 				CB_REFS[CB_REF](...data);
 
- 				return delete CB_REFS[CB_REF];
 
- 			}
 
- 			if (name === "ERROR") console.log("WS: SOCKET ERROR:", data[0]);
 
- 			return this.socket.dispatcher.dispatchEvent(
 
- 				new CustomEvent(name, {
 
- 					detail: data
 
- 				})
 
- 			);
 
- 		};
 
- 		this.socket.onclose = () => {
 
- 			console.log("WS: SOCKET DISCONNECTED");
 
- 			onDisconnect.temp.forEach(cb => cb());
 
- 			onDisconnect.persist.forEach(cb => cb());
 
- 			// try to reconnect every 1000ms
 
- 			setTimeout(() => this.init(url), 1000);
 
- 		};
 
- 		this.socket.onerror = err => {
 
- 			console.log("WS: SOCKET ERROR", err);
 
- 			// new Toast("Cannot perform this action at this time.");
 
- 		};
 
- 	}
 
- };
 
 
  |