feat: add card layout tweak with unified post observer

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-26 21:14:06 -04:00
parent 95f0946e21
commit 5521e39a66
4 changed files with 132 additions and 52 deletions

View File

@@ -1,6 +1,62 @@
(function () {
"use strict";
function startDarkModeObserver(settings) {
var observer = new MutationObserver(function () {
if (settings.darkMode === "auto") {
window.RedditTweaks.loadSettings().then(function (updated) {
if (settings.badgeLayout) {
window.RedditTweaks.badgeTweak.updateColors(updated);
}
if (settings.cardLayout) {
window.RedditTweaks.cardTweak.updateSettings(updated);
}
});
}
});
observer.observe(document.body, {
attributes: true,
attributeFilter: ["class"],
});
}
function startPostObserver(settings) {
var target =
document.getElementById("siteTable") ||
document.querySelector('.content[role="main"]') ||
document.body;
var observer = new MutationObserver(function (mutations) {
var hasNewPosts = false;
for (var i = 0; i < mutations.length; i++) {
var added = mutations[i].addedNodes;
for (var j = 0; j < added.length; j++) {
var node = added[j];
if (node.nodeType !== Node.ELEMENT_NODE) continue;
if ((node.matches && node.matches("div.thing.link")) ||
(node.querySelector && node.querySelector("div.thing.link"))) {
hasNewPosts = true;
break;
}
}
if (hasNewPosts) break;
}
if (hasNewPosts) {
window.RedditTweaks.loadSettings().then(function (updated) {
if (settings.badgeLayout) {
window.RedditTweaks.badgeTweak.processNewPosts(updated);
}
if (settings.cardLayout) {
window.RedditTweaks.cardTweak.processNewPosts(updated);
}
});
}
});
observer.observe(target, { childList: true, subtree: true });
}
async function init() {
const settings = await window.RedditTweaks.loadSettings();
if (!settings.enabled) return;
@@ -10,10 +66,20 @@
window.RedditTweaks.badgeTweak.apply(settings);
}
if (settings.cardLayout) {
window.RedditTweaks.cardTweak.apply(settings);
}
if (settings.badgeLayout || settings.cardLayout) {
startPostObserver(settings);
startDarkModeObserver(settings);
}
browser.storage.onChanged.addListener(function (changes) {
if (
(changes.enabled && changes.enabled.newValue !== changes.enabled.oldValue) ||
(changes.badgeLayout && changes.badgeLayout.newValue !== changes.badgeLayout.oldValue)
(changes.badgeLayout && changes.badgeLayout.newValue !== changes.badgeLayout.oldValue) ||
(changes.cardLayout && changes.cardLayout.newValue !== changes.cardLayout.oldValue)
) {
location.reload();
return;
@@ -23,6 +89,9 @@
if (settings.badgeLayout) {
window.RedditTweaks.badgeTweak.updateColors(updated);
}
if (settings.cardLayout) {
window.RedditTweaks.cardTweak.updateSettings(updated);
}
});
});
}

View File

@@ -1,8 +1,6 @@
(function () {
"use strict";
let contentObserver = null;
let darkModeObserver = null;
let currentSettings = null;
function applyColorsToContainer(container, settings, subredditName) {
@@ -93,52 +91,6 @@
});
}
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");
@@ -155,8 +107,6 @@
function apply(settings) {
currentSettings = settings;
processPosts(settings);
startContentObserver(settings);
startDarkModeObserver();
}
window.RedditTweaks = window.RedditTweaks || {};
@@ -165,5 +115,6 @@
updateColors: updateColors,
isDarkMode: window.RedditTweaks.isDarkMode,
getColorPrefix: window.RedditTweaks.getColorPrefix,
processNewPosts: processPosts,
};
})();

59
content/tweaks/cards.js Normal file
View File

@@ -0,0 +1,59 @@
(function () {
"use strict";
function processPost(post) {
if (post.classList.contains("rt-card")) return;
post.classList.add("rt-card");
}
function processPosts() {
var posts = document.querySelectorAll("div.thing.link:not(.rt-card)");
for (var i = 0; i < posts.length; i++) {
processPost(posts[i]);
}
}
function applyDarkMode(settings) {
if (window.RedditTweaks.isDarkMode(settings)) {
document.documentElement.classList.add("rt-dark");
} else {
document.documentElement.classList.remove("rt-dark");
}
}
function applyBackground(settings) {
if (settings.cardBackground === "shadcn") {
document.documentElement.classList.add("rt-card-bg-shadcn");
} else {
document.documentElement.classList.remove("rt-card-bg-shadcn");
}
}
function applyGap(settings) {
var siteTable = document.getElementById("siteTable");
if (siteTable) {
siteTable.style.setProperty("--rt-card-gap", settings.cardGap + "px");
}
}
function apply(settings) {
document.documentElement.classList.add("rt-card-enabled");
applyDarkMode(settings);
applyBackground(settings);
applyGap(settings);
processPosts();
}
function updateSettings(settings) {
applyDarkMode(settings);
applyBackground(settings);
applyGap(settings);
}
window.RedditTweaks = window.RedditTweaks || {};
window.RedditTweaks.cardTweak = {
apply: apply,
updateSettings: updateSettings,
processNewPosts: processPosts,
};
})();

View File

@@ -15,13 +15,14 @@
},
"content_scripts": [
{
"matches": ["*://old.reddit.com/*", "*://www.reddit.com/*"],
"matches": ["*://old.reddit.com/*"],
"css": ["content/styles/badges.css", "content/styles/cards.css"],
"js": [
"lib/settings.js",
"content/tweaks/badges.js",
"content/tweaks/color-picker.js",
"content/tweaks/color-popover.js",
"content/tweaks/cards.js",
"content/main.js"
],
"run_at": "document_idle"