diff --git a/Twitch Notes/twitch-notes.js b/Twitch Notes/twitch-notes.js index a3b2119..0121eee 100644 --- a/Twitch Notes/twitch-notes.js +++ b/Twitch Notes/twitch-notes.js @@ -1,223 +1,254 @@ (function runTwitchNotes() { - let mousePosition = { x: 0, y: 0 }; - let lastMousePosition = { x: 0, y: 0 }; - let openContainers = {}; - let isMouseDown = false; - let activeContainer = null; - let settingsWindowOpen = false; + const Notes = { + getSavedUserList: () => { + return JSON.parse(localStorage.getItem(LS_UserList) || "[]"); + }, + addUserToSavedList: (username) => { + let userList = Notes.getSavedUserList(); - let LS_UserList = "twitch-note-all-users-list"; - let LS_Prefix = "twitch-note-"; - - document.addEventListener("mousemove", handleMouseMove); - document.addEventListener("mouseup", handleMouseUp); - - function createSettingsButton(buttonContainer) { - const c1 = document.createElement("div"); - c1.style.marginLeft = "0.5rem !important"; - const c2 = document.createElement("div"); - c2.style.display = "inline-flex !important"; - - const settingsButton = document.createElement("button"); - settingsButton.classList.add("twitch-notes-settings-button"); - settingsButton.innerHTML = "Notes"; - settingsButton.addEventListener("click", () => { - console.log("TN Settings"); - }); - - c2.appendChild(settingsButton); - c1.appendChild(c2); - - buttonContainer.lastChild.insertBefore( - c1, - buttonContainer.lastChild.lastChild - ); - } - - function getSavedUserList() { - return JSON.parse(localStorage.getItem(LS_UserList) || "[]"); - } - - function addUserToSavedList(username) { - let userList = getSavedUserList(); - - if (!userList.includes(username)) { - userList.push(username); - localStorage.setItem(LS_UserList, JSON.stringify(userList)); + if (!userList.includes(username)) { + userList.push(username); + localStorage.setItem(LS_UserList, JSON.stringify(userList)); + } + }, + saveNote: (username, note) => { + Notes.addUserToSavedList(username); + localStorage.setItem(LS_Prefix + username, note); + }, + getNote: (username) => { + return localStorage.getItem(LS_Prefix + username) || ""; + } } - } - function saveNote(username, note) { - addUserToSavedList(username); - localStorage.setItem(LS_Prefix + username, note); - } - function getNote(username) { - return localStorage.getItem(LS_Prefix + username) || ""; - } - - function handleMouseMove(event) { - event = event || window.event; - if (isMouseDown) { - if (activeContainer) { - const dx = mousePosition.x - lastMousePosition.x; - const dy = mousePosition.y - lastMousePosition.y; - openContainers[activeContainer].style.top = - parseInt(openContainers[activeContainer].style.top) + dy + "px"; - openContainers[activeContainer].style.left = - parseInt(openContainers[activeContainer].style.left) + dx + "px"; - } + const Mouse = { + mousePosition: {x: 0, y: 0}, + lastMousePosition: {x: 0, y: 0}, + handleMouseMove: (event) => { + if (isMouseDown) { + if (activeContainer) { + const dx = Mouse.mousePosition.x - Mouse.lastMousePosition.x; + const dy = Mouse.mousePosition.y - Mouse.lastMousePosition.y; + openContainers[activeContainer].style.top = + parseInt(openContainers[activeContainer].style.top) + dy + "px"; + openContainers[activeContainer].style.left = + parseInt(openContainers[activeContainer].style.left) + dx + "px"; + } + } + Mouse.updateMousePosition(event.clientX, event.clientY); + }, + handleMouseUp: () => { + activeContainer = null; + isMouseDown = false; + }, + updateMousePosition: (x, y) => { + Mouse.lastMousePosition = {...Mouse.mousePosition}; + Mouse.mousePosition = {x, y}; + } } - updateMousePosition(event.clientX, event.clientY); - } - function handleMouseUp(event) { - activeContainer = null; - isMouseDown = false; - } + function createElement(tag, body, classes, styles, attributes) { + const element = document.createElement(tag); - function updateMousePosition(x, y) { - lastMousePosition = { ...mousePosition }; - mousePosition.x = x; - mousePosition.y = y; - } + if (body) { + element.innerHTML = body; + } - function removeContainer(username) { - if (!openContainers[username]) return; - openContainers[username].remove(); - delete openContainers[username]; - } + if (classes) { + if (typeof classes === 'object') { + for (let className of classes) { + element.classList.add((className)); + } + } else { + element.classList.add(classes); + } + } - function addContainer(username, container) { - if (openContainers[username]) return; - openContainers[username] = container; - document.body.appendChild(container); - } + if (styles) { + if (typeof styles === 'object') { + for (let style in styles) { + element.style[style] = styles[style]; + } + } + } - function openTwitchNote(username) { - // CONTAINER - const container = document.createElement("div"); - container.style.left = mousePosition.x + "px"; - container.style.top = mousePosition.y + 10 + "px"; - container.classList.add("twitch-note-container"); + if (attributes) { + if (typeof attributes === 'object') { + for (let attribute in attributes) { + element.setAttribute(attribute, attributes[attribute]); + } + } + } - // HEADER - const header = document.createElement("div"); - header.classList.add("twitch-note-header"); - header.addEventListener("mousedown", function close() { - activeContainer = username; - isMouseDown = true; - }); - const closeButton = document.createElement("span"); - closeButton.classList.add("twitch-note-close-button"); - closeButton.innerText = "X"; - closeButton.addEventListener("click", function close() { - removeContainer(username); - }); - header.appendChild(closeButton); - const title = document.createElement("span"); - title.classList.add("twitch-note-title"); - title.innerHTML = username; - header.appendChild(title); - container.appendChild(header); + return element; + } - // BODY - const content = document.createElement("div"); - content.classList.add("twitch-note-content"); - content.setAttribute("contentEditable", true); - content.innerHTML = getNote(username); + function createSettingsButton(buttonContainer) { - container.appendChild(content); + const c1 = createElement('div', null, null, {marginLeft: "0.5rem !important"}); + const c2 = createElement('div', null, null, {display: "inline-flex !important"}); + const settingsButton = createElement('button', 'Notes', 'twitch-notes-settings-button'); - const saveButton = document.createElement("div"); - saveButton.classList.add("twitch-note-save-button"); - saveButton.innerText = "SAVE"; - saveButton.addEventListener("click", function () { - saveNote(username, content.innerHTML); - removeContainer(username); - }); + settingsButton.addEventListener("click", toggleSettings); - container.appendChild(saveButton); + c2.appendChild(settingsButton); + c1.appendChild(c2); - addContainer(username, container); - } + buttonContainer.lastChild.insertBefore( + c1, + buttonContainer.lastChild.lastChild + ); + } - let giveUpAt = Date.now() + 20000; + function removeContainer(username) { + if (!openContainers[username]) return; + openContainers[username].remove(); + delete openContainers[username]; + } - let changeInProgress = false; + function addContainer(username, container) { + if (openContainers[username]) return; + openContainers[username] = container; + document.body.appendChild(container); + } - let targetNode; - let buttonContainer; + function openTwitchNote(username) { - do { - targetNode = document.getElementsByClassName( - "chat-scrollable-area__message-container" - )[0]; - } while (!targetNode || giveUpAt < Date.now()); + const container = createElement('div', null, 'twitch-note-container', { + left: Mouse.mousePosition.x + 'px', + top: Mouse.mousePosition.y + 10 + 'px' + }); - do { - buttonContainer = document.getElementsByClassName( - "chat-input__buttons-container" - )[0]; - } while (!buttonContainer || giveUpAt < Date.now()); + const header = createElement('div', null, 'twitch-note-header'); + header.addEventListener("mousedown", function close() { + activeContainer = username; + isMouseDown = true; + }); - createSettingsButton(buttonContainer); + const closeButton = createElement('span', "X", 'twitch-note-close-button') + closeButton.addEventListener("click", function close() { + removeContainer(username); + }); - // Options for the observer (which mutations to observe) - const config = { attributes: true, childList: true, subtree: true }; + const title = createElement('span', username, 'twitch-note-title'); + const content = createElement('div', Notes.getNote(username), 'twitch-note-content', [], { + contentEditable: 'true' + }); - // Callback function to execute when mutations are observed - const callback = (mutationList, observer) => { - if (!changeInProgress) { - for (const mutation of mutationList) { - if (mutation.type === "childList") { - changeInProgress = true; - let nodes = document.getElementsByClassName("chat-line__message"); - let users = []; - for (let node of nodes) { + const saveButton = createElement('div', 'SAVE', 'twitch-note-save-button') + saveButton.addEventListener("click", function () { + Notes.saveNote(username, content.innerHTML); + removeContainer(username); + }); + + header.appendChild(closeButton); + header.appendChild(title); + container.appendChild(header); + container.appendChild(content); + container.appendChild(saveButton); + + addContainer(username, container); + } + + function addNoteBadges() { + let nodes = document.getElementsByClassName("chat-line__message"); + let users = []; + for (let node of nodes) { const n = node.querySelector(".chat-author__display-name"); if (!n) continue; const usernameContainer = node.querySelector( - ".chat-line__username-container" + ".chat-line__username-container" ); const username = n.attributes["data-a-user"].value; if (username) { - let noteButton = usernameContainer.querySelector(".twitch-note"); - if (!noteButton) { - const twitchNote = document.createElement("span"); - twitchNote.classList.add("twitch-note"); - twitchNote.style.cursor = "pointer"; - twitchNote.addEventListener("click", () => { - openTwitchNote(username); - }); + let noteButton = usernameContainer.querySelector(".twitch-note"); + if (!noteButton) { - const img = document.createElement("img"); - img.src = "https://cdn.rdarius.lt/icons/32-id-card.png"; - img.style.height = "18px"; - img.style.paddingRight = "4px"; - twitchNote.appendChild(img); + const twitchNote = createElement('span', null, 'twitch-note', { + cursor: 'pointer', + }) + twitchNote.addEventListener("click", () => { + openTwitchNote(username); + }); - usernameContainer.insertBefore( - twitchNote, - usernameContainer.firstChild - ); - } - if (!users[username]) { - users[username] = 0; - } - users[username]++; + const img = createElement('img', null, null, { + height: '18px', + paddingRight: '4px' + }, { + src: "https://cdn.rdarius.lt/icons/32-id-card.png" + }) + + twitchNote.appendChild(img); + + usernameContainer.insertBefore( + twitchNote, + usernameContainer.firstChild + ); + } + if (!users[username]) { + users[username] = 0; + } + users[username]++; } - } - changeInProgress = false; } - } } - }; - // Create an observer instance linked to the callback function - const observer = new MutationObserver(callback); + function toggleSettings() { + console.log('toggle settings'); + } - // Start observing the target node for configured mutations - observer.observe(targetNode, config); + let openContainers = {}; + let isMouseDown = false; + let activeContainer = null; + // let settingsWindowOpen = false; + + let LS_UserList = "twitch-note-all-users-list"; + let LS_Prefix = "twitch-note-"; + + document.addEventListener("mousemove", Mouse.handleMouseMove); + document.addEventListener("mouseup", Mouse.handleMouseUp); + + let giveUpAt = Date.now() + 20000; + + let changeInProgress = false; + + let targetNode; + let buttonContainer; + + do { + targetNode = document.getElementsByClassName( + "chat-scrollable-area__message-container" + )[0]; + } while (!targetNode || giveUpAt < Date.now()); + + do { + buttonContainer = document.getElementsByClassName( + "chat-input__buttons-container" + )[0]; + } while (!buttonContainer || giveUpAt < Date.now()); + + createSettingsButton(buttonContainer); + + // Options for the observer (which mutations to observe) + const config = {attributes: true, childList: true, subtree: true}; + + // Callback function to execute when mutations are observed + const callback = (mutationList) => { + if (!changeInProgress) { + for (const mutation of mutationList) { + if (mutation.type === "childList") { + changeInProgress = true; + addNoteBadges(); + changeInProgress = false; + } + } + } + }; + + // Create an observer instance linked to the callback function + const observer = new MutationObserver(callback); + + // Start observing the target node for configured mutations + observer.observe(targetNode, config); })();