moebius-web

web based ansi art editor

moebius-web

public/scripts/network.js


function createWorkerHandler(inputHandle) {
    "use strict";
    var worker = new Worker("scripts/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": "ws://" + window.location.hostname + ":" + window.location.port + 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