commit 91f31c9df7a0d7d0c2272845760a1c6d899cf52e Author: Daniel Kluge Date: Wed Nov 9 15:27:44 2022 +0100 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..913384d --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Deactivate WA Web Auto Emojis + +This is a small browser addon, that deactivates the auto replacement of smileys with emojis in WhatsApp Web. +When typing `:D` in WhatsApp Web, instead of just keeping it as text `😀` will be injected. +I don't like that. + +This extensions disables it, by putting an zero-width-space between `:` and `D`. + +There is an option page where you can toggle the behaviour for individual emojis. + +## Known issues +As WhatsApp Web does not use an HTML `` but had the "great idea" to have some div listening to keypresses, it is hard to inject stuff. + +* It does only work, when you are typing at the end of the text. Adding a smiley in the middle of the text will not be disabled. +* It does not work when pasting text. diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..de503a4 --- /dev/null +++ b/manifest.json @@ -0,0 +1,18 @@ +{ + "manifest_version": 3, + "name": "No Auto Emojis in WA Web", + "version": "0.0.1", + "description": "Disable WhatsApp Web Auto Emojis", + "author": "Daniel Kluge", + "content_scripts": [{ + "matches": ["https://web.whatsapp.com/*"], + "js": ["no-auto-emoji.js"] + }], + "permissions": [ + "storage" + ], + "options_ui": { + "page": "options.html", + "open_in_tab": false + } +} \ No newline at end of file diff --git a/no-auto-emoji.js b/no-auto-emoji.js new file mode 100644 index 0000000..7d96d00 --- /dev/null +++ b/no-auto-emoji.js @@ -0,0 +1,75 @@ +function prepareTable(deactivated) { + deactivated = deactivated || []; + const emojiTable = { + "(y)": "👍", + "(Y)": "👍", + "(n)": "👎", + "(N)": "👎", + ":-)": "🙂", + ":)": "🙂", + ":-(": "🙁", + ":(": "🙁", + ":-p": "😛", + ":-P": "😛", + ":P": "😛", + ":-\\": "😕", + ":\\": "😕", + ":-D": "😀", + ":D": "😀", + ":-o": "😮", + ":O": "😮", + ";-)": "😉", + ";)": "😉", + ":-*": "😘", + ":-|": "😐", + ":'(": "😢", + "^_^": "😁", + "<3": "❤️", + ">_<": "😆", + "8)": "😎" + }; + + for (const d of deactivated) { + delete emojiTable[d]; + } + + return emojiTable; +} + +let emojiTable = prepareTable([]); +chrome.storage.sync.get("deactivated", (result) => { + emojiTable = prepareTable(result.deactivated); +}); +chrome.storage.onChanged.addListener((changes, _areaName) => { + if (changes.deactivated?.newValue) emojiTable = prepareTable(changes.deactivated.newValue); +}); + +function fakeInput(input, data) { + input.innerText = data; + input.dispatchEvent(new InputEvent('input', { + inputType: 'insertText', + data, + bubbles: true, + cancelable: false, + composed: true, + detail: 0, + })); +} + +new MutationObserver(() => { + const divInput = document.querySelector("[data-testid=conversation-compose-box-input]"); + if (!divInput || divInput.getAttribute("data-noautoemote")) return; + + divInput.setAttribute("data-noautoemote", "true"); + + divInput.parentElement.addEventListener("beforeinput", e => { + const textField = divInput.querySelector("span"); + const text = (textField?.innerHTML || "") + e.data; + + if (text.substring(text.length - 2) in emojiTable || text.substring(text.length - 3) in emojiTable) { + e.preventDefault(); + fakeInput(divInput, "\u200B"); + fakeInput(divInput, e.data); + } + }); +}).observe(document, { childList: true, subtree: true }); \ No newline at end of file diff --git a/options.html b/options.html new file mode 100644 index 0000000..6019797 --- /dev/null +++ b/options.html @@ -0,0 +1,12 @@ + + + + No Auto Emoji Options + + + +

Select which auto emojis should be blocked:

+ + + + \ No newline at end of file diff --git a/options.js b/options.js new file mode 100644 index 0000000..d962c17 --- /dev/null +++ b/options.js @@ -0,0 +1,63 @@ +async function updateDeactivated(element, isDeactivated) { + console.log(element, isDeactivated); + + let { deactivated } = await chrome.storage.sync.get("deactivated"); + deactivated = deactivated || []; + + if (isDeactivated) { + if (!deactivated.includes(element)) deactivated.push(element); + } else { + if (deactivated.includes(element)) deactivated.splice(deactivated.indexOf(element), 1); + } + await chrome.storage.sync.set({deactivated}) +} + +(async () => { + const listE = document.getElementById("list"); + const emojiTable = { + "(y)": "👍", + "(Y)": "👍", + "(n)": "👎", + "(N)": "👎", + ":-)": "🙂", + ":)": "🙂", + ":-(": "🙁", + ":(": "🙁", + ":-p": "😛", + ":-P": "😛", + ":P": "😛", + ":-\\": "😕", + ":\\": "😕", + ":-D": "😀", + ":D": "😀", + ":-o": "😮", + ":O": "😮", + ";-)": "😉", + ";)": "😉", + ":-*": "😘", + ":-|": "😐", + ":'(": "😢", + "^_^": "😁", + "<3": "❤️", + ">_<": "😆", + "8)": "😎" + }; + let { deactivated } = await chrome.storage.sync.get("deactivated"); + deactivated = deactivated || []; + for (const [key, value] of Object.entries(emojiTable)) { + const li = document.createElement("li"); + const checkbox = document.createElement("input"); + checkbox.type = "checkbox"; + checkbox.id = key; + checkbox.checked = !deactivated.includes(key); + checkbox.addEventListener("change", (e) => { + updateDeactivated(key, !e.target.checked); + }); + const label = document.createElement("label"); + label.htmlFor = key; + label.innerText = `${key} → ${value}`; + li.appendChild(checkbox); + li.appendChild(label); + listE.appendChild(li); + } +})(); \ No newline at end of file