Colorize favorite Reddit subs on homepage
// ==UserScript== | |
// @name Reddit favorites coloring | |
// @version 1 | |
// @description Color favorite sub threads on homepage | |
// @include /^https?://www\.reddit\.com/.*$/ | |
// @run-at document-end | |
// @author Zlatko Masek | |
// @grant none | |
// ==/UserScript== | |
const FAVORITES = new Set(); | |
const ALPHA = '0.2'; | |
const HEX_LENGTH = 6; | |
const convertStringToArrayBuffer = (str) => { | |
let bytes = new Uint8Array(str.length); | |
for (let iii = 0; iii < str.length; iii++) { | |
bytes[iii] = str.charCodeAt(iii); | |
} | |
return bytes; | |
} | |
const convertArrayBufferToHexaDecimal = (buffer) => { | |
let data_view = new DataView(buffer); | |
let iii, len, hex = '', | |
c; | |
for (iii = 0, len = data_view.byteLength; iii < len; iii += 1) { | |
c = data_view.getUint8(iii).toString(16); | |
if (c.length < 2) { | |
c = '0' + c; | |
} | |
hex += c; | |
} | |
return hex; | |
} | |
const hexToRgbA = (hex) => { | |
if (hex.length === 3) { | |
hex = [hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]]; | |
} else { | |
hex = hex.split(''); | |
} | |
hex = `0x${hex.join('')}`; | |
return `rgba(${[(hex >> 16) & 255, (hex >> 8) & 255, hex & 255, ALPHA].join(', ')})`; | |
} | |
const colorize = () => { | |
for (const favorite of FAVORITES) { | |
const favoriteElements = document.querySelectorAll(`a[href="${favorite}"]`); | |
const promise = window.crypto.subtle.digest({ | |
name: 'SHA-1' | |
}, convertStringToArrayBuffer(favorite)); | |
promise.then((result) => { | |
const hex = convertArrayBufferToHexaDecimal(result).substring(0, HEX_LENGTH); | |
for (const element of favoriteElements) { | |
const el = element.parentElement.parentElement.parentElement.parentElement; | |
if (el.hasAttribute('class')) { | |
el.style['background-color'] = hexToRgbA(hex); | |
} | |
} | |
}); | |
} | |
} | |
const removeColor = (favorite) => { | |
const favoriteElements = document.querySelectorAll(`a[href="${favorite}"]`); | |
for (const element of favoriteElements) { | |
const el = element.parentElement.parentElement.parentElement.parentElement; | |
if (el.hasAttribute('class') && el.hasAttribute('style')) { | |
el.removeAttribute('style'); | |
} | |
} | |
} | |
const updateFavorites = () => { | |
const favoriteElements = document.querySelectorAll('[id^="focus-fav"]'); | |
for (const element of favoriteElements) { | |
FAVORITES.add(element.getAttribute('href')); | |
} | |
colorize(); | |
} | |
const init = () => { | |
const findLink = () => { | |
const linkNode = document.querySelector('[id^="focus-fav"]'); | |
if (linkNode) { | |
clearInterval(intervalFind); | |
updateFavorites(); | |
const hamburgerNode = linkNode.parentNode; | |
const hamburgerCallback = (mutationsList) => { | |
for (const mutation of mutationsList) { | |
if (mutation.addedNodes[0] !== undefined) { | |
if (mutation.addedNodes[0].nodeName === 'A' && mutation.addedNodes[0].id.startsWith("focus-fav")) { | |
updateFavorites(); | |
} | |
} | |
if (mutation.removedNodes[0] !== undefined) { | |
if (mutation.removedNodes[0].nodeName === 'A' && mutation.removedNodes[0].id.startsWith("focus-fav")) { | |
FAVORITES.delete(mutation.removedNodes[0].getAttribute('href')); | |
removeColor(mutation.removedNodes[0].getAttribute('href')); | |
} | |
} | |
} | |
} | |
const hamburgerObserver = new MutationObserver(hamburgerCallback); | |
hamburgerObserver.observe(hamburgerNode, { | |
childList: true, | |
subtree: true | |
}); | |
const listCallback = (mutationsList) => { | |
if (FAVORITES.size) { | |
colorize(); | |
} | |
} | |
const listNode = document.querySelector('div[data-redditstyle]').nextSibling; | |
const listObserver = new MutationObserver(listCallback); | |
listObserver.observe(listNode, { | |
childList: true, | |
subtree: true | |
}); | |
} | |
} | |
const intervalFind = setInterval(findLink, 1000); | |
} | |
init(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment