feat: badge DOM manipulation with MutationObservers and dark mode detection
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const settings = await window.RedditTweaks.loadSettings();
|
||||||
|
if (!settings.enabled) return;
|
||||||
|
|
||||||
|
window.RedditTweaks.badgeTweak.apply(settings);
|
||||||
|
|
||||||
|
browser.storage.onChanged.addListener(function (changes) {
|
||||||
|
if (changes.enabled) {
|
||||||
|
location.reload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.RedditTweaks.loadSettings().then(function (updated) {
|
||||||
|
window.RedditTweaks.badgeTweak.updateColors(updated);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
})();
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let contentObserver = null;
|
||||||
|
let darkModeObserver = null;
|
||||||
|
let currentSettings = null;
|
||||||
|
|
||||||
|
function isDarkMode(settings) {
|
||||||
|
if (settings.darkMode === "light") return false;
|
||||||
|
if (settings.darkMode === "dark") return true;
|
||||||
|
return document.body.classList.contains("res-nightmode");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColorPrefix(settings) {
|
||||||
|
return isDarkMode(settings) ? "dark" : "light";
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyColorsToContainer(container, settings, subredditName) {
|
||||||
|
const prefix = getColorPrefix(settings);
|
||||||
|
|
||||||
|
if (isDarkMode(settings)) {
|
||||||
|
container.classList.add("rt-dark");
|
||||||
|
} else {
|
||||||
|
container.classList.remove("rt-dark");
|
||||||
|
}
|
||||||
|
|
||||||
|
const overrides = subredditName && settings.subredditColors[subredditName];
|
||||||
|
|
||||||
|
container.style.setProperty("--rt-sub-bg", overrides?.bg || settings[prefix + ".subredditBgColor"]);
|
||||||
|
container.style.setProperty("--rt-sub-border", overrides?.border || settings[prefix + ".subredditBorderColor"]);
|
||||||
|
container.style.setProperty("--rt-sub-text", overrides?.text || settings[prefix + ".subredditTextColor"]);
|
||||||
|
container.style.setProperty("--rt-com-bg", settings[prefix + ".commentsBgColor"]);
|
||||||
|
container.style.setProperty("--rt-com-border", settings[prefix + ".commentsBorderColor"]);
|
||||||
|
container.style.setProperty("--rt-com-text", settings[prefix + ".commentsTextColor"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeCommentText(text) {
|
||||||
|
const trimmed = text.trim();
|
||||||
|
if (trimmed === "comment") return "0 comments";
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processPost(post, settings) {
|
||||||
|
if (post.hasAttribute("data-rt-processed")) return;
|
||||||
|
|
||||||
|
const entry = post.querySelector(".entry");
|
||||||
|
if (!entry) return;
|
||||||
|
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.className = "reddit-tweaks-badges";
|
||||||
|
|
||||||
|
let subredditName = null;
|
||||||
|
|
||||||
|
const subLink = post.querySelector(".tagline .subreddit");
|
||||||
|
if (subLink) {
|
||||||
|
const badge = document.createElement("a");
|
||||||
|
badge.className = "rt-badge rt-badge--subreddit";
|
||||||
|
badge.href = subLink.href;
|
||||||
|
badge.textContent = subLink.textContent.trim();
|
||||||
|
subredditName = subLink.textContent.trim().replace(/^r\//, "");
|
||||||
|
container.appendChild(badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
const commentsLink = post.querySelector(".flat-list .comments");
|
||||||
|
if (commentsLink) {
|
||||||
|
const badge = document.createElement("a");
|
||||||
|
badge.className = "rt-badge rt-badge--comments";
|
||||||
|
badge.href = commentsLink.href;
|
||||||
|
badge.textContent = normalizeCommentText(commentsLink.textContent);
|
||||||
|
container.appendChild(badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container.children.length === 0) return;
|
||||||
|
|
||||||
|
applyColorsToContainer(container, settings, subredditName);
|
||||||
|
entry.insertBefore(container, entry.firstChild);
|
||||||
|
post.setAttribute("data-rt-processed", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
function processPosts(settings) {
|
||||||
|
const posts = document.querySelectorAll("div.thing.link:not([data-rt-processed])");
|
||||||
|
posts.forEach(function (post) {
|
||||||
|
processPost(post, settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getObserverTarget() {
|
||||||
|
return (
|
||||||
|
document.getElementById("siteTable") ||
|
||||||
|
document.querySelector('.content[role="main"]') ||
|
||||||
|
document.body
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startContentObserver(settings) {
|
||||||
|
if (contentObserver) contentObserver.disconnect();
|
||||||
|
|
||||||
|
const target = getObserverTarget();
|
||||||
|
contentObserver = new MutationObserver(function (mutations) {
|
||||||
|
let hasNewPosts = false;
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
for (const node of mutation.addedNodes) {
|
||||||
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||||
|
if (node.matches && node.matches("div.thing.link")) {
|
||||||
|
hasNewPosts = true;
|
||||||
|
} else if (node.querySelector && node.querySelector("div.thing.link")) {
|
||||||
|
hasNewPosts = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNewPosts) processPosts(currentSettings);
|
||||||
|
});
|
||||||
|
|
||||||
|
contentObserver.observe(target, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
function startDarkModeObserver() {
|
||||||
|
if (darkModeObserver) darkModeObserver.disconnect();
|
||||||
|
|
||||||
|
darkModeObserver = new MutationObserver(function () {
|
||||||
|
if (currentSettings && currentSettings.darkMode === "auto") {
|
||||||
|
updateColors(currentSettings);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
darkModeObserver.observe(document.body, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ["class"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateColors(settings) {
|
||||||
|
currentSettings = settings;
|
||||||
|
const containers = document.querySelectorAll(".reddit-tweaks-badges");
|
||||||
|
containers.forEach(function (container) {
|
||||||
|
const subBadge = container.querySelector(".rt-badge--subreddit");
|
||||||
|
const subredditName = subBadge
|
||||||
|
? subBadge.textContent.trim().replace(/^r\//, "")
|
||||||
|
: null;
|
||||||
|
applyColorsToContainer(container, settings, subredditName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function apply(settings) {
|
||||||
|
currentSettings = settings;
|
||||||
|
processPosts(settings);
|
||||||
|
startContentObserver(settings);
|
||||||
|
startDarkModeObserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.RedditTweaks = window.RedditTweaks || {};
|
||||||
|
window.RedditTweaks.badgeTweak = {
|
||||||
|
apply: apply,
|
||||||
|
updateColors: updateColors,
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user