moebius-web

web based ansi art editor

moebius-web

public/js/network.js


function createWorkerHandler(inputHandle) {
	"use strict";
	var worker = new Worker("js/worker.js");
	var handle = localStorage.getItem("handle");
	if (handle === null) {
		handle = "Anonymous";
		localStorage.setItem("handle", handle);
	}
	inputHandle.value = handle;
	var connected = false;
	worker.postMessage({ "cmd": "handle", "handle": handle });
	showOverlay($("websocket-overlay"));

	function onConnected() {
		var excludedElements = document.getElementsByClassName("excluded-for-websocket");
		for (var i = 0; i < excludedElements.length; i++) {
			excludedElements[i].style.display = "none";
		}
		var includedElement = document.getElementsByClassName("included-for-websocket");
		for (var i = 0; i < includedElement.length; i++) {
			includedElement[i].style.display = "block";
		}
		title.setName(window.location.hostname);
		worker.postMessage({ "cmd": "join", "handle": handle });
		connected = true;
	}

	function onDisconnected() {
		if (connected === true) {
			alert("You were disconnected from the server, try refreshing the page to try again.");
		} else {
			hideOverlay($("websocket-overlay"));
		}
		connected = false;
	}

	function onImageData(columns, rows, data, iceColours, letterSpacing) {
		textArtCanvas.setImageData(columns, rows, data, iceColours, letterSpacing);
		hideOverlay($("websocket-overlay"));
	}

	function onChat(handle, text, showNotification) {
		chat.addConversation(handle, text, showNotification);
	}

	function onJoin(handle, sessionID, showNotification) {
		chat.join(handle, sessionID, showNotification);
	}

	function onPart(sessionID) {
		chat.part(sessionID);
	}

	function onNick(handle, sessionID, showNotification) {
		chat.nick(handle, sessionID, showNotification);
	}

	function onDraw(blocks) {
		textArtCanvas.quickDraw(blocks);
	}

	function onMessage(msg) {
		var data = msg.data;
		switch (data.cmd) {
			case "connected":
				onConnected();
				break;
			case "disconnected":
				onDisconnected();
				break;
			case "imageData":
				onImageData(data.columns, data.rows, new Uint16Array(data.data), data.iceColours, data.letterSpacing);
				break;
			case "chat":
				onChat(data.handle, data.text, data.showNotification);
				break;
			case "join":
				onJoin(data.handle, data.sessionID, data.showNotification);
				break;
			case "part":
				onPart(data.sessionID);
				break;
			case "nick":
				onNick(data.handle, data.sessionID, data.showNotification);
				break;
			case "draw":
				onDraw(data.blocks);
				break;
		}
	}

	function draw(blocks) {
		worker.postMessage({ "cmd": "draw", "blocks": blocks });
	}

	function setHandle(newHandle) {
		if (handle !== newHandle) {
			handle = newHandle;
			localStorage.setItem("handle", handle);
			worker.postMessage({ "cmd": "nick", "handle": handle });
		}
	}

	function sendChat(text) {
		worker.postMessage({ "cmd": "chat", "text": text });
	}

	function isConnected() {
		return connected;
	}

	worker.addEventListener("message", onMessage);
	worker.postMessage({ "cmd": "connect", "url": "wss://" + window.location.hostname + ":1337" + window.location.pathname });

	return {
		"draw": draw,
		"setHandle": setHandle,
		"sendChat": sendChat,
		"isConnected": isConnected
	};
}

function createChatController(divChatButton, divChatWindow, divMessageWindow, divUserList, inputHandle, inputMessage, inputNotificationCheckbox, onFocusCallback, onBlurCallback) {
	"use strict";
	var enabled = false;
	var userList = {};
	var notifications = localStorage.getItem("notifications");
	if (notifications === null) {
		notifications = false;
		localStorage.setItem("notifications", notifications);
	} else {
		notifications = JSON.parse(notifications);
	}
	inputNotificationCheckbox.checked = notifications;

	function scrollToBottom() {
		var rect = divMessageWindow.getBoundingClientRect();
		divMessageWindow.scrollTop = divMessageWindow.scrollHeight - rect.height;
	}

	function newNotification(text) {
		var notification = new Notification(title.getName() + " - ANSiEdit", {
			"body": text,
			"icon": "../images/face.png"
		});
		setTimeout(() => {
			notification.close();
		}, 7000);
	}

	function addConversation(handle, text, showNotification) {
		var div = document.createElement("DIV");
		var spanHandle = document.createElement("SPAN");
		var spanSeperator = document.createElement("SPAN");
		var spanText = document.createElement("SPAN");
		spanHandle.textContent = handle;
		spanHandle.classList.add("handle");
		spanSeperator.textContent = " ";
		spanText.textContent = text;
		div.appendChild(spanHandle);
		div.appendChild(spanSeperator);
		div.appendChild(spanText);
		var rect = divMessageWindow.getBoundingClientRect();
		var doScroll = (rect.height > divMessageWindow.scrollHeight) || (divMessageWindow.scrollTop === divMessageWindow.scrollHeight - rect.height);
		divMessageWindow.appendChild(div);
		if (doScroll) {
			scrollToBottom();
		}
		if (showNotification === true && enabled === false && divChatButton.classList.contains("notification") === false) {
			divChatButton.classList.add("notification");
		}
	}

	function onFocus() {
		onFocusCallback();
	}

	function onBlur() {
		onBlurCallback();
	}

	function blurHandle(evt) {
		if (inputHandle.value === "") {
			inputHandle.value = "Anonymous";
		}
		worker.setHandle(inputHandle.value);
	}

	function keypressHandle(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (keyCode === 13) {
			inputMessage.focus();
		}
	}

	function keypressMessage(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (keyCode === 13) {
			if (inputMessage.value !== "") {
				var text = inputMessage.value;
				inputMessage.value = "";
				worker.sendChat(text);
			}
		}
	}

	inputHandle.addEventListener("focus", onFocus);
	inputHandle.addEventListener("blur", onBlur);
	inputMessage.addEventListener("focus", onFocus);
	inputMessage.addEventListener("blur", onBlur);
	inputHandle.addEventListener("blur", blurHandle);
	inputHandle.addEventListener("keypress", keypressHandle);
	inputMessage.addEventListener("keypress", keypressMessage);

	function toggle() {
		if (enabled === true) {
			divChatWindow.style.display = "none";
			enabled = false;
			onBlurCallback();
			divChatButton.classList.remove("active");
		} else {
			divChatWindow.style.display = "block";
			enabled = true;
			scrollToBottom();
			onFocusCallback();
			inputMessage.focus();
			divChatButton.classList.remove("notification");
			divChatButton.classList.add("active");
		}
	}

	function isEnabled() {
		return enabled;
	}

	function join(handle, sessionID, showNotification) {
		if (userList[sessionID] === undefined) {
			if (notifications === true && showNotification === true) {
				newNotification(handle + " has joined");
			}
			userList[sessionID] = { "handle": handle, "div": document.createElement("DIV") };
			userList[sessionID].div.classList.add("user-name");
			userList[sessionID].div.textContent = handle;
			divUserList.appendChild(userList[sessionID].div);
		}
	}

	function nick(handle, sessionID, showNotification) {
		if (userList[sessionID] !== undefined) {
			if (showNotification === true && notifications === true) {
				newNotification(userList[sessionID].handle + " has changed their name to " + handle);
			}
			userList[sessionID].handle = handle;
			userList[sessionID].div.textContent = handle;
		}
	}

	function part(sessionID) {
		if (userList[sessionID] !== undefined) {
			if (notifications === true) {
				newNotification(userList[sessionID].handle + " has left");
			}
			divUserList.removeChild(userList[sessionID].div);
			delete userList[sessionID];
		}
	}

	function globalToggleKeydown(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (keyCode === 27) {
			toggle();
		}
	}

	function notificationCheckboxClicked(evt) {
		if (inputNotificationCheckbox.checked) {
			if (Notification.permission !== "granted") {
				Notification.requestPermission((permission) => {
					notifications = true;
					localStorage.setItem("notifications", notifications);
				});
			} else {
				notifications = true;
				localStorage.setItem("notifications", notifications);
			}
		} else {
			notifications = false;
			localStorage.setItem("notifications", notifications);
		}
	}

	document.addEventListener("keydown", globalToggleKeydown);
	inputNotificationCheckbox.addEventListener("click", notificationCheckboxClicked);

	return {
		"addConversation": addConversation,
		"toggle": toggle,
		"isEnabled": isEnabled,
		"join": join,
		"nick": nick,
		"part": part
	};
}

Download

raw zip tar